[clangd] Emit semantic highlighting tokens when the main AST is built.
authorJohan Vikstrom <jvikstrom@google.com>
Thu, 27 Jun 2019 15:13:03 +0000 (15:13 +0000)
committerJohan Vikstrom <jvikstrom@google.com>
Thu, 27 Jun 2019 15:13:03 +0000 (15:13 +0000)
Differential Revision: https://reviews.llvm.org/D63821

llvm-svn: 364551

clang-tools-extra/clangd/ClangdServer.cpp
clang-tools-extra/clangd/ClangdServer.h
clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp

index 300ba62..5bfcd48 100644 (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,10 +108,11 @@ 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),
-                    Opts.UpdateDebounce, Opts.RetentionPolicy) {
+      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) {
     if (this->Index != nullptr) {
index d926c42..7da703f 100644 (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.
@@ -304,7 +313,7 @@ private:
   // can be caused by missing includes (e.g. member access in incomplete type).
   bool SuggestMissingIncludes = false;
   bool EnableHiddenFeatures = false;
-
+  
   // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)
   llvm::StringMap<llvm::Optional<FuzzyFindRequest>>
       CachedCompletionFuzzyFindRequestByFile;
index b042192..d7c6d4d 100644 (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