From a997161dd6e832ffd8d01fa28a1c8fc6ca1a3860 Mon Sep 17 00:00:00 2001 From: Artem Sokolovskii Date: Mon, 1 Nov 2021 16:20:08 +0100 Subject: [PATCH] ClangFormat: Synchronize ClangFormat settings with CppEditor codestyle Added synchronization between ClangFormat codestyle settings and CppEditors codestyle settings. All changes which will be done in ClangFormat settings tab settings tabs will be automatically retranslated to CppEditor codestyle settings tabs and vice versa. Change-Id: I408d726c12552856e3c1b72d3ba09b77fff83321 Reviewed-by: Qt CI Bot Reviewed-by: Christian Kandeler --- .../clangformat/clangformatconfigwidget.cpp | 26 +++- .../clangformat/clangformatconfigwidget.h | 16 +- src/plugins/clangformat/clangformatfile.cpp | 143 +++++++++++++++++- src/plugins/clangformat/clangformatfile.h | 9 +- src/plugins/clangformat/clangformatplugin.cpp | 3 +- .../cppcodestylepreferencesfactory.cpp | 11 +- .../cppcodestylepreferencesfactory.h | 3 +- .../cppeditor/cppcodestylesettings.cpp | 26 ++-- src/plugins/cppeditor/cppcodestylesettings.h | 5 +- .../cppeditor/cppcodestylesettingspage.cpp | 28 +++- .../cppeditor/cppcodestylesettingspage.h | 24 ++- 11 files changed, 262 insertions(+), 32 deletions(-) diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp index 0dc6d4c54fe..1a28f4d6995 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatconfigwidget.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -115,7 +116,7 @@ void ClangFormatConfigWidget::showEvent(QShowEvent *event) } ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *project, QWidget *parent) - : CodeStyleEditorWidget(parent) + : CppCodeStyleWidget(parent) , m_project(project) , m_checks(std::make_unique()) , m_ui(std::make_unique()) @@ -438,6 +439,29 @@ void ClangFormatConfigWidget::saveChanges(QObject *sender) fillTable(); updatePreview(); + synchronize(); +} + +void ClangFormatConfigWidget::setCodeStyleSettings(const CppEditor::CppCodeStyleSettings &settings) +{ + m_config->fromCppCodeStyleSettings(settings); + + fillTable(); + updatePreview(); +} + +void ClangFormatConfigWidget::setTabSettings(const TextEditor::TabSettings &settings) +{ + m_config->fromTabSettings(settings); + + fillTable(); + updatePreview(); +} + +void ClangFormatConfigWidget::synchronize() +{ + emit codeStyleSettingsChanged(m_config->toCppCodeStyleSettings(m_project)); + emit tabSettingsChanged(m_config->toTabSettings(m_project)); } void ClangFormatConfigWidget::apply() diff --git a/src/plugins/clangformat/clangformatconfigwidget.h b/src/plugins/clangformat/clangformatconfigwidget.h index 4c261f99924..cf4bc1104c3 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.h +++ b/src/plugins/clangformat/clangformatconfigwidget.h @@ -25,18 +25,15 @@ #pragma once -#include +#include #include #include -namespace ProjectExplorer { -class Project; -} -namespace TextEditor { -class SnippetEditorWidget; -} +namespace ProjectExplorer { class Project; } +namespace TextEditor { class SnippetEditorWidget; } +namespace CppEditor { class CppCodeStyleSettings; } namespace ClangFormat { @@ -46,7 +43,7 @@ class ClangFormatChecksWidget; } class ClangFormatFile; -class ClangFormatConfigWidget : public TextEditor::CodeStyleEditorWidget +class ClangFormatConfigWidget : public CppEditor::CppCodeStyleWidget { Q_OBJECT @@ -55,6 +52,9 @@ public: QWidget *parent = nullptr); ~ClangFormatConfigWidget() override; void apply() override; + void setCodeStyleSettings(const CppEditor::CppCodeStyleSettings &settings) override; + void setTabSettings(const TextEditor::TabSettings &settings) override; + void synchronize() override; private: void onTableChanged(); diff --git a/src/plugins/clangformat/clangformatfile.cpp b/src/plugins/clangformat/clangformatfile.cpp index c9955ef2a3e..44adde76b04 100644 --- a/src/plugins/clangformat/clangformatfile.cpp +++ b/src/plugins/clangformat/clangformatfile.cpp @@ -24,6 +24,12 @@ ****************************************************************************/ #include "clangformatfile.h" +#include "clangformatsettings.h" +#include +#include +#include +#include + #include using namespace ClangFormat; @@ -105,7 +111,7 @@ void ClangFormatFile::saveNewFormat() // workaround: configurationAsText() add comment "# " before BasedOnStyle line const int pos = style.find("# BasedOnStyle"); - if (pos < int(style.size())) + if (pos != int(std::string::npos)) style.erase(pos, 2); m_filePath.writeFileContents(QByteArray::fromStdString(style)); } @@ -114,3 +120,138 @@ void ClangFormatFile::saveNewFormat(QByteArray style) { m_filePath.writeFileContents(style); } + +CppEditor::CppCodeStyleSettings ClangFormatFile::toCppCodeStyleSettings( + ProjectExplorer::Project *project) const +{ + using namespace clang::format; + auto settings = CppEditor::CppCodeStyleSettings::getProjectCodeStyle(project); + + FormatStyle style; + style.Language = clang::format::FormatStyle::LK_Cpp; + const std::error_code error = parseConfiguration(m_filePath.fileContents().toStdString(), + &style); + QTC_ASSERT(error.value() == static_cast(ParseError::Success), return settings); + + // Modifier offset should be opposite to indent width in order indentAccessSpecifiers + // to be false + settings.indentAccessSpecifiers = (style.AccessModifierOffset != -1 * style.IndentWidth); + + settings.indentNamespaceBody = style.NamespaceIndentation + == FormatStyle::NamespaceIndentationKind::NI_All; + settings.indentNamespaceBraces = settings.indentNamespaceBody; + + settings.indentClassBraces = style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths; + settings.indentEnumBraces = settings.indentClassBraces; + settings.indentBlockBraces = settings.indentClassBraces; + settings.indentFunctionBraces = settings.indentClassBraces; + + settings.indentSwitchLabels = style.IndentCaseLabels; + settings.indentBlocksRelativeToSwitchLabels = style.IndentCaseBlocks; + settings.indentStatementsRelativeToSwitchLabels = style.IndentCaseBlocks; + settings.indentControlFlowRelativeToSwitchLabels = style.IndentCaseBlocks; + + if (style.DerivePointerAlignment + && ClangFormatSettings::instance().formatCodeInsteadOfIndent()) { + settings.bindStarToIdentifier = style.PointerAlignment == FormatStyle::PAS_Right; + settings.bindStarToTypeName = style.PointerAlignment == FormatStyle::PAS_Left; + settings.bindStarToLeftSpecifier = style.PointerAlignment == FormatStyle::PAS_Left; + settings.bindStarToRightSpecifier = style.PointerAlignment == FormatStyle::PAS_Right; + } + + return settings; +} + +void ClangFormatFile::fromCppCodeStyleSettings(const CppEditor::CppCodeStyleSettings &settings) +{ + using namespace clang::format; + if (settings.indentAccessSpecifiers) + m_style.AccessModifierOffset = 0; + else + m_style.AccessModifierOffset = -1 * m_style.IndentWidth; + + if (settings.indentNamespaceBody || settings.indentNamespaceBraces) + m_style.NamespaceIndentation = FormatStyle::NamespaceIndentationKind::NI_All; + + if (settings.indentClassBraces || settings.indentEnumBraces || settings.indentBlockBraces + || settings.indentFunctionBraces) + m_style.BreakBeforeBraces = FormatStyle::BS_Whitesmiths; + + m_style.IndentCaseLabels = settings.indentSwitchLabels; + m_style.IndentCaseBlocks = settings.indentBlocksRelativeToSwitchLabels + || settings.indentStatementsRelativeToSwitchLabels + || settings.indentControlFlowRelativeToSwitchLabels; + + if (settings.alignAssignments) + m_style.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; + + if (settings.extraPaddingForConditionsIfConfusingAlign) + m_style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; + + m_style.DerivePointerAlignment = settings.bindStarToIdentifier || settings.bindStarToTypeName + || settings.bindStarToLeftSpecifier + || settings.bindStarToRightSpecifier; + + if ((settings.bindStarToIdentifier || settings.bindStarToRightSpecifier) + && ClangFormatSettings::instance().formatCodeInsteadOfIndent()) + m_style.PointerAlignment = FormatStyle::PAS_Right; + + if ((settings.bindStarToTypeName || settings.bindStarToLeftSpecifier) + && ClangFormatSettings::instance().formatCodeInsteadOfIndent()) + m_style.PointerAlignment = FormatStyle::PAS_Left; + + saveNewFormat(); +} + +TextEditor::TabSettings ClangFormatFile::toTabSettings(ProjectExplorer::Project *project) const +{ + using namespace clang::format; + auto settings = CppEditor::CppCodeStyleSettings::getProjectTabSettings(project); + + FormatStyle style; + style.Language = clang::format::FormatStyle::LK_Cpp; + const std::error_code error = parseConfiguration(m_filePath.fileContents().toStdString(), + &style); + QTC_ASSERT(error.value() == static_cast(ParseError::Success), return settings); + + settings.m_indentSize = style.IndentWidth; + settings.m_tabSize = style.TabWidth; + + switch (style.UseTab) { + case FormatStyle::UT_AlignWithSpaces: + case FormatStyle::UT_ForIndentation: + case FormatStyle::UT_ForContinuationAndIndentation: + settings.m_tabPolicy = TextEditor::TabSettings::TabPolicy::MixedTabPolicy; + break; + case FormatStyle::UT_Never: + settings.m_tabPolicy = TextEditor::TabSettings::TabPolicy::SpacesOnlyTabPolicy; + break; + case FormatStyle::UT_Always: + settings.m_tabPolicy = TextEditor::TabSettings::TabPolicy::TabsOnlyTabPolicy; + break; + } + + return settings; +} + +void ClangFormatFile::fromTabSettings(const TextEditor::TabSettings &settings) +{ + using namespace clang::format; + + m_style.IndentWidth = settings.m_indentSize; + m_style.TabWidth = settings.m_tabSize; + + switch (settings.m_tabPolicy) { + case TextEditor::TabSettings::TabPolicy::MixedTabPolicy: + m_style.UseTab = FormatStyle::UT_ForContinuationAndIndentation; + break; + case TextEditor::TabSettings::TabPolicy::SpacesOnlyTabPolicy: + m_style.UseTab = FormatStyle::UT_Never; + break; + case TextEditor::TabSettings::TabPolicy::TabsOnlyTabPolicy: + m_style.UseTab = FormatStyle::UT_Always; + break; + } + + saveNewFormat(); +} diff --git a/src/plugins/clangformat/clangformatfile.h b/src/plugins/clangformat/clangformatfile.h index 3fe9010f44e..f0dddd4ec03 100644 --- a/src/plugins/clangformat/clangformatfile.h +++ b/src/plugins/clangformat/clangformatfile.h @@ -28,6 +28,10 @@ #include "utils/filepath.h" #include +namespace CppEditor { class CppCodeStyleSettings; } +namespace ProjectExplorer { class Project; } +namespace TextEditor { class TabSettings; } + namespace ClangFormat { class ClangFormatFile @@ -46,6 +50,10 @@ public: using Field = std::pair; QString changeFields(QList fields); QString changeField(Field field); + CppEditor::CppCodeStyleSettings toCppCodeStyleSettings(ProjectExplorer::Project *project) const; + TextEditor::TabSettings toTabSettings(ProjectExplorer::Project *project) const; + void fromCppCodeStyleSettings(const CppEditor::CppCodeStyleSettings &settings); + void fromTabSettings(const TextEditor::TabSettings &settings); private: void saveNewFormat(); @@ -56,5 +64,4 @@ private: clang::format::FormatStyle m_style; }; - } // namespace ClangFormat diff --git a/src/plugins/clangformat/clangformatplugin.cpp b/src/plugins/clangformat/clangformatplugin.cpp index 993f7c83ef6..87322175726 100644 --- a/src/plugins/clangformat/clangformatplugin.cpp +++ b/src/plugins/clangformat/clangformatplugin.cpp @@ -45,6 +45,7 @@ #include #include +#include #include #include @@ -82,7 +83,7 @@ public: return new ClangFormatIndenter(doc); } - std::pair additionalTab(QWidget *parent) const override + std::pair additionalTab(QWidget *parent) const override { if (!parent) return {new ClangFormatConfigWidget(), tr("ClangFormat")}; diff --git a/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp b/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp index 7228e2be8e9..33fa8d6103a 100644 --- a/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp +++ b/src/plugins/cppeditor/cppcodestylepreferencesfactory.cpp @@ -105,13 +105,12 @@ QWidget *CppCodeStylePreferencesFactory::createEditor(TextEditor::ICodeStylePref return nullptr; auto widget = new Internal::CppCodeStylePreferencesWidget(parent); - const auto tab = additionalTab(parent); - if (tab.first) { - widget->addTab(tab.first, tab.second); - } - widget->layout()->setContentsMargins(0, 0, 0, 0); widget->setCodeStyle(cppPreferences); + + const auto tab = additionalTab(parent); + widget->addTab(tab.first, tab.second); + return widget; } @@ -130,7 +129,7 @@ QString CppCodeStylePreferencesFactory::previewText() const return QLatin1String(defaultPreviewText); } -std::pair CppCodeStylePreferencesFactory::additionalTab(QWidget *parent) const +std::pair CppCodeStylePreferencesFactory::additionalTab(QWidget *parent) const { Q_UNUSED(parent) return {nullptr, ""}; diff --git a/src/plugins/cppeditor/cppcodestylepreferencesfactory.h b/src/plugins/cppeditor/cppcodestylepreferencesfactory.h index f7ca14c4a7a..ce38ae6fb79 100644 --- a/src/plugins/cppeditor/cppcodestylepreferencesfactory.h +++ b/src/plugins/cppeditor/cppcodestylepreferencesfactory.h @@ -30,6 +30,7 @@ #include namespace CppEditor { +class CppCodeStyleWidget; class CPPEDITOR_EXPORT CppCodeStylePreferencesFactory : public TextEditor::ICodeStylePreferencesFactory { @@ -44,7 +45,7 @@ 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(QWidget *parent) const; }; } // namespace CppEditor diff --git a/src/plugins/cppeditor/cppcodestylesettings.cpp b/src/plugins/cppeditor/cppcodestylesettings.cpp index 1c81cc610c5..d4b2f3f4d31 100644 --- a/src/plugins/cppeditor/cppcodestylesettings.cpp +++ b/src/plugins/cppeditor/cppcodestylesettings.cpp @@ -177,27 +177,31 @@ bool CppCodeStyleSettings::equals(const CppCodeStyleSettings &rhs) const ; } -Utils::optional CppCodeStyleSettings::currentProjectCodeStyle() +CppCodeStyleSettings CppCodeStyleSettings::getProjectCodeStyle(ProjectExplorer::Project *project) { - ProjectExplorer::Project *project = ProjectExplorer::ProjectTree::currentProject(); if (!project) - return {}; + return currentGlobalCodeStyle(); ProjectExplorer::EditorConfiguration *editorConfiguration = project->editorConfiguration(); - QTC_ASSERT(editorConfiguration, return {}); + QTC_ASSERT(editorConfiguration, return currentGlobalCodeStyle()); TextEditor::ICodeStylePreferences *codeStylePreferences = editorConfiguration->codeStyle(Constants::CPP_SETTINGS_ID); - QTC_ASSERT(codeStylePreferences, return {}); + QTC_ASSERT(codeStylePreferences, return currentGlobalCodeStyle()); auto cppCodeStylePreferences = - dynamic_cast(codeStylePreferences); + dynamic_cast(codeStylePreferences); if (!cppCodeStylePreferences) - return {}; + return currentGlobalCodeStyle(); return cppCodeStylePreferences->currentCodeStyleSettings(); } +CppCodeStyleSettings CppCodeStyleSettings::currentProjectCodeStyle() +{ + return getProjectCodeStyle(ProjectExplorer::ProjectTree::currentProject()); +} + CppCodeStyleSettings CppCodeStyleSettings::currentGlobalCodeStyle() { CppCodeStylePreferences *cppCodeStylePreferences = CppToolsSettings::instance()->cppCodeStyle(); @@ -206,9 +210,8 @@ CppCodeStyleSettings CppCodeStyleSettings::currentGlobalCodeStyle() return cppCodeStylePreferences->currentCodeStyleSettings(); } -TextEditor::TabSettings CppCodeStyleSettings::currentProjectTabSettings() +TextEditor::TabSettings CppCodeStyleSettings::getProjectTabSettings(ProjectExplorer::Project *project) { - ProjectExplorer::Project *project = ProjectExplorer::ProjectTree::currentProject(); if (!project) return currentGlobalTabSettings(); @@ -221,6 +224,11 @@ TextEditor::TabSettings CppCodeStyleSettings::currentProjectTabSettings() return codeStylePreferences->currentTabSettings(); } +TextEditor::TabSettings CppCodeStyleSettings::currentProjectTabSettings() +{ + return getProjectTabSettings(ProjectExplorer::ProjectTree::currentProject()); +} + TextEditor::TabSettings CppCodeStyleSettings::currentGlobalTabSettings() { CppCodeStylePreferences *cppCodeStylePreferences diff --git a/src/plugins/cppeditor/cppcodestylesettings.h b/src/plugins/cppeditor/cppcodestylesettings.h index b554338dcb2..3cda6e44c2b 100644 --- a/src/plugins/cppeditor/cppcodestylesettings.h +++ b/src/plugins/cppeditor/cppcodestylesettings.h @@ -37,6 +37,7 @@ QT_END_NAMESPACE namespace CPlusPlus { class Overview; } namespace TextEditor { class TabSettings; } +namespace ProjectExplorer { class Project; } namespace CppEditor { @@ -97,8 +98,10 @@ public: bool operator==(const CppCodeStyleSettings &s) const { return equals(s); } bool operator!=(const CppCodeStyleSettings &s) const { return !equals(s); } - static Utils::optional currentProjectCodeStyle(); + static CppCodeStyleSettings getProjectCodeStyle(ProjectExplorer::Project *project); + static CppCodeStyleSettings currentProjectCodeStyle(); static CppCodeStyleSettings currentGlobalCodeStyle(); + static TextEditor::TabSettings getProjectTabSettings(ProjectExplorer::Project *project); static TextEditor::TabSettings currentProjectTabSettings(); static TextEditor::TabSettings currentGlobalTabSettings(); diff --git a/src/plugins/cppeditor/cppcodestylesettingspage.cpp b/src/plugins/cppeditor/cppcodestylesettingspage.cpp index 3cf8d08d52e..c56f69dc95b 100644 --- a/src/plugins/cppeditor/cppcodestylesettingspage.cpp +++ b/src/plugins/cppeditor/cppcodestylesettingspage.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -222,6 +223,11 @@ void CppCodeStylePreferencesWidget::setTabSettings(const TabSettings &settings) m_ui->tabSettingsWidget->setTabSettings(settings); } +TextEditor::TabSettings CppCodeStylePreferencesWidget::tabSettings() const +{ + return m_ui->tabSettingsWidget->tabSettings(); +} + void CppCodeStylePreferencesWidget::setCodeStyleSettings(const CppCodeStyleSettings &s, bool preview) { const bool wasBlocked = m_blockUpdates; @@ -274,7 +280,7 @@ void CppCodeStylePreferencesWidget::slotCodeStyleSettingsChanged() if (current) current->setCodeStyleSettings(cppCodeStyleSettings()); } - + emit codeStyleSettingsChanged(cppCodeStyleSettings()); updatePreview(); } @@ -289,6 +295,7 @@ void CppCodeStylePreferencesWidget::slotTabSettingsChanged(const TabSettings &se current->setTabSettings(settings); } + emit tabSettingsChanged(settings); updatePreview(); } @@ -337,9 +344,26 @@ void CppCodeStylePreferencesWidget::setVisualizeWhitespace(bool on) } } -void CppCodeStylePreferencesWidget::addTab(QWidget *page, QString tabName) +void CppCodeStylePreferencesWidget::addTab(CppCodeStyleWidget *page, QString tabName) { + QTC_ASSERT(page, return); m_ui->categoryTab->addTab(page, tabName); + + connect(page, &CppEditor::CppCodeStyleWidget::codeStyleSettingsChanged, + this, [this](const CppEditor::CppCodeStyleSettings &settings) { + setCodeStyleSettings(settings, true); + }); + + connect(page, &CppEditor::CppCodeStyleWidget::tabSettingsChanged, + this, &CppCodeStylePreferencesWidget::setTabSettings); + + connect(this, &CppCodeStylePreferencesWidget::codeStyleSettingsChanged, + page, &CppCodeStyleWidget::setCodeStyleSettings); + + connect(this, &CppCodeStylePreferencesWidget::tabSettingsChanged, + page, &CppCodeStyleWidget::setTabSettings); + + page->synchronize(); } // ------------------ CppCodeStyleSettingsPage diff --git a/src/plugins/cppeditor/cppcodestylesettingspage.h b/src/plugins/cppeditor/cppcodestylesettingspage.h index 17940c4c725..7c04185165f 100644 --- a/src/plugins/cppeditor/cppcodestylesettingspage.h +++ b/src/plugins/cppeditor/cppcodestylesettingspage.h @@ -39,11 +39,29 @@ namespace TextEditor { class TabSettings; class SnippetEditorWidget; class CodeStyleEditor; + class CodeStyleEditorWidget; } namespace CppEditor { class CppCodeStylePreferences; +class CPPEDITOR_EXPORT CppCodeStyleWidget : public TextEditor::CodeStyleEditorWidget +{ + Q_OBJECT +public: + CppCodeStyleWidget(QWidget *parent = nullptr) + : CodeStyleEditorWidget(parent) + {} + + virtual void setCodeStyleSettings(const CppEditor::CppCodeStyleSettings &) {} + virtual void setTabSettings(const TextEditor::TabSettings &) {} + virtual void synchronize() {} + +signals: + void codeStyleSettingsChanged(const CppEditor::CppCodeStyleSettings &); + void tabSettingsChanged(const TextEditor::TabSettings &); +}; + namespace Internal { namespace Ui { class CppCodeStyleSettingsPage; } @@ -56,7 +74,7 @@ public: ~CppCodeStylePreferencesWidget() override; void setCodeStyle(CppCodeStylePreferences *codeStylePreferences); - void addTab(QWidget *page, QString tabName); + void addTab(CppCodeStyleWidget *page, QString tabName); private: void decorateEditors(const TextEditor::FontSettings &fontSettings); @@ -65,6 +83,7 @@ private: void slotCodeStyleSettingsChanged(); void updatePreview(); void setTabSettings(const TextEditor::TabSettings &settings); + TextEditor::TabSettings tabSettings() const; void setCodeStyleSettings(const CppCodeStyleSettings &settings, bool preview = true); void slotCurrentPreferencesChanged(TextEditor::ICodeStylePreferences *, bool preview = true); @@ -74,6 +93,9 @@ private: Ui::CppCodeStyleSettingsPage *m_ui; QList m_previews; bool m_blockUpdates = false; +signals: + void codeStyleSettingsChanged(const CppEditor::CppCodeStyleSettings &); + void tabSettingsChanged(const TextEditor::TabSettings &); };