forked from qt-creator/qt-creator
ClangTools: Apply indention/formatting after fix-its
Fix-its do not follow the current formatting style therefore apply indention/formatting by using indenter. This change will work best when ClangFormat plugin is enabled to not only reindent line but also format it. Task-number: QTCREATORBUG-21448 Change-Id: I8bcafcf49f3118aff7840326547e7a24052469b2 Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
@@ -384,14 +384,10 @@ void ClangFormatIndenter::indent(QTextDocument *doc,
|
||||
}
|
||||
|
||||
QtReplacements ClangFormatIndenter::format(QTextDocument *doc,
|
||||
const Utils::FileName &fileName,
|
||||
const QTextCursor &cursor,
|
||||
const TextEditor::TabSettings & /*tabSettings*/)
|
||||
{
|
||||
TextEditorWidget *editor = TextEditorWidget::currentTextEditorWidget();
|
||||
if (!editor)
|
||||
return QtReplacements();
|
||||
|
||||
const Utils::FileName fileName = editor->textDocument()->filePath();
|
||||
int utf8Offset;
|
||||
int utf8Length;
|
||||
const QByteArray buffer = doc->toPlainText().toUtf8();
|
||||
|
@@ -41,6 +41,7 @@ public:
|
||||
const QTextCursor &cursor,
|
||||
const TextEditor::TabSettings &tabSettings) override;
|
||||
TextEditor::Replacements format(QTextDocument *doc,
|
||||
const Utils::FileName &fileName,
|
||||
const QTextCursor &cursor,
|
||||
const TextEditor::TabSettings &tabSettings) override;
|
||||
void indentBlock(QTextDocument *doc,
|
||||
|
@@ -26,6 +26,13 @@
|
||||
#include "clangfixitsrefactoringchanges.h"
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <cpptools/cppcodestylesettings.h>
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
#include <cpptools/cpptoolsconstants.h>
|
||||
|
||||
#include <texteditor/icodestylepreferencesfactory.h>
|
||||
#include <texteditor/indenter.h>
|
||||
#include <texteditor/texteditorsettings.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
@@ -35,8 +42,11 @@
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
Q_LOGGING_CATEGORY(fixitsLog, "qtc.clangtools.fixits", QtWarningMsg);
|
||||
|
||||
using namespace TextEditor;
|
||||
using namespace Utils;
|
||||
|
||||
namespace ClangTools {
|
||||
@@ -71,6 +81,13 @@ bool FixitsRefactoringFile::apply()
|
||||
|
||||
QTC_ASSERT(!m_filePath.isEmpty(), return false);
|
||||
|
||||
ICodeStylePreferencesFactory *factory = TextEditorSettings::codeStyleFactory(
|
||||
CppTools::Constants::CPP_SETTINGS_ID);
|
||||
std::unique_ptr<TextEditor::Indenter> indenter(factory->createIndenter());
|
||||
|
||||
const TextEditor::TabSettings tabSettings
|
||||
= CppTools::CppCodeStyleSettings::currentProjectTabSettings();
|
||||
|
||||
// Apply changes
|
||||
for (int i=0; i < m_replacementOperations.size(); ++i) {
|
||||
ReplacementOperation &op = *m_replacementOperations[i];
|
||||
@@ -90,6 +107,8 @@ bool FixitsRefactoringFile::apply()
|
||||
cursor.setPosition(op.pos);
|
||||
cursor.setPosition(op.pos + op.length, QTextCursor::KeepAnchor);
|
||||
cursor.insertText(op.text);
|
||||
|
||||
tryToFormat(*indenter, tabSettings, doc, op, i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +127,33 @@ bool FixitsRefactoringFile::apply()
|
||||
return true;
|
||||
}
|
||||
|
||||
void FixitsRefactoringFile::tryToFormat(TextEditor::Indenter &indenter,
|
||||
const TextEditor::TabSettings &tabSettings,
|
||||
QTextDocument *doc,
|
||||
const ReplacementOperation &op,
|
||||
int currentIndex)
|
||||
{
|
||||
QTextCursor cursor(doc);
|
||||
cursor.beginEditBlock();
|
||||
cursor.setPosition(op.pos);
|
||||
cursor.movePosition(QTextCursor::Right,
|
||||
QTextCursor::KeepAnchor,
|
||||
op.text.length());
|
||||
const Replacements replacements = indenter.format(doc,
|
||||
Utils::FileName::fromString(op.fileName),
|
||||
cursor,
|
||||
tabSettings);
|
||||
cursor.endEditBlock();
|
||||
|
||||
if (replacements.empty())
|
||||
return;
|
||||
|
||||
if (hasIntersection(op.fileName, replacements, currentIndex + 1))
|
||||
doc->undo(&cursor);
|
||||
else
|
||||
shiftAffectedReplacements(op.fileName, replacements, currentIndex + 1);
|
||||
}
|
||||
|
||||
QTextDocument *FixitsRefactoringFile::document(const QString &filePath) const
|
||||
{
|
||||
if (m_documents.find(filePath) == m_documents.end()) {
|
||||
@@ -148,5 +194,45 @@ void FixitsRefactoringFile::shiftAffectedReplacements(const ReplacementOperation
|
||||
}
|
||||
}
|
||||
|
||||
bool FixitsRefactoringFile::hasIntersection(const QString &fileName,
|
||||
const Replacements &replacements,
|
||||
int startIndex) const
|
||||
{
|
||||
for (int i = startIndex; i < m_replacementOperations.size(); ++i) {
|
||||
const ReplacementOperation ¤t = *m_replacementOperations[i];
|
||||
if (fileName != current.fileName)
|
||||
continue;
|
||||
|
||||
// Usually the number of replacements is from 1 to 3.
|
||||
if (std::any_of(replacements.begin(),
|
||||
replacements.end(),
|
||||
[¤t](const const Replacement &replacement) {
|
||||
return replacement.offset + replacement.length > current.pos
|
||||
&& replacement.offset < current.pos + current.length;
|
||||
})) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FixitsRefactoringFile::shiftAffectedReplacements(const QString &fileName,
|
||||
const Replacements &replacements,
|
||||
int startIndex)
|
||||
{
|
||||
for (int i = startIndex; i < m_replacementOperations.size(); ++i) {
|
||||
ReplacementOperation ¤t = *m_replacementOperations[i];
|
||||
if (fileName != current.fileName)
|
||||
continue;
|
||||
|
||||
for (const auto &replacement : replacements) {
|
||||
if (replacement.offset > current.pos)
|
||||
break;
|
||||
current.pos += replacement.text.size() - replacement.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangTools
|
||||
|
@@ -32,6 +32,13 @@
|
||||
#include <QTextDocument>
|
||||
#include <QVector>
|
||||
|
||||
namespace TextEditor {
|
||||
class Indenter;
|
||||
class Replacement;
|
||||
using Replacements = std::vector<Replacement>;
|
||||
class TabSettings;
|
||||
}
|
||||
|
||||
namespace ClangTools {
|
||||
namespace Internal {
|
||||
|
||||
@@ -65,6 +72,18 @@ private:
|
||||
QTextDocument *document(const QString &filePath) const;
|
||||
void shiftAffectedReplacements(const ReplacementOperation &op, int startIndex);
|
||||
|
||||
void tryToFormat(TextEditor::Indenter &indenter,
|
||||
const TextEditor::TabSettings &tabSettings,
|
||||
QTextDocument *doc,
|
||||
const ReplacementOperation &op,
|
||||
int currentIndex);
|
||||
void shiftAffectedReplacements(const QString &fileName,
|
||||
const TextEditor::Replacements &replacements,
|
||||
int startIndex);
|
||||
bool hasIntersection(const QString &fileName,
|
||||
const TextEditor::Replacements &replacements,
|
||||
int startIndex) const;
|
||||
|
||||
QString m_filePath;
|
||||
mutable Utils::TextFileFormat m_textFileFormat;
|
||||
mutable QHash<QString, QTextDocument *> m_documents;
|
||||
|
@@ -179,7 +179,6 @@ public:
|
||||
QVector<DiagnosticItem *> itemsInvalidated;
|
||||
|
||||
fileInfo.file.setReplacements(ops);
|
||||
|
||||
model->removeWatchedPath(ops.first()->fileName);
|
||||
if (fileInfo.file.apply()) {
|
||||
itemsApplied = itemsScheduled;
|
||||
|
@@ -42,9 +42,9 @@ bool Indenter::isElectricCharacter(const QChar &) const
|
||||
}
|
||||
|
||||
void Indenter::indentBlock(QTextDocument *doc,
|
||||
const QTextBlock &block,
|
||||
const QChar &typedChar,
|
||||
const TabSettings &tabSettings)
|
||||
const QTextBlock &block,
|
||||
const QChar &typedChar,
|
||||
const TabSettings &tabSettings)
|
||||
{
|
||||
Q_UNUSED(doc);
|
||||
Q_UNUSED(typedChar);
|
||||
@@ -103,6 +103,7 @@ void Indenter::reindent(QTextDocument *doc, const QTextCursor &cursor, const Tab
|
||||
}
|
||||
|
||||
Replacements Indenter::format(QTextDocument *doc,
|
||||
const Utils::FileName & /*fileName*/,
|
||||
const QTextCursor &cursor,
|
||||
const TabSettings &tabSettings)
|
||||
{
|
||||
|
@@ -39,6 +39,8 @@ class QTextBlock;
|
||||
class QChar;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Utils { class FileName; }
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class ICodeStylePreferences;
|
||||
@@ -85,6 +87,7 @@ public:
|
||||
|
||||
// By default just calls indent with default settings.
|
||||
virtual Replacements format(QTextDocument *doc,
|
||||
const Utils::FileName &fileName,
|
||||
const QTextCursor &cursor,
|
||||
const TabSettings &tabSettings);
|
||||
|
||||
|
@@ -428,7 +428,7 @@ void TextDocument::autoReindent(const QTextCursor &cursor)
|
||||
|
||||
void TextDocument::autoFormat(const QTextCursor &cursor)
|
||||
{
|
||||
d->m_indenter->format(&d->m_document, cursor, tabSettings());
|
||||
d->m_indenter->format(&d->m_document, filePath(), cursor, tabSettings());
|
||||
}
|
||||
|
||||
QTextCursor TextDocument::indent(const QTextCursor &cursor, bool blockSelection, int column,
|
||||
|
Reference in New Issue
Block a user