diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 2b6044f3ac3..c65d8ee95c9 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -997,7 +997,8 @@ public: HelpItem::Category category = HelpItem::Unknown, const QString &type = {}); - void handleSemanticTokens(TextDocument *doc, const QList &tokens); + void handleSemanticTokens(TextDocument *doc, const QList &tokens, + int version); enum class AstCallbackMode { SyncIfPossible, AlwaysAsync }; using TextDocOrFile = const Utils::variant; @@ -1177,8 +1178,9 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir) const auto hideDiagsHandler = []{ ClangDiagnosticManager::clearTaskHubIssues(); }; setDiagnosticsHandlers(textMarkCreator, hideDiagsHandler); setSymbolStringifier(displayNameFromDocumentSymbol); - setSemanticTokensHandler([this](TextDocument *doc, const QList &tokens) { - d->handleSemanticTokens(doc, tokens); + setSemanticTokensHandler([this](TextDocument *doc, const QList &tokens, + int version) { + d->handleSemanticTokens(doc, tokens, version); }); hoverHandler()->setHelpItemProvider([this](const HoverRequest::Response &response, const DocumentUri &uri) { @@ -2454,18 +2456,29 @@ static void semanticHighlighter(QFutureInterface &future, // Sometimes we have no choice, as for #include directives, which appear neither // in the semantic tokens nor in the AST. void ClangdClient::Private::handleSemanticTokens(TextDocument *doc, - const QList &tokens) + const QList &tokens, + int version) { SubtaskTimer t(highlightingTimer); - qCDebug(clangdLog()) << "handling LSP tokens" << doc->filePath() << tokens.size(); + qCDebug(clangdLog) << "handling LSP tokens" << doc->filePath() << tokens.size(); + if (version != q->documentVersion(doc->filePath())) { + qCDebug(clangdLogHighlight) << "LSP tokens outdated; aborting highlighting procedure" + << version << q->documentVersion(doc->filePath()); + return; + } for (const ExpandedSemanticToken &t : tokens) qCDebug(clangdLogHighlight()) << '\t' << t.line << t.column << t.length << t.type << t.modifiers; - const auto astHandler = [this, tokens, doc](const AstNode &ast, const MessageId &) { + const auto astHandler = [this, tokens, doc, version](const AstNode &ast, const MessageId &) { FinalizingSubtaskTimer t(highlightingTimer); if (!q->documentOpen(doc)) return; + if (version != q->documentVersion(doc->filePath())) { + qCDebug(clangdLogHighlight) << "AST not up to date; aborting highlighting procedure" + << version << q->documentVersion(doc->filePath()); + return; + } if (clangdLogAst().isDebugEnabled()) ast.print(); diff --git a/src/plugins/languageclient/semantichighlightsupport.cpp b/src/plugins/languageclient/semantichighlightsupport.cpp index e30320ce982..a1b43729d4a 100644 --- a/src/plugins/languageclient/semantichighlightsupport.cpp +++ b/src/plugins/languageclient/semantichighlightsupport.cpp @@ -451,8 +451,9 @@ void SemanticTokenSupport::highlight(const Utils::FilePath &filePath) SyntaxHighlighter *highlighter = doc->syntaxHighlighter(); if (!highlighter) return; - const QList tokens = m_tokens.value(filePath).tokens.toTokens(m_tokenTypes, - m_tokenModifiers); + const VersionedTokens versionedTokens = m_tokens.value(filePath); + const QList tokens = versionedTokens.tokens + .toTokens(m_tokenTypes, m_tokenModifiers); if (m_tokensHandler) { int line = 1; int column = 1; @@ -477,7 +478,7 @@ void SemanticTokenSupport::highlight(const Utils::FilePath &filePath) expandedToken.length = token.length; expandedTokens << expandedToken; }; - m_tokensHandler(doc, expandedTokens); + m_tokensHandler(doc, expandedTokens, versionedTokens.version); return; } int line = 1; diff --git a/src/plugins/languageclient/semantichighlightsupport.h b/src/plugins/languageclient/semantichighlightsupport.h index 4a8a639f319..1a90101b3e8 100644 --- a/src/plugins/languageclient/semantichighlightsupport.h +++ b/src/plugins/languageclient/semantichighlightsupport.h @@ -48,8 +48,8 @@ public: QString type; QStringList modifiers; }; -using SemanticTokensHandler = std::function &)>; +using SemanticTokensHandler = std::function &, int)>; namespace SemanticHighligtingSupport {