forked from qt-creator/qt-creator
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:
@@ -710,29 +710,6 @@ private:
|
|||||||
const ProposalHandler m_handler;
|
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
|
class ClangdClient::Private
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -771,7 +748,6 @@ public:
|
|||||||
|
|
||||||
ClangdClient * const q;
|
ClangdClient * const q;
|
||||||
const CppEditor::ClangdSettings::Data settings;
|
const CppEditor::ClangdSettings::Data settings;
|
||||||
DoxygenAssistProvider doxygenAssistProvider;
|
|
||||||
QHash<quint64, ReferencesData> runningFindUsages;
|
QHash<quint64, ReferencesData> runningFindUsages;
|
||||||
Utils::optional<FollowSymbolData> followSymbolData;
|
Utils::optional<FollowSymbolData> followSymbolData;
|
||||||
Utils::optional<SwitchDeclDefData> switchDeclDefData;
|
Utils::optional<SwitchDeclDefData> switchDeclDefData;
|
||||||
@@ -793,12 +769,15 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClangdCompletionAssistProvider : public LanguageClientCompletionAssistProvider
|
class ClangdClient::ClangdCompletionAssistProvider : public LanguageClientCompletionAssistProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClangdCompletionAssistProvider(ClangdClient *client);
|
ClangdCompletionAssistProvider(ClangdClient *client);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
TextEditor::IAssistProcessor *createProcessor(
|
||||||
|
const TextEditor::AssistInterface *assistInterface) const override;
|
||||||
|
|
||||||
int activationCharSequenceLength() const override { return 3; }
|
int activationCharSequenceLength() const override { return 3; }
|
||||||
bool isActivationCharSequence(const QString &sequence) const override;
|
bool isActivationCharSequence(const QString &sequence) const override;
|
||||||
bool isContinuationChar(const QChar &c) const override;
|
bool isContinuationChar(const QChar &c) const override;
|
||||||
@@ -806,6 +785,8 @@ private:
|
|||||||
void applyCompletionItem(const CompletionItem &item,
|
void applyCompletionItem(const CompletionItem &item,
|
||||||
TextEditor::TextDocumentManipulatorInterface &manipulator,
|
TextEditor::TextDocumentManipulatorInterface &manipulator,
|
||||||
QChar typedChar);
|
QChar typedChar);
|
||||||
|
|
||||||
|
ClangdClient::Private *m_data = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
|
ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
|
||||||
@@ -1102,49 +1083,18 @@ void ClangdClient::enableTesting()
|
|||||||
{
|
{
|
||||||
d->isTesting = true;
|
d->isTesting = true;
|
||||||
setCompletionProposalHandler([this](TextEditor::IAssistProposal *proposal) {
|
setCompletionProposalHandler([this](TextEditor::IAssistProposal *proposal) {
|
||||||
emit proposalReady(proposal);
|
QMetaObject::invokeMethod(this, [this, proposal] { emit proposalReady(proposal); },
|
||||||
|
Qt::QueuedConnection);
|
||||||
});
|
});
|
||||||
setFunctionHintProposalHandler([this](TextEditor::IAssistProposal *proposal) {
|
setFunctionHintProposalHandler([this](TextEditor::IAssistProposal *proposal) {
|
||||||
emit proposalReady(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)
|
void ClangdClient::openEditorDocument(TextEditor::BaseTextEditor *editor)
|
||||||
{
|
{
|
||||||
if (!documentOpen(editor->textDocument()))
|
if (!documentOpen(editor->textDocument()))
|
||||||
openDocument(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)
|
void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Location> &locations)
|
||||||
@@ -2713,8 +2663,9 @@ QString ClangdDiagnostic::category() const
|
|||||||
return typedValue<QString>("category");
|
return typedValue<QString>("category");
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangdCompletionAssistProvider::ClangdCompletionAssistProvider(ClangdClient *client)
|
ClangdClient::ClangdCompletionAssistProvider::ClangdCompletionAssistProvider(ClangdClient *client)
|
||||||
: LanguageClientCompletionAssistProvider(client)
|
: LanguageClientCompletionAssistProvider(client)
|
||||||
|
, m_data(client->d)
|
||||||
{
|
{
|
||||||
setItemsTransformer([](const Utils::FilePath &filePath, const QString &content,
|
setItemsTransformer([](const Utils::FilePath &filePath, const QString &content,
|
||||||
int pos, const QList<CompletionItem> &items) {
|
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 &ch = sequence.at(2);
|
||||||
const QChar &ch2 = sequence.at(1);
|
const QChar &ch2 = sequence.at(1);
|
||||||
@@ -2769,12 +2742,12 @@ bool ClangdCompletionAssistProvider::isActivationCharSequence(const QString &seq
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClangdCompletionAssistProvider::isContinuationChar(const QChar &c) const
|
bool ClangdClient::ClangdCompletionAssistProvider::isContinuationChar(const QChar &c) const
|
||||||
{
|
{
|
||||||
return CppEditor::isValidIdentifierChar(c);
|
return CppEditor::isValidIdentifierChar(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangdCompletionAssistProvider::applyCompletionItem(
|
void ClangdClient::ClangdCompletionAssistProvider::applyCompletionItem(
|
||||||
const CompletionItem &item, TextEditor::TextDocumentManipulatorInterface &manipulator,
|
const CompletionItem &item, TextEditor::TextDocumentManipulatorInterface &manipulator,
|
||||||
QChar typedChar)
|
QChar typedChar)
|
||||||
{
|
{
|
||||||
|
@@ -98,6 +98,7 @@ private:
|
|||||||
class FollowSymbolData;
|
class FollowSymbolData;
|
||||||
class VirtualFunctionAssistProcessor;
|
class VirtualFunctionAssistProcessor;
|
||||||
class VirtualFunctionAssistProvider;
|
class VirtualFunctionAssistProvider;
|
||||||
|
class ClangdCompletionAssistProvider;
|
||||||
Private * const d;
|
Private * const d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -78,6 +78,7 @@ protected:
|
|||||||
void setItemsTransformer(const CompletionItemsTransformer &transformer);
|
void setItemsTransformer(const CompletionItemsTransformer &transformer);
|
||||||
void setApplyHelper(const CompletionApplyHelper &applyHelper);
|
void setApplyHelper(const CompletionApplyHelper &applyHelper);
|
||||||
Client *client() const { return m_client; }
|
Client *client() const { return m_client; }
|
||||||
|
const ProposalHandler &proposalHandler() const { return m_proposalHandler; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<QString> m_triggerChars;
|
QList<QString> m_triggerChars;
|
||||||
|
@@ -783,7 +783,6 @@ public:
|
|||||||
TextMark* m_dragMark = nullptr;
|
TextMark* m_dragMark = nullptr;
|
||||||
|
|
||||||
QScopedPointer<ClipboardAssistProvider> m_clipboardAssistProvider;
|
QScopedPointer<ClipboardAssistProvider> m_clipboardAssistProvider;
|
||||||
TextEditorWidget::AssistRequestHandler m_assistRequestHandler;
|
|
||||||
|
|
||||||
QScopedPointer<AutoCompleter> m_autoCompleter;
|
QScopedPointer<AutoCompleter> m_autoCompleter;
|
||||||
CommentDefinition m_commentDefinition;
|
CommentDefinition m_commentDefinition;
|
||||||
@@ -3534,11 +3533,6 @@ void TextEditorWidget::showTextMarksToolTip(const QPoint &pos,
|
|||||||
d->showTextMarksToolTip(pos, marks, mainTextMark);
|
d->showTextMarksToolTip(pos, marks, mainTextMark);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditorWidget::setAssistRequestHandler(const AssistRequestHandler &handler)
|
|
||||||
{
|
|
||||||
d->m_assistRequestHandler = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextEditorWidgetPrivate::processTooltipRequest(const QTextCursor &c)
|
void TextEditorWidgetPrivate::processTooltipRequest(const QTextCursor &c)
|
||||||
{
|
{
|
||||||
const QPoint toolTipPoint = q->toolTipPosition(c);
|
const QPoint toolTipPoint = q->toolTipPosition(c);
|
||||||
@@ -8546,9 +8540,6 @@ QTextBlock TextEditorWidget::blockForVerticalOffset(int offset) const
|
|||||||
|
|
||||||
void TextEditorWidget::invokeAssist(AssistKind kind, IAssistProvider *provider)
|
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())
|
if (kind == QuickFix && d->m_snippetOverlay->isVisible())
|
||||||
d->m_snippetOverlay->accept();
|
d->m_snippetOverlay->accept();
|
||||||
|
|
||||||
|
@@ -288,10 +288,6 @@ public:
|
|||||||
const TextMarks &marks,
|
const TextMarks &marks,
|
||||||
const TextMark *mainTextMark = nullptr) const;
|
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);
|
void invokeAssist(AssistKind assistKind, IAssistProvider *provider = nullptr);
|
||||||
|
|
||||||
virtual TextEditor::AssistInterface *createAssistInterface(AssistKind assistKind,
|
virtual TextEditor::AssistInterface *createAssistInterface(AssistKind assistKind,
|
||||||
|
Reference in New Issue
Block a user