Nebiroth updated this revision to Diff 122529.
Nebiroth added a comment.

Decls and MacroInfos vectors are now private and passed by reference instead of 
copied.
DeclarationLocationsFinder does not store Locations anymore, instead the vector 
is filled in their respective methods in ClangdUnit.cpp
Refactored if condition
Removed redundant newlines at end of test file.


https://reviews.llvm.org/D38425

Files:
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/ClangdUnit.cpp
  clangd/ClangdUnit.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  test/clangd/documenthighlight.test
  test/clangd/initialize-params-invalid.test
  test/clangd/initialize-params.test

Index: test/clangd/initialize-params.test
===================================================================
--- test/clangd/initialize-params.test
+++ test/clangd/initialize-params.test
@@ -20,6 +20,7 @@
 # CHECK-NEXT:      },
 # CHECK-NEXT:      "definitionProvider": true,
 # CHECK-NEXT:      "documentFormattingProvider": true,
+# CHECK-NEXT:	   "documentHighlightProvider": true,
 # CHECK-NEXT:      "documentOnTypeFormattingProvider": {
 # CHECK-NEXT:        "firstTriggerCharacter": "}",
 # CHECK-NEXT:        "moreTriggerCharacter": []
Index: test/clangd/initialize-params-invalid.test
===================================================================
--- test/clangd/initialize-params-invalid.test
+++ test/clangd/initialize-params-invalid.test
@@ -20,6 +20,7 @@
 # CHECK-NEXT:      },
 # CHECK-NEXT:      "definitionProvider": true,
 # CHECK-NEXT:      "documentFormattingProvider": true,
+# CHECK-NEXT:	   "documentHighlightProvider": true,
 # CHECK-NEXT:      "documentOnTypeFormattingProvider": {
 # CHECK-NEXT:        "firstTriggerCharacter": "}",
 # CHECK-NEXT:        "moreTriggerCharacter": []
@@ -40,6 +41,7 @@
 # CHECK-NEXT:      "textDocumentSync": 1
 # CHECK-NEXT:    }
 # CHECK-NEXT:  }
+
 Content-Length: 44
 
 {"jsonrpc":"2.0","id":3,"method":"shutdown"}
Index: test/clangd/documenthighlight.test
===================================================================
--- /dev/null
+++ test/clangd/documenthighlight.test
@@ -0,0 +1,37 @@
+# RUN: clangd -run-synchronously < %s | FileCheck %s
+# It is absolutely vital that this file has CRLF line endings.
+#
+Content-Length: 125
+
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+
+Content-Length: 455
+
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();}\n"}}}
+
+Content-Length: 156
+
+{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}}
+# Go to local variable
+# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":12,"line":16},"start":{"character":4,"line":16}}},{"kind":0,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}}]}
+
+
+Content-Length: 157
+
+{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}}
+# Go to local variable
+# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":9,"line":12},"start":{"character":4,"line":12}}},{"kind":1,"range":{"end":{"character":21,"line":18},"start":{"character":17,"line":18}}},{"kind":216,"range":{"end":{"character":21,"line":18},"start":{"character":17,"line":18}}},{"kind":220,"range":{"end":{"character":8,"line":19},"start":{"character":4,"line":19}}}]}
+
+Content-Length: 157
+
+{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}}
+# Go to local variable
+# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":22,"line":4},"start":{"character":5,"line":4}}},{"kind":0,"range":{"end":{"character":25,"line":21},"start":{"character":8,"line":21}}}]}
+
+Content-Length: 48
+
+{"jsonrpc":"2.0","id":10000,"method":"shutdown"}
+
+Content-Length: 33
+
+{"jsonrpc":"2.0":"method":"exit"}							
\ No newline at end of file
Index: clangd/ProtocolHandlers.h
===================================================================
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -31,7 +31,6 @@
 public:
   using Ctx = RequestContext;
   virtual ~ProtocolCallbacks() = default;
-
   virtual void onInitialize(Ctx C, InitializeParams &Params) = 0;
   virtual void onShutdown(Ctx C, ShutdownParams &Params) = 0;
   virtual void onExit(Ctx C, ExitParams &Params) = 0;
@@ -54,6 +53,8 @@
   virtual void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) = 0;
   virtual void onCommand(Ctx C, ExecuteCommandParams &Params) = 0;
   virtual void onRename(Ctx C, RenameParams &Parames) = 0;
+  virtual void onDocumentHighlight(Ctx C,
+                                   TextDocumentPositionParams &Params) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out,
Index: clangd/ProtocolHandlers.cpp
===================================================================
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -46,12 +46,12 @@
   JSONOutput *Out;
   ProtocolCallbacks *Callbacks;
 };
-
 } // namespace
 
 void clangd::registerCallbackHandlers(JSONRPCDispatcher &Dispatcher,
                                       JSONOutput &Out,
                                       ProtocolCallbacks &Callbacks) {
+
   HandlerRegisterer Register{Dispatcher, &Out, &Callbacks};
 
   Register("initialize", &ProtocolCallbacks::onInitialize);
@@ -74,4 +74,6 @@
   Register("textDocument/rename", &ProtocolCallbacks::onRename);
   Register("workspace/didChangeWatchedFiles", &ProtocolCallbacks::onFileEvent);
   Register("workspace/executeCommand", &ProtocolCallbacks::onCommand);
+  Register("textDocument/documentHighlight",
+           &ProtocolCallbacks::onDocumentHighlight);
 }
Index: clangd/Protocol.h
===================================================================
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -603,6 +603,39 @@
                                             clangd::Logger &Logger);
 };
 
+enum class DocumentHighlightKind { Text = 1, Read = 2, Write = 3 };
+
+/**
+ * A document highlight is a range inside a text document which deserves
+ * special attention. Usually a document highlight is visualized by changing
+ * the background color of its range.
+ *
+ */
+struct DocumentHighlight {
+  /*
+   *
+	 * The range this highlight applies to.
+	 */
+  Range range;
+
+  /**
+   * The highlight kind, default is DocumentHighlightKind.Text.
+   */
+  DocumentHighlightKind kind = DocumentHighlightKind::Text;
+  int test = 3;
+
+  friend bool operator<(const DocumentHighlight &LHS,
+                        const DocumentHighlight &RHS) {
+    return std::tie(LHS.range) < std::tie(RHS.range);
+  }
+
+  friend bool operator==(const DocumentHighlight &LHS,
+                         const DocumentHighlight &RHS) {
+    return LHS.kind == RHS.kind && LHS.range == RHS.range;
+  }
+
+  static json::Expr unparse(const DocumentHighlight &DH);
+};
 } // namespace clangd
 } // namespace clang
 
Index: clangd/Protocol.cpp
===================================================================
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -1121,3 +1121,18 @@
   }
   return Result;
 }
+
+json::Expr DocumentHighlight::unparse(const DocumentHighlight &DH) {
+
+  // int temp = DocumentHighlightKind::Text;
+
+  return json::obj{
+          {"range", Range::unparse(DH.range)},
+          {"kind", (int) DH.kind},
+      };
+
+//  llvm::raw_string_ostream(Result)
+//      << llvm::formatv("{\"range\": {0}", Range::unparse(DH.range)) << ","
+//      << llvm::format(R"( "kind": %d)", DH.kind) << "}";
+//  return Result;
+}
Index: clangd/ClangdUnit.h
===================================================================
--- clangd/ClangdUnit.h
+++ clangd/ClangdUnit.h
@@ -304,14 +304,22 @@
                             std::shared_ptr<PCHContainerOperations> PCHs,
                             clangd::Logger &Logger);
 
+
 /// Get the beginning SourceLocation at a specified \p Pos.
 SourceLocation getBeginningOfIdentifier(ParsedAST &Unit, const Position &Pos,
                                         const FileEntry *FE);
 
+Location addDeclarationLocation(ParsedAST &AST, SourceRange SR);
+
+DocumentHighlight addHighlightLocation(ParsedAST &AST, SourceRange SR, DocumentHighlightKind Kind);
+
 /// Get definition of symbol at a specified \p Pos.
 std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos,
                                       clangd::Logger &Logger);
 
+std::vector<DocumentHighlight>
+findDocumentHighlights(ParsedAST &AST, Position Pos, clangd::Logger &Logger);
+
 /// For testing/debugging purposes. Note that this method deserializes all
 /// unserialized Decls, so use with care.
 void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS);
Index: clangd/ClangdUnit.cpp
===================================================================
--- clangd/ClangdUnit.cpp
+++ clangd/ClangdUnit.cpp
@@ -913,7 +913,9 @@
 
 /// Finds declarations locations that a given source location refers to.
 class DeclarationLocationsFinder : public index::IndexDataConsumer {
-  std::vector<Location> DeclarationLocations;
+  std::vector<const Decl *> Decls;
+  std::vector<MacroInfo *> MacroInfos;
+  std::vector<DocumentHighlightKind> Kinds;
   const SourceLocation &SearchedLocation;
   const ASTContext &AST;
   Preprocessor &PP;
@@ -924,59 +926,41 @@
                              ASTContext &AST, Preprocessor &PP)
       : SearchedLocation(SearchedLocation), AST(AST), PP(PP) {}
 
-  std::vector<Location> takeLocations() {
-    // Don't keep the same location multiple times.
-    // This can happen when nodes in the AST are visited twice.
-    std::sort(DeclarationLocations.begin(), DeclarationLocations.end());
-    auto last =
-        std::unique(DeclarationLocations.begin(), DeclarationLocations.end());
-    DeclarationLocations.erase(last, DeclarationLocations.end());
-    return std::move(DeclarationLocations);
-  }
-
   bool
   handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
                       ArrayRef<index::SymbolRelation> Relations, FileID FID,
                       unsigned Offset,
                       index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
+
     if (isSearchedLocation(FID, Offset)) {
-      addDeclarationLocation(D->getSourceRange());
+      Decls.push_back(D);
+      DocumentHighlightKind Kind;
+      switch (Roles) {
+      case (unsigned)index::SymbolRole::Read:
+        Kind = DocumentHighlightKind::Read;
+        break;
+      case (unsigned)index::SymbolRole::Write:
+        Kind = DocumentHighlightKind::Write;
+        break;
+      default:
+        Kind = DocumentHighlightKind::Text;
+        break;
+      }
+      Kinds.push_back(Kind);
     }
     return true;
   }
 
+  std::vector<const Decl *> getDecls() { return Decls; };
+  std::vector<MacroInfo *> getMacroInfos() { return MacroInfos; };
+  std::vector<DocumentHighlightKind> getKinds() { return Kinds; };
+
 private:
   bool isSearchedLocation(FileID FID, unsigned Offset) const {
     const SourceManager &SourceMgr = AST.getSourceManager();
     return SourceMgr.getFileOffset(SearchedLocation) == Offset &&
            SourceMgr.getFileID(SearchedLocation) == FID;
   }
-
-  void addDeclarationLocation(const SourceRange &ValSourceRange) {
-    const SourceManager &SourceMgr = AST.getSourceManager();
-    const LangOptions &LangOpts = AST.getLangOpts();
-    SourceLocation LocStart = ValSourceRange.getBegin();
-    SourceLocation LocEnd = Lexer::getLocForEndOfToken(ValSourceRange.getEnd(),
-                                                       0, SourceMgr, LangOpts);
-    Position Begin;
-    Begin.line = SourceMgr.getSpellingLineNumber(LocStart) - 1;
-    Begin.character = SourceMgr.getSpellingColumnNumber(LocStart) - 1;
-    Position End;
-    End.line = SourceMgr.getSpellingLineNumber(LocEnd) - 1;
-    End.character = SourceMgr.getSpellingColumnNumber(LocEnd) - 1;
-    Range R = {Begin, End};
-    Location L;
-    if (const FileEntry *F =
-            SourceMgr.getFileEntryForID(SourceMgr.getFileID(LocStart))) {
-      StringRef FilePath = F->tryGetRealPathName();
-      if (FilePath.empty())
-        FilePath = F->getName();
-      L.uri = URI::fromFile(FilePath);
-      L.range = R;
-      DeclarationLocations.push_back(L);
-    }
-  }
-
   void finish() override {
     // Also handle possible macro at the searched location.
     Token Result;
@@ -998,17 +982,76 @@
         MacroDefinition MacroDef =
             PP.getMacroDefinitionAtLoc(IdentifierInfo, BeforeSearchedLocation);
         MacroInfo *MacroInf = MacroDef.getMacroInfo();
-        if (MacroInf) {
-          addDeclarationLocation(SourceRange(MacroInf->getDefinitionLoc(),
-                                             MacroInf->getDefinitionEndLoc()));
-        }
+        if (MacroInf)
+          MacroInfos.push_back(MacroInf);
       }
     }
   }
 };
 
+/// Finds document highlights that a given FileID and file offset refers to.
+class DocumentHighlightsFinder : public index::IndexDataConsumer {
+  std::vector<const Decl *> &Decls;
+  std::vector<DocumentHighlightKind> Kinds;
+  std::vector<SourceRange> SourceRanges;
+  const ASTContext &AST;
+  Preprocessor &PP;
+
+public:
+  DocumentHighlightsFinder(raw_ostream &OS, ASTContext &AST, Preprocessor &PP,
+                           std::vector<const Decl *> &Decls,
+                           std::vector<DocumentHighlightKind> Kinds)
+      : Decls(Decls), Kinds(Kinds), AST(AST), PP(PP) {}
+
+  bool
+  handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
+                      ArrayRef<index::SymbolRelation> Relations, FileID FID,
+                      unsigned Offset,
+                      index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
+    const SourceManager &SourceMgr = AST.getSourceManager();
+    if (SourceMgr.getMainFileID() != FID ||
+        std::find(Decls.begin(), Decls.end(), D) == Decls.end()) {
+      return true;
+    }
+    SourceLocation Begin, End;
+    const LangOptions &LangOpts = AST.getLangOpts();
+    SourceLocation StartOfFileLoc = SourceMgr.getLocForStartOfFile(FID);
+    SourceLocation HightlightStartLoc = StartOfFileLoc.getLocWithOffset(Offset);
+    End =
+        Lexer::getLocForEndOfToken(HightlightStartLoc, 0, SourceMgr, LangOpts);
+    SourceRange SR(HightlightStartLoc, End);
+    SourceRanges.push_back(SR);
+
+    return true;
+  }
+
+  std::vector<const Decl *> getDecls() { return Decls; };
+  std::vector<DocumentHighlightKind> getKinds() { return Kinds; };
+  std::vector<SourceRange> getSourceRanges() { return SourceRanges; };
+};
+
 } // namespace
 
+Location clangd::addDeclarationLocation(ParsedAST &AST, SourceRange SR) {
+  const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
+  SourceLocation LocStart = SR.getBegin();
+  SourceLocation LocEnd =
+      Lexer::getLocForEndOfToken(SR.getEnd(), 0, SourceMgr, LangOpts);
+  Position Begin;
+  Begin.line = SourceMgr.getSpellingLineNumber(LocStart) - 1;
+  Begin.character = SourceMgr.getSpellingColumnNumber(LocStart) - 1;
+  Position End;
+  End.line = SourceMgr.getSpellingLineNumber(LocEnd) - 1;
+  End.character = SourceMgr.getSpellingColumnNumber(LocEnd) - 1;
+  Range R = {Begin, End};
+  Location L;
+  L.uri =
+      URI::fromFile(SourceMgr.getFilename(SourceMgr.getSpellingLoc(LocStart)));
+  L.range = R;
+  return L;
+}
+
 std::vector<Location> clangd::findDefinitions(ParsedAST &AST, Position Pos,
                                               clangd::Logger &Logger) {
   const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
@@ -1029,7 +1072,107 @@
   indexTopLevelDecls(AST.getASTContext(), AST.getTopLevelDecls(),
                      DeclLocationsFinder, IndexOpts);
 
-  return DeclLocationsFinder->takeLocations();
+  std::vector<Location> DeclarationLocations;
+
+  for (unsigned I = 0; I < DeclLocationsFinder->getDecls().size(); I++) {
+    DeclarationLocations.push_back(addDeclarationLocation(
+        AST, DeclLocationsFinder->getDecls()[I]->getSourceRange()));
+  }
+
+  for (unsigned I = 0; I < DeclLocationsFinder->getMacroInfos().size(); I++) {
+    DeclarationLocations.push_back(addDeclarationLocation(
+        AST,
+        SourceRange(
+            DeclLocationsFinder->getMacroInfos()[I]->getDefinitionLoc(),
+            DeclLocationsFinder->getMacroInfos()[I]->getDefinitionEndLoc())));
+  }
+
+  // Don't keep the same location multiple times.
+  // This can happen when nodes in the AST are visited twice.
+  std::sort(DeclarationLocations.begin(), DeclarationLocations.end());
+  auto last =
+      std::unique(DeclarationLocations.begin(), DeclarationLocations.end());
+  DeclarationLocations.erase(last, DeclarationLocations.end());
+  return std::move(DeclarationLocations);
+}
+
+DocumentHighlight clangd::addHighlightLocation(ParsedAST &AST, SourceRange SR,
+                                               DocumentHighlightKind Kind) {
+  const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
+  SourceLocation LocStart = SR.getBegin();
+  SourceLocation LocEnd =
+      Lexer::getLocForEndOfToken(SR.getEnd(), 0, SourceMgr, LangOpts);
+  Position Begin;
+  Begin.line = SourceMgr.getSpellingLineNumber(LocStart) - 1;
+  Begin.character = SourceMgr.getSpellingColumnNumber(LocStart) - 1;
+  Position End;
+  End.line = SourceMgr.getSpellingLineNumber(LocEnd) - 1;
+  End.character = SourceMgr.getSpellingColumnNumber(LocEnd) - 1;
+  Range R = {Begin, End};
+  DocumentHighlight DH;
+  DH.range = R;
+  DH.kind = Kind;
+  return DH;
+}
+
+std::vector<DocumentHighlight>
+clangd::findDocumentHighlights(ParsedAST &AST, Position Pos,
+                               clangd::Logger &Logger) {
+  const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+  const FileEntry *FE = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+  if (!FE)
+    return {};
+
+  SourceLocation SourceLocationBeg = getBeginningOfIdentifier(AST, Pos, FE);
+
+  auto DeclLocationsFinder = std::make_shared<DeclarationLocationsFinder>(
+      llvm::errs(), SourceLocationBeg, AST.getASTContext(),
+      AST.getPreprocessor());
+  index::IndexingOptions IndexOpts;
+  IndexOpts.SystemSymbolFilter =
+      index::IndexingOptions::SystemSymbolFilterKind::All;
+  IndexOpts.IndexFunctionLocals = true;
+
+  indexTopLevelDecls(AST.getASTContext(), AST.getTopLevelDecls(),
+                     DeclLocationsFinder, IndexOpts);
+
+  std::vector<const Decl *> TempDecls = DeclLocationsFinder->getDecls();
+  std::vector<MacroInfo *> TempMacroInfos =
+      DeclLocationsFinder->getMacroInfos();
+  std::vector<DocumentHighlightKind> TempKinds =
+      DeclLocationsFinder->getKinds();
+
+  auto DocHighlightsFinder = std::make_shared<DocumentHighlightsFinder>(
+      llvm::errs(), AST.getASTContext(), AST.getPreprocessor(), TempDecls,
+      TempKinds);
+
+  indexTopLevelDecls(AST.getASTContext(), AST.getTopLevelDecls(),
+                     DocHighlightsFinder, IndexOpts);
+
+  std::vector<DocumentHighlight> HighlightLocations;
+
+  for (unsigned I = 0; I < DocHighlightsFinder->getSourceRanges().size(); I++) {
+    HighlightLocations.push_back(
+        addHighlightLocation(AST, DocHighlightsFinder->getSourceRanges()[I],
+                             DocHighlightsFinder->getKinds()[I]));
+  }
+
+  for (unsigned I = 0; I < DeclLocationsFinder->getMacroInfos().size(); I++) {
+    HighlightLocations.push_back(addHighlightLocation(
+        AST,
+        SourceRange(
+            DeclLocationsFinder->getMacroInfos()[I]->getDefinitionLoc(),
+            DeclLocationsFinder->getMacroInfos()[I]->getDefinitionEndLoc()),
+        DocHighlightsFinder->getKinds()[I]));
+  }
+
+  // Don't keep the same location multiple times.
+  // This can happen when nodes in the AST are visited twice.
+  std::sort(HighlightLocations.begin(), HighlightLocations.end());
+  auto last = std::unique(HighlightLocations.begin(), HighlightLocations.end());
+  HighlightLocations.erase(last, HighlightLocations.end());
+  return std::move(HighlightLocations);
 }
 
 void ParsedAST::ensurePreambleDeclsDeserialized() {
Index: clangd/ClangdServer.h
===================================================================
--- clangd/ClangdServer.h
+++ clangd/ClangdServer.h
@@ -284,6 +284,10 @@
   /// given a header file and vice versa.
   llvm::Optional<Path> switchSourceHeader(PathRef Path);
 
+  /// Get document highlights for a symbol hovered on.
+  Tagged<std::vector<DocumentHighlight>> findDocumentHighlights(PathRef File,
+                                                                Position Pos);
+
   /// Run formatting for \p Rng inside \p File.
   std::vector<tooling::Replacement> formatRange(PathRef File, Range Rng);
   /// Run formatting for the whole \p File.
Index: clangd/ClangdServer.cpp
===================================================================
--- clangd/ClangdServer.cpp
+++ clangd/ClangdServer.cpp
@@ -506,6 +506,26 @@
   return llvm::None;
 }
 
+Tagged<std::vector<DocumentHighlight>>
+ClangdServer::findDocumentHighlights(PathRef File, Position Pos) {
+  auto FileContents = DraftMgr.getDraft(File);
+  assert(FileContents.Draft &&
+         "findDocumentHighlights is called for non-added document");
+
+  auto TaggedFS = FSProvider.getTaggedFileSystem(File);
+
+  std::shared_ptr<CppFile> Resources = Units.getFile(File);
+  assert(Resources && "Calling findDocumentHighlights on non-added file");
+
+  std::vector<DocumentHighlight> Result;
+  Resources->getAST().get()->runUnderLock([Pos, &Result, this](ParsedAST *AST) {
+    if (!AST)
+      return;
+    Result = clangd::findDocumentHighlights(*AST, Pos, Logger);
+  });
+  return make_tagged(std::move(Result), TaggedFS.Tag);
+}
+
 std::future<void> ClangdServer::scheduleReparseAndDiags(
     PathRef File, VersionedDraft Contents, std::shared_ptr<CppFile> Resources,
     Tagged<IntrusiveRefCntPtr<vfs::FileSystem>> TaggedFS) {
Index: clangd/ClangdLSPServer.h
===================================================================
--- clangd/ClangdLSPServer.h
+++ clangd/ClangdLSPServer.h
@@ -68,6 +68,7 @@
   void onSignatureHelp(Ctx C, TextDocumentPositionParams &Params) override;
   void onGoToDefinition(Ctx C, TextDocumentPositionParams &Params) override;
   void onSwitchSourceHeader(Ctx C, TextDocumentIdentifier &Params) override;
+  void onDocumentHighlight(Ctx C, TextDocumentPositionParams &Params) override;
   void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) override;
   void onCommand(Ctx C, ExecuteCommandParams &Params) override;
   void onRename(Ctx C, RenameParams &Parames) override;
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -57,12 +57,14 @@
                  {"triggerCharacters", {"(", ","}},
              }},
             {"definitionProvider", true},
+            {"documentHighlightProvider", true},
             {"renameProvider", true},
             {"executeCommandProvider",
              json::obj{
                  {"commands", {ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND}},
              }},
         }}}});
+
   if (Params.rootUri && !Params.rootUri->file.empty())
     Server.setRootPath(Params.rootUri->file);
   else if (Params.rootPath && !Params.rootPath->empty())
@@ -235,6 +237,27 @@
   C.reply(Result ? URI::fromFile(*Result).uri : "");
 }
 
+void ClangdLSPServer::onDocumentHighlight(Ctx C,
+                                          TextDocumentPositionParams &Params) {
+
+  auto Items = Server
+                   .findDocumentHighlights(Params.textDocument.uri.file,
+                                           Position{Params.position.line,
+                                                    Params.position.character})
+                   .Value;
+
+  std::string Highlights;
+
+//  for (const auto &Item : Items) {
+//    Highlights += DocumentHighlight::unparse(Item);
+//    Highlights += ",";
+//  }
+//  if (!Highlights.empty())
+//    Highlights.pop_back();
+//  C.reply("[" + Highlights + "]");
+  C.reply(json::ary(Items));
+}
+
 ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount,
                                  bool SnippetCompletions,
                                  llvm::Optional<StringRef> ResourceDir,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to