diff options
author | David Schulz <[email protected]> | 2024-06-28 08:35:40 +0200 |
---|---|---|
committer | David Schulz <[email protected]> | 2024-07-01 11:49:02 +0000 |
commit | 9ad0a5a6419b4c8a8cc29370967a37d1b31e6417 (patch) | |
tree | 02b46384333082f708e460bf19d69b3ac503c5f2 /src/plugins | |
parent | f09a694cfcfac9a52deb57c2a95778f491c7897d (diff) |
Editor: reduce complexity of TextDocumentManipulator
Move implementations either to the TextEditorWidget, TextDocument, or to
the caller side. This makes the TextDocumentManipulator basically a
repeater so we can easily replace it with a TextEditorWidget in the
next step.
Change-Id: I04de3cb295b56fbaae99145f8e579fe405b065a5
Reviewed-by: Christian Kandeler <[email protected]>
Diffstat (limited to 'src/plugins')
15 files changed, 92 insertions, 115 deletions
diff --git a/src/plugins/clangcodemodel/clangdcompletion.cpp b/src/plugins/clangcodemodel/clangdcompletion.cpp index 0f0f716eab0..bc7b19a8ea5 100644 --- a/src/plugins/clangcodemodel/clangdcompletion.cpp +++ b/src/plugins/clangcodemodel/clangdcompletion.cpp @@ -288,7 +288,7 @@ void ClangdCompletionItem::apply(TextDocumentManipulator &manipulator, int cursorOffset = 0; bool setAutoCompleteSkipPos = false; int currentPos = manipulator.currentPosition(); - const QTextDocument * const doc = manipulator.textCursorAt(currentPos).document(); + const QTextDocument * const doc = manipulator.document(); const Range range = edit->range(); const int rangeStart = range.start().toPositionInDocument(doc); if (isFunctionLike && completionSettings.m_autoInsertBrackets) { @@ -383,13 +383,14 @@ void ClangdCompletionItem::apply(TextDocumentManipulator &manipulator, textToBeInserted += extraCharacters; const int length = currentPos - rangeStart + extraLength; - const bool isReplaced = manipulator.replace(rangeStart, length, textToBeInserted); + const int oldRevision = manipulator.document()->revision(); + manipulator.replace(rangeStart, length, textToBeInserted); manipulator.setCursorPosition(rangeStart + textToBeInserted.length()); - if (isReplaced) { + if (manipulator.document()->revision() != oldRevision) { if (cursorOffset) manipulator.setCursorPosition(manipulator.currentPosition() + cursorOffset); if (setAutoCompleteSkipPos) - manipulator.setAutoCompleteSkipPosition(manipulator.currentPosition()); + manipulator.addAutoCompleteSkipPosition(); } if (auto additionalEdits = item.additionalTextEdits()) { diff --git a/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp index 856d1336ad7..2ad430a2a5a 100644 --- a/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp +++ b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp @@ -51,8 +51,9 @@ void ClangPreprocessorAssistProposalItem::apply(TextEditor::TextDocumentManipula extraCharacters += m_typedCharacter; // Avoid inserting characters that are already there - const int endsPosition = manipulator.positionAt(TextEditor::EndOfLinePosition); - const QString existingText = manipulator.textAt(manipulator.currentPosition(), endsPosition - manipulator.currentPosition()); + QTextCursor c = manipulator.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 diff --git a/src/plugins/clangcodemodel/test/clangdtests.cpp b/src/plugins/clangcodemodel/test/clangdtests.cpp index fb0975f2fa4..719cfba93a1 100644 --- a/src/plugins/clangcodemodel/test/clangdtests.cpp +++ b/src/plugins/clangcodemodel/test/clangdtests.cpp @@ -1659,7 +1659,7 @@ void ClangdTestCompletion::testCompleteGlobals() item->apply(manipulator, cursorPos); QCOMPARE(manipulator.getLine(7), " globalFunction() /* COMPLETE HERE */"); QCOMPARE(manipulator.cursorPos(), Text::Position({7, 19})); - QCOMPARE(manipulator.skipPos(), -1); + QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testCompleteMembers() @@ -1679,7 +1679,7 @@ void ClangdTestCompletion::testCompleteMembers() item->apply(manipulator, cursorPos); QCOMPARE(manipulator.getLine(7), " s.member /* COMPLETE HERE */"); QCOMPARE(manipulator.cursorPos(), Text::Position({7, 12})); - QCOMPARE(manipulator.skipPos(), -1); + QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testCompleteMembersFromInside() @@ -1697,7 +1697,7 @@ void ClangdTestCompletion::testCompleteMembersFromInside() item->apply(manipulator, cursorPos); QCOMPARE(manipulator.getLine(4), " privateFunc() /* COMPLETE HERE */"); QCOMPARE(manipulator.cursorPos(), Text::Position({4, 21})); - QCOMPARE(manipulator.skipPos(), -1); + QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testCompleteMembersFromOutside() @@ -1715,7 +1715,7 @@ void ClangdTestCompletion::testCompleteMembersFromOutside() item->apply(manipulator, cursorPos); QCOMPARE(manipulator.getLine(13), " c.publicFunc() /* COMPLETE HERE */"); QCOMPARE(manipulator.cursorPos(), Text::Position({13, 18})); - QCOMPARE(manipulator.skipPos(), -1); + QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testCompleteMembersFromFriend() @@ -1733,7 +1733,7 @@ void ClangdTestCompletion::testCompleteMembersFromFriend() item->apply(manipulator, cursorPos); QCOMPARE(manipulator.getLine(14), " C().privateFunc() /* COMPLETE HERE */"); QCOMPARE(manipulator.cursorPos(), Text::Position({14, 21})); - QCOMPARE(manipulator.skipPos(), -1); + QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testFunctionAddress() @@ -1750,7 +1750,7 @@ void ClangdTestCompletion::testFunctionAddress() item->apply(manipulator, cursorPos); QCOMPARE(manipulator.getLine(7), " const auto p = &S::memberFunc /* COMPLETE HERE */;"); QCOMPARE(manipulator.cursorPos(), Text::Position({7, 33})); - QCOMPARE(manipulator.skipPos(), -1); + QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testFunctionHints() @@ -1814,7 +1814,7 @@ void ClangdTestCompletion::testCompleteClassAndConstructor() item->apply(manipulator, cursorPos); QCOMPARE(manipulator.getLine(7), " Foo( /* COMPLETE HERE */"); QCOMPARE(manipulator.cursorPos(), Text::Position({7, 8})); - QCOMPARE(manipulator.skipPos(), -1); + QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testCompletePrivateFunctionDefinition() @@ -1841,7 +1841,7 @@ void ClangdTestCompletion::testCompleteWithDotToArrowCorrection() item->apply(manipulator, cursorPos); QCOMPARE(manipulator.getLine(4), " bar->member /* COMPLETE HERE */"); QCOMPARE(manipulator.cursorPos(), Text::Position({4, 15})); - QCOMPARE(manipulator.skipPos(), -1); + QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testDontCompleteWithDotToArrowCorrectionForFloats() @@ -1872,7 +1872,7 @@ void ClangdTestCompletion::testCompleteCodeInGeneratedUiFile() item->apply(manipulator, cursorPos); QCOMPARE(manipulator.getLine(34), " ui->setupUi( /* COMPLETE HERE */"); QCOMPARE(manipulator.cursorPos(), Text::Position({34, 16})); - QCOMPARE(manipulator.skipPos(), -1); + QVERIFY(manipulator.editor()->autoCompleteHighlightPositions().isEmpty()); } void ClangdTestCompletion::testSignalCompletion_data() diff --git a/src/plugins/cppeditor/cppcompletionassist.cpp b/src/plugins/cppeditor/cppcompletionassist.cpp index f94a44de425..bbb94ee3d19 100644 --- a/src/plugins/cppeditor/cppcompletionassist.cpp +++ b/src/plugins/cppeditor/cppcompletionassist.cpp @@ -322,7 +322,7 @@ void CppAssistProposalItem::applyContextualContent(TextDocumentManipulator &mani if (cursorOffset) manipulator.setCursorPosition(manipulator.currentPosition() + cursorOffset); if (setAutoCompleteSkipPos) - manipulator.setAutoCompleteSkipPosition(manipulator.currentPosition()); + manipulator.addAutoCompleteSkipPosition(); } // -------------------- diff --git a/src/plugins/languageclient/languageclientutils.cpp b/src/plugins/languageclient/languageclientutils.cpp index 1572243b782..561d91a4b1a 100644 --- a/src/plugins/languageclient/languageclientutils.cpp +++ b/src/plugins/languageclient/languageclientutils.cpp @@ -105,7 +105,7 @@ void applyTextEdit(TextDocumentManipulator &manipulator, bool newTextIsSnippet) { const Range range = edit.range(); - const QTextDocument *doc = manipulator.textCursorAt(manipulator.currentPosition()).document(); + const QTextDocument *doc = manipulator.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) { diff --git a/src/plugins/qmljseditor/qmljscompletionassist.cpp b/src/plugins/qmljseditor/qmljscompletionassist.cpp index 60fb80028e7..10803a7d7ed 100644 --- a/src/plugins/qmljseditor/qmljscompletionassist.cpp +++ b/src/plugins/qmljseditor/qmljscompletionassist.cpp @@ -388,7 +388,7 @@ void QmlJSAssistProposalItem::applyContextualContent(TextEditor::TextDocumentMan manipulator.replace(basePosition, length, content); if (cursorOffset) { manipulator.setCursorPosition(manipulator.currentPosition() + cursorOffset); - manipulator.setAutoCompleteSkipPosition(manipulator.currentPosition()); + manipulator.addAutoCompleteSkipPosition(); } } diff --git a/src/plugins/texteditor/circularclipboardassist.cpp b/src/plugins/texteditor/circularclipboardassist.cpp index 44b53c96e86..25c62f10d18 100644 --- a/src/plugins/texteditor/circularclipboardassist.cpp +++ b/src/plugins/texteditor/circularclipboardassist.cpp @@ -51,7 +51,7 @@ public: TextEditorWidget::duplicateMimeData(m_mimeData.get())); //Paste - manipulator.paste(); + manipulator.editor()->paste(); } private: diff --git a/src/plugins/texteditor/codeassist/assistproposalitem.cpp b/src/plugins/texteditor/codeassist/assistproposalitem.cpp index 8b494ba6f0e..abade26cec2 100644 --- a/src/plugins/texteditor/codeassist/assistproposalitem.cpp +++ b/src/plugins/texteditor/codeassist/assistproposalitem.cpp @@ -113,7 +113,7 @@ void AssistProposalItem::apply(TextDocumentManipulator &manipulator, int basePos applyQuickFix(manipulator, basePosition); } else { applyContextualContent(manipulator, basePosition); - manipulator.encourageApply(); + manipulator.editor()->encourageApply(); } } diff --git a/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp b/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp index 1f3e61650c0..da6781fe3a9 100644 --- a/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp +++ b/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp @@ -111,7 +111,7 @@ void KeywordsAssistProposalItem::applyContextualContent(TextDocumentManipulator if (cursorOffset) manipulator.setCursorPosition(manipulator.currentPosition() + cursorOffset); if (setAutoCompleteSkipPosition) - manipulator.setAutoCompleteSkipPosition(manipulator.currentPosition()); + manipulator.addAutoCompleteSkipPosition(); } // ------------------------- diff --git a/src/plugins/texteditor/codeassist/textdocumentmanipulator.cpp b/src/plugins/texteditor/codeassist/textdocumentmanipulator.cpp index e6f0284fec3..36d7a6d27ce 100644 --- a/src/plugins/texteditor/codeassist/textdocumentmanipulator.cpp +++ b/src/plugins/texteditor/codeassist/textdocumentmanipulator.cpp @@ -18,11 +18,6 @@ int TextDocumentManipulator::currentPosition() const return m_textEditorWidget->position(); } -int TextDocumentManipulator::positionAt(TextPositionOperation textPositionOperation) const -{ - return m_textEditorWidget->position(textPositionOperation); -} - QChar TextDocumentManipulator::characterAt(int position) const { return m_textEditorWidget->characterAt(position); @@ -33,114 +28,56 @@ QString TextDocumentManipulator::textAt(int position, int length) const return m_textEditorWidget->textAt(position, length); } -QTextCursor TextDocumentManipulator::textCursorAt(int position) const -{ - auto cursor = m_textEditorWidget->textCursor(); - cursor.setPosition(position); - - return cursor; -} - -void TextDocumentManipulator::setCursorPosition(int position) +QTextCursor TextDocumentManipulator::textCursor() const { - m_textEditorWidget->setCursorPosition(position); + return m_textEditorWidget->textCursor(); } -void TextDocumentManipulator::setAutoCompleteSkipPosition(int position) +QTextCursor TextDocumentManipulator::textCursorAt(int position) const { - QTextCursor cursor = m_textEditorWidget->textCursor(); - cursor.setPosition(position); - m_textEditorWidget->setAutoCompleteSkipPosition(cursor); + return m_textEditorWidget->textCursorAt(position); } -bool TextDocumentManipulator::replace(int position, int length, const QString &text) +QTextDocument *TextDocumentManipulator::document() const { - bool textWillBeReplaced = textIsDifferentAt(position, length, text); - - if (textWillBeReplaced) - replaceWithoutCheck(position, length, text); - - return textWillBeReplaced; + return m_textEditorWidget->document(); } -void TextDocumentManipulator::insertCodeSnippet(int position, - const QString &text, - const SnippetParser &parse) +TextEditorWidget *TextDocumentManipulator::editor() const { - auto cursor = m_textEditorWidget->textCursor(); - cursor.setPosition(position, QTextCursor::KeepAnchor); - m_textEditorWidget->insertCodeSnippet(cursor, text, parse); + return m_textEditorWidget; } -void TextDocumentManipulator::paste() +void TextDocumentManipulator::setCursorPosition(int position) { - m_textEditorWidget->paste(); + m_textEditorWidget->setCursorPosition(position); } -void TextDocumentManipulator::encourageApply() +void TextDocumentManipulator::addAutoCompleteSkipPosition() { - m_textEditorWidget->encourageApply(); + m_textEditorWidget->setAutoCompleteSkipPosition(m_textEditorWidget->textCursor()); } -namespace { - -bool hasOnlyBlanksBeforeCursorInLine(QTextCursor textCursor) +void TextDocumentManipulator::replace(int position, int length, const QString &text) { - textCursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); - - const auto textBeforeCursor = textCursor.selectedText(); - - const auto nonSpace = std::find_if(textBeforeCursor.cbegin(), - textBeforeCursor.cend(), - [] (const QChar &signBeforeCursor) { - return !signBeforeCursor.isSpace(); - }); - - return nonSpace == textBeforeCursor.cend(); -} - + m_textEditorWidget->replace(position, length, text); } -void TextDocumentManipulator::autoIndent(int position, int length) +void TextDocumentManipulator::insertCodeSnippet(int position, + const QString &text, + const SnippetParser &parse) { - auto cursor = m_textEditorWidget->textCursor(); - cursor.setPosition(position); - if (hasOnlyBlanksBeforeCursorInLine(cursor)) { - cursor.setPosition(position + length, QTextCursor::KeepAnchor); - - m_textEditorWidget->textDocument()->autoIndent(cursor); - } + m_textEditorWidget->insertCodeSnippet(position, text, parse); } QString TextDocumentManipulator::getLine(int line) const { - return m_textEditorWidget->document()->findBlockByNumber(line - 1).text(); + return m_textEditorWidget->textDocument()->blockText(line - 1); } Utils::Text::Position TextDocumentManipulator::cursorPos() const { - return Utils::Text::Position::fromCursor(m_textEditorWidget->textCursor()); -} - -int TextDocumentManipulator::skipPos() const -{ - const QList<QTextCursor> highlights = m_textEditorWidget->autoCompleteHighlightPositions(); - return highlights.isEmpty() ? -1 : highlights.first().position(); -} - -bool TextDocumentManipulator::textIsDifferentAt(int position, int length, const QString &text) const -{ - const auto textToBeReplaced = m_textEditorWidget->textAt(position, length); - - return text != textToBeReplaced; -} - -void TextDocumentManipulator::replaceWithoutCheck(int position, int length, const QString &text) -{ - auto cursor = m_textEditorWidget->textCursor(); - cursor.setPosition(position); - cursor.setPosition(position + length, QTextCursor::KeepAnchor); - cursor.insertText(text); + return m_textEditorWidget->lineColumn(); } } // namespace TextEditor diff --git a/src/plugins/texteditor/codeassist/textdocumentmanipulator.h b/src/plugins/texteditor/codeassist/textdocumentmanipulator.h index 6e6e553dec0..4f045b92185 100644 --- a/src/plugins/texteditor/codeassist/textdocumentmanipulator.h +++ b/src/plugins/texteditor/codeassist/textdocumentmanipulator.h @@ -24,25 +24,22 @@ public: TextDocumentManipulator(TextEditorWidget *textEditorWidget); int currentPosition() const; - int positionAt(TextPositionOperation textPositionOperation) 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 setAutoCompleteSkipPosition(int position); - bool replace(int position, int length, const QString &text); + void addAutoCompleteSkipPosition(); + void replace(int position, int length, const QString &text); void insertCodeSnippet(int position, const QString &text, const SnippetParser &parse); - void paste(); - void encourageApply(); - void autoIndent(int position, int length); QString getLine(int line) const; Utils::Text::Position cursorPos() const; - int skipPos() const; - private: bool textIsDifferentAt(int position, int length, const QString &text) const; void replaceWithoutCheck(int position, int length, const QString &text); diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index 835a3a88114..79c0d3ff8ab 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -340,6 +340,11 @@ QChar TextDocument::characterAt(int pos) const return document()->characterAt(pos); } +QString TextDocument::blockText(int blockNumber) const +{ + return document()->findBlockByNumber(blockNumber).text(); +} + void TextDocument::setTypingSettings(const TypingSettings &typingSettings) { d->m_typingSettings = typingSettings; diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h index f5ffec7aa0e..f08d18f2456 100644 --- a/src/plugins/texteditor/textdocument.h +++ b/src/plugins/texteditor/textdocument.h @@ -59,6 +59,7 @@ public: virtual QString plainText() const; virtual QString textAt(int pos, int length) const; virtual QChar characterAt(int pos) const; + QString blockText(int blockNumber) const; void setTypingSettings(const TypingSettings &typingSettings); void setStorageSettings(const StorageSettings &storageSettings); diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index c3b2ff72151..0834b621ba1 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -3226,7 +3226,7 @@ public: QTextCursor cursor; }; -void TextEditorWidget::insertCodeSnippet(const QTextCursor &cursor_arg, +void TextEditorWidget::insertCodeSnippet(int basePosition, const QString &snippet, const SnippetParser &parse) { @@ -3239,7 +3239,8 @@ void TextEditorWidget::insertCodeSnippet(const QTextCursor &cursor_arg, QTC_ASSERT(std::holds_alternative<ParsedSnippet>(result), return); ParsedSnippet data = std::get<ParsedSnippet>(result); - QTextCursor cursor = cursor_arg; + QTextCursor cursor = textCursor(); + cursor.setPosition(basePosition, QTextCursor::KeepAnchor); cursor.beginEditBlock(); cursor.removeSelectedText(); const int startCursorPosition = cursor.position(); @@ -3433,6 +3434,18 @@ int TextEditorWidget::position(TextPositionOperation posOp, int at) const return -1; } +QTextCursor TextEditorWidget::textCursorAt(int position) const +{ + QTextCursor c = textCursor(); + c.setPosition(position); + return c; +} + +Text::Position TextEditorWidget::lineColumn() const +{ + return Utils::Text::Position::fromCursor(textCursor()); +} + QRect TextEditorWidget::cursorRect(int pos) const { QTextCursor tc = textCursor(); @@ -9583,6 +9596,22 @@ void TextEditorWidget::replace(int length, const QString &string) tc.insertText(string); } +void TextEditorWidget::replace(int pos, int length, const QString &string) +{ + if (length == string.length()) { + bool different = false; + for (int i = 0; !different && pos < length; ++i) + different = document()->characterAt(pos) != string.at(i); + if (!different) + return; + } + + QTextCursor tc = textCursor(); + tc.setPosition(pos); + tc.setPosition(pos + length, QTextCursor::KeepAnchor); + tc.insertText(string); +} + void BaseTextEditor::setCursorPosition(int pos) { editorWidget()->setCursorPosition(pos); diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h index defd96f42d7..9e2fe41dfbd 100644 --- a/src/plugins/texteditor/texteditor.h +++ b/src/plugins/texteditor/texteditor.h @@ -18,6 +18,7 @@ #include <utils/elidinglabel.h> #include <utils/link.h> #include <utils/multitextcursor.h> +#include <utils/textutils.h> #include <utils/uncommentselection.h> #include <QPlainTextEdit> @@ -196,6 +197,8 @@ public: void gotoLine(int line, int column = 0, bool centerLine = true, bool animate = false); int position(TextPositionOperation posOp = CurrentPosition, int at = -1) const; + QTextCursor textCursorAt(int position) const; + Utils::Text::Position lineColumn() const; void convertPosition(int pos, int *line, int *column) const; using QPlainTextEdit::cursorRect; QRect cursorRect(int pos) const; @@ -268,7 +271,9 @@ public: void setReadOnly(bool b); - void insertCodeSnippet(const QTextCursor &cursor, + // replaces the text from the current cursor position to the base position with the snippet + // and starts the snippet replacement mode + void insertCodeSnippet(int basePosition, const QString &snippet, const SnippetParser &parse); @@ -609,6 +614,7 @@ public: void remove(int length); void replace(int length, const QString &string); + void replace(int pos, int length, const QString &string); QChar characterAt(int pos) const; QString textAt(int from, int to) const; |