aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2021-10-07 10:58:54 +0200
committerChristian Kandeler <christian.kandeler@qt.io>2021-10-07 09:36:49 +0000
commitcd453a5c67d210898fefcd9e36ac67e3c6069b00 (patch)
tree83d9f50f2787a6781e74733a9b8fad7228c2a8f7
parentcfc732fe8f5934da3beba50849d1a378c2efbc47 (diff)
ClangCodeModel: Refer to clangd for the AST node under the cursor
The question which concrete AST node corresponds to a given cursor position is surprisingly difficult to answer, and clangd already has a lot of code for this. Therefore, we always refer to clangd to get a concrete node, even if we already have the full AST. Change-Id: I5d1528d776ee459a53b8e650a616ea7019ec59bf Reviewed-by: David Schulz <david.schulz@qt.io>
-rw-r--r--src/plugins/clangcodemodel/clangdclient.cpp69
1 files changed, 34 insertions, 35 deletions
diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp
index fb3efa95ec..5b3e76bee8 100644
--- a/src/plugins/clangcodemodel/clangdclient.cpp
+++ b/src/plugins/clangcodemodel/clangdclient.cpp
@@ -316,14 +316,6 @@ static QList<AstNode> getAstPath(const AstNode &root, const Range &range)
return path;
}
-static AstNode getAstNode(const AstNode &root, const Range &range)
-{
- const QList<AstNode> path = getAstPath(root, range);
- if (!path.isEmpty())
- return path.last();
- return {};
-}
-
static Usage::Type getUsageType(const QList<AstNode> &path)
{
bool potentialWrite = false;
@@ -926,7 +918,7 @@ public:
using TextDocOrFile = const Utils::variant<const TextDocument *, Utils::FilePath>;
using AstHandler = const std::function<void(const AstNode &ast, const MessageId &)>;
MessageId getAndHandleAst(TextDocOrFile &doc, AstHandler &astHandler,
- AstCallbackMode callbackMode);
+ AstCallbackMode callbackMode, const Range &range = {});
ClangdClient * const q;
const CppEditor::ClangdSettings::Data settings;
@@ -1571,16 +1563,16 @@ void ClangdClient::followSymbol(TextDocument *document,
return;
}
- const auto astHandler = [this, id = d->followSymbolData->id, range = Range(cursor)]
+ const auto astHandler = [this, id = d->followSymbolData->id]
(const AstNode &ast, const MessageId &) {
qCDebug(clangdLog) << "received ast response for cursor";
if (!d->followSymbolData || d->followSymbolData->id != id)
return;
- d->followSymbolData->cursorNode = getAstNode(ast, range);
+ d->followSymbolData->cursorNode = ast;
if (d->followSymbolData->defLink.hasValidTarget())
d->handleGotoDefinitionResult();
};
- d->getAndHandleAst(document, astHandler, Private::AstCallbackMode::SyncIfPossible);
+ d->getAndHandleAst(document, astHandler, Private::AstCallbackMode::AlwaysAsync, Range(cursor));
}
void ClangdClient::switchDeclDef(TextDocument *document, const QTextCursor &cursor,
@@ -2030,18 +2022,19 @@ void ClangdClient::Private::handleGotoImplementationResult(
: TextDocOrFile(defLinkFilePath);
const Position defLinkPos(followSymbolData->defLink.targetLine - 1,
followSymbolData->defLink.targetColumn);
- const auto astHandler = [this, range = Range(defLinkPos, defLinkPos), id = followSymbolData->id]
+ const auto astHandler = [this, id = followSymbolData->id]
(const AstNode &ast, const MessageId &) {
qCDebug(clangdLog) << "received ast response for def link";
if (!followSymbolData || followSymbolData->id != id)
return;
- followSymbolData->defLinkNode = getAstNode(ast, range);
+ followSymbolData->defLinkNode = ast;
if (followSymbolData->pendingSymbolInfoRequests.isEmpty()
&& followSymbolData->pendingGotoDefRequests.isEmpty()) {
handleDocumentInfoResults();
}
};
- getAndHandleAst(defLinkDocVariant, astHandler, AstCallbackMode::SyncIfPossible);
+ getAndHandleAst(defLinkDocVariant, astHandler, AstCallbackMode::AlwaysAsync,
+ Range(defLinkPos, defLinkPos));
}
void ClangdClient::Private::handleDocumentInfoResults()
@@ -2727,26 +2720,30 @@ void ClangdCompletionItem::apply(TextDocumentManipulatorInterface &manipulator,
MessageId ClangdClient::Private::getAndHandleAst(const TextDocOrFile &doc,
const AstHandler &astHandler,
- AstCallbackMode callbackMode)
+ AstCallbackMode callbackMode, const Range &range)
{
const auto textDocPtr = Utils::get_if<const TextDocument *>(&doc);
const TextDocument * const textDoc = textDocPtr ? *textDocPtr : nullptr;
const Utils::FilePath filePath = textDoc ? textDoc->filePath()
: Utils::get<Utils::FilePath>(doc);
- // If the document's AST is in the cache and is up to date, call the handler.
- if (const auto ast = textDoc ? astCache.get(textDoc) : externalAstCache.get(filePath)) {
- qCDebug(clangdLog) << "using AST from cache";
- switch (callbackMode) {
- case AstCallbackMode::SyncIfPossible:
- astHandler(*ast, {});
- break;
- case AstCallbackMode::AlwaysAsync:
- QMetaObject::invokeMethod(q, [ast, astHandler] { astHandler(*ast, {}); },
+ // If the entire AST is requested and the document's AST is in the cache and it is up to date,
+ // call the handler.
+ const bool fullAstRequested = !range.isValid();
+ if (fullAstRequested) {
+ if (const auto ast = textDoc ? astCache.get(textDoc) : externalAstCache.get(filePath)) {
+ qCDebug(clangdLog) << "using AST from cache";
+ switch (callbackMode) {
+ case AstCallbackMode::SyncIfPossible:
+ astHandler(*ast, {});
+ break;
+ case AstCallbackMode::AlwaysAsync:
+ QMetaObject::invokeMethod(q, [ast, astHandler] { astHandler(*ast, {}); },
Qt::QueuedConnection);
- break;
+ break;
+ }
+ return {};
}
- return {};
}
// Otherwise retrieve the AST from clangd.
@@ -2754,7 +2751,6 @@ MessageId ClangdClient::Private::getAndHandleAst(const TextDocOrFile &doc,
class AstParams : public JsonObject
{
public:
- AstParams() {}
AstParams(const TextDocumentIdentifier &document, const Range &range = {})
{
setTextDocument(document);
@@ -2784,19 +2780,22 @@ MessageId ClangdClient::Private::getAndHandleAst(const TextDocOrFile &doc,
explicit AstRequest(const AstParams &params) : Request("textDocument/ast", params) {}
};
- AstRequest request(AstParams(TextDocumentIdentifier(DocumentUri::fromFilePath(filePath))));
+ AstRequest request(AstParams(TextDocumentIdentifier(DocumentUri::fromFilePath(filePath)),
+ range));
request.setResponseCallback([this, filePath, guardedTextDoc = QPointer(textDoc), astHandler,
- docRev = textDoc ? getRevision(textDoc) : -1,
+ fullAstRequested, docRev = textDoc ? getRevision(textDoc) : -1,
fileRev = getRevision(filePath), reqId = request.id()]
(AstRequest::Response response) {
qCDebug(clangdLog) << "retrieved AST from clangd";
const auto result = response.result();
const AstNode ast = result ? *result : AstNode();
- if (guardedTextDoc) {
- if (docRev == getRevision(guardedTextDoc))
- astCache.insert(guardedTextDoc, ast);
- } else if (fileRev == getRevision(filePath) && !q->documentForFilePath(filePath)) {
- externalAstCache.insert(filePath, ast);
+ if (fullAstRequested) {
+ if (guardedTextDoc) {
+ if (docRev == getRevision(guardedTextDoc))
+ astCache.insert(guardedTextDoc, ast);
+ } else if (fileRev == getRevision(filePath) && !q->documentForFilePath(filePath)) {
+ externalAstCache.insert(filePath, ast);
+ }
}
astHandler(ast, reqId);
});