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 <christian.kandeler@qt.io>
This commit is contained in:
David Schulz
2021-09-15 08:10:30 +02:00
parent 6bbbaca696
commit 17b05bc3e8
5 changed files with 37 additions and 75 deletions

View File

@@ -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<quint64, ReferencesData> runningFindUsages;
Utils::optional<FollowSymbolData> followSymbolData;
Utils::optional<SwitchDeclDefData> 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<Location> &locations)
@@ -2713,8 +2663,9 @@ QString ClangdDiagnostic::category() const
return typedValue<QString>("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<CompletionItem> &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)
{

View File

@@ -98,6 +98,7 @@ private:
class FollowSymbolData;
class VirtualFunctionAssistProcessor;
class VirtualFunctionAssistProvider;
class ClangdCompletionAssistProvider;
Private * const d;
};

View File

@@ -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<QString> m_triggerChars;

View File

@@ -783,7 +783,6 @@ public:
TextMark* m_dragMark = nullptr;
QScopedPointer<ClipboardAssistProvider> m_clipboardAssistProvider;
TextEditorWidget::AssistRequestHandler m_assistRequestHandler;
QScopedPointer<AutoCompleter> 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();

View File

@@ -288,10 +288,6 @@ public:
const TextMarks &marks,
const TextMark *mainTextMark = nullptr) const;
using AssistRequestHandler = std::function<bool(TextEditorWidget *editorWidget,
AssistKind assistKind, IAssistProvider *provider)>;
void setAssistRequestHandler(const AssistRequestHandler &handler);
void invokeAssist(AssistKind assistKind, IAssistProvider *provider = nullptr);
virtual TextEditor::AssistInterface *createAssistInterface(AssistKind assistKind,