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 <christian.kandeler@qt.io>
This commit is contained in:
Artem Sokolovskii
2022-12-12 15:30:29 +01:00
committed by Christian Kandeler
parent 192605f01c
commit feb72dd084
5 changed files with 194 additions and 14 deletions

View File

@@ -40,7 +40,7 @@ ClangFormatGlobalConfigWidget::ClangFormatGlobalConfigWidget(ProjectExplorer::Pr
using namespace Layouting; using namespace Layouting;
Group globalSettingsGroupBox { Group globalSettingsGroupBox {
title(tr("ClangFormat global setting:")), title(tr("ClangFormat settings:")),
Column { Column {
Row { m_formattingModeLabel, m_indentingOrFormatting, st }, Row { m_formattingModeLabel, m_indentingOrFormatting, st },
m_formatWhileTyping, m_formatWhileTyping,
@@ -62,7 +62,6 @@ ClangFormatGlobalConfigWidget::ClangFormatGlobalConfigWidget(ProjectExplorer::Pr
m_formattingModeLabel->hide(); m_formattingModeLabel->hide();
m_formatOnSave->hide(); m_formatOnSave->hide();
m_formatWhileTyping->hide(); m_formatWhileTyping->hide();
m_indentingOrFormatting->hide();
return; return;
} }
globalSettingsGroupBox.widget->show(); globalSettingsGroupBox.widget->show();
@@ -95,8 +94,18 @@ void ClangFormatGlobalConfigWidget::initIndentationOrFormattingCombobox()
m_indentingOrFormatting->insertItem(static_cast<int>(ClangFormatSettings::Mode::Disable), m_indentingOrFormatting->insertItem(static_cast<int>(ClangFormatSettings::Mode::Disable),
tr("Disable")); tr("Disable"));
if (m_project) {
m_indentingOrFormatting->setCurrentIndex(
m_project->namedSettings(Constants::MODE_ID).toInt());
} else {
m_indentingOrFormatting->setCurrentIndex( m_indentingOrFormatting->setCurrentIndex(
static_cast<int>(ClangFormatSettings::instance().mode())); static_cast<int>(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() bool ClangFormatGlobalConfigWidget::projectClangFormatFileExists()
@@ -138,10 +147,6 @@ void ClangFormatGlobalConfigWidget::initOverrideCheckBox()
connect(m_overrideDefault, &QCheckBox::toggled, this, [this](bool checked) { connect(m_overrideDefault, &QCheckBox::toggled, this, [this](bool checked) {
if (m_project) if (m_project)
m_project->setNamedSettings(Constants::OVERRIDE_FILE_ID, checked); 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(); ClangFormatSettings &settings = ClangFormatSettings::instance();
settings.setFormatOnSave(m_formatOnSave->isChecked()); settings.setFormatOnSave(m_formatOnSave->isChecked());
settings.setFormatWhileTyping(m_formatWhileTyping->isChecked()); settings.setFormatWhileTyping(m_formatWhileTyping->isChecked());
settings.setMode(static_cast<ClangFormatSettings::Mode>(m_indentingOrFormatting->currentIndex())); if (!m_project) {
settings.setMode(
static_cast<ClangFormatSettings::Mode>(m_indentingOrFormatting->currentIndex()));
settings.setOverrideDefaultFile(m_overrideDefault->isChecked());
}
settings.write(); settings.write();
} }

View File

@@ -7,11 +7,19 @@
#include "clangformatutils.h" #include "clangformatutils.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <cppeditor/cppcodestylepreferencesfactory.h>
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h> #include <extensionsystem/pluginspec.h>
#include <utils/genericconstants.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <texteditor/tabsettings.h> #include <texteditor/tabsettings.h>
#include <texteditor/textdocumentlayout.h> #include <texteditor/textdocumentlayout.h>
#include <utils/genericconstants.h>
using namespace clang; using namespace clang;
using namespace format; using namespace format;
@@ -101,4 +109,125 @@ bool ClangFormatIndenter::formatWhileTyping() const
return ClangFormatSettings::instance().formatWhileTyping() && formatCodeInsteadOfIndent(); return ClangFormatSettings::instance().formatWhileTyping() && formatCodeInsteadOfIndent();
} }
// ClangFormatIndenterWrapper
ClangFormatForwardingIndenter::ClangFormatForwardingIndenter(QTextDocument *doc)
: TextEditor::Indenter(doc)
, m_clangFormatIndenter(std::make_unique<ClangFormatIndenter>(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<ClangFormatSettings::Mode>(
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<QTextBlock> &blocks,
const TextEditor::TabSettings &tabSettings,
int cursorPositionInEditor)
{
return currentIndenter()->indentationForBlocks(blocks, tabSettings, cursorPositionInEditor);
}
std::optional<TextEditor::TabSettings> 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<int> ClangFormatForwardingIndenter::margin() const
{
return currentIndenter()->margin();
}
} // namespace ClangFormat } // namespace ClangFormat

View File

@@ -22,4 +22,48 @@ private:
int lastSaveRevision() const override; 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<QTextBlock> &blocks,
const TextEditor::TabSettings &tabSettings,
int cursorPositionInEditor = -1) override;
std::optional<TextEditor::TabSettings> 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<int> margin() const override;
private:
TextEditor::Indenter *currentIndenter() const;
std::unique_ptr<TextEditor::Indenter> m_clangFormatIndenter;
std::unique_ptr<TextEditor::Indenter> m_cppIndenter;
};
} // namespace ClangFormat } // namespace ClangFormat

View File

@@ -62,9 +62,7 @@ class ClangFormatStyleFactory : public CppEditor::CppCodeStylePreferencesFactory
public: public:
TextEditor::Indenter *createIndenter(QTextDocument *doc) const override TextEditor::Indenter *createIndenter(QTextDocument *doc) const override
{ {
if (ClangFormatSettings::instance().mode() == ClangFormatSettings::Disable) return new ClangFormatForwardingIndenter(doc);
return CppEditor::CppCodeStylePreferencesFactory::createIndenter(doc);
return new ClangFormatIndenter(doc);
} }
std::pair<CppEditor::CppCodeStyleWidget *, QString> additionalTab( std::pair<CppEditor::CppCodeStyleWidget *, QString> additionalTab(

View File

@@ -39,7 +39,7 @@ public:
: m_doc(doc) : 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; virtual ~Indenter() = default;