From ccdc2936976f126cd377c97a0b84d69162c246ec Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 28 Jun 2024 11:29:38 +0200 Subject: [PATCH] Editor: remove TextDocumentManipulator Change-Id: Iacd7cd40ace77c79eecca3e4e699eb308d0c27de Reviewed-by: Christian Kandeler --- src/plugins/clangcodemodel/clangdclient.cpp | 1 - .../clangcodemodel/clangdcompletion.cpp | 131 ++++++++++++++---- .../clangpreprocessorassistproposalitem.cpp | 13 +- .../clangpreprocessorassistproposalitem.h | 2 +- src/plugins/clangcodemodel/clangutils.cpp | 37 +---- src/plugins/clangcodemodel/clangutils.h | 52 ------- .../clangcodemodel/test/clangdtests.cpp | 91 ++++++------ src/plugins/cppeditor/cppcompletionassist.cpp | 32 +++-- .../cppvirtualfunctionproposalitem.cpp | 2 +- .../cppvirtualfunctionproposalitem.h | 2 +- src/plugins/fakevim/fakevimplugin.cpp | 2 +- .../languageclientcompletionassist.cpp | 22 +-- .../languageclientcompletionassist.h | 2 +- .../languageclient/languageclientutils.cpp | 13 +- .../languageclient/languageclientutils.h | 2 +- .../qmljseditor/qmljscompletionassist.cpp | 17 +-- .../qmljseditor/qmljscompletionassist.h | 2 +- src/plugins/texteditor/CMakeLists.txt | 1 - .../texteditor/circularclipboardassist.cpp | 5 +- .../codeassist/assistproposalitem.cpp | 28 ++-- .../codeassist/assistproposalitem.h | 8 +- .../codeassist/assistproposaliteminterface.h | 6 +- .../texteditor/codeassist/codeassist_test.cpp | 2 +- .../texteditor/codeassist/codeassistant.cpp | 4 +- .../codeassist/keywordscompletionassist.cpp | 15 +- .../codeassist/keywordscompletionassist.h | 2 +- .../codeassist/textdocumentmanipulator.cpp | 83 ----------- .../codeassist/textdocumentmanipulator.h | 51 ------- .../snippets/snippetassistcollector.cpp | 6 +- src/plugins/texteditor/texteditor.qbs | 2 - 30 files changed, 250 insertions(+), 386 deletions(-) delete mode 100644 src/plugins/texteditor/codeassist/textdocumentmanipulator.cpp delete mode 100644 src/plugins/texteditor/codeassist/textdocumentmanipulator.h diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 42148a25037..16832965b88 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -54,7 +54,6 @@ #include #include #include -#include #include #include #include diff --git a/src/plugins/clangcodemodel/clangdcompletion.cpp b/src/plugins/clangcodemodel/clangdcompletion.cpp index bc7b19a8ea5..4ff9c748f4f 100644 --- a/src/plugins/clangcodemodel/clangdcompletion.cpp +++ b/src/plugins/clangcodemodel/clangdcompletion.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include @@ -44,6 +46,83 @@ namespace ClangCodeModel::Internal { static Q_LOGGING_CATEGORY(clangdLogCompletion, "qtc.clangcodemodel.clangd.completion", QtWarningMsg); +static void moveToPreviousChar(TextEditor::TextEditorWidget *editorWidget, QTextCursor &cursor) +{ + cursor.movePosition(QTextCursor::PreviousCharacter); + while (editorWidget->characterAt(cursor.position()).isSpace()) + cursor.movePosition(QTextCursor::PreviousCharacter); +} + +static bool matchPreviousWord(TextEditor::TextEditorWidget *editorWidget, QTextCursor cursor, QString pattern) +{ + cursor.movePosition(QTextCursor::PreviousWord); + while (editorWidget->characterAt(cursor.position()) == ':') + cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor, 2); + + int previousWordStart = cursor.position(); + cursor.movePosition(QTextCursor::NextWord); + moveToPreviousChar(editorWidget, cursor); + QString toMatch = editorWidget->textAt(previousWordStart, cursor.position() - previousWordStart + 1); + + pattern = pattern.simplified(); + while (!pattern.isEmpty() && pattern.endsWith(toMatch)) { + pattern.chop(toMatch.length()); + if (pattern.endsWith(' ')) + pattern.chop(1); + if (!pattern.isEmpty()) { + cursor.movePosition(QTextCursor::StartOfWord); + cursor.movePosition(QTextCursor::PreviousWord); + previousWordStart = cursor.position(); + cursor.movePosition(QTextCursor::NextWord); + moveToPreviousChar(editorWidget, cursor); + toMatch = editorWidget->textAt(previousWordStart, cursor.position() - previousWordStart + 1); + } + } + return pattern.isEmpty(); +} + +static QString textUntilPreviousStatement(TextEditor::TextEditorWidget *editorWidget, + int startPosition) +{ + static const QString stopCharacters(";{}#"); + + int endPosition = 0; + for (int i = startPosition; i >= 0 ; --i) { + if (stopCharacters.contains(editorWidget->characterAt(i))) { + endPosition = i + 1; + break; + } + } + + return editorWidget->textAt(endPosition, startPosition - endPosition); +} + +// 7.3.3: using typename(opt) nested-name-specifier unqualified-id ; +static bool isAtUsingDeclaration(TextEditor::TextEditorWidget *editorWidget, int basePosition) +{ + using namespace CPlusPlus; + SimpleLexer lexer; + lexer.setLanguageFeatures(LanguageFeatures::defaultFeatures()); + const QString textToLex = textUntilPreviousStatement(editorWidget, basePosition); + const Tokens tokens = lexer(textToLex); + if (tokens.empty()) + return false; + + // The nested-name-specifier always ends with "::", so check for this first. + const Token lastToken = tokens[tokens.size() - 1]; + if (lastToken.kind() != T_COLON_COLON) + return false; + + return contains(tokens, [](const Token &token) { return token.kind() == T_USING; }); +} + +static void moveToPreviousWord(TextEditor::TextEditorWidget *editorWidget, QTextCursor &cursor) +{ + cursor.movePosition(QTextCursor::PreviousWord); + while (editorWidget->characterAt(cursor.position()) == ':') + cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor, 2); +} + enum class CustomAssistMode { Preprocessor, IncludePath }; class CustomAssistProcessor : public IAssistProcessor @@ -74,7 +153,7 @@ class ClangdCompletionItem : public LanguageClientCompletionItem { public: using LanguageClientCompletionItem::LanguageClientCompletionItem; - void apply(TextDocumentManipulator &manipulator, int basePosition) const override; + void apply(TextEditorWidget *editorWidget, int basePosition) const override; enum class SpecialQtType { Signal, Slot, None }; static SpecialQtType getQtType(const CompletionItem &item); @@ -246,9 +325,11 @@ bool ClangdCompletionAssistProvider::isInCommentOrString(const AssistInterface * return CppEditor::isInCommentOrString(interface, features); } -void ClangdCompletionItem::apply(TextDocumentManipulator &manipulator, - int /*basePosition*/) const +void ClangdCompletionItem::apply(TextEditorWidget *editorWidget, + int /*basePosition*/) const { + QTC_ASSERT(editorWidget, return); + const CompletionItem item = this->item(); QChar typedChar = triggeredCommitCharacter(); const auto edit = item.textEdit(); @@ -287,8 +368,8 @@ void ClangdCompletionItem::apply(TextDocumentManipulator &manipulator, int extraLength = 0; int cursorOffset = 0; bool setAutoCompleteSkipPos = false; - int currentPos = manipulator.currentPosition(); - const QTextDocument * const doc = manipulator.document(); + int currentPos = editorWidget->position(); + const QTextDocument * const doc = editorWidget->document(); const Range range = edit->range(); const int rangeStart = range.start().toPositionInDocument(doc); if (isFunctionLike && completionSettings.m_autoInsertBrackets) { @@ -296,19 +377,19 @@ void ClangdCompletionItem::apply(TextDocumentManipulator &manipulator, // in which case it would be annoying if we put the cursor after the already automatically // inserted closing parenthesis. const bool skipClosingParenthesis = typedChar != '('; - QTextCursor cursor = manipulator.textCursorAt(rangeStart); + QTextCursor cursor = editorWidget->textCursorAt(rangeStart); bool abandonParen = false; - if (matchPreviousWord(manipulator, cursor, "&")) { - moveToPreviousWord(manipulator, cursor); - moveToPreviousChar(manipulator, cursor); - const QChar prevChar = manipulator.characterAt(cursor.position()); + if (matchPreviousWord(editorWidget, cursor, "&")) { + moveToPreviousWord(editorWidget, cursor); + moveToPreviousChar(editorWidget, cursor); + const QChar prevChar = editorWidget->characterAt(cursor.position()); cursor.setPosition(rangeStart); abandonParen = QString("(;,{}=").contains(prevChar); } if (!abandonParen) - abandonParen = isAtUsingDeclaration(manipulator, rangeStart); - if (!abandonParen && !isMacroCall && matchPreviousWord(manipulator, cursor, detail)) + abandonParen = isAtUsingDeclaration(editorWidget, rangeStart); + if (!abandonParen && !isMacroCall && matchPreviousWord(editorWidget, cursor, detail)) abandonParen = true; // function definition if (!abandonParen) { if (completionSettings.m_spaceAfterFunctionName) @@ -319,7 +400,7 @@ void ClangdCompletionItem::apply(TextDocumentManipulator &manipulator, // If the function doesn't return anything, automatically place the semicolon, // unless we're doing a scope completion (then it might be function definition). - const QChar characterAtCursor = manipulator.characterAt(currentPos); + const QChar characterAtCursor = editorWidget->characterAt(currentPos); bool endWithSemicolon = typedChar == ';'; const QChar semicolon = typedChar.isNull() ? QLatin1Char(';') : typedChar; if (endWithSemicolon && characterAtCursor == semicolon) { @@ -335,7 +416,7 @@ void ClangdCompletionItem::apply(TextDocumentManipulator &manipulator, typedChar = {}; } } else { - const QChar lookAhead = manipulator.characterAt(currentPos + 1); + const QChar lookAhead = editorWidget->characterAt(currentPos + 1); if (MatchingText::shouldInsertMatchingText(lookAhead)) { extraCharacters += ')'; --cursorOffset; @@ -360,13 +441,13 @@ void ClangdCompletionItem::apply(TextDocumentManipulator &manipulator, // Avoid inserting characters that are already there // For include file completions, also consider a possibly pre-existing // closing quote or angle bracket. - QTextCursor cursor = manipulator.textCursorAt(rangeStart); + QTextCursor cursor = editorWidget->textCursorAt(rangeStart); cursor.movePosition(QTextCursor::EndOfWord); if (kind == CompletionItemKind::File && !textToBeInserted.isEmpty() - && textToBeInserted.right(1) == manipulator.textAt(cursor.position(), 1)) { + && textToBeInserted.right(1) == editorWidget->textAt(cursor.position(), 1)) { cursor.setPosition(cursor.position() + 1); } - const QString textAfterCursor = manipulator.textAt(currentPos, cursor.position() - currentPos); + const QString textAfterCursor = editorWidget->textAt(currentPos, cursor.position() - currentPos); if (currentPos < cursor.position() && textToBeInserted != textAfterCursor && textToBeInserted.indexOf(textAfterCursor, currentPos - rangeStart) >= 0) { @@ -374,7 +455,7 @@ void ClangdCompletionItem::apply(TextDocumentManipulator &manipulator, } for (int i = 0; i < extraCharacters.length(); ++i) { const QChar a = extraCharacters.at(i); - const QChar b = manipulator.characterAt(currentPos + i); + const QChar b = editorWidget->characterAt(currentPos + i); if (a == b) ++extraLength; else @@ -383,19 +464,19 @@ void ClangdCompletionItem::apply(TextDocumentManipulator &manipulator, textToBeInserted += extraCharacters; const int length = currentPos - rangeStart + extraLength; - const int oldRevision = manipulator.document()->revision(); - manipulator.replace(rangeStart, length, textToBeInserted); - manipulator.setCursorPosition(rangeStart + textToBeInserted.length()); - if (manipulator.document()->revision() != oldRevision) { + const int oldRevision = editorWidget->document()->revision(); + editorWidget->replace(rangeStart, length, textToBeInserted); + editorWidget->setCursorPosition(rangeStart + textToBeInserted.length()); + if (editorWidget->document()->revision() != oldRevision) { if (cursorOffset) - manipulator.setCursorPosition(manipulator.currentPosition() + cursorOffset); + editorWidget->setCursorPosition(editorWidget->position() + cursorOffset); if (setAutoCompleteSkipPos) - manipulator.addAutoCompleteSkipPosition(); + editorWidget->setAutoCompleteSkipPosition(editorWidget->textCursor()); } if (auto additionalEdits = item.additionalTextEdits()) { for (const auto &edit : *additionalEdits) - applyTextEdit(manipulator, edit); + applyTextEdit(editorWidget, edit); } } diff --git a/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp index 2ad430a2a5a..87924ad7f50 100644 --- a/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp +++ b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp @@ -28,10 +28,11 @@ bool ClangPreprocessorAssistProposalItem::implicitlyApplies() const return true; } -void ClangPreprocessorAssistProposalItem::apply(TextEditor::TextDocumentManipulator &manipulator, +void ClangPreprocessorAssistProposalItem::apply(TextEditor::TextEditorWidget *editorWidget, int basePosition) const { // TODO move in an extra class under tests + QTC_ASSERT(editorWidget, return); QString textToBeInserted = text(); @@ -51,13 +52,13 @@ void ClangPreprocessorAssistProposalItem::apply(TextEditor::TextDocumentManipula extraCharacters += m_typedCharacter; // Avoid inserting characters that are already there - QTextCursor c = manipulator.textCursor(); + QTextCursor c = editorWidget->textCursor(); c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); const QString existingText = c.selectedText(); int existLength = 0; if (!existingText.isEmpty()) { // Calculate the exist length in front of the extra chars - existLength = textToBeInserted.length() - (manipulator.currentPosition() - basePosition); + existLength = textToBeInserted.length() - (editorWidget->position() - basePosition); while (!existingText.startsWith(textToBeInserted.right(existLength))) { if (--existLength == 0) break; @@ -65,7 +66,7 @@ void ClangPreprocessorAssistProposalItem::apply(TextEditor::TextDocumentManipula } for (int i = 0; i < extraCharacters.length(); ++i) { const QChar a = extraCharacters.at(i); - const QChar b = manipulator.characterAt(manipulator.currentPosition() + i + existLength); + const QChar b = editorWidget->characterAt(editorWidget->position() + i + existLength); if (a == b) ++extraLength; else @@ -75,9 +76,9 @@ void ClangPreprocessorAssistProposalItem::apply(TextEditor::TextDocumentManipula textToBeInserted += extraCharacters; // Insert the remainder of the name - const int length = manipulator.currentPosition() - basePosition + existLength + extraLength; + const int length = editorWidget->position() - basePosition + existLength + extraLength; - manipulator.replace(basePosition, length, textToBeInserted); + editorWidget->replace(basePosition, length, textToBeInserted); } void ClangPreprocessorAssistProposalItem::setText(const QString &text) diff --git a/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.h b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.h index 0e4901ff923..54c70bb2bf0 100644 --- a/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.h +++ b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.h @@ -17,7 +17,7 @@ public: ~ClangPreprocessorAssistProposalItem() noexcept override = default; bool prematurelyApplies(const QChar &typedChar) const final; bool implicitlyApplies() const final; - void apply(TextEditor::TextDocumentManipulator &manipulator, int basePosition) const final; + void apply(TextEditor::TextEditorWidget *editorWidget, int basePosition) const final; void setText(const QString &text); QString text() const final; diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index b09134cddf2..e5b7c16c866 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -302,41 +302,6 @@ const QStringList globalClangOptions() return ClangDiagnosticConfigsModel::globalDiagnosticOptions(); } -// 7.3.3: using typename(opt) nested-name-specifier unqualified-id ; -bool isAtUsingDeclaration(TextEditor::TextDocumentManipulator &manipulator, int basePosition) -{ - using namespace CPlusPlus; - SimpleLexer lexer; - lexer.setLanguageFeatures(LanguageFeatures::defaultFeatures()); - const QString textToLex = textUntilPreviousStatement(manipulator, basePosition); - const Tokens tokens = lexer(textToLex); - if (tokens.empty()) - return false; - - // The nested-name-specifier always ends with "::", so check for this first. - const Token lastToken = tokens[tokens.size() - 1]; - if (lastToken.kind() != T_COLON_COLON) - return false; - - return contains(tokens, [](const Token &token) { return token.kind() == T_USING; }); -} - -QString textUntilPreviousStatement(TextEditor::TextDocumentManipulator &manipulator, - int startPosition) -{ - static const QString stopCharacters(";{}#"); - - int endPosition = 0; - for (int i = startPosition; i >= 0 ; --i) { - if (stopCharacters.contains(manipulator.characterAt(i))) { - endPosition = i + 1; - break; - } - } - - return manipulator.textAt(endPosition, startPosition - endPosition); -} - CompilerOptionsBuilder clangOptionsBuilder(const ProjectPart &projectPart, const ClangDiagnosticConfig &warningsConfig, const FilePath &clangIncludeDir, diff --git a/src/plugins/clangcodemodel/clangutils.h b/src/plugins/clangcodemodel/clangutils.h index 23d384fdc3a..ef413037506 100644 --- a/src/plugins/clangcodemodel/clangutils.h +++ b/src/plugins/clangcodemodel/clangutils.h @@ -22,8 +22,6 @@ class ClangDiagnosticConfig; class CppEditorDocumentHandle; } -namespace TextEditor { class TextDocumentManipulator; } - namespace ProjectExplorer { class Project; } namespace ClangCodeModel { @@ -81,56 +79,6 @@ private: const int m_squareBracketStartIndex; }; -template -void moveToPreviousChar(const CharacterProvider &provider, QTextCursor &cursor) -{ - cursor.movePosition(QTextCursor::PreviousCharacter); - while (provider.characterAt(cursor.position()).isSpace()) - cursor.movePosition(QTextCursor::PreviousCharacter); -} - -template -void moveToPreviousWord(CharacterProvider &provider, QTextCursor &cursor) -{ - cursor.movePosition(QTextCursor::PreviousWord); - while (provider.characterAt(cursor.position()) == ':') - cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor, 2); -} - -template -bool matchPreviousWord(const CharacterProvider &provider, QTextCursor cursor, QString pattern) -{ - cursor.movePosition(QTextCursor::PreviousWord); - while (provider.characterAt(cursor.position()) == ':') - cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor, 2); - - int previousWordStart = cursor.position(); - cursor.movePosition(QTextCursor::NextWord); - moveToPreviousChar(provider, cursor); - QString toMatch = provider.textAt(previousWordStart, cursor.position() - previousWordStart + 1); - - pattern = pattern.simplified(); - while (!pattern.isEmpty() && pattern.endsWith(toMatch)) { - pattern.chop(toMatch.length()); - if (pattern.endsWith(' ')) - pattern.chop(1); - if (!pattern.isEmpty()) { - cursor.movePosition(QTextCursor::StartOfWord); - cursor.movePosition(QTextCursor::PreviousWord); - previousWordStart = cursor.position(); - cursor.movePosition(QTextCursor::NextWord); - moveToPreviousChar(provider, cursor); - toMatch = provider.textAt(previousWordStart, cursor.position() - previousWordStart + 1); - } - } - return pattern.isEmpty(); -} - -QString textUntilPreviousStatement( - TextEditor::TextDocumentManipulator &manipulator, int startPosition); - -bool isAtUsingDeclaration(TextEditor::TextDocumentManipulator &manipulator, int basePosition); - class ClangSourceRange { public: diff --git a/src/plugins/clangcodemodel/test/clangdtests.cpp b/src/plugins/clangcodemodel/test/clangdtests.cpp index 719cfba93a1..2d1fd879c9a 100644 --- a/src/plugins/clangcodemodel/test/clangdtests.cpp +++ b/src/plugins/clangcodemodel/test/clangdtests.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -1655,11 +1654,11 @@ void ClangdTestCompletion::testCompleteGlobals() const AssistProposalItemInterface * const item = getItem(proposal, " globalFunction()", "void"); QVERIFY(item); - TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget()); - item->apply(manipulator, cursorPos); - QCOMPARE(manipulator.getLine(7), " globalFunction() /* COMPLETE HERE */"); - QCOMPARE(manipulator.cursorPos(), Text::Position({7, 19})); - QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); + auto editor = TextEditorWidget::currentTextEditorWidget(); + item->apply(editor, cursorPos); + QCOMPARE(editor->textDocument()->blockText(6), " globalFunction() /* COMPLETE HERE */"); + QCOMPARE(editor->lineColumn(), Text::Position({7, 19})); + QVERIFY(editor->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testCompleteMembers() @@ -1675,11 +1674,11 @@ void ClangdTestCompletion::testCompleteMembers() const AssistProposalItemInterface * const item = getItem(proposal, " member", "int"); QVERIFY(item); - TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget()); - item->apply(manipulator, cursorPos); - QCOMPARE(manipulator.getLine(7), " s.member /* COMPLETE HERE */"); - QCOMPARE(manipulator.cursorPos(), Text::Position({7, 12})); - QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); + auto editor = TextEditorWidget::currentTextEditorWidget(); + item->apply(editor, cursorPos); + QCOMPARE(editor->textDocument()->blockText(6), " s.member /* COMPLETE HERE */"); + QCOMPARE(editor->lineColumn(), Text::Position({7, 12})); + QVERIFY(editor->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testCompleteMembersFromInside() @@ -1693,11 +1692,11 @@ void ClangdTestCompletion::testCompleteMembersFromInside() const AssistProposalItemInterface * const item = getItem(proposal, " privateFunc()", "void"); QVERIFY(item); - TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget()); - item->apply(manipulator, cursorPos); - QCOMPARE(manipulator.getLine(4), " privateFunc() /* COMPLETE HERE */"); - QCOMPARE(manipulator.cursorPos(), Text::Position({4, 21})); - QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); + auto editor = TextEditorWidget::currentTextEditorWidget(); + item->apply(editor, cursorPos); + QCOMPARE(editor->textDocument()->blockText(3), " privateFunc() /* COMPLETE HERE */"); + QCOMPARE(editor->lineColumn(), Text::Position({4, 21})); + QVERIFY(editor->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testCompleteMembersFromOutside() @@ -1711,11 +1710,11 @@ void ClangdTestCompletion::testCompleteMembersFromOutside() const AssistProposalItemInterface * const item = getItem(proposal, " publicFunc()", "void"); QVERIFY(item); - TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget()); - item->apply(manipulator, cursorPos); - QCOMPARE(manipulator.getLine(13), " c.publicFunc() /* COMPLETE HERE */"); - QCOMPARE(manipulator.cursorPos(), Text::Position({13, 18})); - QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); + auto editor = TextEditorWidget::currentTextEditorWidget(); + item->apply(editor, cursorPos); + QCOMPARE(editor->textDocument()->blockText(12), " c.publicFunc() /* COMPLETE HERE */"); + QCOMPARE(editor->lineColumn(), Text::Position({13, 18})); + QVERIFY(editor->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testCompleteMembersFromFriend() @@ -1729,11 +1728,11 @@ void ClangdTestCompletion::testCompleteMembersFromFriend() const AssistProposalItemInterface * const item = getItem(proposal, " privateFunc()", "void"); QVERIFY(item); - TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget()); - item->apply(manipulator, cursorPos); - QCOMPARE(manipulator.getLine(14), " C().privateFunc() /* COMPLETE HERE */"); - QCOMPARE(manipulator.cursorPos(), Text::Position({14, 21})); - QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); + auto editor = TextEditorWidget::currentTextEditorWidget(); + item->apply(editor, cursorPos); + QCOMPARE(editor->textDocument()->blockText(13), " C().privateFunc() /* COMPLETE HERE */"); + QCOMPARE(editor->lineColumn(), Text::Position({14, 21})); + QVERIFY(editor->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testFunctionAddress() @@ -1746,11 +1745,11 @@ void ClangdTestCompletion::testFunctionAddress() const AssistProposalItemInterface * const item = getItem(proposal, " memberFunc()", "void"); QVERIFY(item); - TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget()); - item->apply(manipulator, cursorPos); - QCOMPARE(manipulator.getLine(7), " const auto p = &S::memberFunc /* COMPLETE HERE */;"); - QCOMPARE(manipulator.cursorPos(), Text::Position({7, 33})); - QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); + auto editor = TextEditorWidget::currentTextEditorWidget(); + item->apply(editor, cursorPos); + QCOMPARE(editor->textDocument()->blockText(6), " const auto p = &S::memberFunc /* COMPLETE HERE */;"); + QCOMPARE(editor->lineColumn(), Text::Position({7, 33})); + QVERIFY(editor->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testFunctionHints() @@ -1810,11 +1809,11 @@ void ClangdTestCompletion::testCompleteClassAndConstructor() const AssistProposalItemInterface * const item = getItem(proposal, QString::fromUtf8(" Foo(…)"), "[2 overloads]"); QVERIFY(item); - TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget()); - item->apply(manipulator, cursorPos); - QCOMPARE(manipulator.getLine(7), " Foo( /* COMPLETE HERE */"); - QCOMPARE(manipulator.cursorPos(), Text::Position({7, 8})); - QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); + auto editor = TextEditorWidget::currentTextEditorWidget(); + item->apply(editor, cursorPos); + QCOMPARE(editor->textDocument()->blockText(6), " Foo( /* COMPLETE HERE */"); + QCOMPARE(editor->lineColumn(), Text::Position({7, 8})); + QVERIFY(editor->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testCompletePrivateFunctionDefinition() @@ -1837,11 +1836,11 @@ void ClangdTestCompletion::testCompleteWithDotToArrowCorrection() QVERIFY(proposal); const AssistProposalItemInterface * const item = getItem(proposal, " member", "int"); QVERIFY(item); - TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget()); - item->apply(manipulator, cursorPos); - QCOMPARE(manipulator.getLine(4), " bar->member /* COMPLETE HERE */"); - QCOMPARE(manipulator.cursorPos(), Text::Position({4, 15})); - QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); + auto editor = TextEditorWidget::currentTextEditorWidget(); + item->apply(editor, cursorPos); + QCOMPARE(editor->textDocument()->blockText(3), " bar->member /* COMPLETE HERE */"); + QCOMPARE(editor->lineColumn(), Text::Position({4, 15})); + QVERIFY(editor->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testDontCompleteWithDotToArrowCorrectionForFloats() @@ -1868,11 +1867,11 @@ void ClangdTestCompletion::testCompleteCodeInGeneratedUiFile() const AssistProposalItemInterface * const item = getItem( proposal, " setupUi(QMainWindow *MainWindow)", "void"); QVERIFY(item); - TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget()); - item->apply(manipulator, cursorPos); - QCOMPARE(manipulator.getLine(34), " ui->setupUi( /* COMPLETE HERE */"); - QCOMPARE(manipulator.cursorPos(), Text::Position({34, 16})); - QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); + auto editor = TextEditorWidget::currentTextEditorWidget(); + item->apply(editor, cursorPos); + QCOMPARE(editor->textDocument()->blockText(33), " ui->setupUi( /* COMPLETE HERE */"); + QCOMPARE(editor->lineColumn(), Text::Position({34, 16})); + QVERIFY(editor->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testSignalCompletion_data() diff --git a/src/plugins/cppeditor/cppcompletionassist.cpp b/src/plugins/cppeditor/cppcompletionassist.cpp index bbb94ee3d19..7c30d76d478 100644 --- a/src/plugins/cppeditor/cppcompletionassist.cpp +++ b/src/plugins/cppeditor/cppcompletionassist.cpp @@ -64,7 +64,7 @@ class CppAssistProposalItem final : public AssistProposalItem public: ~CppAssistProposalItem() noexcept override = default; bool prematurelyApplies(const QChar &c) const override; - void applyContextualContent(TextDocumentManipulator &manipulator, int basePosition) const override; + void applyContextualContent(TextEditorWidget *editorWidget, int basePosition) const override; bool isOverloaded() const { return m_isOverloaded; } void markAsOverloaded() { m_isOverloaded = true; } @@ -143,9 +143,9 @@ bool CppAssistProposalItem::prematurelyApplies(const QChar &typedChar) const return false; } -static bool isDereferenced(TextDocumentManipulator &manipulator, int basePosition) +static bool isDereferenced(TextEditorWidget *editorWidget, int basePosition) { - QTextCursor cursor = manipulator.textCursorAt(basePosition); + QTextCursor cursor = editorWidget->textCursorAt(basePosition); cursor.setPosition(basePosition); BackwardsScanner scanner(cursor, LanguageFeatures()); @@ -173,8 +173,10 @@ quint64 CppAssistProposalItem::hash() const return 0; } -void CppAssistProposalItem::applyContextualContent(TextDocumentManipulator &manipulator, int basePosition) const +void CppAssistProposalItem::applyContextualContent(TextEditorWidget *editorWidget, int basePosition) const { + QTC_ASSERT(editorWidget, return); + Symbol *symbol = nullptr; if (data().isValid()) @@ -224,7 +226,7 @@ void CppAssistProposalItem::applyContextualContent(TextDocumentManipulator &mani if (function->argumentCount() == 0) extraChars += QLatin1Char('<'); #endif - } else if (!isDereferenced(manipulator, basePosition) && !function->isAmbiguous()) { + } else if (!isDereferenced(editorWidget, basePosition) && !function->isAmbiguous()) { // When the user typed the opening parenthesis, he'll likely also type the closing one, // in which case it would be annoying if we put the cursor after the already automatically // inserted closing parenthesis. @@ -238,7 +240,7 @@ void CppAssistProposalItem::applyContextualContent(TextDocumentManipulator &mani // If the function doesn't return anything, automatically place the semicolon, // unless we're doing a scope completion (then it might be function definition). - const QChar characterAtCursor = manipulator.characterAt(manipulator.currentPosition()); + const QChar characterAtCursor = editorWidget->characterAt(editorWidget->position()); bool endWithSemicolon = m_typedChar == QLatin1Char(';') || (function->returnType()->asVoidType() && m_completionOperator != T_COLON_COLON); const QChar semicolon = m_typedChar.isNull() ? QLatin1Char(';') : m_typedChar; @@ -256,7 +258,7 @@ void CppAssistProposalItem::applyContextualContent(TextDocumentManipulator &mani m_typedChar = QChar(); } } else if (autoParenthesesEnabled) { - const QChar lookAhead = manipulator.characterAt(manipulator.currentPosition() + 1); + const QChar lookAhead = editorWidget->characterAt(editorWidget->position() + 1); if (MatchingText::shouldInsertMatchingText(lookAhead)) { extraChars += QLatin1Char(')'); --cursorOffset; @@ -294,10 +296,10 @@ void CppAssistProposalItem::applyContextualContent(TextDocumentManipulator &mani } // Avoid inserting characters that are already there - int currentPosition = manipulator.currentPosition(); - QTextCursor cursor = manipulator.textCursorAt(basePosition); + int currentPosition = editorWidget->position(); + QTextCursor cursor = editorWidget->textCursorAt(basePosition); cursor.movePosition(QTextCursor::EndOfWord); - const QString textAfterCursor = manipulator.textAt(currentPosition, + const QString textAfterCursor = editorWidget->textAt(currentPosition, cursor.position() - currentPosition); if (toInsert != textAfterCursor && toInsert.indexOf(textAfterCursor, currentPosition - basePosition) >= 0) { @@ -306,7 +308,7 @@ void CppAssistProposalItem::applyContextualContent(TextDocumentManipulator &mani for (int i = 0; i < extraChars.length(); ++i) { const QChar a = extraChars.at(i); - const QChar b = manipulator.characterAt(currentPosition + i); + const QChar b = editorWidget->characterAt(currentPosition + i); if (a == b) ++extraLength; else @@ -317,12 +319,12 @@ void CppAssistProposalItem::applyContextualContent(TextDocumentManipulator &mani // Insert the remainder of the name const int length = currentPosition - basePosition + extraLength; - manipulator.replace(basePosition, length, toInsert); - manipulator.setCursorPosition(basePosition + toInsert.length()); + editorWidget->replace(basePosition, length, toInsert); + editorWidget->setCursorPosition(basePosition + toInsert.length()); if (cursorOffset) - manipulator.setCursorPosition(manipulator.currentPosition() + cursorOffset); + editorWidget->setCursorPosition(editorWidget->position() + cursorOffset); if (setAutoCompleteSkipPos) - manipulator.addAutoCompleteSkipPosition(); + editorWidget->setAutoCompleteSkipPosition(editorWidget->textCursor()); } // -------------------- diff --git a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.cpp b/src/plugins/cppeditor/cppvirtualfunctionproposalitem.cpp index adb6a843b41..2758c3791dd 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.cpp +++ b/src/plugins/cppeditor/cppvirtualfunctionproposalitem.cpp @@ -15,7 +15,7 @@ VirtualFunctionProposalItem::VirtualFunctionProposalItem( { } -void VirtualFunctionProposalItem::apply(TextEditor::TextDocumentManipulator &, int) const +void VirtualFunctionProposalItem::apply(TextEditor::TextEditorWidget *, int) const { if (!m_link.hasValidTarget()) return; diff --git a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h b/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h index 5ef1bf2444a..dd9f4fba49b 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h +++ b/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h @@ -16,7 +16,7 @@ public: VirtualFunctionProposalItem(const Utils::Link &link, bool openInSplit = true); ~VirtualFunctionProposalItem() noexcept override = default; - void apply(TextEditor::TextDocumentManipulator &manipulator, int basePosition) const override; + void apply(TextEditor::TextEditorWidget *editorWidget, int basePosition) const override; Utils::Link link() const { return m_link; } // Exposed for tests private: diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 4431507226a..621889a07a7 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -893,7 +893,7 @@ public: return text() == m_provider->needle(); } - void applyContextualContent(TextDocumentManipulator &, int) const override + void applyContextualContent(TextEditorWidget *, int) const override { QTC_ASSERT(m_provider->handler(), return); m_provider->handler()->handleReplay(text().mid(m_provider->needle().size())); diff --git a/src/plugins/languageclient/languageclientcompletionassist.cpp b/src/plugins/languageclient/languageclientcompletionassist.cpp index 5b14e27dda1..1b0d46bf37c 100644 --- a/src/plugins/languageclient/languageclientcompletionassist.cpp +++ b/src/plugins/languageclient/languageclientcompletionassist.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -53,23 +54,24 @@ bool LanguageClientCompletionItem::prematurelyApplies(const QChar &typedCharacte return false; } -void LanguageClientCompletionItem::apply(TextDocumentManipulator &manipulator, +void LanguageClientCompletionItem::apply(TextEditorWidget *editorWidget, int /*basePosition*/) const { + QTC_ASSERT(editorWidget, return); if (auto edit = m_item.textEdit()) { - applyTextEdit(manipulator, *edit, isSnippet()); + applyTextEdit(editorWidget, *edit, isSnippet()); } else { - const int pos = manipulator.currentPosition(); + const int pos = editorWidget->position(); const QString textToInsert(m_item.insertText().value_or(text())); int length = 0; for (auto it = textToInsert.crbegin(), end = textToInsert.crend(); it != end; ++it) { - if (it->toLower() != manipulator.characterAt(pos - length - 1).toLower()) { + if (it->toLower() != editorWidget->characterAt(pos - length - 1).toLower()) { length = 0; break; } ++length; } - QTextCursor cursor = manipulator.textCursorAt(pos); + QTextCursor cursor = editorWidget->textCursorAt(pos); cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); const QString blockTextUntilPosition = cursor.selectedText(); static QRegularExpression identifier("[a-zA-Z_][a-zA-Z0-9_]*$"); @@ -77,19 +79,19 @@ void LanguageClientCompletionItem::apply(TextDocumentManipulator &manipulator, int matchLength = match.hasMatch() ? match.capturedLength(0) : 0; length = qMax(length, matchLength); if (isSnippet()) { - manipulator.replace(pos - length, length, {}); - manipulator.insertCodeSnippet(pos - length, textToInsert, &parseSnippet); + editorWidget->replace(pos - length, length, {}); + editorWidget->insertCodeSnippet(pos - length, textToInsert, &parseSnippet); } else { - manipulator.replace(pos - length, length, textToInsert); + editorWidget->replace(pos - length, length, textToInsert); } } if (auto additionalEdits = m_item.additionalTextEdits()) { for (const auto &edit : *additionalEdits) - applyTextEdit(manipulator, edit); + applyTextEdit(editorWidget, edit); } if (!m_triggeredCommitCharacter.isNull()) - manipulator.insertCodeSnippet(manipulator.currentPosition(), + editorWidget->insertCodeSnippet(editorWidget->position(), m_triggeredCommitCharacter, &Snippet::parse); } diff --git a/src/plugins/languageclient/languageclientcompletionassist.h b/src/plugins/languageclient/languageclientcompletionassist.h index 131d5095a8e..6598dddd494 100644 --- a/src/plugins/languageclient/languageclientcompletionassist.h +++ b/src/plugins/languageclient/languageclientcompletionassist.h @@ -97,7 +97,7 @@ public: QString filterText() const override; bool implicitlyApplies() const override; bool prematurelyApplies(const QChar &typedCharacter) const override; - void apply(TextEditor::TextDocumentManipulator &manipulator, int basePosition) const override; + void apply(TextEditor::TextEditorWidget *editorWidget, int basePosition) const override; QIcon icon() const override; QString detail() const override; bool isSnippet() const override; diff --git a/src/plugins/languageclient/languageclientutils.cpp b/src/plugins/languageclient/languageclientutils.cpp index 561d91a4b1a..ce02785e9c8 100644 --- a/src/plugins/languageclient/languageclientutils.cpp +++ b/src/plugins/languageclient/languageclientutils.cpp @@ -15,7 +15,6 @@ #include #include -#include #include #include #include @@ -100,19 +99,17 @@ bool applyTextEdits(const Client *client, return file->apply(editsToChangeSet(edits, file->document())); } -void applyTextEdit(TextDocumentManipulator &manipulator, - const TextEdit &edit, - bool newTextIsSnippet) +void applyTextEdit(TextEditorWidget *editorWidget, const TextEdit &edit, bool newTextIsSnippet) { const Range range = edit.range(); - const QTextDocument *doc = manipulator.document(); + const QTextDocument *doc = editorWidget->document(); const int start = Text::positionInText(doc, range.start().line() + 1, range.start().character() + 1); const int end = Text::positionInText(doc, range.end().line() + 1, range.end().character() + 1); if (newTextIsSnippet) { - manipulator.replace(start, end - start, {}); - manipulator.insertCodeSnippet(start, edit.newText(), &parseSnippet); + editorWidget->replace(start, end - start, {}); + editorWidget->insertCodeSnippet(start, edit.newText(), &parseSnippet); } else { - manipulator.replace(start, end - start, edit.newText()); + editorWidget->replace(start, end - start, edit.newText()); } } diff --git a/src/plugins/languageclient/languageclientutils.h b/src/plugins/languageclient/languageclientutils.h index d0f4ca791a1..3096cfde0fa 100644 --- a/src/plugins/languageclient/languageclientutils.h +++ b/src/plugins/languageclient/languageclientutils.h @@ -37,7 +37,7 @@ bool LANGUAGECLIENT_EXPORT applyTextEdits(const Client *client, const QList &edits); bool LANGUAGECLIENT_EXPORT applyDocumentChange(const Client *client, const LanguageServerProtocol::DocumentChange &change); -void LANGUAGECLIENT_EXPORT applyTextEdit(TextEditor::TextDocumentManipulator &manipulator, +void LANGUAGECLIENT_EXPORT applyTextEdit(TextEditor::TextEditorWidget *editorWidget, const LanguageServerProtocol::TextEdit &edit, bool newTextIsSnippet = false); void LANGUAGECLIENT_EXPORT diff --git a/src/plugins/qmljseditor/qmljscompletionassist.cpp b/src/plugins/qmljseditor/qmljscompletionassist.cpp index 10803a7d7ed..e4d6af4afca 100644 --- a/src/plugins/qmljseditor/qmljscompletionassist.cpp +++ b/src/plugins/qmljseditor/qmljscompletionassist.cpp @@ -355,11 +355,12 @@ bool QmlJSAssistProposalItem::prematurelyApplies(const QChar &c) const || (text().endsWith(QLatin1Char('.')) && c == QLatin1Char('.')); } -void QmlJSAssistProposalItem::applyContextualContent(TextEditor::TextDocumentManipulator &manipulator, +void QmlJSAssistProposalItem::applyContextualContent(TextEditorWidget *editorWidget, int basePosition) const { - const int currentPosition = manipulator.currentPosition(); - manipulator.replace(basePosition, currentPosition - basePosition, QString()); + QTC_ASSERT(editorWidget, return); + const int currentPosition = editorWidget->position(); + editorWidget->replace(basePosition, currentPosition - basePosition, QString()); QString content = text(); int cursorOffset = 0; @@ -378,17 +379,17 @@ void QmlJSAssistProposalItem::applyContextualContent(TextEditor::TextDocumentMan int replacedLength = 0; for (int i = 0; i < replaceable.length(); ++i) { const QChar a = replaceable.at(i); - const QChar b = manipulator.characterAt(manipulator.currentPosition() + i); + const QChar b = editorWidget->characterAt(editorWidget->position() + i); if (a == b) ++replacedLength; else break; } - const int length = manipulator.currentPosition() - basePosition + replacedLength; - manipulator.replace(basePosition, length, content); + const int length = editorWidget->position() - basePosition + replacedLength; + editorWidget->replace(basePosition, length, content); if (cursorOffset) { - manipulator.setCursorPosition(manipulator.currentPosition() + cursorOffset); - manipulator.addAutoCompleteSkipPosition(); + editorWidget->setCursorPosition(editorWidget->position() + cursorOffset); + editorWidget->setAutoCompleteSkipPosition(editorWidget->textCursor()); } } diff --git a/src/plugins/qmljseditor/qmljscompletionassist.h b/src/plugins/qmljseditor/qmljscompletionassist.h index 001d198f7c7..352c29c68c2 100644 --- a/src/plugins/qmljseditor/qmljscompletionassist.h +++ b/src/plugins/qmljseditor/qmljscompletionassist.h @@ -32,7 +32,7 @@ class QmlJSAssistProposalItem final : public TextEditor::AssistProposalItem { public: bool prematurelyApplies(const QChar &c) const final; - void applyContextualContent(TextEditor::TextDocumentManipulator &manipulator, + void applyContextualContent(TextEditor::TextEditorWidget *editorWidget, int basePosition) const final; }; diff --git a/src/plugins/texteditor/CMakeLists.txt b/src/plugins/texteditor/CMakeLists.txt index 1dd379fec71..010fa53b0e5 100644 --- a/src/plugins/texteditor/CMakeLists.txt +++ b/src/plugins/texteditor/CMakeLists.txt @@ -41,7 +41,6 @@ add_qtc_plugin(TextEditor codeassist/iassistprovider.cpp codeassist/iassistprovider.h codeassist/ifunctionhintproposalmodel.cpp codeassist/ifunctionhintproposalmodel.h codeassist/keywordscompletionassist.cpp codeassist/keywordscompletionassist.h - codeassist/textdocumentmanipulator.cpp codeassist/textdocumentmanipulator.h codecchooser.cpp codecchooser.h codestyleeditor.cpp codestyleeditor.h codestylepool.cpp codestylepool.h diff --git a/src/plugins/texteditor/circularclipboardassist.cpp b/src/plugins/texteditor/circularclipboardassist.cpp index 25c62f10d18..62b5e760c29 100644 --- a/src/plugins/texteditor/circularclipboardassist.cpp +++ b/src/plugins/texteditor/circularclipboardassist.cpp @@ -37,8 +37,9 @@ public: setText(text); } - void apply(TextDocumentManipulator &manipulator, int /*basePosition*/) const final + void apply(TextEditorWidget *editorWidget, int /*basePosition*/) const final { + QTC_ASSERT(editorWidget, return); //Move to last in circular clipboard if (CircularClipboard * clipboard = CircularClipboard::instance()) { @@ -51,7 +52,7 @@ public: TextEditorWidget::duplicateMimeData(m_mimeData.get())); //Paste - manipulator.editor()->paste(); + editorWidget->paste(); } private: diff --git a/src/plugins/texteditor/codeassist/assistproposalitem.cpp b/src/plugins/texteditor/codeassist/assistproposalitem.cpp index abade26cec2..b2e9f525cfe 100644 --- a/src/plugins/texteditor/codeassist/assistproposalitem.cpp +++ b/src/plugins/texteditor/codeassist/assistproposalitem.cpp @@ -105,33 +105,35 @@ bool AssistProposalItem::prematurelyApplies(const QChar &c) const return false; } -void AssistProposalItem::apply(TextDocumentManipulator &manipulator, int basePosition) const +void AssistProposalItem::apply(TextEditorWidget *editorWidget, int basePosition) const { + QTC_ASSERT(editorWidget, return); if (data().canConvert()) { - applySnippet(manipulator, basePosition); + applySnippet(editorWidget, basePosition); } else if (data().canConvert()) { - applyQuickFix(manipulator, basePosition); + applyQuickFix(editorWidget, basePosition); } else { - applyContextualContent(manipulator, basePosition); - manipulator.editor()->encourageApply(); + applyContextualContent(editorWidget, basePosition); + editorWidget->encourageApply(); } } -void AssistProposalItem::applyContextualContent(TextDocumentManipulator &manipulator, int basePosition) const +void AssistProposalItem::applyContextualContent(TextEditorWidget *editorWidget, int basePosition) const { - const int currentPosition = manipulator.currentPosition(); - manipulator.replace(basePosition, currentPosition - basePosition, text()); - + QTC_ASSERT(editorWidget, return); + const int currentPosition = editorWidget->position(); + editorWidget->replace(basePosition, currentPosition - basePosition, text()); } -void AssistProposalItem::applySnippet(TextDocumentManipulator &manipulator, int basePosition) const +void AssistProposalItem::applySnippet(TextEditorWidget *editorWidget, int basePosition) const { - manipulator.insertCodeSnippet(basePosition, data().toString(), &Snippet::parse); + QTC_ASSERT(editorWidget, return); + editorWidget->insertCodeSnippet(basePosition, data().toString(), &Snippet::parse); } -void AssistProposalItem::applyQuickFix(TextDocumentManipulator &manipulator, int basePosition) const +void AssistProposalItem::applyQuickFix(TextEditorWidget *editorWidget, int basePosition) const { - Q_UNUSED(manipulator) + Q_UNUSED(editorWidget) Q_UNUSED(basePosition) QuickFixOperation::Ptr op = data().value(); diff --git a/src/plugins/texteditor/codeassist/assistproposalitem.h b/src/plugins/texteditor/codeassist/assistproposalitem.h index 09527f31238..ee1782a15a6 100644 --- a/src/plugins/texteditor/codeassist/assistproposalitem.h +++ b/src/plugins/texteditor/codeassist/assistproposalitem.h @@ -20,7 +20,7 @@ public: QString text() const override; bool implicitlyApplies() const override; bool prematurelyApplies(const QChar &c) const override; - void apply(TextDocumentManipulator &manipulator, int basePosition) const override; + void apply(TextEditorWidget *editorWidget, int basePosition) const override; void setIcon(const QIcon &icon); QIcon icon() const final; @@ -37,9 +37,9 @@ public: bool isValid() const final; quint64 hash() const override; - virtual void applyContextualContent(TextDocumentManipulator &manipulator, int basePosition) const; - virtual void applySnippet(TextDocumentManipulator &manipulator, int basePosition) const; - virtual void applyQuickFix(TextDocumentManipulator &manipulator, int basePosition) const; + virtual void applyContextualContent(TextEditorWidget *editorWidget, int basePosition) const; + virtual void applySnippet(TextEditorWidget *editorWidget, int basePosition) const; + virtual void applyQuickFix(TextEditorWidget *editorWidget, int basePosition) const; private: QIcon m_icon; diff --git a/src/plugins/texteditor/codeassist/assistproposaliteminterface.h b/src/plugins/texteditor/codeassist/assistproposaliteminterface.h index 083a8048b64..2492b0e2617 100644 --- a/src/plugins/texteditor/codeassist/assistproposaliteminterface.h +++ b/src/plugins/texteditor/codeassist/assistproposaliteminterface.h @@ -3,7 +3,7 @@ #pragma once -#include "textdocumentmanipulator.h" +#include QT_BEGIN_NAMESPACE class QIcon; @@ -14,6 +14,8 @@ QT_END_NAMESPACE namespace TextEditor { +class TextEditorWidget; + class TEXTEDITOR_EXPORT AssistProposalItemInterface { public: @@ -36,7 +38,7 @@ public: virtual QString filterText() const { return text(); } virtual bool implicitlyApplies() const = 0; virtual bool prematurelyApplies(const QChar &typedCharacter) const = 0; - virtual void apply(TextDocumentManipulator &manipulator, int basePosition) const = 0; + virtual void apply(TextEditorWidget *editorWidget, int basePosition) const = 0; virtual QIcon icon() const = 0; virtual QString detail() const = 0; virtual bool isKeyword() const { return false; } diff --git a/src/plugins/texteditor/codeassist/codeassist_test.cpp b/src/plugins/texteditor/codeassist/codeassist_test.cpp index c1ef339ff30..cd49d6579fc 100644 --- a/src/plugins/texteditor/codeassist/codeassist_test.cpp +++ b/src/plugins/texteditor/codeassist/codeassist_test.cpp @@ -46,7 +46,7 @@ public: class OpenEditorItem final : public TestProposalItem { public: - void apply(TextDocumentManipulator &, int) const final + void apply(TextEditorWidget *, int) const final { m_openedEditor = Core::EditorManager::openEditor(m_filePath, Core::Constants::K_DEFAULT_TEXT_EDITOR_ID); diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp index 0bdf34efaba..ad637631817 100644 --- a/src/plugins/texteditor/codeassist/codeassistant.cpp +++ b/src/plugins/texteditor/codeassist/codeassistant.cpp @@ -9,7 +9,6 @@ #include "iassistproposalwidget.h" #include "assistinterface.h" #include "assistproposalitem.h" -#include "textdocumentmanipulator.h" #include #include @@ -302,8 +301,7 @@ void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistR void CodeAssistantPrivate::processProposalItem(AssistProposalItemInterface *proposalItem) { QTC_ASSERT(m_proposalWidget, return); - TextDocumentManipulator manipulator(m_editorWidget); - proposalItem->apply(manipulator, m_proposalWidget->basePosition()); + proposalItem->apply(m_editorWidget, m_proposalWidget->basePosition()); destroyContext(); m_editorWidget->encourageApply(); if (!proposalItem->isSnippet()) diff --git a/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp b/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp index da6781fe3a9..6e9abb3190b 100644 --- a/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp +++ b/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp @@ -72,20 +72,21 @@ bool KeywordsAssistProposalItem::prematurelyApplies(const QChar &c) const return c == QLatin1Char('(') && m_isFunction; } -void KeywordsAssistProposalItem::applyContextualContent(TextDocumentManipulator &manipulator, +void KeywordsAssistProposalItem::applyContextualContent(TextEditorWidget *editorWidget, int basePosition) const { + QTC_ASSERT(editorWidget, return); const CompletionSettings &settings = TextEditorSettings::completionSettings(); - int replaceLength = manipulator.currentPosition() - basePosition; + int replaceLength = editorWidget->position() - basePosition; QString toInsert = text(); int cursorOffset = 0; - const QChar characterAtCurrentPosition = manipulator.characterAt(manipulator.currentPosition()); + const QChar characterAtCurrentPosition = editorWidget->characterAt(editorWidget->position()); bool setAutoCompleteSkipPosition = false; if (m_isFunction && settings.m_autoInsertBrackets) { if (settings.m_spaceAfterFunctionName) { - if (manipulator.textAt(manipulator.currentPosition(), 2) == QLatin1String(" (")) { + if (editorWidget->textAt(editorWidget->position(), 2) == QLatin1String(" (")) { cursorOffset = 2; } else if ( characterAtCurrentPosition == QLatin1Char('(') || characterAtCurrentPosition == QLatin1Char(' ')) { @@ -107,11 +108,11 @@ void KeywordsAssistProposalItem::applyContextualContent(TextDocumentManipulator } } - manipulator.replace(basePosition, replaceLength, toInsert); + editorWidget->replace(basePosition, replaceLength, toInsert); if (cursorOffset) - manipulator.setCursorPosition(manipulator.currentPosition() + cursorOffset); + editorWidget->setCursorPosition(editorWidget->position() + cursorOffset); if (setAutoCompleteSkipPosition) - manipulator.addAutoCompleteSkipPosition(); + editorWidget->setAutoCompleteSkipPosition(editorWidget->textCursor()); } // ------------------------- diff --git a/src/plugins/texteditor/codeassist/keywordscompletionassist.h b/src/plugins/texteditor/codeassist/keywordscompletionassist.h index a5a29e60ef6..fa22b0790df 100644 --- a/src/plugins/texteditor/codeassist/keywordscompletionassist.h +++ b/src/plugins/texteditor/codeassist/keywordscompletionassist.h @@ -40,7 +40,7 @@ public: KeywordsAssistProposalItem(bool isFunction); bool prematurelyApplies(const QChar &c) const final; - void applyContextualContent(TextDocumentManipulator &manipulator, int basePosition) const final; + void applyContextualContent(TextEditorWidget *editorWidget, int basePosition) const final; private: bool m_isFunction; }; diff --git a/src/plugins/texteditor/codeassist/textdocumentmanipulator.cpp b/src/plugins/texteditor/codeassist/textdocumentmanipulator.cpp deleted file mode 100644 index 36d7a6d27ce..00000000000 --- a/src/plugins/texteditor/codeassist/textdocumentmanipulator.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "textdocumentmanipulator.h" - -#include -#include - -namespace TextEditor { - -TextDocumentManipulator::TextDocumentManipulator(TextEditorWidget *textEditorWidget) - : m_textEditorWidget(textEditorWidget) -{ -} - -int TextDocumentManipulator::currentPosition() const -{ - return m_textEditorWidget->position(); -} - -QChar TextDocumentManipulator::characterAt(int position) const -{ - return m_textEditorWidget->characterAt(position); -} - -QString TextDocumentManipulator::textAt(int position, int length) const -{ - return m_textEditorWidget->textAt(position, length); -} - -QTextCursor TextDocumentManipulator::textCursor() const -{ - return m_textEditorWidget->textCursor(); -} - -QTextCursor TextDocumentManipulator::textCursorAt(int position) const -{ - return m_textEditorWidget->textCursorAt(position); -} - -QTextDocument *TextDocumentManipulator::document() const -{ - return m_textEditorWidget->document(); -} - -TextEditorWidget *TextDocumentManipulator::editor() const -{ - return m_textEditorWidget; -} - -void TextDocumentManipulator::setCursorPosition(int position) -{ - m_textEditorWidget->setCursorPosition(position); -} - -void TextDocumentManipulator::addAutoCompleteSkipPosition() -{ - m_textEditorWidget->setAutoCompleteSkipPosition(m_textEditorWidget->textCursor()); -} - -void TextDocumentManipulator::replace(int position, int length, const QString &text) -{ - m_textEditorWidget->replace(position, length, text); -} - -void TextDocumentManipulator::insertCodeSnippet(int position, - const QString &text, - const SnippetParser &parse) -{ - m_textEditorWidget->insertCodeSnippet(position, text, parse); -} - -QString TextDocumentManipulator::getLine(int line) const -{ - return m_textEditorWidget->textDocument()->blockText(line - 1); -} - -Utils::Text::Position TextDocumentManipulator::cursorPos() const -{ - return m_textEditorWidget->lineColumn(); -} - -} // namespace TextEditor diff --git a/src/plugins/texteditor/codeassist/textdocumentmanipulator.h b/src/plugins/texteditor/codeassist/textdocumentmanipulator.h deleted file mode 100644 index 4f045b92185..00000000000 --- a/src/plugins/texteditor/codeassist/textdocumentmanipulator.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include -#include - -#include - -QT_BEGIN_NAMESPACE -class QChar; -class QString; -class QTextCursor; -QT_END_NAMESPACE - -namespace TextEditor { - -class TextEditorWidget; - -class TEXTEDITOR_EXPORT TextDocumentManipulator -{ -public: - TextDocumentManipulator(TextEditorWidget *textEditorWidget); - - int currentPosition() const; - QChar characterAt(int position) const; - QString textAt(int position, int length) const; - QTextCursor textCursor() const; - QTextCursor textCursorAt(int position) const; - QTextDocument *document() const; - TextEditorWidget *editor() const; - - void setCursorPosition(int position); - void addAutoCompleteSkipPosition(); - void replace(int position, int length, const QString &text); - void insertCodeSnippet(int position, const QString &text, const SnippetParser &parse); - - QString getLine(int line) const; - - Utils::Text::Position cursorPos() const; - -private: - bool textIsDifferentAt(int position, int length, const QString &text) const; - void replaceWithoutCheck(int position, int length, const QString &text); - -private: - TextEditorWidget *m_textEditorWidget; -}; - -} // namespace TextEditor diff --git a/src/plugins/texteditor/snippets/snippetassistcollector.cpp b/src/plugins/texteditor/snippets/snippetassistcollector.cpp index e98aa41dd94..f48ecd19bfc 100644 --- a/src/plugins/texteditor/snippets/snippetassistcollector.cpp +++ b/src/plugins/texteditor/snippets/snippetassistcollector.cpp @@ -5,6 +5,7 @@ #include "snippetscollection.h" #include +#include #include using namespace TextEditor; @@ -24,9 +25,10 @@ public: } bool implicitlyApplies() const override { return false; } bool prematurelyApplies(const QChar &) const override { return false; } - void apply(TextDocumentManipulator &manipulator, int basePosition) const override + void apply(TextEditorWidget *editorWidget, int basePosition) const override { - manipulator.insertCodeSnippet(basePosition, m_snippet.content(), &Snippet::parse); + QTC_ASSERT(editorWidget, return); + editorWidget->insertCodeSnippet(basePosition, m_snippet.content(), &Snippet::parse); } QIcon icon() const override { return m_icon; } QString detail() const override { return m_snippet.generateTip(); } diff --git a/src/plugins/texteditor/texteditor.qbs b/src/plugins/texteditor/texteditor.qbs index 0646d1f9eca..d0d0a020799 100644 --- a/src/plugins/texteditor/texteditor.qbs +++ b/src/plugins/texteditor/texteditor.qbs @@ -197,8 +197,6 @@ QtcPlugin { "ifunctionhintproposalmodel.h", "keywordscompletionassist.cpp", "keywordscompletionassist.h", - "textdocumentmanipulator.cpp", - "textdocumentmanipulator.h", ] }