Editor: Simplify TextDocumentManipulator

The TextDocumentManipulatorInterface was introduced to decouple
modification operations from QTextDocument. But nowadays all tests and
production code usages are backed by a QTextDocument, so we can remove
this abstraction layer again. The first step is to merge the interface
and all manipulator implementations.

Change-Id: Idd1609df549d3b120dd516d5161af9aa8aa571ca
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
David Schulz
2024-06-26 12:38:17 +02:00
parent ef3a4fd9e3
commit 39a448c62e
32 changed files with 113 additions and 193 deletions

View File

@@ -54,7 +54,7 @@
#include <texteditor/codeassist/assistinterface.h>
#include <texteditor/codeassist/iassistprocessor.h>
#include <texteditor/codeassist/iassistprovider.h>
#include <texteditor/codeassist/textdocumentmanipulatorinterface.h>
#include <texteditor/codeassist/textdocumentmanipulator.h>
#include <texteditor/texteditor.h>
#include <utils/algorithm.h>
#include <utils/async.h>

View File

@@ -74,8 +74,7 @@ class ClangdCompletionItem : public LanguageClientCompletionItem
{
public:
using LanguageClientCompletionItem::LanguageClientCompletionItem;
void apply(TextDocumentManipulatorInterface &manipulator,
int basePosition) const override;
void apply(TextDocumentManipulator &manipulator, int basePosition) const override;
enum class SpecialQtType { Signal, Slot, None };
static SpecialQtType getQtType(const CompletionItem &item);
@@ -247,7 +246,7 @@ bool ClangdCompletionAssistProvider::isInCommentOrString(const AssistInterface *
return CppEditor::isInCommentOrString(interface, features);
}
void ClangdCompletionItem::apply(TextDocumentManipulatorInterface &manipulator,
void ClangdCompletionItem::apply(TextDocumentManipulator &manipulator,
int /*basePosition*/) const
{
const CompletionItem item = this->item();

View File

@@ -28,7 +28,7 @@ bool ClangPreprocessorAssistProposalItem::implicitlyApplies() const
return true;
}
void ClangPreprocessorAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface &manipulator,
void ClangPreprocessorAssistProposalItem::apply(TextEditor::TextDocumentManipulator &manipulator,
int basePosition) const
{
// TODO move in an extra class under tests

View File

@@ -17,8 +17,7 @@ public:
~ClangPreprocessorAssistProposalItem() noexcept override = default;
bool prematurelyApplies(const QChar &typedChar) const final;
bool implicitlyApplies() const final;
void apply(TextEditor::TextDocumentManipulatorInterface &manipulator,
int basePosition) const final;
void apply(TextEditor::TextDocumentManipulator &manipulator, int basePosition) const final;
void setText(const QString &text);
QString text() const final;

View File

@@ -20,7 +20,7 @@
#include <projectexplorer/kitaspects.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
#include <texteditor/codeassist/textdocumentmanipulatorinterface.h>
#include <texteditor/codeassist/textdocumentmanipulator.h>
#include <cplusplus/SimpleLexer.h>
#include <utils/algorithm.h>
@@ -303,8 +303,7 @@ const QStringList globalClangOptions()
}
// 7.3.3: using typename(opt) nested-name-specifier unqualified-id ;
bool isAtUsingDeclaration(TextEditor::TextDocumentManipulatorInterface &manipulator,
int basePosition)
bool isAtUsingDeclaration(TextEditor::TextDocumentManipulator &manipulator, int basePosition)
{
using namespace CPlusPlus;
SimpleLexer lexer;
@@ -322,7 +321,7 @@ bool isAtUsingDeclaration(TextEditor::TextDocumentManipulatorInterface &manipula
return contains(tokens, [](const Token &token) { return token.kind() == T_USING; });
}
QString textUntilPreviousStatement(TextEditor::TextDocumentManipulatorInterface &manipulator,
QString textUntilPreviousStatement(TextEditor::TextDocumentManipulator &manipulator,
int startPosition)
{
static const QString stopCharacters(";{}#");

View File

@@ -22,7 +22,7 @@ class ClangDiagnosticConfig;
class CppEditorDocumentHandle;
}
namespace TextEditor { class TextDocumentManipulatorInterface; }
namespace TextEditor { class TextDocumentManipulator; }
namespace ProjectExplorer { class Project; }
@@ -126,11 +126,10 @@ bool matchPreviousWord(const CharacterProvider &provider, QTextCursor cursor, QS
return pattern.isEmpty();
}
QString textUntilPreviousStatement(TextEditor::TextDocumentManipulatorInterface &manipulator,
int startPosition);
QString textUntilPreviousStatement(
TextEditor::TextDocumentManipulator &manipulator, int startPosition);
bool isAtUsingDeclaration(TextEditor::TextDocumentManipulatorInterface &manipulator,
int basePosition);
bool isAtUsingDeclaration(TextEditor::TextDocumentManipulator &manipulator, int basePosition);
class ClangSourceRange
{

View File

@@ -30,7 +30,7 @@
#include <texteditor/codeassist/assistproposaliteminterface.h>
#include <texteditor/codeassist/genericproposal.h>
#include <texteditor/codeassist/ifunctionhintproposalmodel.h>
#include <texteditor/codeassist/textdocumentmanipulatorinterface.h>
#include <texteditor/codeassist/textdocumentmanipulator.h>
#include <texteditor/semantichighlighter.h>
#include <texteditor/textmark.h>
@@ -1530,76 +1530,6 @@ void ClangdTestHighlighting::testIfdefedOutBlocks()
}
class Manipulator final : public TextDocumentManipulatorInterface
{
public:
Manipulator()
{
const auto textEditor = static_cast<BaseTextEditor *>(EditorManager::currentEditor());
QVERIFY(textEditor);
m_doc = textEditor->textDocument()->document();
m_cursor = textEditor->editorWidget()->textCursor();
}
int currentPosition() const override { return m_cursor.position(); }
int positionAt(TextPositionOperation) const override { return 0; }
QChar characterAt(int position) const override { return m_doc->characterAt(position); }
QString textAt(int position, int length) const override
{
return m_doc->toPlainText().mid(position, length);
}
QTextCursor textCursorAt(int position) const override
{
QTextCursor cursor(m_doc);
cursor.setPosition(position);
return cursor;
}
void setCursorPosition(int position) override { m_cursor.setPosition(position); }
void setAutoCompleteSkipPosition(int position) override { m_skipPos = position; }
bool replace(int position, int length, const QString &text) override
{
QTextCursor cursor = textCursorAt(position);
cursor.setPosition(position + length, QTextCursor::KeepAnchor);
cursor.insertText(text);
return true;
}
void insertCodeSnippet(int pos, const QString &text, const SnippetParser &parser) override
{
const auto parseResult = parser(text);
if (const auto snippet = std::get_if<ParsedSnippet>(&parseResult)) {
if (!snippet->parts.isEmpty())
textCursorAt(pos).insertText(snippet->parts.first().text);
}
}
void paste() override {}
void encourageApply() override {}
void autoIndent(int, int) override {}
QString getLine(int line) const { return m_doc->findBlockByNumber(line - 1).text(); }
QPair<int, int> cursorPos() const
{
const int pos = currentPosition();
QPair<int, int> lineAndColumn;
Text::convertPosition(m_doc, pos, &lineAndColumn.first, &lineAndColumn.second);
return lineAndColumn;
}
int skipPos() const { return m_skipPos; }
private:
QTextDocument *m_doc;
QTextCursor m_cursor;
int m_skipPos = -1;
};
class ClangdTestCompletion final : public ClangdTest
{
Q_OBJECT
@@ -1723,10 +1653,10 @@ void ClangdTestCompletion::testCompleteGlobals()
const AssistProposalItemInterface * const item = getItem(proposal, " globalFunction()", "void");
QVERIFY(item);
Manipulator manipulator;
TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget());
item->apply(manipulator, cursorPos);
QCOMPARE(manipulator.getLine(7), " globalFunction() /* COMPLETE HERE */");
QCOMPARE(manipulator.cursorPos(), qMakePair(7, 19));
QCOMPARE(manipulator.cursorPos(), Text::Position(7, 19));
QCOMPARE(manipulator.skipPos(), -1);
}
@@ -1743,10 +1673,10 @@ void ClangdTestCompletion::testCompleteMembers()
const AssistProposalItemInterface * const item = getItem(proposal, " member", "int");
QVERIFY(item);
Manipulator manipulator;
TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget());
item->apply(manipulator, cursorPos);
QCOMPARE(manipulator.getLine(7), " s.member /* COMPLETE HERE */");
QCOMPARE(manipulator.cursorPos(), qMakePair(7, 12));
QCOMPARE(manipulator.cursorPos(), Text::Position(7, 12));
QCOMPARE(manipulator.skipPos(), -1);
}
@@ -1761,10 +1691,10 @@ void ClangdTestCompletion::testCompleteMembersFromInside()
const AssistProposalItemInterface * const item = getItem(proposal, " privateFunc()", "void");
QVERIFY(item);
Manipulator manipulator;
TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget());
item->apply(manipulator, cursorPos);
QCOMPARE(manipulator.getLine(4), " privateFunc() /* COMPLETE HERE */");
QCOMPARE(manipulator.cursorPos(), qMakePair(4, 21));
QCOMPARE(manipulator.cursorPos(), Text::Position(4, 21));
QCOMPARE(manipulator.skipPos(), -1);
}
@@ -1779,10 +1709,10 @@ void ClangdTestCompletion::testCompleteMembersFromOutside()
const AssistProposalItemInterface * const item = getItem(proposal, " publicFunc()", "void");
QVERIFY(item);
Manipulator manipulator;
TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget());
item->apply(manipulator, cursorPos);
QCOMPARE(manipulator.getLine(13), " c.publicFunc() /* COMPLETE HERE */");
QCOMPARE(manipulator.cursorPos(), qMakePair(13, 18));
QCOMPARE(manipulator.cursorPos(), Text::Position(13, 18));
QCOMPARE(manipulator.skipPos(), -1);
}
@@ -1797,10 +1727,10 @@ void ClangdTestCompletion::testCompleteMembersFromFriend()
const AssistProposalItemInterface * const item = getItem(proposal, " privateFunc()", "void");
QVERIFY(item);
Manipulator manipulator;
TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget());
item->apply(manipulator, cursorPos);
QCOMPARE(manipulator.getLine(14), " C().privateFunc() /* COMPLETE HERE */");
QCOMPARE(manipulator.cursorPos(), qMakePair(14, 21));
QCOMPARE(manipulator.cursorPos(), Text::Position(14, 21));
QCOMPARE(manipulator.skipPos(), -1);
}
@@ -1814,10 +1744,10 @@ void ClangdTestCompletion::testFunctionAddress()
const AssistProposalItemInterface * const item = getItem(proposal, " memberFunc()", "void");
QVERIFY(item);
Manipulator manipulator;
TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget());
item->apply(manipulator, cursorPos);
QCOMPARE(manipulator.getLine(7), " const auto p = &S::memberFunc /* COMPLETE HERE */;");
QCOMPARE(manipulator.cursorPos(), qMakePair(7, 33));
QCOMPARE(manipulator.cursorPos(), Text::Position(7, 33));
QCOMPARE(manipulator.skipPos(), -1);
}
@@ -1878,10 +1808,10 @@ void ClangdTestCompletion::testCompleteClassAndConstructor()
const AssistProposalItemInterface * const item
= getItem(proposal, QString::fromUtf8(" Foo(…)"), "[2 overloads]");
QVERIFY(item);
Manipulator manipulator;
TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget());
item->apply(manipulator, cursorPos);
QCOMPARE(manipulator.getLine(7), " Foo( /* COMPLETE HERE */");
QCOMPARE(manipulator.cursorPos(), qMakePair(7, 8));
QCOMPARE(manipulator.cursorPos(), Text::Position(7, 8));
QCOMPARE(manipulator.skipPos(), -1);
}
@@ -1905,10 +1835,10 @@ void ClangdTestCompletion::testCompleteWithDotToArrowCorrection()
QVERIFY(proposal);
const AssistProposalItemInterface * const item = getItem(proposal, " member", "int");
QVERIFY(item);
Manipulator manipulator;
TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget());
item->apply(manipulator, cursorPos);
QCOMPARE(manipulator.getLine(4), " bar->member /* COMPLETE HERE */");
QCOMPARE(manipulator.cursorPos(), qMakePair(4, 15));
QCOMPARE(manipulator.cursorPos(), Text::Position(4, 15));
QCOMPARE(manipulator.skipPos(), -1);
}
@@ -1936,10 +1866,10 @@ void ClangdTestCompletion::testCompleteCodeInGeneratedUiFile()
const AssistProposalItemInterface * const item = getItem(
proposal, " setupUi(QMainWindow *MainWindow)", "void");
QVERIFY(item);
Manipulator manipulator;
TextDocumentManipulator manipulator(TextEditorWidget::currentTextEditorWidget());
item->apply(manipulator, cursorPos);
QCOMPARE(manipulator.getLine(34), " ui->setupUi( /* COMPLETE HERE */");
QCOMPARE(manipulator.cursorPos(), qMakePair(34, 16));
QCOMPARE(manipulator.cursorPos(), Text::Position(34, 16));
QCOMPARE(manipulator.skipPos(), -1);
}