ClangCodeModel: Check doc revision when highlighting with clangd

Change-Id: I981d375e3656e89bb66516218e3f4e33ee8bbb9e
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2021-10-22 15:06:46 +02:00
parent 2eb50afd9c
commit 6f26a1545c
3 changed files with 25 additions and 11 deletions

View File

@@ -997,7 +997,8 @@ public:
HelpItem::Category category = HelpItem::Unknown, HelpItem::Category category = HelpItem::Unknown,
const QString &type = {}); const QString &type = {});
void handleSemanticTokens(TextDocument *doc, const QList<ExpandedSemanticToken> &tokens); void handleSemanticTokens(TextDocument *doc, const QList<ExpandedSemanticToken> &tokens,
int version);
enum class AstCallbackMode { SyncIfPossible, AlwaysAsync }; enum class AstCallbackMode { SyncIfPossible, AlwaysAsync };
using TextDocOrFile = const Utils::variant<const TextDocument *, Utils::FilePath>; using TextDocOrFile = const Utils::variant<const TextDocument *, Utils::FilePath>;
@@ -1177,8 +1178,9 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
const auto hideDiagsHandler = []{ ClangDiagnosticManager::clearTaskHubIssues(); }; const auto hideDiagsHandler = []{ ClangDiagnosticManager::clearTaskHubIssues(); };
setDiagnosticsHandlers(textMarkCreator, hideDiagsHandler); setDiagnosticsHandlers(textMarkCreator, hideDiagsHandler);
setSymbolStringifier(displayNameFromDocumentSymbol); setSymbolStringifier(displayNameFromDocumentSymbol);
setSemanticTokensHandler([this](TextDocument *doc, const QList<ExpandedSemanticToken> &tokens) { setSemanticTokensHandler([this](TextDocument *doc, const QList<ExpandedSemanticToken> &tokens,
d->handleSemanticTokens(doc, tokens); int version) {
d->handleSemanticTokens(doc, tokens, version);
}); });
hoverHandler()->setHelpItemProvider([this](const HoverRequest::Response &response, hoverHandler()->setHelpItemProvider([this](const HoverRequest::Response &response,
const DocumentUri &uri) { const DocumentUri &uri) {
@@ -2454,18 +2456,29 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
// Sometimes we have no choice, as for #include directives, which appear neither // Sometimes we have no choice, as for #include directives, which appear neither
// in the semantic tokens nor in the AST. // in the semantic tokens nor in the AST.
void ClangdClient::Private::handleSemanticTokens(TextDocument *doc, void ClangdClient::Private::handleSemanticTokens(TextDocument *doc,
const QList<ExpandedSemanticToken> &tokens) const QList<ExpandedSemanticToken> &tokens,
int version)
{ {
SubtaskTimer t(highlightingTimer); 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) for (const ExpandedSemanticToken &t : tokens)
qCDebug(clangdLogHighlight()) << '\t' << t.line << t.column << t.length << t.type qCDebug(clangdLogHighlight()) << '\t' << t.line << t.column << t.length << t.type
<< t.modifiers; << 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); FinalizingSubtaskTimer t(highlightingTimer);
if (!q->documentOpen(doc)) if (!q->documentOpen(doc))
return; 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()) if (clangdLogAst().isDebugEnabled())
ast.print(); ast.print();

View File

@@ -451,8 +451,9 @@ void SemanticTokenSupport::highlight(const Utils::FilePath &filePath)
SyntaxHighlighter *highlighter = doc->syntaxHighlighter(); SyntaxHighlighter *highlighter = doc->syntaxHighlighter();
if (!highlighter) if (!highlighter)
return; return;
const QList<SemanticToken> tokens = m_tokens.value(filePath).tokens.toTokens(m_tokenTypes, const VersionedTokens versionedTokens = m_tokens.value(filePath);
m_tokenModifiers); const QList<SemanticToken> tokens = versionedTokens.tokens
.toTokens(m_tokenTypes, m_tokenModifiers);
if (m_tokensHandler) { if (m_tokensHandler) {
int line = 1; int line = 1;
int column = 1; int column = 1;
@@ -477,7 +478,7 @@ void SemanticTokenSupport::highlight(const Utils::FilePath &filePath)
expandedToken.length = token.length; expandedToken.length = token.length;
expandedTokens << expandedToken; expandedTokens << expandedToken;
}; };
m_tokensHandler(doc, expandedTokens); m_tokensHandler(doc, expandedTokens, versionedTokens.version);
return; return;
} }
int line = 1; int line = 1;

View File

@@ -48,8 +48,8 @@ public:
QString type; QString type;
QStringList modifiers; QStringList modifiers;
}; };
using SemanticTokensHandler = std::function<void(TextEditor::TextDocument *doc, using SemanticTokensHandler = std::function<void(TextEditor::TextDocument *,
const QList<ExpandedSemanticToken> &)>; const QList<ExpandedSemanticToken> &, int)>;
namespace SemanticHighligtingSupport { namespace SemanticHighligtingSupport {