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

Removed some commented lines and temporary code
Streamlined and removed some code that overlaps/conflicts with code hover patch 
so it's easier to merge (patch https://reviews.llvm.org/D35894)

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": []
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,7 +46,6 @@
   JSONOutput *Out;
   ProtocolCallbacks *Callbacks;
 };
-
 } // namespace
 
 void clangd::registerCallbackHandlers(JSONRPCDispatcher &Dispatcher,
@@ -74,4 +73,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
@@ -615,6 +615,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
@@ -1128,3 +1128,11 @@
   }
   return Result;
 }
+
+json::Expr DocumentHighlight::unparse(const DocumentHighlight &DH) {
+
+  return json::obj{
+          {"range", Range::unparse(DH.range)},
+          {"kind", (int) DH.kind},
+      };
+}
Index: clangd/ClangdUnit.h
===================================================================
--- clangd/ClangdUnit.h
+++ clangd/ClangdUnit.h
@@ -315,10 +315,20 @@
 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);
 
+
+Location getDeclarationLocation(ParsedAST &AST, const SourceRange &ValSourceRange);
+
+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
@@ -941,6 +941,9 @@
 /// Finds declarations locations that a given source location refers to.
 class DeclarationLocationsFinder : public index::IndexDataConsumer {
   std::vector<Location> DeclarationLocations;
+  std::vector<const Decl *> DeclarationDecls;
+  std::vector<const MacroInfo *> DeclarationMacroInfos;
+  std::vector<DocumentHighlightKind> Kinds;
   const SourceLocation &SearchedLocation;
   const ASTContext &AST;
   Preprocessor &PP;
@@ -951,6 +954,26 @@
                              ASTContext &AST, Preprocessor &PP)
       : SearchedLocation(SearchedLocation), AST(AST), PP(PP) {}
 
+  std::vector<const Decl *> takeDecls() {
+       // Don't keep the same location multiple times.
+       // This can happen when nodes in the AST are visited twice.
+       std::sort(DeclarationDecls.begin(), DeclarationDecls.end());
+       auto last =
+           std::unique(DeclarationDecls.begin(), DeclarationDecls.end());
+       DeclarationDecls.erase(last, DeclarationDecls.end());
+       return std::move(DeclarationDecls);
+  }
+
+  std::vector<const MacroInfo *> takeDeclarationMacroInfos() {
+    // Don't keep the same location multiple times.
+    // This can happen when nodes in the AST are visited twice.
+    std::sort(DeclarationMacroInfos.begin(), DeclarationMacroInfos.end());
+    auto last =
+        std::unique(DeclarationMacroInfos.begin(), DeclarationMacroInfos.end());
+    DeclarationMacroInfos.erase(last, DeclarationMacroInfos.end());
+    return std::move(DeclarationMacroInfos);
+  }
+
   std::vector<Location> takeLocations() {
     // Don't keep the same location multiple times.
     // This can happen when nodes in the AST are visited twice.
@@ -966,12 +989,31 @@
                       ArrayRef<index::SymbolRelation> Relations, FileID FID,
                       unsigned Offset,
                       index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
+
     if (isSearchedLocation(FID, Offset)) {
       addDeclarationLocation(D->getSourceRange());
+      DeclarationDecls.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 *> getDeclarationDecls() { return DeclarationDecls; };
+  std::vector<const MacroInfo *> getDeclarationMacroInfos() { return DeclarationMacroInfos; };
+  std::vector<DocumentHighlightKind> getKinds() { return Kinds; };
+
 private:
   bool isSearchedLocation(FileID FID, unsigned Offset) const {
     const SourceManager &SourceMgr = AST.getSourceManager();
@@ -984,7 +1026,7 @@
     const LangOptions &LangOpts = AST.getLangOpts();
     SourceLocation LocStart = ValSourceRange.getBegin();
     SourceLocation LocEnd = Lexer::getLocForEndOfToken(ValSourceRange.getEnd(),
-                                                       0, SourceMgr, LangOpts);
+    0, SourceMgr, LangOpts);
     Position Begin;
     Begin.line = SourceMgr.getSpellingLineNumber(LocStart) - 1;
     Begin.character = SourceMgr.getSpellingColumnNumber(LocStart) - 1;
@@ -994,15 +1036,15 @@
     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);
-    }
-  }
+          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.
@@ -1026,16 +1068,77 @@
             PP.getMacroDefinitionAtLoc(IdentifierInfo, BeforeSearchedLocation);
         MacroInfo *MacroInf = MacroDef.getMacroInfo();
         if (MacroInf) {
-          addDeclarationLocation(SourceRange(MacroInf->getDefinitionLoc(),
-                                             MacroInf->getDefinitionEndLoc()));
+          addDeclarationLocation(SourceRange(MacroInf->getDefinitionLoc(), MacroInf->getDefinitionEndLoc()));
+          DeclarationMacroInfos.push_back(MacroInf);
         }
       }
     }
   }
 };
 
+/// Finds document highlights that a given FileID and file offset refers to.
+class DocumentHighlightsFinder : public index::IndexDataConsumer {
+  std::vector<const Decl *> &DeclarationDecls;
+  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)
+      : DeclarationDecls(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(DeclarationDecls.begin(), DeclarationDecls.end(), D) == DeclarationDecls.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 *> getDeclarationDecls() { return DeclarationDecls; };
+  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();
@@ -1059,6 +1162,109 @@
   return DeclLocationsFinder->takeLocations();
 }
 
+Location clangd::getDeclarationLocation(ParsedAST &AST,
+                                        const SourceRange &ValSourceRange) {
+  const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().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;
+  }
+  return L;
+}
+
+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->getDeclarationDecls();
+  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->getDeclarationMacroInfos().size(); I++) {
+    HighlightLocations.push_back(addHighlightLocation(
+        AST,
+        SourceRange(
+            DeclLocationsFinder->getDeclarationMacroInfos()[I]->getDefinitionLoc(),
+            DeclLocationsFinder->getDeclarationMacroInfos()[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() {
   if (PendingTopLevelDecls.empty())
     return;
Index: clangd/ClangdServer.h
===================================================================
--- clangd/ClangdServer.h
+++ clangd/ClangdServer.h
@@ -287,6 +287,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
@@ -504,6 +504,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())
@@ -234,6 +236,18 @@
   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;
+
+  C.reply(json::ary(Items));
+}
+
 ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount,
                                  bool StorePreamblesInMemory,
                                  bool SnippetCompletions,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to