diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp
index bcede8c0101..f0d4808cf5c 100644
--- a/src/plugins/clangformat/clangformatconfigwidget.cpp
+++ b/src/plugins/clangformat/clangformatconfigwidget.cpp
@@ -131,6 +131,7 @@ void ClangFormatConfigWidget::hideGlobalCheckboxes()
{
m_ui->formatAlways->hide();
m_ui->formatWhileTyping->hide();
+ m_ui->formatOnSave->hide();
}
void ClangFormatConfigWidget::showGlobalCheckboxes()
@@ -140,6 +141,9 @@ void ClangFormatConfigWidget::showGlobalCheckboxes()
m_ui->formatWhileTyping->setChecked(ClangFormatSettings::instance().formatWhileTyping());
m_ui->formatWhileTyping->show();
+
+ m_ui->formatOnSave->setChecked(ClangFormatSettings::instance().formatOnSave());
+ m_ui->formatOnSave->show();
}
void ClangFormatConfigWidget::initialize()
@@ -200,7 +204,6 @@ void ClangFormatConfigWidget::fillTable()
std::string configText = clang::format::configurationAsText(style);
std::istringstream stream(configText);
readTable(m_ui->clangFormatOptionsTable, stream);
-
}
ClangFormatConfigWidget::~ClangFormatConfigWidget() = default;
@@ -211,6 +214,7 @@ void ClangFormatConfigWidget::apply()
ClangFormatSettings &settings = ClangFormatSettings::instance();
settings.setFormatCodeInsteadOfIndent(m_ui->formatAlways->isChecked());
settings.setFormatWhileTyping(m_ui->formatWhileTyping->isChecked());
+ settings.setFormatOnSave(m_ui->formatOnSave->isChecked());
settings.write();
}
diff --git a/src/plugins/clangformat/clangformatconfigwidget.ui b/src/plugins/clangformat/clangformatconfigwidget.ui
index 37f228e97cc..2094bca1090 100644
--- a/src/plugins/clangformat/clangformatconfigwidget.ui
+++ b/src/plugins/clangformat/clangformatconfigwidget.ui
@@ -40,6 +40,13 @@
+ -
+
+
+ Format edited code on file save
+
+
+
-
diff --git a/src/plugins/clangformat/clangformatconstants.h b/src/plugins/clangformat/clangformatconstants.h
index 40b43e56407..8b7cbcf9bd2 100644
--- a/src/plugins/clangformat/clangformatconstants.h
+++ b/src/plugins/clangformat/clangformatconstants.h
@@ -33,5 +33,6 @@ static const char SAMPLE_FILE_NAME[] = "test.cpp";
static const char SETTINGS_ID[] = "ClangFormat";
static const char FORMAT_CODE_INSTEAD_OF_INDENT_ID[] = "ClangFormat.FormatCodeInsteadOfIndent";
static const char FORMAT_WHILE_TYPING_ID[] = "ClangFormat.FormatWhileTyping";
+static const char FORMAT_CODE_ON_SAVE_ID[] = "ClangFormat.FormatCodeOnSave";
} // namespace Constants
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatindenter.cpp b/src/plugins/clangformat/clangformatindenter.cpp
index f1ece90164a..ef9dbf5d1ca 100644
--- a/src/plugins/clangformat/clangformatindenter.cpp
+++ b/src/plugins/clangformat/clangformatindenter.cpp
@@ -87,4 +87,9 @@ int ClangFormatIndenter::lastSaveRevision() const
return qobject_cast(m_doc->documentLayout())->lastSaveRevision;
}
+bool ClangFormatIndenter::formatOnSave() const
+{
+ return ClangFormatSettings::instance().formatOnSave();
+}
+
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatindenter.h b/src/plugins/clangformat/clangformatindenter.h
index dca5f583a64..6d605eb5c91 100644
--- a/src/plugins/clangformat/clangformatindenter.h
+++ b/src/plugins/clangformat/clangformatindenter.h
@@ -36,6 +36,7 @@ class ClangFormatIndenter final : public ClangFormatBaseIndenter
public:
ClangFormatIndenter(QTextDocument *doc);
Utils::optional tabSettings() const override;
+ bool formatOnSave() const override;
private:
bool formatCodeInsteadOfIndent() const override;
diff --git a/src/plugins/clangformat/clangformatsettings.cpp b/src/plugins/clangformat/clangformatsettings.cpp
index d8369bf5efd..8be2b3cefee 100644
--- a/src/plugins/clangformat/clangformatsettings.cpp
+++ b/src/plugins/clangformat/clangformatsettings.cpp
@@ -44,6 +44,8 @@ ClangFormatSettings::ClangFormatSettings()
= settings->value(QLatin1String(Constants::FORMAT_CODE_INSTEAD_OF_INDENT_ID), false).toBool();
m_formatWhileTyping = settings->value(QLatin1String(Constants::FORMAT_WHILE_TYPING_ID), false)
.toBool();
+ m_formatOnSave = settings->value(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), false)
+ .toBool();
settings->endGroup();
}
@@ -54,6 +56,7 @@ void ClangFormatSettings::write() const
settings->setValue(QLatin1String(Constants::FORMAT_CODE_INSTEAD_OF_INDENT_ID),
m_formatCodeInsteadOfIndent);
settings->setValue(QLatin1String(Constants::FORMAT_WHILE_TYPING_ID), m_formatWhileTyping);
+ settings->setValue(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), m_formatOnSave);
settings->endGroup();
}
@@ -77,4 +80,14 @@ bool ClangFormatSettings::formatWhileTyping() const
return m_formatWhileTyping;
}
+void ClangFormatSettings::setFormatOnSave(bool enable)
+{
+ m_formatOnSave = enable;
+}
+
+bool ClangFormatSettings::formatOnSave() const
+{
+ return m_formatOnSave;
+}
+
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatsettings.h b/src/plugins/clangformat/clangformatsettings.h
index 4a62eb83035..0ea9ed9747e 100644
--- a/src/plugins/clangformat/clangformatsettings.h
+++ b/src/plugins/clangformat/clangformatsettings.h
@@ -40,9 +40,13 @@ public:
void setFormatWhileTyping(bool enable);
bool formatWhileTyping() const;
+
+ void setFormatOnSave(bool enable);
+ bool formatOnSave() const;
private:
bool m_formatCodeInsteadOfIndent = false;
bool m_formatWhileTyping = false;
+ bool m_formatOnSave = false;
};
} // namespace ClangFormat
diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp
index c8951c12ebc..d18735c7501 100644
--- a/src/plugins/cppeditor/cppeditordocument.cpp
+++ b/src/plugins/cppeditor/cppeditordocument.cpp
@@ -44,6 +44,7 @@
#include
#include
+#include
#include
#include
@@ -447,5 +448,47 @@ TextEditor::TabSettings CppEditorDocument::tabSettings() const
return indenter()->tabSettings().value_or(TextEditor::TextDocument::tabSettings());
}
+static int formatRange(QTextDocument *doc,
+ TextEditor::Indenter *indenter,
+ std::pair editedRange,
+ const TextEditor::TabSettings &tabSettings)
+{
+ QTextCursor cursor(doc);
+ cursor.setPosition(editedRange.first);
+ cursor.setPosition(editedRange.second, QTextCursor::KeepAnchor);
+ const int oldBlockCount = doc->blockCount();
+ indenter->format(cursor, tabSettings);
+ return doc->blockCount() - oldBlockCount;
+}
+
+bool CppEditorDocument::save(QString *errorString, const QString &fileName, bool autoSave)
+{
+ if (indenter()->formatOnSave()) {
+ auto *layout = qobject_cast(document()->documentLayout());
+ const int documentRevision = layout->lastSaveRevision;
+
+ std::pair editedRange;
+ for (int i = 0; i < document()->blockCount(); ++i) {
+ const QTextBlock block = document()->findBlockByNumber(i);
+ if (block.revision() == documentRevision) {
+ if (editedRange.first != -1)
+ i += formatRange(document(), indenter(), editedRange, tabSettings());
+
+ editedRange = std::make_pair(-1, -1);
+ continue;
+ }
+
+ // block.revision() != documentRevision
+ if (editedRange.first == -1)
+ editedRange.first = block.position();
+ editedRange.second = block.position() + block.length();
+ }
+ if (editedRange.first != -1)
+ formatRange(document(), indenter(), editedRange, tabSettings());
+ }
+
+ return TextEditor::TextDocument::save(errorString, fileName, autoSave);
+}
+
} // namespace Internal
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppeditordocument.h b/src/plugins/cppeditor/cppeditordocument.h
index 44fe04becb7..26cff2043aa 100644
--- a/src/plugins/cppeditor/cppeditordocument.h
+++ b/src/plugins/cppeditor/cppeditordocument.h
@@ -69,6 +69,10 @@ public:
QFuture cursorInfo(const CppTools::CursorInfoParams ¶ms);
TextEditor::TabSettings tabSettings() const override;
+ bool save(QString *errorString,
+ const QString &fileName = QString(),
+ bool autoSave = false) override;
+
signals:
void codeWarningsUpdated(unsigned contentsRevision,
const QList selections,
diff --git a/src/plugins/texteditor/indenter.h b/src/plugins/texteditor/indenter.h
index bb23c9d7ac2..2907ea783ce 100644
--- a/src/plugins/texteditor/indenter.h
+++ b/src/plugins/texteditor/indenter.h
@@ -99,6 +99,8 @@ public:
return Replacements();
}
+ virtual bool formatOnSave() const { return false; }
+
// Expects a list of blocks in order of occurrence in the document.
virtual IndentationForBlock indentationForBlocks(const QVector &blocks,
const TabSettings &tabSettings,