forked from qt-creator/qt-creator
ClangCodeModel: Use dedicated completion assist provider for clangd
The pure LSP-based implementation is too inflexible with regards to activation characters. Change-Id: I386a60b80f59e1b48254d55c2a47f1a1ffe1f97f Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -40,6 +40,7 @@
|
|||||||
#include <cplusplus/MatchingText.h>
|
#include <cplusplus/MatchingText.h>
|
||||||
#include <cppeditor/cppeditorconstants.h>
|
#include <cppeditor/cppeditorconstants.h>
|
||||||
#include <cppeditor/cppcodemodelsettings.h>
|
#include <cppeditor/cppcodemodelsettings.h>
|
||||||
|
#include <cppeditor/cppcompletionassistprovider.h>
|
||||||
#include <cppeditor/cppdoxygen.h>
|
#include <cppeditor/cppdoxygen.h>
|
||||||
#include <cppeditor/cppeditorwidget.h>
|
#include <cppeditor/cppeditorwidget.h>
|
||||||
#include <cppeditor/cppfindreferences.h>
|
#include <cppeditor/cppfindreferences.h>
|
||||||
@@ -768,10 +769,6 @@ public:
|
|||||||
void handleSemanticTokens(TextEditor::TextDocument *doc,
|
void handleSemanticTokens(TextEditor::TextDocument *doc,
|
||||||
const QList<ExpandedSemanticToken> &tokens);
|
const QList<ExpandedSemanticToken> &tokens);
|
||||||
|
|
||||||
void applyCompletionItem(const CompletionItem &item,
|
|
||||||
TextEditor::TextDocumentManipulatorInterface &manipulator,
|
|
||||||
QChar typedChar);
|
|
||||||
|
|
||||||
ClangdClient * const q;
|
ClangdClient * const q;
|
||||||
const CppEditor::ClangdSettings::Data settings;
|
const CppEditor::ClangdSettings::Data settings;
|
||||||
DoxygenAssistProvider doxygenAssistProvider;
|
DoxygenAssistProvider doxygenAssistProvider;
|
||||||
@@ -796,6 +793,21 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ClangdCompletionAssistProvider : public LanguageClientCompletionAssistProvider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClangdCompletionAssistProvider(ClangdClient *client);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int activationCharSequenceLength() const override { return 3; }
|
||||||
|
bool isActivationCharSequence(const QString &sequence) const override;
|
||||||
|
bool isContinuationChar(const QChar &c) const override;
|
||||||
|
|
||||||
|
void applyCompletionItem(const CompletionItem &item,
|
||||||
|
TextEditor::TextDocumentManipulatorInterface &manipulator,
|
||||||
|
QChar typedChar);
|
||||||
|
};
|
||||||
|
|
||||||
ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
|
ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
|
||||||
: Client(clientInterface(project, jsonDbDir)), d(new Private(this, project))
|
: Client(clientInterface(project, jsonDbDir)), d(new Private(this, project))
|
||||||
{
|
{
|
||||||
@@ -805,6 +817,7 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
|
|||||||
"text/x-c++hdr", "text/x-c++src", "text/x-objc++src", "text/x-objcsrc"};
|
"text/x-c++hdr", "text/x-c++src", "text/x-objc++src", "text/x-objcsrc"};
|
||||||
setSupportedLanguage(langFilter);
|
setSupportedLanguage(langFilter);
|
||||||
setActivateDocumentAutomatically(true);
|
setActivateDocumentAutomatically(true);
|
||||||
|
setCompletionAssistProvider(new ClangdCompletionAssistProvider(this));
|
||||||
if (!project) {
|
if (!project) {
|
||||||
QJsonObject initOptions;
|
QJsonObject initOptions;
|
||||||
const QStringList clangOptions = createClangOptions(
|
const QStringList clangOptions = createClangOptions(
|
||||||
@@ -879,34 +892,6 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
|
|||||||
const DocumentUri &uri) {
|
const DocumentUri &uri) {
|
||||||
gatherHelpItemForTooltip(response, uri);
|
gatherHelpItemForTooltip(response, uri);
|
||||||
});
|
});
|
||||||
setCompletionItemsTransformer([](const Utils::FilePath &filePath, const QString &content,
|
|
||||||
int pos, const QList<CompletionItem> &items) {
|
|
||||||
qCDebug(clangdLog) << "received" << items.count() << "completions";
|
|
||||||
|
|
||||||
// If there are signals among the candidates, we employ the built-in code model to find out
|
|
||||||
// whether the cursor was on the second argument of a (dis)connect() call.
|
|
||||||
// If so, we offer only signals, as nothing else makes sense in that context.
|
|
||||||
static const auto criterion = [](const CompletionItem &ci) {
|
|
||||||
const Utils::optional<MarkupOrString> doc = ci.documentation();
|
|
||||||
if (!doc)
|
|
||||||
return false;
|
|
||||||
QString docText;
|
|
||||||
if (Utils::holds_alternative<QString>(*doc))
|
|
||||||
docText = Utils::get<QString>(*doc);
|
|
||||||
else if (Utils::holds_alternative<MarkupContent>(*doc))
|
|
||||||
docText = Utils::get<MarkupContent>(*doc).content();
|
|
||||||
return docText.contains("Annotation: qt_signal");
|
|
||||||
};
|
|
||||||
if (pos != -1 && Utils::anyOf(items, criterion) && CppEditor::CppModelManager::instance()
|
|
||||||
->positionRequiresSignal(filePath.toString(), content.toUtf8(), pos)) {
|
|
||||||
return Utils::filtered(items, criterion);
|
|
||||||
}
|
|
||||||
return items;
|
|
||||||
});
|
|
||||||
setCompletionApplyHelper([this](const CompletionItem &item,
|
|
||||||
TextEditor::TextDocumentManipulatorInterface &manipulator, QChar typedChar) {
|
|
||||||
d->applyCompletionItem(item, manipulator, typedChar);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(this, &Client::workDone, this,
|
connect(this, &Client::workDone, this,
|
||||||
[this, p = QPointer(project)](const ProgressToken &token) {
|
[this, p = QPointer(project)](const ProgressToken &token) {
|
||||||
@@ -2615,8 +2600,176 @@ void ClangdClient::Private::handleSemanticTokens(TextEditor::TextDocument *doc,
|
|||||||
q->sendContent(astReq, SendDocUpdates::Ignore);
|
q->sendContent(astReq, SendDocUpdates::Ignore);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangdClient::Private::applyCompletionItem(const CompletionItem &item,
|
void ClangdClient::VirtualFunctionAssistProcessor::cancel()
|
||||||
TextEditor::TextDocumentManipulatorInterface &manipulator, QChar typedChar)
|
{
|
||||||
|
resetData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangdClient::VirtualFunctionAssistProcessor::update()
|
||||||
|
{
|
||||||
|
if (!m_data->followSymbolData->editorWidget)
|
||||||
|
return;
|
||||||
|
setAsyncProposalAvailable(createProposal(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangdClient::VirtualFunctionAssistProcessor::finalize()
|
||||||
|
{
|
||||||
|
if (!m_data->followSymbolData->editorWidget)
|
||||||
|
return;
|
||||||
|
const auto proposal = createProposal(true);
|
||||||
|
if (m_data->followSymbolData->editorWidget->isInTestMode()) {
|
||||||
|
m_data->followSymbolData->symbolsToDisplay.clear();
|
||||||
|
const auto immediateProposal = createProposal(false);
|
||||||
|
m_data->followSymbolData->editorWidget->setProposals(immediateProposal, proposal);
|
||||||
|
} else {
|
||||||
|
setAsyncProposalAvailable(proposal);
|
||||||
|
}
|
||||||
|
resetData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangdClient::VirtualFunctionAssistProcessor::resetData()
|
||||||
|
{
|
||||||
|
if (!m_data)
|
||||||
|
return;
|
||||||
|
m_data->followSymbolData->virtualFuncAssistProcessor = nullptr;
|
||||||
|
m_data->followSymbolData.reset();
|
||||||
|
m_data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextEditor::IAssistProposal *ClangdClient::VirtualFunctionAssistProcessor::createProposal(bool final) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_data && m_data->followSymbolData, return nullptr);
|
||||||
|
|
||||||
|
QList<TextEditor::AssistProposalItemInterface *> items;
|
||||||
|
bool needsBaseDeclEntry = !m_data->followSymbolData->defLinkNode.range()
|
||||||
|
.contains(Position(m_data->followSymbolData->cursor));
|
||||||
|
for (const SymbolData &symbol : qAsConst(m_data->followSymbolData->symbolsToDisplay)) {
|
||||||
|
Utils::Link link = symbol.second;
|
||||||
|
if (m_data->followSymbolData->defLink == link) {
|
||||||
|
if (!needsBaseDeclEntry)
|
||||||
|
continue;
|
||||||
|
needsBaseDeclEntry = false;
|
||||||
|
} else {
|
||||||
|
const Utils::Link defLink = m_data->followSymbolData->declDefMap.value(symbol.second);
|
||||||
|
if (defLink.hasValidTarget())
|
||||||
|
link = defLink;
|
||||||
|
}
|
||||||
|
items << createEntry(symbol.first, link);
|
||||||
|
}
|
||||||
|
if (needsBaseDeclEntry)
|
||||||
|
items << createEntry({}, m_data->followSymbolData->defLink);
|
||||||
|
if (!final) {
|
||||||
|
const auto infoItem = new CppEditor::VirtualFunctionProposalItem({}, false);
|
||||||
|
infoItem->setText(ClangdClient::tr("collecting overrides ..."));
|
||||||
|
infoItem->setOrder(-1);
|
||||||
|
items << infoItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CppEditor::VirtualFunctionProposal(
|
||||||
|
m_data->followSymbolData->cursor.position(),
|
||||||
|
items, m_data->followSymbolData->openInSplit);
|
||||||
|
}
|
||||||
|
|
||||||
|
CppEditor::VirtualFunctionProposalItem *
|
||||||
|
ClangdClient::VirtualFunctionAssistProcessor::createEntry(const QString &name,
|
||||||
|
const Utils::Link &link) const
|
||||||
|
{
|
||||||
|
const auto item = new CppEditor::VirtualFunctionProposalItem(
|
||||||
|
link, m_data->followSymbolData->openInSplit);
|
||||||
|
QString text = name;
|
||||||
|
if (link == m_data->followSymbolData->defLink) {
|
||||||
|
item->setOrder(1000); // Ensure base declaration is on top.
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
text = ClangdClient::tr("<base declaration>");
|
||||||
|
} else if (m_data->followSymbolData->defLinkNode.isPureVirtualDeclaration()
|
||||||
|
|| m_data->followSymbolData->defLinkNode.isPureVirtualDefinition()) {
|
||||||
|
text += " = 0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item->setText(text);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextEditor::IAssistProcessor *ClangdClient::VirtualFunctionAssistProvider::createProcessor() const
|
||||||
|
{
|
||||||
|
return m_data->followSymbolData->virtualFuncAssistProcessor
|
||||||
|
= new VirtualFunctionAssistProcessor(m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::optional<QList<CodeAction> > ClangdDiagnostic::codeActions() const
|
||||||
|
{
|
||||||
|
return optionalArray<LanguageServerProtocol::CodeAction>("codeActions");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ClangdDiagnostic::category() const
|
||||||
|
{
|
||||||
|
return typedValue<QString>("category");
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangdCompletionAssistProvider::ClangdCompletionAssistProvider(ClangdClient *client)
|
||||||
|
: LanguageClientCompletionAssistProvider(client)
|
||||||
|
{
|
||||||
|
setItemsTransformer([](const Utils::FilePath &filePath, const QString &content,
|
||||||
|
int pos, const QList<CompletionItem> &items) {
|
||||||
|
qCDebug(clangdLog) << "received" << items.count() << "completions";
|
||||||
|
|
||||||
|
// If there are signals among the candidates, we employ the built-in code model to find out
|
||||||
|
// whether the cursor was on the second argument of a (dis)connect() call.
|
||||||
|
// If so, we offer only signals, as nothing else makes sense in that context.
|
||||||
|
static const auto criterion = [](const CompletionItem &ci) {
|
||||||
|
const Utils::optional<MarkupOrString> doc = ci.documentation();
|
||||||
|
if (!doc)
|
||||||
|
return false;
|
||||||
|
QString docText;
|
||||||
|
if (Utils::holds_alternative<QString>(*doc))
|
||||||
|
docText = Utils::get<QString>(*doc);
|
||||||
|
else if (Utils::holds_alternative<MarkupContent>(*doc))
|
||||||
|
docText = Utils::get<MarkupContent>(*doc).content();
|
||||||
|
return docText.contains("Annotation: qt_signal");
|
||||||
|
};
|
||||||
|
if (pos != -1 && Utils::anyOf(items, criterion) && CppEditor::CppModelManager::instance()
|
||||||
|
->positionRequiresSignal(filePath.toString(), content.toUtf8(), pos)) {
|
||||||
|
return Utils::filtered(items, criterion);
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
});
|
||||||
|
|
||||||
|
setApplyHelper([this](const CompletionItem &item,
|
||||||
|
TextEditor::TextDocumentManipulatorInterface &manipulator, QChar typedChar) {
|
||||||
|
applyCompletionItem(item, manipulator, typedChar);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClangdCompletionAssistProvider::isActivationCharSequence(const QString &sequence) const
|
||||||
|
{
|
||||||
|
const QChar &ch = sequence.at(2);
|
||||||
|
const QChar &ch2 = sequence.at(1);
|
||||||
|
const QChar &ch3 = sequence.at(0);
|
||||||
|
unsigned kind = T_EOF_SYMBOL;
|
||||||
|
const int pos = CppEditor::CppCompletionAssistProvider::activationSequenceChar(
|
||||||
|
ch, ch2, ch3, &kind, false, false);
|
||||||
|
if (pos == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// We want to minimize unneeded completion requests, as those trigger document updates,
|
||||||
|
// which trigger re-highlighting and diagnostics, which we try to delay.
|
||||||
|
// Therefore, we do not trigger on syntax elements that often occur in non-applicable
|
||||||
|
// contexts, such as '(', '<' or '/'.
|
||||||
|
switch (kind) {
|
||||||
|
case T_DOT: case T_COLON_COLON: case T_ARROW: case T_DOT_STAR: case T_ARROW_STAR: case T_POUND:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClangdCompletionAssistProvider::isContinuationChar(const QChar &c) const
|
||||||
|
{
|
||||||
|
return CppEditor::isValidIdentifierChar(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangdCompletionAssistProvider::applyCompletionItem(
|
||||||
|
const CompletionItem &item, TextEditor::TextDocumentManipulatorInterface &manipulator,
|
||||||
|
QChar typedChar)
|
||||||
{
|
{
|
||||||
const auto edit = item.textEdit();
|
const auto edit = item.textEdit();
|
||||||
if (!edit)
|
if (!edit)
|
||||||
@@ -2734,112 +2887,6 @@ void ClangdClient::Private::applyCompletionItem(const CompletionItem &item,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangdClient::VirtualFunctionAssistProcessor::cancel()
|
|
||||||
{
|
|
||||||
resetData();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangdClient::VirtualFunctionAssistProcessor::update()
|
|
||||||
{
|
|
||||||
if (!m_data->followSymbolData->editorWidget)
|
|
||||||
return;
|
|
||||||
setAsyncProposalAvailable(createProposal(false));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangdClient::VirtualFunctionAssistProcessor::finalize()
|
|
||||||
{
|
|
||||||
if (!m_data->followSymbolData->editorWidget)
|
|
||||||
return;
|
|
||||||
const auto proposal = createProposal(true);
|
|
||||||
if (m_data->followSymbolData->editorWidget->isInTestMode()) {
|
|
||||||
m_data->followSymbolData->symbolsToDisplay.clear();
|
|
||||||
const auto immediateProposal = createProposal(false);
|
|
||||||
m_data->followSymbolData->editorWidget->setProposals(immediateProposal, proposal);
|
|
||||||
} else {
|
|
||||||
setAsyncProposalAvailable(proposal);
|
|
||||||
}
|
|
||||||
resetData();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangdClient::VirtualFunctionAssistProcessor::resetData()
|
|
||||||
{
|
|
||||||
if (!m_data)
|
|
||||||
return;
|
|
||||||
m_data->followSymbolData->virtualFuncAssistProcessor = nullptr;
|
|
||||||
m_data->followSymbolData.reset();
|
|
||||||
m_data = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextEditor::IAssistProposal *ClangdClient::VirtualFunctionAssistProcessor::createProposal(bool final) const
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_data && m_data->followSymbolData, return nullptr);
|
|
||||||
|
|
||||||
QList<TextEditor::AssistProposalItemInterface *> items;
|
|
||||||
bool needsBaseDeclEntry = !m_data->followSymbolData->defLinkNode.range()
|
|
||||||
.contains(Position(m_data->followSymbolData->cursor));
|
|
||||||
for (const SymbolData &symbol : qAsConst(m_data->followSymbolData->symbolsToDisplay)) {
|
|
||||||
Utils::Link link = symbol.second;
|
|
||||||
if (m_data->followSymbolData->defLink == link) {
|
|
||||||
if (!needsBaseDeclEntry)
|
|
||||||
continue;
|
|
||||||
needsBaseDeclEntry = false;
|
|
||||||
} else {
|
|
||||||
const Utils::Link defLink = m_data->followSymbolData->declDefMap.value(symbol.second);
|
|
||||||
if (defLink.hasValidTarget())
|
|
||||||
link = defLink;
|
|
||||||
}
|
|
||||||
items << createEntry(symbol.first, link);
|
|
||||||
}
|
|
||||||
if (needsBaseDeclEntry)
|
|
||||||
items << createEntry({}, m_data->followSymbolData->defLink);
|
|
||||||
if (!final) {
|
|
||||||
const auto infoItem = new CppEditor::VirtualFunctionProposalItem({}, false);
|
|
||||||
infoItem->setText(ClangdClient::tr("collecting overrides ..."));
|
|
||||||
infoItem->setOrder(-1);
|
|
||||||
items << infoItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CppEditor::VirtualFunctionProposal(
|
|
||||||
m_data->followSymbolData->cursor.position(),
|
|
||||||
items, m_data->followSymbolData->openInSplit);
|
|
||||||
}
|
|
||||||
|
|
||||||
CppEditor::VirtualFunctionProposalItem *
|
|
||||||
ClangdClient::VirtualFunctionAssistProcessor::createEntry(const QString &name,
|
|
||||||
const Utils::Link &link) const
|
|
||||||
{
|
|
||||||
const auto item = new CppEditor::VirtualFunctionProposalItem(
|
|
||||||
link, m_data->followSymbolData->openInSplit);
|
|
||||||
QString text = name;
|
|
||||||
if (link == m_data->followSymbolData->defLink) {
|
|
||||||
item->setOrder(1000); // Ensure base declaration is on top.
|
|
||||||
if (text.isEmpty()) {
|
|
||||||
text = ClangdClient::tr("<base declaration>");
|
|
||||||
} else if (m_data->followSymbolData->defLinkNode.isPureVirtualDeclaration()
|
|
||||||
|| m_data->followSymbolData->defLinkNode.isPureVirtualDefinition()) {
|
|
||||||
text += " = 0";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
item->setText(text);
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextEditor::IAssistProcessor *ClangdClient::VirtualFunctionAssistProvider::createProcessor() const
|
|
||||||
{
|
|
||||||
return m_data->followSymbolData->virtualFuncAssistProcessor
|
|
||||||
= new VirtualFunctionAssistProcessor(m_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::optional<QList<CodeAction> > ClangdDiagnostic::codeActions() const
|
|
||||||
{
|
|
||||||
return optionalArray<LanguageServerProtocol::CodeAction>("codeActions");
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ClangdDiagnostic::category() const
|
|
||||||
{
|
|
||||||
return typedValue<QString>("category");
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangCodeModel
|
} // namespace ClangCodeModel
|
||||||
|
|
||||||
|
|||||||
@@ -1027,22 +1027,6 @@ SymbolStringifier Client::symbolStringifier() const
|
|||||||
return m_symbolStringifier;
|
return m_symbolStringifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::setCompletionItemsTransformer(const CompletionItemsTransformer &transformer)
|
|
||||||
{
|
|
||||||
if (const auto provider = qobject_cast<LanguageClientCompletionAssistProvider *>(
|
|
||||||
m_clientProviders.completionAssistProvider)) {
|
|
||||||
provider->setItemsTransformer(transformer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::setCompletionApplyHelper(const CompletionApplyHelper &applyHelper)
|
|
||||||
{
|
|
||||||
if (const auto provider = qobject_cast<LanguageClientCompletionAssistProvider *>(
|
|
||||||
m_clientProviders.completionAssistProvider)) {
|
|
||||||
provider->setApplyHelper(applyHelper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::setCompletionProposalHandler(const ProposalHandler &handler)
|
void Client::setCompletionProposalHandler(const ProposalHandler &handler)
|
||||||
{
|
{
|
||||||
if (const auto provider = qobject_cast<LanguageClientCompletionAssistProvider *>(
|
if (const auto provider = qobject_cast<LanguageClientCompletionAssistProvider *>(
|
||||||
@@ -1067,6 +1051,12 @@ void Client::setSnippetsGroup(const QString &group)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::setCompletionAssistProvider(LanguageClientCompletionAssistProvider *provider)
|
||||||
|
{
|
||||||
|
delete m_clientProviders.completionAssistProvider;
|
||||||
|
m_clientProviders.completionAssistProvider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
void Client::start()
|
void Client::start()
|
||||||
{
|
{
|
||||||
LanguageClientManager::addClient(this);
|
LanguageClientManager::addClient(this);
|
||||||
|
|||||||
@@ -183,11 +183,10 @@ public:
|
|||||||
void setSemanticTokensHandler(const SemanticTokensHandler &handler);
|
void setSemanticTokensHandler(const SemanticTokensHandler &handler);
|
||||||
void setSymbolStringifier(const LanguageServerProtocol::SymbolStringifier &stringifier);
|
void setSymbolStringifier(const LanguageServerProtocol::SymbolStringifier &stringifier);
|
||||||
LanguageServerProtocol::SymbolStringifier symbolStringifier() const;
|
LanguageServerProtocol::SymbolStringifier symbolStringifier() const;
|
||||||
void setCompletionItemsTransformer(const CompletionItemsTransformer &transformer);
|
|
||||||
void setCompletionApplyHelper(const CompletionApplyHelper &applyHelper);
|
|
||||||
void setCompletionProposalHandler(const ProposalHandler &handler);
|
void setCompletionProposalHandler(const ProposalHandler &handler);
|
||||||
void setFunctionHintProposalHandler(const ProposalHandler &handler);
|
void setFunctionHintProposalHandler(const ProposalHandler &handler);
|
||||||
void setSnippetsGroup(const QString &group);
|
void setSnippetsGroup(const QString &group);
|
||||||
|
void setCompletionAssistProvider(LanguageClientCompletionAssistProvider *provider);
|
||||||
|
|
||||||
// logging
|
// logging
|
||||||
void log(const QString &message) const;
|
void log(const QString &message) const;
|
||||||
|
|||||||
@@ -71,11 +71,14 @@ public:
|
|||||||
|
|
||||||
void setTriggerCharacters(const Utils::optional<QList<QString>> triggerChars);
|
void setTriggerCharacters(const Utils::optional<QList<QString>> triggerChars);
|
||||||
|
|
||||||
void setItemsTransformer(const CompletionItemsTransformer &transformer);
|
|
||||||
void setApplyHelper(const CompletionApplyHelper &applyHelper);
|
|
||||||
void setProposalHandler(const ProposalHandler &handler) { m_proposalHandler = handler; }
|
void setProposalHandler(const ProposalHandler &handler) { m_proposalHandler = handler; }
|
||||||
void setSnippetsGroup(const QString &group) { m_snippetsGroup = group; }
|
void setSnippetsGroup(const QString &group) { m_snippetsGroup = group; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setItemsTransformer(const CompletionItemsTransformer &transformer);
|
||||||
|
void setApplyHelper(const CompletionApplyHelper &applyHelper);
|
||||||
|
Client *client() const { return m_client; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<QString> m_triggerChars;
|
QList<QString> m_triggerChars;
|
||||||
CompletionItemsTransformer m_itemsTransformer;
|
CompletionItemsTransformer m_itemsTransformer;
|
||||||
|
|||||||
Reference in New Issue
Block a user