From feb72dd0845b50cbcd5c79b4a1241e3953b3043e Mon Sep 17 00:00:00 2001 From: Artem Sokolovskii Date: Mon, 12 Dec 2022 15:30:29 +0100 Subject: [PATCH] ClangFormat: Make formatting mode a project option - Added the possibility to set formatting mode for every project separately. The indenter will be switched for a file if the mode changes. Fixes: QTCREATORBUG-28188 Change-Id: I4e7f9841c54f9b6763586c16672a10ca36bf843d Reviewed-by: Christian Kandeler --- .../clangformatglobalconfigwidget.cpp | 27 ++-- .../clangformat/clangformatindenter.cpp | 131 +++++++++++++++++- src/plugins/clangformat/clangformatindenter.h | 44 ++++++ src/plugins/clangformat/clangformatplugin.cpp | 4 +- src/plugins/texteditor/indenter.h | 2 +- 5 files changed, 194 insertions(+), 14 deletions(-) diff --git a/src/plugins/clangformat/clangformatglobalconfigwidget.cpp b/src/plugins/clangformat/clangformatglobalconfigwidget.cpp index bac4977de8d..ab7e8b7b03c 100644 --- a/src/plugins/clangformat/clangformatglobalconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatglobalconfigwidget.cpp @@ -40,7 +40,7 @@ ClangFormatGlobalConfigWidget::ClangFormatGlobalConfigWidget(ProjectExplorer::Pr using namespace Layouting; Group globalSettingsGroupBox { - title(tr("ClangFormat global setting:")), + title(tr("ClangFormat settings:")), Column { Row { m_formattingModeLabel, m_indentingOrFormatting, st }, m_formatWhileTyping, @@ -62,7 +62,6 @@ ClangFormatGlobalConfigWidget::ClangFormatGlobalConfigWidget(ProjectExplorer::Pr m_formattingModeLabel->hide(); m_formatOnSave->hide(); m_formatWhileTyping->hide(); - m_indentingOrFormatting->hide(); return; } globalSettingsGroupBox.widget->show(); @@ -95,8 +94,18 @@ void ClangFormatGlobalConfigWidget::initIndentationOrFormattingCombobox() m_indentingOrFormatting->insertItem(static_cast(ClangFormatSettings::Mode::Disable), tr("Disable")); - m_indentingOrFormatting->setCurrentIndex( - static_cast(ClangFormatSettings::instance().mode())); + if (m_project) { + m_indentingOrFormatting->setCurrentIndex( + m_project->namedSettings(Constants::MODE_ID).toInt()); + } else { + m_indentingOrFormatting->setCurrentIndex( + static_cast(ClangFormatSettings::instance().mode())); + } + + connect(m_indentingOrFormatting, &QComboBox::currentIndexChanged, this, [this](int index) { + if (m_project) + m_project->setNamedSettings(Constants::MODE_ID, index); + }); } bool ClangFormatGlobalConfigWidget::projectClangFormatFileExists() @@ -138,10 +147,6 @@ void ClangFormatGlobalConfigWidget::initOverrideCheckBox() connect(m_overrideDefault, &QCheckBox::toggled, this, [this](bool checked) { if (m_project) m_project->setNamedSettings(Constants::OVERRIDE_FILE_ID, checked); - else { - ClangFormatSettings::instance().setOverrideDefaultFile(checked); - ClangFormatSettings::instance().write(); - } }); } @@ -151,7 +156,11 @@ void ClangFormatGlobalConfigWidget::apply() ClangFormatSettings &settings = ClangFormatSettings::instance(); settings.setFormatOnSave(m_formatOnSave->isChecked()); settings.setFormatWhileTyping(m_formatWhileTyping->isChecked()); - settings.setMode(static_cast(m_indentingOrFormatting->currentIndex())); + if (!m_project) { + settings.setMode( + static_cast(m_indentingOrFormatting->currentIndex())); + settings.setOverrideDefaultFile(m_overrideDefault->isChecked()); + } settings.write(); } diff --git a/src/plugins/clangformat/clangformatindenter.cpp b/src/plugins/clangformat/clangformatindenter.cpp index 8328d3fdfba..ee6ac81e9ce 100644 --- a/src/plugins/clangformat/clangformatindenter.cpp +++ b/src/plugins/clangformat/clangformatindenter.cpp @@ -7,11 +7,19 @@ #include "clangformatutils.h" #include + +#include + #include #include + +#include + +#include +#include + #include #include -#include using namespace clang; using namespace format; @@ -101,4 +109,125 @@ bool ClangFormatIndenter::formatWhileTyping() const return ClangFormatSettings::instance().formatWhileTyping() && formatCodeInsteadOfIndent(); } +// ClangFormatIndenterWrapper + +ClangFormatForwardingIndenter::ClangFormatForwardingIndenter(QTextDocument *doc) + : TextEditor::Indenter(doc) + , m_clangFormatIndenter(std::make_unique(doc)) + , m_cppIndenter(CppEditor::CppCodeStylePreferencesFactory().createIndenter(doc)) +{} + +ClangFormatForwardingIndenter::~ClangFormatForwardingIndenter() = default; + +void ClangFormatForwardingIndenter::setFileName(const Utils::FilePath &fileName) +{ + m_fileName = fileName; + m_clangFormatIndenter->setFileName(fileName); + m_cppIndenter->setFileName(fileName); +} + +TextEditor::Indenter *ClangFormatForwardingIndenter::currentIndenter() const +{ + const ProjectExplorer::Project *projectForFile + = ProjectExplorer::SessionManager::projectForFile(m_fileName); + + ClangFormatSettings::Mode mode = projectForFile ? static_cast( + projectForFile->namedSettings(Constants::MODE_ID).toInt()) + : ClangFormatSettings::instance().mode(); + + if (mode == ClangFormatSettings::Disable) + return m_cppIndenter.get(); + + return m_clangFormatIndenter.get(); +} + +bool ClangFormatForwardingIndenter::isElectricCharacter(const QChar &ch) const +{ + return currentIndenter()->isElectricCharacter(ch); +} + +void ClangFormatForwardingIndenter::setCodeStylePreferences( + TextEditor::ICodeStylePreferences *preferences) +{ + currentIndenter()->setCodeStylePreferences(preferences); +} + +void ClangFormatForwardingIndenter::invalidateCache() +{ + currentIndenter()->invalidateCache(); +} + +int ClangFormatForwardingIndenter::indentFor(const QTextBlock &block, + const TextEditor::TabSettings &tabSettings, + int cursorPositionInEditor) +{ + return currentIndenter()->indentFor(block, tabSettings, cursorPositionInEditor); +} + +int ClangFormatForwardingIndenter::visualIndentFor(const QTextBlock &block, + const TextEditor::TabSettings &tabSettings) +{ + return currentIndenter()->visualIndentFor(block, tabSettings); +} + +void ClangFormatForwardingIndenter::autoIndent(const QTextCursor &cursor, + const TextEditor::TabSettings &tabSettings, + int cursorPositionInEditor) +{ + currentIndenter()->autoIndent(cursor, tabSettings, cursorPositionInEditor); +} + +Utils::Text::Replacements ClangFormatForwardingIndenter::format( + const TextEditor::RangesInLines &rangesInLines) +{ + return currentIndenter()->format(rangesInLines); +} + + +bool ClangFormatForwardingIndenter::formatOnSave() const +{ + return currentIndenter()->formatOnSave(); +} + +TextEditor::IndentationForBlock ClangFormatForwardingIndenter::indentationForBlocks( + const QVector &blocks, + const TextEditor::TabSettings &tabSettings, + int cursorPositionInEditor) +{ + return currentIndenter()->indentationForBlocks(blocks, tabSettings, cursorPositionInEditor); +} + +std::optional ClangFormatForwardingIndenter::tabSettings() const +{ + return currentIndenter()->tabSettings(); +} + +void ClangFormatForwardingIndenter::indentBlock(const QTextBlock &block, + const QChar &typedChar, + const TextEditor::TabSettings &tabSettings, + int cursorPositionInEditor) +{ + currentIndenter()->indentBlock(block, typedChar, tabSettings, cursorPositionInEditor); +} + +void ClangFormatForwardingIndenter::indent(const QTextCursor &cursor, + const QChar &typedChar, + const TextEditor::TabSettings &tabSettings, + int cursorPositionInEditor) +{ + currentIndenter()->indent(cursor, typedChar, tabSettings, cursorPositionInEditor); +} + +void ClangFormatForwardingIndenter::reindent(const QTextCursor &cursor, + const TextEditor::TabSettings &tabSettings, + int cursorPositionInEditor) +{ + currentIndenter()->reindent(cursor, tabSettings, cursorPositionInEditor); +} + +std::optional ClangFormatForwardingIndenter::margin() const +{ + return currentIndenter()->margin(); +} + } // namespace ClangFormat diff --git a/src/plugins/clangformat/clangformatindenter.h b/src/plugins/clangformat/clangformatindenter.h index 0303b3c0666..c1aef312658 100644 --- a/src/plugins/clangformat/clangformatindenter.h +++ b/src/plugins/clangformat/clangformatindenter.h @@ -22,4 +22,48 @@ private: int lastSaveRevision() const override; }; +class ClangFormatForwardingIndenter : public TextEditor::Indenter +{ +public: + explicit ClangFormatForwardingIndenter(QTextDocument *doc); + ~ClangFormatForwardingIndenter() override; + + void setFileName(const Utils::FilePath &fileName) override; + bool isElectricCharacter(const QChar &ch) const override; + void setCodeStylePreferences(TextEditor::ICodeStylePreferences *preferences) override; + void invalidateCache() override; + int indentFor(const QTextBlock &block, + const TextEditor::TabSettings &tabSettings, + int cursorPositionInEditor = -1) override; + int visualIndentFor(const QTextBlock &block, + const TextEditor::TabSettings &tabSettings) override; + void autoIndent(const QTextCursor &cursor, + const TextEditor::TabSettings &tabSettings, + int cursorPositionInEditor = -1) override; + Utils::Text::Replacements format(const TextEditor::RangesInLines &rangesInLines) override; + bool formatOnSave() const override; + TextEditor::IndentationForBlock indentationForBlocks(const QVector &blocks, + const TextEditor::TabSettings &tabSettings, + int cursorPositionInEditor = -1) override; + std::optional tabSettings() const override; + void indentBlock(const QTextBlock &block, + const QChar &typedChar, + const TextEditor::TabSettings &tabSettings, + int cursorPositionInEditor = -1) override; + void indent(const QTextCursor &cursor, + const QChar &typedChar, + const TextEditor::TabSettings &tabSettings, + int cursorPositionInEditor = -1) override; + virtual void reindent(const QTextCursor &cursor, + const TextEditor::TabSettings &tabSettings, + int cursorPositionInEditor = -1) override; + std::optional margin() const override; + +private: + TextEditor::Indenter *currentIndenter() const; + + std::unique_ptr m_clangFormatIndenter; + std::unique_ptr m_cppIndenter; +}; + } // namespace ClangFormat diff --git a/src/plugins/clangformat/clangformatplugin.cpp b/src/plugins/clangformat/clangformatplugin.cpp index 6d05ace459f..10baa28e098 100644 --- a/src/plugins/clangformat/clangformatplugin.cpp +++ b/src/plugins/clangformat/clangformatplugin.cpp @@ -62,9 +62,7 @@ class ClangFormatStyleFactory : public CppEditor::CppCodeStylePreferencesFactory public: TextEditor::Indenter *createIndenter(QTextDocument *doc) const override { - if (ClangFormatSettings::instance().mode() == ClangFormatSettings::Disable) - return CppEditor::CppCodeStylePreferencesFactory::createIndenter(doc); - return new ClangFormatIndenter(doc); + return new ClangFormatForwardingIndenter(doc); } std::pair additionalTab( diff --git a/src/plugins/texteditor/indenter.h b/src/plugins/texteditor/indenter.h index 91c11f043a5..2c80d97e657 100644 --- a/src/plugins/texteditor/indenter.h +++ b/src/plugins/texteditor/indenter.h @@ -39,7 +39,7 @@ public: : m_doc(doc) {} - void setFileName(const Utils::FilePath &fileName) { m_fileName = fileName; } + virtual void setFileName(const Utils::FilePath &fileName) { m_fileName = fileName; } virtual ~Indenter() = default;