From 17b05bc3e8f48a264a6fda87013e1239661c0436 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 15 Sep 2021 08:10:30 +0200 Subject: [PATCH] Clangd: Create correct code assist processor in provider ... for the context of the code assist instead of using a callback from the text editor. Change-Id: I636b1b267a944895d4ff732e3c0a8811332ec14f Reviewed-by: Christian Kandeler --- src/plugins/clangcodemodel/clangdclient.cpp | 97 +++++++------------ src/plugins/clangcodemodel/clangdclient.h | 1 + .../languageclientcompletionassist.h | 1 + src/plugins/texteditor/texteditor.cpp | 9 -- src/plugins/texteditor/texteditor.h | 4 - 5 files changed, 37 insertions(+), 75 deletions(-) diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index bb0920aee65..dcbf45da420 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -710,29 +710,6 @@ private: const ProposalHandler m_handler; }; -class DoxygenAssistProvider : public TextEditor::IAssistProvider -{ -public: - void setProposalHandler(const ProposalHandler &handler) { m_proposalHandler = handler; } - - void setParameters(int position, unsigned completionOperator) - { - m_position = position; - m_completionOperator = completionOperator; - } - -private: - RunType runType() const override { return Synchronous; } - TextEditor::IAssistProcessor *createProcessor(const TextEditor::AssistInterface *) const override - { - return new DoxygenAssistProcessor(m_position, m_completionOperator, m_proposalHandler); - } - - ProposalHandler m_proposalHandler; - int m_position = 0; - unsigned m_completionOperator = 0; -}; - class ClangdClient::Private { public: @@ -771,7 +748,6 @@ public: ClangdClient * const q; const CppEditor::ClangdSettings::Data settings; - DoxygenAssistProvider doxygenAssistProvider; QHash runningFindUsages; Utils::optional followSymbolData; Utils::optional switchDeclDefData; @@ -793,12 +769,15 @@ public: } }; -class ClangdCompletionAssistProvider : public LanguageClientCompletionAssistProvider +class ClangdClient::ClangdCompletionAssistProvider : public LanguageClientCompletionAssistProvider { public: ClangdCompletionAssistProvider(ClangdClient *client); private: + TextEditor::IAssistProcessor *createProcessor( + const TextEditor::AssistInterface *assistInterface) const override; + int activationCharSequenceLength() const override { return 3; } bool isActivationCharSequence(const QString &sequence) const override; bool isContinuationChar(const QChar &c) const override; @@ -806,6 +785,8 @@ private: void applyCompletionItem(const CompletionItem &item, TextEditor::TextDocumentManipulatorInterface &manipulator, QChar typedChar); + + ClangdClient::Private *m_data = nullptr; }; ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir) @@ -1102,49 +1083,18 @@ void ClangdClient::enableTesting() { d->isTesting = true; setCompletionProposalHandler([this](TextEditor::IAssistProposal *proposal) { - emit proposalReady(proposal); + QMetaObject::invokeMethod(this, [this, proposal] { emit proposalReady(proposal); }, + Qt::QueuedConnection); }); setFunctionHintProposalHandler([this](TextEditor::IAssistProposal *proposal) { emit proposalReady(proposal); }); - d->doxygenAssistProvider.setProposalHandler([this](TextEditor::IAssistProposal *proposal) { - QMetaObject::invokeMethod(this, [this, proposal] { emit proposalReady(proposal); }, - Qt::QueuedConnection); - }); } void ClangdClient::openEditorDocument(TextEditor::BaseTextEditor *editor) { if (!documentOpen(editor->textDocument())) openDocument(editor->textDocument()); - const auto assistRequestHandler = [self = QPointer(this)]( - TextEditor::TextEditorWidget *editorWidget, TextEditor::AssistKind kind, - TextEditor::IAssistProvider *provider) { - if (!self) - return false; - if (kind != TextEditor::Completion || provider) - return false; - ClangCompletionContextAnalyzer contextAnalyzer(editorWidget->document(), - editorWidget->position(), false, {}); - contextAnalyzer.analyze(); - self->setSnippetsGroup(contextAnalyzer.addSnippets() - ? CppEditor::Constants::CPP_SNIPPETS_GROUP_ID : QString()); - switch (contextAnalyzer.completionAction()) { - case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen: - qCDebug(clangdLog) << "completion changed to function hint"; - editorWidget->invokeAssist(TextEditor::FunctionHint, provider); - return true; - case ClangCompletionContextAnalyzer::CompleteDoxygenKeyword: - self->d->doxygenAssistProvider.setParameters(contextAnalyzer.positionForProposal(), - contextAnalyzer.completionOperator()); - editorWidget->invokeAssist(kind, &self->d->doxygenAssistProvider); - return true; - default: - break; - } - return false; - }; - editor->editorWidget()->setAssistRequestHandler(assistRequestHandler); } void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList &locations) @@ -2713,8 +2663,9 @@ QString ClangdDiagnostic::category() const return typedValue("category"); } -ClangdCompletionAssistProvider::ClangdCompletionAssistProvider(ClangdClient *client) +ClangdClient::ClangdCompletionAssistProvider::ClangdCompletionAssistProvider(ClangdClient *client) : LanguageClientCompletionAssistProvider(client) + , m_data(client->d) { setItemsTransformer([](const Utils::FilePath &filePath, const QString &content, int pos, const QList &items) { @@ -2747,7 +2698,29 @@ ClangdCompletionAssistProvider::ClangdCompletionAssistProvider(ClangdClient *cli }); } -bool ClangdCompletionAssistProvider::isActivationCharSequence(const QString &sequence) const +TextEditor::IAssistProcessor *ClangdClient::ClangdCompletionAssistProvider::createProcessor( + const TextEditor::AssistInterface *assistInterface) const +{ + ClangCompletionContextAnalyzer contextAnalyzer(assistInterface->textDocument(), + assistInterface->position(), false, {}); + contextAnalyzer.analyze(); + client()->setSnippetsGroup( + contextAnalyzer.addSnippets() ? CppEditor::Constants::CPP_SNIPPETS_GROUP_ID : QString()); + switch (contextAnalyzer.completionAction()) { + case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen: + qCDebug(clangdLog) << "completion changed to function hint"; + return new FunctionHintProcessor(client(), proposalHandler()); + case ClangCompletionContextAnalyzer::CompleteDoxygenKeyword: + return new DoxygenAssistProcessor(contextAnalyzer.positionForProposal(), + contextAnalyzer.completionOperator(), + proposalHandler()); + default: + break; + } + return LanguageClientCompletionAssistProvider::createProcessor(assistInterface); +} + +bool ClangdClient::ClangdCompletionAssistProvider::isActivationCharSequence(const QString &sequence) const { const QChar &ch = sequence.at(2); const QChar &ch2 = sequence.at(1); @@ -2769,12 +2742,12 @@ bool ClangdCompletionAssistProvider::isActivationCharSequence(const QString &seq return false; } -bool ClangdCompletionAssistProvider::isContinuationChar(const QChar &c) const +bool ClangdClient::ClangdCompletionAssistProvider::isContinuationChar(const QChar &c) const { return CppEditor::isValidIdentifierChar(c); } -void ClangdCompletionAssistProvider::applyCompletionItem( +void ClangdClient::ClangdCompletionAssistProvider::applyCompletionItem( const CompletionItem &item, TextEditor::TextDocumentManipulatorInterface &manipulator, QChar typedChar) { diff --git a/src/plugins/clangcodemodel/clangdclient.h b/src/plugins/clangcodemodel/clangdclient.h index 79454fd05c1..7c8ef426fcc 100644 --- a/src/plugins/clangcodemodel/clangdclient.h +++ b/src/plugins/clangcodemodel/clangdclient.h @@ -98,6 +98,7 @@ private: class FollowSymbolData; class VirtualFunctionAssistProcessor; class VirtualFunctionAssistProvider; + class ClangdCompletionAssistProvider; Private * const d; }; diff --git a/src/plugins/languageclient/languageclientcompletionassist.h b/src/plugins/languageclient/languageclientcompletionassist.h index 61a7626655a..24f0243326a 100644 --- a/src/plugins/languageclient/languageclientcompletionassist.h +++ b/src/plugins/languageclient/languageclientcompletionassist.h @@ -78,6 +78,7 @@ protected: void setItemsTransformer(const CompletionItemsTransformer &transformer); void setApplyHelper(const CompletionApplyHelper &applyHelper); Client *client() const { return m_client; } + const ProposalHandler &proposalHandler() const { return m_proposalHandler; } private: QList m_triggerChars; diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 02753033cfd..5f0fa3a48b0 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -783,7 +783,6 @@ public: TextMark* m_dragMark = nullptr; QScopedPointer m_clipboardAssistProvider; - TextEditorWidget::AssistRequestHandler m_assistRequestHandler; QScopedPointer m_autoCompleter; CommentDefinition m_commentDefinition; @@ -3534,11 +3533,6 @@ void TextEditorWidget::showTextMarksToolTip(const QPoint &pos, d->showTextMarksToolTip(pos, marks, mainTextMark); } -void TextEditorWidget::setAssistRequestHandler(const AssistRequestHandler &handler) -{ - d->m_assistRequestHandler = handler; -} - void TextEditorWidgetPrivate::processTooltipRequest(const QTextCursor &c) { const QPoint toolTipPoint = q->toolTipPosition(c); @@ -8546,9 +8540,6 @@ QTextBlock TextEditorWidget::blockForVerticalOffset(int offset) const void TextEditorWidget::invokeAssist(AssistKind kind, IAssistProvider *provider) { - if (d->m_assistRequestHandler && d->m_assistRequestHandler(this, kind, provider)) - return; - if (kind == QuickFix && d->m_snippetOverlay->isVisible()) d->m_snippetOverlay->accept(); diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h index 36de5e24632..70224a18ff9 100644 --- a/src/plugins/texteditor/texteditor.h +++ b/src/plugins/texteditor/texteditor.h @@ -288,10 +288,6 @@ public: const TextMarks &marks, const TextMark *mainTextMark = nullptr) const; - using AssistRequestHandler = std::function; - void setAssistRequestHandler(const AssistRequestHandler &handler); - void invokeAssist(AssistKind assistKind, IAssistProvider *provider = nullptr); virtual TextEditor::AssistInterface *createAssistInterface(AssistKind assistKind,