forked from qt-creator/qt-creator
ClangFormat: Format edited chunks of file on save
The similar implementation to the one in Beautifier plugin with the difference that the clangformat indenter logic is used and only modified chunks are formatted. That means that all code which was not touched will stay in the initial condition. Change-Id: I47b11eb99852454ed0031ef6cfc6dbed1ecd390d Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -40,6 +40,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="formatOnSave">
|
||||
<property name="text">
|
||||
<string>Format edited code on file save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="projectHasClangFormat">
|
||||
<property name="text">
|
||||
|
@@ -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
|
||||
|
@@ -87,4 +87,9 @@ int ClangFormatIndenter::lastSaveRevision() const
|
||||
return qobject_cast<TextEditor::TextDocumentLayout *>(m_doc->documentLayout())->lastSaveRevision;
|
||||
}
|
||||
|
||||
bool ClangFormatIndenter::formatOnSave() const
|
||||
{
|
||||
return ClangFormatSettings::instance().formatOnSave();
|
||||
}
|
||||
|
||||
} // namespace ClangFormat
|
||||
|
@@ -36,6 +36,7 @@ class ClangFormatIndenter final : public ClangFormatBaseIndenter
|
||||
public:
|
||||
ClangFormatIndenter(QTextDocument *doc);
|
||||
Utils::optional<TextEditor::TabSettings> tabSettings() const override;
|
||||
bool formatOnSave() const override;
|
||||
|
||||
private:
|
||||
bool formatCodeInsteadOfIndent() const override;
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -44,6 +44,7 @@
|
||||
#include <projectexplorer/session.h>
|
||||
|
||||
#include <texteditor/icodestylepreferencesfactory.h>
|
||||
#include <texteditor/textdocumentlayout.h>
|
||||
#include <texteditor/texteditorsettings.h>
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
@@ -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<int, int> 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<TextEditor::TextDocumentLayout *>(document()->documentLayout());
|
||||
const int documentRevision = layout->lastSaveRevision;
|
||||
|
||||
std::pair<int, int> 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
|
||||
|
@@ -69,6 +69,10 @@ public:
|
||||
QFuture<CppTools::CursorInfo> 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<QTextEdit::ExtraSelection> selections,
|
||||
|
@@ -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<QTextBlock> &blocks,
|
||||
const TabSettings &tabSettings,
|
||||
|
Reference in New Issue
Block a user