From 7574ec3e21255cb25a020dca410459644986c91b Mon Sep 17 00:00:00 2001 From: Artem Sokolovskii Date: Mon, 4 Apr 2022 14:53:05 +0200 Subject: [PATCH] ClangFormat: Add the logical settings management Now there are changeable and unchangeable settings, as it works for usual codestyle settings. They save parallel with codestyle settings but in another dir. In general, the behavior became similar to usual codestyle settings. ToDo: Make indenter use this settings instead standard one and instead project settings when "override" checkbox is checked. Change-Id: I639dbda296932bf9b967a11f1cc4fda120415ed9 Reviewed-by: Christian Kandeler Reviewed-by: --- .../clangformat/clangformatconfigwidget.cpp | 18 +++++---- .../clangformat/clangformatconfigwidget.h | 3 +- src/plugins/clangformat/clangformatfile.cpp | 37 +++++++++++++------ src/plugins/clangformat/clangformatfile.h | 6 ++- src/plugins/clangformat/clangformatplugin.cpp | 8 ++-- src/plugins/clangformat/clangformatutils.cpp | 13 ++++++- src/plugins/clangformat/clangformatutils.h | 2 + .../cppcodestylepreferencesfactory.cpp | 5 ++- .../cppcodestylepreferencesfactory.h | 3 +- .../texteditor/codestyleselectorwidget.cpp | 1 + 10 files changed, 67 insertions(+), 29 deletions(-) diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp index 9d44fe1dcc8..2a6f3f9b6b5 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatconfigwidget.cpp @@ -43,7 +43,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -100,19 +102,22 @@ bool ClangFormatConfigWidget::eventFilter(QObject *object, QEvent *event) return QWidget::eventFilter(object, event); } -ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *project, QWidget *parent) +ClangFormatConfigWidget::ClangFormatConfigWidget(TextEditor::ICodeStylePreferences *codeStyle, + ProjectExplorer::Project *project, + QWidget *parent) : CppCodeStyleWidget(parent) , m_project(project) , m_checks(std::make_unique()) , m_ui(std::make_unique()) { m_ui->setupUi(this); + setEnabled(!codeStyle->isReadOnly()); Utils::FilePath filePath = Core::ICore::userResourcePath(); - if (m_project) - filePath = filePath / "clang-format/" / currentProjectUniqueId(); - filePath = filePath / QLatin1String(Constants::SETTINGS_FILE_NAME); - m_config = std::make_unique(filePath); + filePath = filePath / "clang-format/" + / Utils::FileUtils::fileSystemFriendlyName(codeStyle->displayName()) + / QLatin1String(Constants::SETTINGS_FILE_NAME); + m_config = std::make_unique(filePath, codeStyle->isReadOnly()); initChecksAndPreview(); showCombobox(); @@ -329,8 +334,7 @@ void ClangFormatConfigWidget::fillTable() Utils::ExecuteOnDestruction executeOnDestruction([this]() { m_disableTableUpdate = false; }); m_disableTableUpdate = true; - const std::string configText = m_project ? currentProjectConfigText() - : currentGlobalConfigText(); + const std::string configText = readFile(m_config->filePath().path()); for (QObject *child : m_checksWidget->children()) { if (!qobject_cast(child) && !qobject_cast(child) diff --git a/src/plugins/clangformat/clangformatconfigwidget.h b/src/plugins/clangformat/clangformatconfigwidget.h index fb6ffa04e0b..9a460892501 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.h +++ b/src/plugins/clangformat/clangformatconfigwidget.h @@ -48,7 +48,8 @@ class ClangFormatConfigWidget : public CppEditor::CppCodeStyleWidget Q_OBJECT public: - explicit ClangFormatConfigWidget(ProjectExplorer::Project *project = nullptr, + explicit ClangFormatConfigWidget(TextEditor::ICodeStylePreferences *codeStyle, + ProjectExplorer::Project *project = nullptr, QWidget *parent = nullptr); ~ClangFormatConfigWidget() override; void apply() override; diff --git a/src/plugins/clangformat/clangformatfile.cpp b/src/plugins/clangformat/clangformatfile.cpp index 3c64ebe1b48..b439dc5698b 100644 --- a/src/plugins/clangformat/clangformatfile.cpp +++ b/src/plugins/clangformat/clangformatfile.cpp @@ -25,6 +25,7 @@ #include "clangformatfile.h" #include "clangformatsettings.h" +#include "clangformatutils.h" #include #include #include @@ -34,11 +35,18 @@ using namespace ClangFormat; -ClangFormatFile::ClangFormatFile(Utils::FilePath filePath) +ClangFormatFile::ClangFormatFile(Utils::FilePath filePath, bool isReadOnly) : m_filePath(filePath) + , m_isReadOnly(isReadOnly) { if (!m_filePath.exists()) { - resetStyleToLLVM(); + // create file and folder + m_filePath.parentDir().createDir(); + std::fstream newStyleFile(m_filePath.path().toStdString(), std::fstream::out); + if (newStyleFile.is_open()) { + newStyleFile.close(); + } + resetStyleToQtC(); return; } @@ -46,7 +54,7 @@ ClangFormatFile::ClangFormatFile(Utils::FilePath filePath) const std::error_code error = clang::format::parseConfiguration(m_filePath.fileContents().toStdString(), &m_style); if (error.value() != static_cast(clang::format::ParseError::Success)) { - resetStyleToLLVM(); + resetStyleToQtC(); } } @@ -65,10 +73,15 @@ void ClangFormatFile::setStyle(clang::format::FormatStyle style) saveNewFormat(); } -void ClangFormatFile::resetStyleToLLVM() +bool ClangFormatFile::isReadOnly() const { - m_style = clang::format::getLLVMStyle(); - saveNewFormat(); + return m_isReadOnly; +} + +void ClangFormatFile::resetStyleToQtC() +{ + m_style = qtcStyle(); + saveStyleToFile(m_style, m_filePath); } void ClangFormatFile::setBasedOnStyle(QString styleName) @@ -107,17 +120,17 @@ QString ClangFormatFile::changeFields(QList fields) void ClangFormatFile::saveNewFormat() { - std::string style = clang::format::configurationAsText(m_style); + if (m_isReadOnly) + return; - // workaround: configurationAsText() add comment "# " before BasedOnStyle line - const int pos = style.find("# BasedOnStyle"); - if (pos != int(std::string::npos)) - style.erase(pos, 2); - m_filePath.writeFileContents(QByteArray::fromStdString(style)); + saveStyleToFile(m_style, m_filePath); } void ClangFormatFile::saveNewFormat(QByteArray style) { + if (m_isReadOnly) + return; + m_filePath.writeFileContents(style); } diff --git a/src/plugins/clangformat/clangformatfile.h b/src/plugins/clangformat/clangformatfile.h index f0dddd4ec03..da864c2a753 100644 --- a/src/plugins/clangformat/clangformatfile.h +++ b/src/plugins/clangformat/clangformatfile.h @@ -37,11 +37,11 @@ namespace ClangFormat { class ClangFormatFile { public: - explicit ClangFormatFile(Utils::FilePath file); + explicit ClangFormatFile(Utils::FilePath file, bool isReadOnly); clang::format::FormatStyle format(); Utils::FilePath filePath(); - void resetStyleToLLVM(); + void resetStyleToQtC(); void setBasedOnStyle(QString styleName); void setStyle(clang::format::FormatStyle style); QString setStyle(QString style); @@ -54,6 +54,7 @@ public: TextEditor::TabSettings toTabSettings(ProjectExplorer::Project *project) const; void fromCppCodeStyleSettings(const CppEditor::CppCodeStyleSettings &settings); void fromTabSettings(const TextEditor::TabSettings &settings); + bool isReadOnly() const; private: void saveNewFormat(); @@ -62,6 +63,7 @@ private: private: Utils::FilePath m_filePath; clang::format::FormatStyle m_style; + const bool m_isReadOnly; }; } // namespace ClangFormat diff --git a/src/plugins/clangformat/clangformatplugin.cpp b/src/plugins/clangformat/clangformatplugin.cpp index 0fbc44eefe9..78204ae3696 100644 --- a/src/plugins/clangformat/clangformatplugin.cpp +++ b/src/plugins/clangformat/clangformatplugin.cpp @@ -84,11 +84,13 @@ public: return new ClangFormatIndenter(doc); } - std::pair additionalTab(QWidget *parent) const override + std::pair additionalTab( + TextEditor::ICodeStylePreferences *codeStyle, QWidget *parent) const override { if (!parent) - return {new ClangFormatConfigWidget(), tr("ClangFormat")}; - return {new ClangFormatConfigWidget(SessionManager::startupProject()), tr("ClangFormat")}; + return {new ClangFormatConfigWidget(codeStyle), tr("ClangFormat")}; + return {new ClangFormatConfigWidget(codeStyle, SessionManager::startupProject()), + tr("ClangFormat")}; } }; diff --git a/src/plugins/clangformat/clangformatutils.cpp b/src/plugins/clangformat/clangformatutils.cpp index cf32bff3545..21fab5cc931 100644 --- a/src/plugins/clangformat/clangformatutils.cpp +++ b/src/plugins/clangformat/clangformatutils.cpp @@ -200,6 +200,17 @@ QString currentProjectUniqueId() .toHex(0)); } +void saveStyleToFile(clang::format::FormatStyle style, Utils::FilePath filePath) +{ + std::string styleStr = clang::format::configurationAsText(style); + + // workaround: configurationAsText() add comment "# " before BasedOnStyle line + const int pos = styleStr.find("# BasedOnStyle"); + if (pos != int(std::string::npos)) + styleStr.erase(pos, 2); + filePath.writeFileContents(QByteArray::fromStdString(styleStr)); +} + static bool useProjectOverriddenSettings() { const Project *project = SessionManager::startupProject(); @@ -371,7 +382,7 @@ void addQtcStatementMacros(clang::format::FormatStyle &style) } } -static std::string readFile(const QString &path) +std::string readFile(const QString &path) { const std::string defaultStyle = clang::format::configurationAsText(qtcStyle()); diff --git a/src/plugins/clangformat/clangformatutils.h b/src/plugins/clangformat/clangformatutils.h index 3caf6c9d6fc..aa7a8f30cc1 100644 --- a/src/plugins/clangformat/clangformatutils.h +++ b/src/plugins/clangformat/clangformatutils.h @@ -46,10 +46,12 @@ std::string currentGlobalConfigText(); clang::format::FormatStyle currentProjectStyle(); clang::format::FormatStyle currentGlobalStyle(); +std::string readFile(const QString &path); // Is the style from the matching .clang-format file or global one if it's not found. QString configForFile(Utils::FilePath fileName); clang::format::FormatStyle styleForFile(Utils::FilePath fileName); +void saveStyleToFile(clang::format::FormatStyle style, Utils::FilePath filePath); void addQtcStatementMacros(clang::format::FormatStyle &style); clang::format::FormatStyle qtcStyle(); diff --git a/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp b/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp index c417f945c22..c3ec1b345eb 100644 --- a/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp +++ b/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp @@ -109,7 +109,7 @@ TextEditor::CodeStyleEditorWidget *CppCodeStylePreferencesFactory::createEditor( widget->layout()->setContentsMargins(0, 0, 0, 0); widget->setCodeStyle(cppPreferences); - const auto tab = additionalTab(parent); + const auto tab = additionalTab(preferences, parent); widget->addTab(tab.first, tab.second); return widget; @@ -131,8 +131,9 @@ QString CppCodeStylePreferencesFactory::previewText() const } std::pair CppCodeStylePreferencesFactory::additionalTab( - QWidget *parent) const + TextEditor::ICodeStylePreferences *codeStyle, QWidget *parent) const { + Q_UNUSED(codeStyle) Q_UNUSED(parent) return {nullptr, ""}; } diff --git a/src/plugins/cppeditor/cppcodestylepreferencesfactory.h b/src/plugins/cppeditor/cppcodestylepreferencesfactory.h index 60c123a64ec..8c5848bb87a 100644 --- a/src/plugins/cppeditor/cppcodestylepreferencesfactory.h +++ b/src/plugins/cppeditor/cppcodestylepreferencesfactory.h @@ -45,7 +45,8 @@ public: TextEditor::Indenter *createIndenter(QTextDocument *doc) const override; QString snippetProviderGroupId() const override; QString previewText() const override; - virtual std::pair additionalTab(QWidget *parent) const; + virtual std::pair additionalTab( + TextEditor::ICodeStylePreferences *codeStyle, QWidget *parent) const; }; } // namespace CppEditor diff --git a/src/plugins/texteditor/codestyleselectorwidget.cpp b/src/plugins/texteditor/codestyleselectorwidget.cpp index 11cd927a34b..ca1616cb1cc 100644 --- a/src/plugins/texteditor/codestyleselectorwidget.cpp +++ b/src/plugins/texteditor/codestyleselectorwidget.cpp @@ -104,6 +104,7 @@ CodeStyleDialog::CodeStyleDialog(ICodeStylePreferencesFactory *factory, m_codeStyle->setValue(codeStyle->value()); m_codeStyle->setId(codeStyle->id()); m_codeStyle->setDisplayName(m_originalDisplayName); + m_codeStyle->setReadOnly(codeStyle->isReadOnly()); TextEditor::CodeStyleEditorWidget *editor = factory->createEditor(m_codeStyle, this); m_buttons = new QDialogButtonBox(