From 4743724d4cf696848635439196cdaa0e0b5572b5 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 4 Jul 2023 10:05:33 +0200 Subject: [PATCH] Editor: replace Utils::Text::Replacement with Utils::ChangeSet::EditOp for formatting Removes the last usage of Utils::Text::Replacement with a more commonly used pattern. Change-Id: I0912bf61388a58ddaba424380ec139f9aa15fc4c Reviewed-by: Christian Kandeler --- src/libs/utils/changeset.h | 2 + .../clangformat/clangformatbaseindenter.cpp | 80 +++++++++---------- .../clangformat/clangformatbaseindenter.h | 28 +++---- .../clangformat/clangformatindenter.cpp | 2 +- src/plugins/clangformat/clangformatindenter.h | 4 +- .../clangfixitsrefactoringchanges.cpp | 13 +-- .../clangfixitsrefactoringchanges.h | 2 +- .../clangtools/documentquickfixfactory.cpp | 1 + .../cmakeprojectmanager/cmakeeditor.cpp | 1 + .../languageclientformatter.cpp | 2 +- src/plugins/texteditor/indenter.h | 8 +- 11 files changed, 74 insertions(+), 69 deletions(-) diff --git a/src/libs/utils/changeset.h b/src/libs/utils/changeset.h index 915cee3778d..4afaefab463 100644 --- a/src/libs/utils/changeset.h +++ b/src/libs/utils/changeset.h @@ -103,6 +103,8 @@ private: bool m_error; }; +using EditOperations = QList; + inline bool operator<(const ChangeSet::Range &r1, const ChangeSet::Range &r2) { return r1.start < r2.start; diff --git a/src/plugins/clangformat/clangformatbaseindenter.cpp b/src/plugins/clangformat/clangformatbaseindenter.cpp index cf04958d28a..8e8d6013253 100644 --- a/src/plugins/clangformat/clangformatbaseindenter.cpp +++ b/src/plugins/clangformat/clangformatbaseindenter.cpp @@ -361,12 +361,11 @@ static Utils::Text::Position utf16LineColumn(const QByteArray &utf8Buffer, int u utf8Offset - startOfLineOffset)).length(); return position; } -Utils::Text::Replacements utf16Replacements(const QTextDocument *doc, - const QByteArray &utf8Buffer, - const clang::tooling::Replacements &replacements) +Utils::ChangeSet convertReplacements(const QTextDocument *doc, + const QByteArray &utf8Buffer, + const clang::tooling::Replacements &replacements) { - Utils::Text::Replacements convertedReplacements; - convertedReplacements.reserve(replacements.size()); + Utils::ChangeSet convertedReplacements; for (const clang::tooling::Replacement &replacement : replacements) { Utils::Text::Position lineColUtf16 = utf16LineColumn( @@ -412,7 +411,7 @@ Utils::Text::Replacements utf16Replacements(const QTextDocument *doc, } if (!replacementText.isEmpty() || utf16Length > 0) - convertedReplacements.emplace_back(utf16Offset, utf16Length, replacementText); + convertedReplacements.replace(utf16Offset, utf16Offset + utf16Length, replacementText); } return convertedReplacements; @@ -427,19 +426,21 @@ QString selectedLines(QTextDocument *doc, const QTextBlock &startBlock, const QT - startBlock.position() - 1)); } -int indentationForBlock(const Utils::Text::Replacements &toReplace, +int indentationForBlock(const Utils::ChangeSet &toReplace, const QByteArray &buffer, const QTextBlock ¤tBlock) { const int utf8Offset = Utils::Text::utf8NthLineOffset(currentBlock.document(), buffer, currentBlock.blockNumber() + 1); - auto replacementIt = std::find_if(toReplace.begin(), - toReplace.end(), - [utf8Offset](const Utils::Text::Replacement &replacement) { - return replacement.offset == utf8Offset - 1; - }); - if (replacementIt == toReplace.end()) + auto ops = toReplace.operationList(); + + auto replacementIt + = std::find_if(ops.begin(), ops.end(), [utf8Offset](const Utils::ChangeSet::EditOp &op) { + QTC_ASSERT(op.type == Utils::ChangeSet::EditOp::Replace, return false); + return op.pos1 == utf8Offset - 1; + }); + if (replacementIt == ops.end()) return -1; int afterLineBreak = replacementIt->text.lastIndexOf('\n'); @@ -493,20 +494,20 @@ ClangFormatBaseIndenter::ClangFormatBaseIndenter(QTextDocument *doc) : TextEditor::Indenter(doc) {} -Utils::Text::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer, - const QTextBlock &startBlock, - const QTextBlock &endBlock, - int cursorPositionInEditor, - ReplacementsToKeep replacementsToKeep, - const QChar &typedChar, - bool secondTry) const +Utils::ChangeSet ClangFormatBaseIndenter::replacements(QByteArray buffer, + const QTextBlock &startBlock, + const QTextBlock &endBlock, + int cursorPositionInEditor, + ReplacementsToKeep replacementsToKeep, + const QChar &typedChar, + bool secondTry) const { - QTC_ASSERT(replacementsToKeep != ReplacementsToKeep::All, return Utils::Text::Replacements()); + QTC_ASSERT(replacementsToKeep != ReplacementsToKeep::All, return Utils::ChangeSet()); QTC_ASSERT(!m_fileName.isEmpty(), return {}); QByteArray originalBuffer = buffer; int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, startBlock.blockNumber() + 1); - QTC_ASSERT(utf8Offset >= 0, return Utils::Text::Replacements();); + QTC_ASSERT(utf8Offset >= 0, return Utils::ChangeSet();); int utf8Length = selectedLines(m_doc, startBlock, endBlock).toUtf8().size(); int rangeStart = 0; @@ -556,11 +557,11 @@ Utils::Text::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffe true); } - return utf16Replacements(m_doc, buffer, filtered); + return convertReplacements(m_doc, buffer, filtered); } -Utils::Text::Replacements ClangFormatBaseIndenter::format( - const TextEditor::RangesInLines &rangesInLines, FormattingMode mode) +Utils::EditOperations ClangFormatBaseIndenter::format(const TextEditor::RangesInLines &rangesInLines, + FormattingMode mode) { bool doFormatting = mode == FormattingMode::Forced || formatCodeInsteadOfIndent(); #ifdef WITH_TESTS @@ -572,7 +573,7 @@ Utils::Text::Replacements ClangFormatBaseIndenter::format( QTC_ASSERT(!m_fileName.isEmpty(), return {}); if (rangesInLines.empty()) - return Utils::Text::Replacements(); + return {}; const QByteArray buffer = m_doc->toPlainText().toUtf8(); std::vector ranges; @@ -598,7 +599,7 @@ Utils::Text::Replacements ClangFormatBaseIndenter::format( auto changedCode = clang::tooling::applyAllReplacements(buffer.data(), clangReplacements); QTC_ASSERT(changedCode, { qDebug() << QString::fromStdString(llvm::toString(changedCode.takeError())); - return Utils::Text::Replacements(); + return {}; }); ranges = clang::tooling::calculateRangesAfterReplacements(clangReplacements, ranges); @@ -610,13 +611,14 @@ Utils::Text::Replacements ClangFormatBaseIndenter::format( &status); clangReplacements = clangReplacements.merge(formatReplacements); - const Utils::Text::Replacements toReplace = utf16Replacements(m_doc, buffer, clangReplacements); - Utils::Text::applyReplacements(m_doc, toReplace); + Utils::ChangeSet changeSet = convertReplacements(m_doc, buffer, clangReplacements); + const Utils::EditOperations editOperations = changeSet.operationList(); + changeSet.apply(m_doc); - return toReplace; + return editOperations; } -Utils::Text::Replacements ClangFormatBaseIndenter::indentsFor(QTextBlock startBlock, +Utils::ChangeSet ClangFormatBaseIndenter::indentsFor(QTextBlock startBlock, const QTextBlock &endBlock, const QChar &typedChar, int cursorPositionInEditor, @@ -625,7 +627,7 @@ Utils::Text::Replacements ClangFormatBaseIndenter::indentsFor(QTextBlock startBl if (typedChar != QChar::Null && cursorPositionInEditor > 0 && m_doc->characterAt(cursorPositionInEditor - 1) == typedChar && doNotIndentInContext(m_doc, cursorPositionInEditor - 1)) { - return Utils::Text::Replacements(); + return Utils::ChangeSet(); } startBlock = reverseFindLastEmptyBlock(startBlock); @@ -664,7 +666,8 @@ void ClangFormatBaseIndenter::indentBlocks(const QTextBlock &startBlock, const QChar &typedChar, int cursorPositionInEditor) { - applyReplacements(m_doc, indentsFor(startBlock, endBlock, typedChar, cursorPositionInEditor)); + Utils::ChangeSet changeset = indentsFor(startBlock, endBlock, typedChar, cursorPositionInEditor); + changeset.apply(m_doc); } void ClangFormatBaseIndenter::indent(const QTextCursor &cursor, @@ -708,12 +711,9 @@ int ClangFormatBaseIndenter::indentFor(const QTextBlock &block, const TextEditor::TabSettings & /*tabSettings*/, int cursorPositionInEditor) { - Utils::Text::Replacements toReplace = indentsFor(block, - block, - QChar::Null, - cursorPositionInEditor, - false); - if (toReplace.empty()) + Utils::ChangeSet toReplace + = indentsFor(block, block, QChar::Null, cursorPositionInEditor, false); + if (toReplace.isEmpty()) return -1; const QByteArray buffer = m_doc->toPlainText().toUtf8(); @@ -728,7 +728,7 @@ TextEditor::IndentationForBlock ClangFormatBaseIndenter::indentationForBlocks( TextEditor::IndentationForBlock ret; if (blocks.isEmpty()) return ret; - Utils::Text::Replacements toReplace = indentsFor(blocks.front(), + Utils::ChangeSet toReplace = indentsFor(blocks.front(), blocks.back(), QChar::Null, cursorPositionInEditor); diff --git a/src/plugins/clangformat/clangformatbaseindenter.h b/src/plugins/clangformat/clangformatbaseindenter.h index 6330d757290..e20470321d8 100644 --- a/src/plugins/clangformat/clangformatbaseindenter.h +++ b/src/plugins/clangformat/clangformatbaseindenter.h @@ -31,8 +31,8 @@ public: void autoIndent(const QTextCursor &cursor, const TextEditor::TabSettings &tabSettings, int cursorPositionInEditor = -1) override; - Utils::Text::Replacements format(const TextEditor::RangesInLines &rangesInLines, - FormattingMode mode = FormattingMode::Forced) override; + Utils::EditOperations format(const TextEditor::RangesInLines &rangesInLines, + FormattingMode mode = FormattingMode::Forced) override; void indentBlock(const QTextBlock &block, const QChar &typedChar, @@ -60,18 +60,18 @@ private: const QTextBlock &endBlock, const QChar &typedChar, int cursorPositionInEditor); - Utils::Text::Replacements indentsFor(QTextBlock startBlock, - const QTextBlock &endBlock, - const QChar &typedChar, - int cursorPositionInEditor, - bool trimTrailingWhitespace = true); - Utils::Text::Replacements replacements(QByteArray buffer, - const QTextBlock &startBlock, - const QTextBlock &endBlock, - int cursorPositionInEditor, - ReplacementsToKeep replacementsToKeep, - const QChar &typedChar = QChar::Null, - bool secondTry = false) const; + Utils::ChangeSet indentsFor(QTextBlock startBlock, + const QTextBlock &endBlock, + const QChar &typedChar, + int cursorPositionInEditor, + bool trimTrailingWhitespace = true); + Utils::ChangeSet replacements(QByteArray buffer, + const QTextBlock &startBlock, + const QTextBlock &endBlock, + int cursorPositionInEditor, + ReplacementsToKeep replacementsToKeep, + const QChar &typedChar = QChar::Null, + bool secondTry = false) const; struct CachedStyle { clang::format::FormatStyle style = clang::format::getNoStyle(); diff --git a/src/plugins/clangformat/clangformatindenter.cpp b/src/plugins/clangformat/clangformatindenter.cpp index 2da8a95ad36..821a434f11c 100644 --- a/src/plugins/clangformat/clangformatindenter.cpp +++ b/src/plugins/clangformat/clangformatindenter.cpp @@ -173,7 +173,7 @@ void ClangFormatForwardingIndenter::autoIndent(const QTextCursor &cursor, currentIndenter()->autoIndent(cursor, tabSettings, cursorPositionInEditor); } -Utils::Text::Replacements ClangFormatForwardingIndenter::format( +Utils::EditOperations ClangFormatForwardingIndenter::format( const TextEditor::RangesInLines &rangesInLines, FormattingMode mode) { return currentIndenter()->format(rangesInLines, mode); diff --git a/src/plugins/clangformat/clangformatindenter.h b/src/plugins/clangformat/clangformatindenter.h index 5e6aca135ef..be3d54e6c8d 100644 --- a/src/plugins/clangformat/clangformatindenter.h +++ b/src/plugins/clangformat/clangformatindenter.h @@ -40,8 +40,8 @@ public: void autoIndent(const QTextCursor &cursor, const TextEditor::TabSettings &tabSettings, int cursorPositionInEditor = -1) override; - Utils::Text::Replacements format(const TextEditor::RangesInLines &rangesInLines, - FormattingMode mode) override; + Utils::EditOperations format(const TextEditor::RangesInLines &rangesInLines, + FormattingMode mode) override; bool formatOnSave() const override; TextEditor::IndentationForBlock indentationForBlocks(const QVector &blocks, const TextEditor::TabSettings &tabSettings, diff --git a/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp b/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp index 5f5102d7944..4eeb72f94f1 100644 --- a/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp +++ b/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp @@ -126,9 +126,9 @@ void FixitsRefactoringFile::format(TextEditor::Indenter &indenter, const int end = doc->findBlock(op.pos + op.length).blockNumber() + 1; ranges.push_back({start, end}); } - const Text::Replacements replacements = indenter.format(ranges); + const EditOperations replacements = indenter.format(ranges); - if (replacements.empty()) + if (replacements.isEmpty()) return; shiftAffectedReplacements(operationsForFile.front()->filePath, @@ -179,7 +179,7 @@ void FixitsRefactoringFile::shiftAffectedReplacements(const ReplacementOperation } void FixitsRefactoringFile::shiftAffectedReplacements(const FilePath &filePath, - const Text::Replacements &replacements, + const EditOperations &replacements, int startIndex) { for (int i = startIndex; i < m_replacementOperations.size(); ++i) { @@ -187,10 +187,11 @@ void FixitsRefactoringFile::shiftAffectedReplacements(const FilePath &filePath, if (filePath != current.filePath) continue; - for (const auto &replacement : replacements) { - if (replacement.offset > current.pos) + for (const auto &op : replacements) { + QTC_ASSERT(op.type == ChangeSet::EditOp::Replace, continue); + if (op.pos1 > current.pos) break; - current.pos += replacement.text.size() - replacement.length; + current.pos += op.text.size() - op.length1; } } } diff --git a/src/plugins/clangtools/clangfixitsrefactoringchanges.h b/src/plugins/clangtools/clangfixitsrefactoringchanges.h index 7a1eecc9fc9..30c1f819dfe 100644 --- a/src/plugins/clangtools/clangfixitsrefactoringchanges.h +++ b/src/plugins/clangtools/clangfixitsrefactoringchanges.h @@ -48,7 +48,7 @@ private: const ReplacementOperations &operationsForFile, int firstOperationIndex); void shiftAffectedReplacements(const Utils::FilePath &filePath, - const Utils::Text::Replacements &replacements, + const Utils::EditOperations &replacements, int startIndex); mutable Utils::TextFileFormat m_textFileFormat; diff --git a/src/plugins/clangtools/documentquickfixfactory.cpp b/src/plugins/clangtools/documentquickfixfactory.cpp index c9875b0180c..e9807a8bcba 100644 --- a/src/plugins/clangtools/documentquickfixfactory.cpp +++ b/src/plugins/clangtools/documentquickfixfactory.cpp @@ -9,6 +9,7 @@ #include #include +#include namespace ClangTools { namespace Internal { diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp index f2fb0a18f4c..0f2dbe39d54 100644 --- a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/src/plugins/languageclient/languageclientformatter.cpp b/src/plugins/languageclient/languageclientformatter.cpp index e0dc144dc00..c3790e42cb5 100644 --- a/src/plugins/languageclient/languageclientformatter.cpp +++ b/src/plugins/languageclient/languageclientformatter.cpp @@ -93,7 +93,7 @@ QFutureWatcher *LanguageClientFormatter::format( m_ignoreCancel = true; m_progress.reportStarted(); auto watcher = new QFutureWatcher(); - QObject::connect(watcher, &QFutureWatcher::canceled, [this]() { + QObject::connect(watcher, &QFutureWatcher::canceled, [this]() { cancelCurrentRequest(); }); watcher->setFuture(m_progress.future()); diff --git a/src/plugins/texteditor/indenter.h b/src/plugins/texteditor/indenter.h index 11c6aa87d8b..042724d3bf3 100644 --- a/src/plugins/texteditor/indenter.h +++ b/src/plugins/texteditor/indenter.h @@ -3,8 +3,8 @@ #pragma once +#include #include -#include #include #include @@ -71,10 +71,10 @@ public: } enum class FormattingMode { Forced, Settings }; - virtual Utils::Text::Replacements format(const RangesInLines &, - FormattingMode = FormattingMode::Forced) + virtual Utils::EditOperations format(const RangesInLines &, + FormattingMode = FormattingMode::Forced) { - return Utils::Text::Replacements(); + return Utils::EditOperations(); } virtual bool formatOnSave() const { return false; }