VitaNuo updated this revision to Diff 509041.
VitaNuo added a comment.

Replace the used symbol computation impl.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144862/new/

https://reviews.llvm.org/D144862

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/XRefs.h

Index: clang-tools-extra/clangd/XRefs.h
===================================================================
--- clang-tools-extra/clangd/XRefs.h
+++ clang-tools-extra/clangd/XRefs.h
@@ -32,6 +32,8 @@
 namespace clangd {
 class ParsedAST;
 
+std::vector<CodeLens> findCodeLens(ParsedAST &AST);
+
 // Describes where a symbol is declared and defined (as far as clangd knows).
 // There are three cases:
 //  - a declaration only, no definition is known (e.g. only header seen)
Index: clang-tools-extra/clangd/XRefs.cpp
===================================================================
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -10,12 +10,15 @@
 #include "FindSymbols.h"
 #include "FindTarget.h"
 #include "HeuristicResolver.h"
+#include "IncludeCleaner.h"
 #include "ParsedAST.h"
 #include "Protocol.h"
 #include "Quality.h"
 #include "Selection.h"
 #include "SourceCode.h"
 #include "URI.h"
+#include "clang-include-cleaner/Analysis.h"
+#include "clang-include-cleaner/Types.h"
 #include "index/Index.h"
 #include "index/Merge.h"
 #include "index/Relation.h"
@@ -51,6 +54,7 @@
 #include "clang/Tooling/Syntax/Tokens.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallSet.h"
@@ -61,6 +65,7 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
 #include <optional>
+#include <string>
 #include <vector>
 
 namespace clang {
@@ -1312,8 +1317,67 @@
 }
 } // namespace
 
+std::vector<CodeLens> findCodeLens(ParsedAST &AST) {
+  const auto &SM = AST.getSourceManager();
+  std::vector<CodeLens> Result;
+  auto Includes = AST.getIncludeStructure().MainFileIncludes;
+  auto ConvertedMainFileIncludes = convertIncludes(SM, Includes);
+  for (auto &Inc : Includes) {
+    llvm::DenseSet<include_cleaner::Symbol> UsedSyms;
+    auto AnalyzedInclude = convertIncludes(SM, Inc);
+    include_cleaner::walkUsed(
+        AST.getLocalTopLevelDecls(), collectMacroReferences(AST),
+        AST.getPragmaIncludes(), SM,
+        [&](const include_cleaner::SymbolReference &Ref,
+            llvm::ArrayRef<include_cleaner::Header> Providers) {
+          if (Ref.RT != include_cleaner::RefType::Explicit)
+            return;
+
+          for (const auto &H : Providers) {
+            auto MatchingIncludes = ConvertedMainFileIncludes.match(H);
+            // No match for this provider in the main file.
+            if (MatchingIncludes.empty())
+              continue;
+
+            // Check if the referenced include matches this provider.
+            if (!AnalyzedInclude.match(H).empty()) {
+              UsedSyms.insert(Ref.Target);
+            }
+
+            // Don't look for rest of the providers once we've found a match
+            // in the main file.
+            break;
+          }
+        });
+
+    // Compute the length of the #include line
+    auto IncludeLen =
+        std::string{"#include"}.length() + Inc.Written.length() + 1;
+    CodeLens Lens;
+    Lens.range = clangd::Range{Position{Inc.HashLine, 0},
+                               Position{Inc.HashLine, (int)IncludeLen}};
+
+    Command Cmd;
+    Cmd.title = std::to_string(UsedSyms.size()) + " used symbols";
+    Cmd.command = "references-view.findReferences";
+    
+    auto MainFilePath = AST.tuPath();
+    auto URIMainFile = URIForFile::canonicalize(MainFilePath, MainFilePath);
+   
+    Cmd.argument = TextDocumentIdentifier{URIMainFile};
+    const Position &P = sourceLocToPosition(SM, SM.getComposedLoc(SM.getMainFileID(), Inc.HashOffset));
+    Cmd.argument2 = P;
+    Lens.command = Cmd;
+    Result.push_back(Lens);  
+  }
+  
+  return Result;
+}
+
 ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
                                 const SymbolIndex *Index, bool AddContext) {
+  llvm::errs() << "Find references for path: " << AST.tuPath() << "\n";
+  llvm::errs() << "Find references for position: " << Pos << "\n";
   ReferencesResult Results;
   const SourceManager &SM = AST.getSourceManager();
   auto MainFilePath = AST.tuPath();
@@ -1324,6 +1388,58 @@
     return {};
   }
 
+  auto Includes = AST.getIncludeStructure().MainFileIncludes;
+  auto ConvertedMainFileIncludes = convertIncludes(SM, Includes);
+  for (auto &Inc : Includes) {
+    if (Inc.HashLine != Pos.line)
+      continue;
+
+    auto ReferencedInclude = convertIncludes(SM, Inc);
+    include_cleaner::walkUsed(
+        AST.getLocalTopLevelDecls(), collectMacroReferences(AST),
+        AST.getPragmaIncludes(), SM,
+        [&](const include_cleaner::SymbolReference &Ref,
+            llvm::ArrayRef<include_cleaner::Header> Providers) {
+          if (Ref.RT != include_cleaner::RefType::Explicit)
+            return;
+
+          auto Loc = SM.getFileLoc(Ref.RefLocation);
+          for (const auto &H : Providers) {
+            auto MatchingIncludes = ConvertedMainFileIncludes.match(H);
+            // No match for this provider in the main file.
+            if (MatchingIncludes.empty())
+              continue;
+
+            // Check if the referenced include matches this provider.
+            if (!ReferencedInclude.match(H).empty()) {
+              ReferencesResult::Reference Result;
+              auto TokLen =
+                  Lexer::MeasureTokenLength(Loc, SM, AST.getLangOpts());
+              Result.Loc.range =
+                  halfOpenToRange(SM, CharSourceRange::getCharRange(
+                                          Loc, Loc.getLocWithOffset(TokLen)));
+              Result.Loc.uri = URIMainFile;
+              Results.References.push_back(std::move(Result));
+            }
+
+            // Don't look for rest of the providers once we've found a match
+            // in the main file.
+            return;
+          }
+        });
+    if (Results.References.empty())
+      return {};
+
+    // Add the #include line to the references list.
+    auto IncludeLen =
+        std::string{"#include"}.length() + Inc.Written.length() + 1;
+    ReferencesResult::Reference Result;
+    Result.Loc.range = clangd::Range{Position{Inc.HashLine, 0},
+                                     Position{Inc.HashLine, (int)IncludeLen}};
+    Result.Loc.uri = URIMainFile;
+    Results.References.push_back(std::move(Result));
+  }
+
   llvm::DenseSet<SymbolID> IDsToQuery, OverriddenMethods;
 
   const auto *IdentifierAtCursor =
Index: clang-tools-extra/clangd/Protocol.h
===================================================================
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -998,6 +998,7 @@
   // This is `arguments?: []any` in LSP.
   // All clangd's commands accept a single argument (or none => null).
   llvm::json::Value argument = nullptr;
+  llvm::json::Value argument2 = nullptr;
 };
 bool fromJSON(const llvm::json::Value &, ExecuteCommandParams &,
               llvm::json::Path);
@@ -1876,6 +1877,23 @@
 llvm::json::Value toJSON(const ASTNode &);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const ASTNode &);
 
+/// Parameters for the code lens request.
+struct CodeLensParams {
+  TextDocumentIdentifier textDocument;
+};
+bool fromJSON(const llvm::json::Value &, CodeLensParams &,
+              llvm::json::Path);
+
+/// Code lens response payload.
+struct CodeLens {
+  /// The range in which this code lens is valid.
+  Range range;
+  /// The command this code lens represents.
+  Command command;
+};
+llvm::json::Value toJSON(const CodeLens &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const CodeLens &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/Protocol.cpp
===================================================================
--- clang-tools-extra/clangd/Protocol.cpp
+++ clang-tools-extra/clangd/Protocol.cpp
@@ -535,6 +535,23 @@
   return O && O.map("textDocument", R.textDocument);
 }
 
+bool fromJSON(const llvm::json::Value &Params, CodeLensParams &R,
+              llvm::json::Path P) {
+  llvm::json::ObjectMapper O(Params, P);
+  return O && O.map("textDocument", R.textDocument);
+}
+
+llvm::json::Value toJSON(const CodeLens &CL) {
+  return llvm::json::Object {
+    {"range", CL.range},
+    {"command", CL.command}
+  };
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const CodeLens &CL) {
+  return OS << "Code lens: " << CL.range.start << '-' << CL.range.end;
+}
+
 bool fromJSON(const llvm::json::Value &Params, DidSaveTextDocumentParams &R,
               llvm::json::Path P) {
   llvm::json::ObjectMapper O(Params, P);
@@ -810,9 +827,19 @@
 }
 
 llvm::json::Value toJSON(const Command &C) {
+  llvm::errs() << "ENCODING COMMAND: ";
+  llvm::errs() << C.title << "\n";
+  llvm::errs() << C.command << "\n";
+  llvm::errs() << C.argument << "\n";
+  llvm::errs() << C.argument2 << "\n";
   auto Cmd = llvm::json::Object{{"title", C.title}, {"command", C.command}};
   if (!C.argument.getAsNull())
-    Cmd["arguments"] = llvm::json::Array{C.argument};
+    Cmd["arguments"] = llvm::json::Array{C.argument, C.argument2};
+  
+  llvm::errs() << "DECODING COMMAND: ";
+  llvm::json::Array *Args = Cmd.getArray("arguments");
+  llvm::errs() << "FIRST ARG: " << (*Args)[0] << "\n";
+  llvm::errs() << "SECOND ARG: " << (*Args)[1] << "\n";
   return std::move(Cmd);
 }
 
@@ -888,8 +915,10 @@
 bool fromJSON(const llvm::json::Value &Params, TextDocumentPositionParams &R,
               llvm::json::Path P) {
   llvm::json::ObjectMapper O(Params, P);
+  const auto &PositionSuccess = O.map("position", R.position);
+  llvm::errs() << "REF PARAMS FROM JSON: " << R.position << "\n";
   return O && O.map("textDocument", R.textDocument) &&
-         O.map("position", R.position);
+         PositionSuccess;
 }
 
 bool fromJSON(const llvm::json::Value &Params, CompletionContext &R,
Index: clang-tools-extra/clangd/ClangdServer.h
===================================================================
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -305,6 +305,9 @@
   void findReferences(PathRef File, Position Pos, uint32_t Limit,
                       bool AddContainer, Callback<ReferencesResult> CB);
 
+  /// Retrieve code lenses.
+  void findCodeLens(PathRef File, Callback<std::vector<CodeLens>> CB);
+
   /// Run formatting for the \p File with content \p Code.
   /// If \p Rng is non-null, formats only that region.
   void formatFile(PathRef File, std::optional<Range> Rng,
Index: clang-tools-extra/clangd/ClangdServer.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -911,6 +911,17 @@
   WorkScheduler->runWithAST("References", File, std::move(Action));
 }
 
+void ClangdServer::findCodeLens(PathRef File, Callback<std::vector<CodeLens>> CB) {
+  auto Action = [CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
+    if (!InpAST) 
+      return CB(InpAST.takeError());    
+    
+    CB(clangd::findCodeLens(InpAST->AST));
+  };
+
+  WorkScheduler->runWithAST("CodeLens", File, std::move(Action));
+}
+
 void ClangdServer::symbolInfo(PathRef File, Position Pos,
                               Callback<std::vector<SymbolDetails>> CB) {
   auto Action =
Index: clang-tools-extra/clangd/ClangdLSPServer.h
===================================================================
--- clang-tools-extra/clangd/ClangdLSPServer.h
+++ clang-tools-extra/clangd/ClangdLSPServer.h
@@ -173,6 +173,9 @@
   void onCommandApplyEdit(const WorkspaceEdit &, Callback<llvm::json::Value>);
   void onCommandApplyTweak(const TweakArgs &, Callback<llvm::json::Value>);
 
+  /// Implement code lens.
+  void onCodeLens(const CodeLensParams &Params, Callback<std::vector<CodeLens>> Reply);
+
   /// Outgoing LSP calls.
   LSPBinder::OutgoingMethod<ApplyWorkspaceEditParams,
                             ApplyWorkspaceEditResponse>
Index: clang-tools-extra/clangd/ClangdLSPServer.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -586,6 +586,7 @@
       {"clangdInlayHintsProvider", true},
       {"inlayHintProvider", true},
       {"foldingRangeProvider", true},
+      {"codeLensProvider", true},
   };
 
   {
@@ -1379,6 +1380,8 @@
 void ClangdLSPServer::onReference(
     const ReferenceParams &Params,
     Callback<std::vector<ReferenceLocation>> Reply) {
+  llvm::errs() << "DOC: " << Params.textDocument.uri.file() << "\n";
+  llvm::errs() << "POSITION: " << Params.position << "\n";
   Server->findReferences(Params.textDocument.uri.file(), Params.position,
                          Opts.ReferencesLimit, SupportsReferenceContainer,
                          [Reply = std::move(Reply),
@@ -1399,6 +1402,11 @@
                          });
 }
 
+void ClangdLSPServer::onCodeLens(const CodeLensParams &Params,
+    Callback<std::vector<CodeLens>> Reply) {
+  Server->findCodeLens(Params.textDocument.uri.file(), std::move(Reply));
+}
+
 void ClangdLSPServer::onGoToType(const TextDocumentPositionParams &Params,
                                  Callback<std::vector<Location>> Reply) {
   Server->findType(
@@ -1589,6 +1597,7 @@
   Bind.method("textDocument/typeDefinition", this, &ClangdLSPServer::onGoToType);
   Bind.method("textDocument/implementation", this, &ClangdLSPServer::onGoToImplementation);
   Bind.method("textDocument/references", this, &ClangdLSPServer::onReference);
+  Bind.method("textDocument/codeLens", this, &ClangdLSPServer::onCodeLens);
   Bind.method("textDocument/switchSourceHeader", this, &ClangdLSPServer::onSwitchSourceHeader);
   Bind.method("textDocument/prepareRename", this, &ClangdLSPServer::onPrepareRename);
   Bind.method("textDocument/rename", this, &ClangdLSPServer::onRename);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to