Index: clang-tools-extra/trunk/clangd/ClangdServer.h =================================================================== --- clang-tools-extra/trunk/clangd/ClangdServer.h +++ clang-tools-extra/trunk/clangd/ClangdServer.h @@ -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 @@ std::vector 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 Highlightings) {} }; /// When set, used by ClangdServer to get clang-tidy options for each particular @@ -131,6 +137,9 @@ /// Clangd will execute compiler drivers matching one of these globs to /// fetch system include path. std::vector QueryDriverGlobs; + + /// Enable semantic highlighting features. + bool SemanticHighlighting = false; }; // Sensible default options for use in tests. // Features like indexing must be enabled if desired. @@ -304,7 +313,7 @@ // can be caused by missing includes (e.g. member access in incomplete type). bool SuggestMissingIncludes = false; bool EnableHiddenFeatures = false; - + // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex) llvm::StringMap> CachedCompletionFuzzyFindRequestByFile; Index: clang-tools-extra/trunk/clangd/ClangdServer.cpp =================================================================== --- clang-tools-extra/trunk/clangd/ClangdServer.cpp +++ clang-tools-extra/trunk/clangd/ClangdServer.cpp @@ -48,8 +48,10 @@ // 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 PP, @@ -61,6 +63,8 @@ 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 Diags) override { @@ -74,6 +78,7 @@ private: FileIndex *FIndex; DiagnosticsConsumer &DiagConsumer; + bool SemanticHighlighting; }; } // namespace @@ -82,6 +87,7 @@ Opts.UpdateDebounce = std::chrono::steady_clock::duration::zero(); // Faster! Opts.StorePreamblesInMemory = true; Opts.AsyncThreadsCount = 4; // Consistent! + Opts.SemanticHighlighting = true; return Opts; } @@ -102,10 +108,11 @@ // 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(DynamicIdx.get(), - DiagConsumer), - Opts.UpdateDebounce, Opts.RetentionPolicy) { + WorkScheduler( + CDB, Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory, + llvm::make_unique( + 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) { if (this->Index != nullptr) { Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp =================================================================== --- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp +++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp @@ -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(ClangdSemanticHighlightingTest, GeneratesHighlightsWhenFileChange) { + class HighlightingsCounterDiagConsumer : public DiagnosticsConsumer { + public: + std::atomic Count = {0}; + + void onDiagnosticsReady(PathRef, std::vector) override {} + void onHighlightingsReady( + PathRef File, std::vector 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