[clangd] Emit semantic highlighting tokens when the main AST is built.

Differential Revision: https://reviews.llvm.org/D63821

llvm-svn: 364551
This commit is contained in:
Johan Vikstrom 2019-06-27 15:13:03 +00:00
parent a4771e9dfd
commit 6b8a2515ba
3 changed files with 49 additions and 7 deletions

View File

@ -48,8 +48,10 @@ namespace {
// Update the FileIndex with new ASTs and plumb the diagnostics responses.
struct UpdateIndexCallbacks : public ParsingCallbacks {
UpdateIndexCallbacks(FileIndex *FIndex, DiagnosticsConsumer &DiagConsumer)
: FIndex(FIndex), DiagConsumer(DiagConsumer) {}
UpdateIndexCallbacks(FileIndex *FIndex, DiagnosticsConsumer &DiagConsumer,
bool SemanticHighlighting)
: FIndex(FIndex), DiagConsumer(DiagConsumer),
SemanticHighlighting(SemanticHighlighting) {}
void onPreambleAST(PathRef Path, ASTContext &Ctx,
std::shared_ptr<clang::Preprocessor> PP,
@ -61,6 +63,8 @@ struct UpdateIndexCallbacks : public ParsingCallbacks {
void onMainAST(PathRef Path, ParsedAST &AST) override {
if (FIndex)
FIndex->updateMain(Path, AST);
if (SemanticHighlighting)
DiagConsumer.onHighlightingsReady(Path, getSemanticHighlightings(AST));
}
void onDiagnostics(PathRef File, std::vector<Diag> Diags) override {
@ -74,6 +78,7 @@ struct UpdateIndexCallbacks : public ParsingCallbacks {
private:
FileIndex *FIndex;
DiagnosticsConsumer &DiagConsumer;
bool SemanticHighlighting;
};
} // namespace
@ -82,6 +87,7 @@ ClangdServer::Options ClangdServer::optsForTest() {
Opts.UpdateDebounce = std::chrono::steady_clock::duration::zero(); // Faster!
Opts.StorePreamblesInMemory = true;
Opts.AsyncThreadsCount = 4; // Consistent!
Opts.SemanticHighlighting = true;
return Opts;
}
@ -102,9 +108,10 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
// is parsed.
// FIXME(ioeric): this can be slow and we may be able to index on less
// critical paths.
WorkScheduler(CDB, Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
llvm::make_unique<UpdateIndexCallbacks>(DynamicIdx.get(),
DiagConsumer),
WorkScheduler(
CDB, Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
llvm::make_unique<UpdateIndexCallbacks>(
DynamicIdx.get(), DiagConsumer, Opts.SemanticHighlighting),
Opts.UpdateDebounce, Opts.RetentionPolicy) {
// Adds an index to the stack, at higher priority than existing indexes.
auto AddIndex = [&](SymbolIndex *Idx) {

View File

@ -18,6 +18,7 @@
#include "Function.h"
#include "GlobalCompilationDatabase.h"
#include "Protocol.h"
#include "SemanticHighlighting.h"
#include "TUScheduler.h"
#include "XRefs.h"
#include "index/Background.h"
@ -49,6 +50,11 @@ public:
std::vector<Diag> Diagnostics) = 0;
/// Called whenever the file status is updated.
virtual void onFileUpdated(PathRef File, const TUStatus &Status){};
/// Called by ClangdServer when some \p Highlightings for \p File are ready.
virtual void
onHighlightingsReady(PathRef File,
std::vector<HighlightingToken> Highlightings) {}
};
/// When set, used by ClangdServer to get clang-tidy options for each particular
@ -131,6 +137,9 @@ public:
/// Clangd will execute compiler drivers matching one of these globs to
/// fetch system include path.
std::vector<std::string> QueryDriverGlobs;
/// Enable semantic highlighting features.
bool SemanticHighlighting = false;
};
// Sensible default options for use in tests.
// Features like indexing must be enabled if desired.

View File

@ -7,7 +7,9 @@
//===----------------------------------------------------------------------===//
#include "Annotations.h"
#include "ClangdServer.h"
#include "SemanticHighlighting.h"
#include "TestFS.h"
#include "TestTU.h"
#include "gmock/gmock.h"
@ -64,6 +66,30 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
}
}
TEST(ClangdSemanticHighlightingTest, GeneratesHighlightsWhenFileChange) {
class HighlightingsCounterDiagConsumer : public DiagnosticsConsumer {
public:
std::atomic<int> Count = {0};
void onDiagnosticsReady(PathRef, std::vector<Diag>) override {}
void onHighlightingsReady(
PathRef File, std::vector<HighlightingToken> Highlightings) override {
++Count;
}
};
auto FooCpp = testPath("foo.cpp");
MockFSProvider FS;
FS.Files[FooCpp] = "";
MockCompilationDatabase MCD;
HighlightingsCounterDiagConsumer DiagConsumer;
ClangdServer Server(MCD, FS, DiagConsumer, ClangdServer::optsForTest());
Server.addDocument(FooCpp, "int a;");
ASSERT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for server";
ASSERT_EQ(DiagConsumer.Count, 1);
}
} // namespace
} // namespace clangd
} // namespace clang