malaperle updated this revision to Diff 157732.
malaperle added a comment.

Fix silly bug I introduced in last minute clean-up.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D49920

Files:
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  clangd/XRefs.cpp
  clangd/XRefs.h
  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
@@ -29,6 +29,7 @@
 # CHECK-NEXT:        ]
 # CHECK-NEXT:      },
 # CHECK-NEXT:      "hoverProvider": true,
+# CHECK-NEXT:      "referencesProvider": true,
 # CHECK-NEXT:      "renameProvider": true,
 # CHECK-NEXT:      "signatureHelpProvider": {
 # CHECK-NEXT:        "triggerCharacters": [
Index: test/clangd/initialize-params-invalid.test
===================================================================
--- test/clangd/initialize-params-invalid.test
+++ test/clangd/initialize-params-invalid.test
@@ -29,6 +29,7 @@
 # CHECK-NEXT:        ]
 # CHECK-NEXT:      },
 # CHECK-NEXT:      "hoverProvider": true,
+# CHECK-NEXT:      "referencesProvider": true,
 # CHECK-NEXT:      "renameProvider": true,
 # CHECK-NEXT:      "signatureHelpProvider": {
 # CHECK-NEXT:        "triggerCharacters": [
Index: clangd/XRefs.h
===================================================================
--- clangd/XRefs.h
+++ clangd/XRefs.h
@@ -30,6 +30,9 @@
 std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
                                                       Position Pos);
 
+std::vector<Location> findReferences(ParsedAST &AST, Position Pos,
+                                     bool IncludeDeclaration);
+
 /// Get the hover information when hovering at \p Pos.
 llvm::Optional<Hover> getHover(ParsedAST &AST, Position Pos);
 
Index: clangd/XRefs.cpp
===================================================================
--- clangd/XRefs.cpp
+++ clangd/XRefs.cpp
@@ -211,6 +211,58 @@
   return SymbolID(USR);
 }
 
+/// Finds declarations locations that a given source Decl refers to, in the main
+/// file.
+class ReferenceLocationsFinder : public index::IndexDataConsumer {
+  std::vector<Location> ReferenceLocations;
+  ParsedAST &AST;
+  const Decl *ReferencedDecl;
+  index::SymbolRoleSet InterestingRoleSet;
+
+public:
+  ReferenceLocationsFinder(ParsedAST &AST, const Decl *D,
+                           bool IncludeDeclaration)
+      : AST(AST), ReferencedDecl(D),
+        InterestingRoleSet(
+            static_cast<index::SymbolRoleSet>(index::SymbolRole::Reference)) {
+    if (IncludeDeclaration)
+      InterestingRoleSet |=
+          static_cast<index::SymbolRoleSet>(index::SymbolRole::Declaration) |
+          static_cast<index::SymbolRoleSet>(index::SymbolRole::Definition);
+  }
+
+  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(ReferenceLocations.begin(), ReferenceLocations.end());
+    auto last =
+        std::unique(ReferenceLocations.begin(), ReferenceLocations.end());
+    ReferenceLocations.erase(last, ReferenceLocations.end());
+    return std::move(ReferenceLocations);
+  }
+
+  bool
+  handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
+                      ArrayRef<index::SymbolRelation> Relations,
+                      SourceLocation Loc,
+                      index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
+    const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+    if (D != ReferencedDecl || !SourceMgr.isWrittenInMainFile(Loc)) {
+      return true;
+    }
+
+    // The end loc is adjusted in makeLocation with getLocForEndOfToken.
+    SourceRange Range(Loc, Loc);
+
+    if (Roles & InterestingRoleSet) {
+      auto L = makeLocation(AST, Range);
+      if (L)
+        ReferenceLocations.push_back(*L);
+    }
+    return true;
+  }
+};
+
 } // namespace
 
 std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos,
@@ -324,6 +376,45 @@
   return Result;
 }
 
+std::vector<Location> findReferences(ParsedAST &AST, Position Pos,
+                                     bool IncludeDeclaration) {
+  SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
+  SourceLocation SourceLocationBeg =
+      getBeginningOfIdentifier(AST, Pos, SourceMgr.getMainFileID());
+
+  DeclarationAndMacrosFinder DeclMacrosFinder(llvm::errs(), SourceLocationBeg,
+                                              AST.getASTContext(),
+                                              AST.getPreprocessor());
+  index::IndexingOptions IndexOpts;
+  IndexOpts.SystemSymbolFilter =
+      index::IndexingOptions::SystemSymbolFilterKind::All;
+  IndexOpts.IndexFunctionLocals = true;
+  indexTopLevelDecls(AST.getASTContext(), AST.getLocalTopLevelDecls(),
+                     DeclMacrosFinder, IndexOpts);
+  std::vector<const Decl *> Decls = DeclMacrosFinder.takeDecls();
+  if (Decls.empty())
+    return {};
+
+  // Make CXXConstructorDecl lower priority. For example:
+  // MyClass Obj;
+  // We likely want to find the references to Obj not MyClass()
+  std::sort(Decls.begin(), Decls.end(), [](const Decl *&D1, const Decl *&D2) {
+    return !dyn_cast<CXXConstructorDecl>(D1);
+  });
+
+  const Decl *D = Decls[0];
+
+  if (!index::isFunctionLocalSymbol(D)) {
+    return {};
+  }
+
+  ReferenceLocationsFinder ReferencesFinder(AST, D, IncludeDeclaration);
+  indexTopLevelDecls(AST.getASTContext(), AST.getLocalTopLevelDecls(),
+                     ReferencesFinder, IndexOpts);
+
+  return ReferencesFinder.takeLocations();
+}
+
 namespace {
 
 /// Finds document highlights that a given list of declarations refers to.
Index: clangd/ProtocolHandlers.h
===================================================================
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams &Params) = 0;
   virtual void onHover(TextDocumentPositionParams &Params) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams &Params) = 0;
+  virtual void onReferences(ReferenceParams &Params) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher &Dispatcher,
Index: clangd/ProtocolHandlers.cpp
===================================================================
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
            &ProtocolCallbacks::onChangeConfiguration);
   Register("workspace/symbol", &ProtocolCallbacks::onWorkspaceSymbol);
+  Register("textDocument/references", &ProtocolCallbacks::onReferences);
 }
Index: clangd/Protocol.h
===================================================================
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -633,6 +633,17 @@
 };
 llvm::json::Value toJSON(const Hover &H);
 
+struct ReferenceContext {
+  /// Include the declaration of the current symbol.
+  bool includeDeclaration;
+};
+bool fromJSON(const llvm::json::Value &Params, ReferenceContext &R);
+
+struct ReferenceParams : public TextDocumentPositionParams {
+  ReferenceContext context;
+};
+bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R);
+
 /// The kind of a completion entry.
 enum class CompletionItemKind {
   Missing = 0,
Index: clangd/Protocol.cpp
===================================================================
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -509,6 +509,17 @@
   return std::move(Result);
 }
 
+bool fromJSON(const json::Value &Params, ReferenceContext &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("includeDeclaration", R.includeDeclaration);
+}
+
+bool fromJSON(const json::Value &Params, ReferenceParams &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("context", R.context) &&
+         O.map("textDocument", R.textDocument) && O.map("position", R.position);
+}
+
 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const CompletionItem &I) {
   O << I.label << " - " << toJSON(I);
   return O;
Index: clangd/ClangdServer.h
===================================================================
--- clangd/ClangdServer.h
+++ clangd/ClangdServer.h
@@ -136,6 +136,11 @@
   void findDefinitions(PathRef File, Position Pos,
                        Callback<std::vector<Location>> CB);
 
+  /// Get references of symbol at a specified \p Line and
+  /// \p Column in \p File.
+  void findReferences(PathRef File, Position Pos, bool IncludeDeclaration,
+                      Callback<std::vector<Location>> CB);
+
   /// Helper function that returns a path to the corresponding source file when
   /// given a header file and vice versa.
   llvm::Optional<Path> switchSourceHeader(PathRef Path);
Index: clangd/ClangdServer.cpp
===================================================================
--- clangd/ClangdServer.cpp
+++ clangd/ClangdServer.cpp
@@ -452,6 +452,21 @@
                                  RootPath ? *RootPath : ""));
 }
 
+void ClangdServer::findReferences(PathRef File, Position Pos,
+                                  bool IncludeDeclaration,
+                                  Callback<std::vector<Location>> CB) {
+  auto FS = FSProvider.getFileSystem();
+  auto Action = [this, Pos, FS,
+                 IncludeDeclaration](Callback<std::vector<Location>> CB,
+                                     llvm::Expected<InputsAndAST> InpAST) {
+    if (!InpAST)
+      return CB(InpAST.takeError());
+    CB(clangd::findReferences(InpAST->AST, Pos, IncludeDeclaration));
+  };
+
+  WorkScheduler.runWithAST("Definitions", File, Bind(Action, std::move(CB)));
+}
+
 void ClangdServer::documentSymbols(
     StringRef File, Callback<std::vector<SymbolInformation>> CB) {
   auto Action = [](Callback<std::vector<SymbolInformation>> CB,
Index: clangd/ClangdLSPServer.h
===================================================================
--- clangd/ClangdLSPServer.h
+++ clangd/ClangdLSPServer.h
@@ -75,6 +75,7 @@
   void onRename(RenameParams &Parames) override;
   void onHover(TextDocumentPositionParams &Params) override;
   void onChangeConfiguration(DidChangeConfigurationParams &Params) override;
+  void onReferences(ReferenceParams &Params) override;
 
   std::vector<Fix> getFixes(StringRef File, const clangd::Diagnostic &D);
 
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -119,6 +119,7 @@
              json::Object{
                  {"commands", {ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND}},
              }},
+            {"referencesProvider", true},
         }}}});
 }
 
@@ -413,6 +414,18 @@
   }
 }
 
+void ClangdLSPServer::onReferences(ReferenceParams &Params) {
+  Server.findReferences(Params.textDocument.uri.file(), Params.position,
+                        Params.context.includeDeclaration,
+                        [](llvm::Expected<std::vector<Location>> Items) {
+                          if (!Items)
+                            return replyError(
+                                ErrorCode::InvalidParams,
+                                llvm::toString(Items.takeError()));
+                          reply(json::Array(*Items));
+                        });
+}
+
 ClangdLSPServer::ClangdLSPServer(JSONOutput &Out,
                                  const clangd::CodeCompleteOptions &CCOpts,
                                  llvm::Optional<Path> CompileCommandsDir,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to