VitaNuo created this revision.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
VitaNuo requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

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/Hover.cpp
  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
@@ -16,6 +16,8 @@
 #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"
@@ -62,9 +64,11 @@
 #include "llvm/Support/raw_ostream.h"
 #include <optional>
 #include <vector>
+#include <string> 
 
 namespace clang {
 namespace clangd {
+std::string HelloString = "Hello";
 namespace {
 
 // Returns the single definition of the entity declared by D, if visible.
@@ -74,6 +78,7 @@
 // Kinds of nodes that always return nullptr here will not have definitions
 // reported by locateSymbolAt().
 const NamedDecl *getDefinition(const NamedDecl *D) {
+  std::string AnotherString;
   assert(D);
   // Decl has one definition that we can find.
   if (const auto *TD = dyn_cast<TagDecl>(D))
@@ -118,6 +123,7 @@
 // FindSymbols.
 std::optional<Location> toLSPLocation(const SymbolLocation &Loc,
                                       llvm::StringRef TUPath) {
+  std::string ThirdString;
   if (!Loc)
     return std::nullopt;
   auto Uri = URI::parse(Loc.FileURI);
@@ -1213,8 +1219,50 @@
   return std::nullopt;
 }
 
+std::vector<include_cleaner::SymbolReference>
+collectMacroReferences(ParsedAST &AST) {
+  const auto &SM = AST.getSourceManager();
+  //  FIXME: !!this is a hacky way to collect macro references.
+  std::vector<include_cleaner::SymbolReference> Macros;
+  auto &PP = AST.getPreprocessor();
+  for (const syntax::Token &Tok :
+       AST.getTokens().spelledTokens(SM.getMainFileID())) {
+    auto Macro = locateMacroAt(Tok, PP);
+    if (!Macro)
+      continue;
+    if (auto DefLoc = Macro->Info->getDefinitionLoc(); DefLoc.isValid())
+      Macros.push_back(
+          {Tok.location(),
+           include_cleaner::Macro{/*Name=*/PP.getIdentifierInfo(Tok.text(SM)),
+                                  DefLoc},
+           include_cleaner::RefType::Explicit});
+  }
+  return Macros;
+}
+
 } // namespace
 
+include_cleaner::Includes
+convertIncludes(const SourceManager &SM,
+                const llvm::ArrayRef<Inclusion> MainFileIncludes) {
+  include_cleaner::Includes Includes;
+  for (const Inclusion &Inc : MainFileIncludes) {
+    include_cleaner::Include TransformedInc;
+    llvm::StringRef WrittenRef = llvm::StringRef(Inc.Written);
+    TransformedInc.Spelled = WrittenRef.trim("\"<>");
+    TransformedInc.HashLocation =
+        SM.getComposedLoc(SM.getMainFileID(), Inc.HashOffset);
+    TransformedInc.Line = Inc.HashLine + 1;
+    TransformedInc.Angled = WrittenRef.starts_with("<");
+    auto FE = SM.getFileManager().getFile(Inc.Resolved);
+    if (!FE)
+      continue;
+    TransformedInc.Resolved = *FE;
+    Includes.add(std::move(TransformedInc));
+  }
+  return Includes;
+}
+
 std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
                                                       Position Pos) {
   const SourceManager &SM = AST.getSourceManager();
@@ -1231,11 +1279,96 @@
           DeclRelation::TemplatePattern | DeclRelation::Alias;
       auto TargetDecls =
           targetDecl(N->ASTNode, Relations, AST.getHeuristicResolver());
+
+      const IncludeStructure &Includes = AST.getIncludeStructure();
+      include_cleaner::Includes ConvertedIncludes =
+      convertIncludes(AST.getSourceManager(), Includes.MainFileIncludes);
+      include_cleaner::walkUsed(
+        AST.getLocalTopLevelDecls(),
+        collectMacroReferences(AST),
+        AST.getPragmaIncludes(),
+        AST.getSourceManager(),
+        [&](const include_cleaner::SymbolReference &Ref,
+        llvm::ArrayRef<include_cleaner::Header> Providers) {
+            // std::string SymbolName;
+            // switch (Ref.Target.kind()) {
+            // case include_cleaner::Symbol::Macro:
+            //   break;
+            // case include_cleaner::Symbol::Declaration:
+            //   SymbolName = static_cast<const NamedDecl &>(Ref.Target.declaration()).getNameAsString();
+            //   if (SymbolName == "string") {
+            //     llvm::errs() << "FOUND STRING" << "\n";
+            //     llvm::errs() << "CUR LOCATION: " << "\n";
+            //     llvm::errs() << SM.getDecomposedLoc(*CurLoc).second << "\n"; 
+            //     llvm::errs() << "REF LOCATION: " << "\n";
+            //     llvm::errs() << SM.getDecomposedLoc(Ref.RefLocation).second << "\n";   
+            //   }
+            //   break;
+            // }
+            if (Ref.RefLocation != *CurLoc) {
+              return;  
+            }
+            llvm::errs() << "GOT PAST THE GUARD" << "\n";
+            // the location under cursor corresponds to the current symbol reference
+            // need to find the position of the include
+            for (const auto &H : Providers) {
+            //   switch (H.kind()) {
+            //     case include_cleaner::Header::Physical:
+            //       llvm::errs() << "It's a physical provider\n";
+            //       if (auto HeaderID = Includes.getID(H.physical())) {
+            //         llvm::errs() << "Physical provider: " << Includes.getRealPath(*HeaderID) << "\n";
+            //       }
+            //     break;
+            //     case include_cleaner::Header::Standard:
+            //       llvm::errs() << "It's a standard provider\n";
+            //       for (auto HeaderID : Includes.StdlibHeaders.lookup(H.standard())) {
+            //         llvm::errs() << "Standard provider: " << Includes.getRealPath(HeaderID) << "\n";
+            //       }
+            //     break;
+            //     case include_cleaner::Header::Verbatim:
+            //       llvm::errs() << "It's a verbatim provider\n";
+            //       for (auto Inc : Includes.MainFileIncludes) {
+            //         if (auto HeaderID = Inc.HeaderID) {
+            //           llvm::errs() << "Verbatim provider: " <<
+            //            Includes.getRealPath(static_cast<IncludeStructure::HeaderID>(*HeaderID)) << "\n";
+            //         }
+            //       }
+            //   }
+              for (auto Inc : Includes.MainFileIncludes) {
+                if (Inc.Written == "<string>") {
+                  llvm::errs() << "Included in main: " << Inc.Written << "\n";
+                }
+              }
+              for (auto *&Inc : ConvertedIncludes.match(H)) {
+                llvm::errs() << "Found match\n";
+                auto FID = SM.getFileID(SM.getFileLoc(Inc->HashLocation));
+                llvm::errs() << "FID: " << FID.getHashValue() << "\n";
+                auto Highlight = toHighlight(Inc->HashLocation, AST.getTokens());
+                llvm::errs() <<(Highlight.has_value() ? "Highlight" : "No highlight") << "\n";
+                // found the include in the includes list
+                // navigate to location
+                if (auto Highlight = toHighlight(Inc->HashLocation, AST.getTokens())) {
+                  for (unsigned i = 1; i < 17; i++) {
+                    if (auto HighlightNext = toHighlight(SM.getComposedLoc(SM.getMainFileID(),
+                     SM.getDecomposedLoc(Inc->HashLocation).second + i), AST.getTokens())) {
+                        Result.push_back(*HighlightNext);
+                     }
+                  }
+                  llvm::errs() << "COULD BUILD THE HIGHLIGHT FOR " << Inc->Spelled << "\n";
+                  Result.push_back(*Highlight);
+                } else {
+                   llvm::errs() << "COULD NOT BUILD THE HIGHLIGHT FOR " << Inc->Spelled << "\n";
+                }
+              }
+            }
+      });
+
       if (!TargetDecls.empty()) {
         // FIXME: we may get multiple DocumentHighlights with the same location
         // and different kinds, deduplicate them.
         for (const auto &Ref : findRefs(TargetDecls, AST, /*PerToken=*/true))
           Result.push_back(toHighlight(Ref, SM));
+        // TODO (bakalova) include-cleaner analysis here
         return true;
       }
       auto ControlFlow = relatedControlFlow(*N);
@@ -1312,6 +1445,90 @@
 }
 } // namespace
 
+std::vector<CodeLens> findCodeLens(ParsedAST &AST) {
+  // TODO(bakalova) find ranges
+  // TODO(bakalova) find used symbols
+
+  std::vector<CodeLens> Result;
+  std::vector<Inclusion> Includes = AST.getIncludeStructure().MainFileIncludes;
+
+  IncludeSpelling S;
+  S.spelling = "string";
+  for (auto Inclusion : Includes) {
+    std::set<std::string> UsedSymbols;
+    walkUsed(AST.getLocalTopLevelDecls(),
+        collectMacroReferences(AST),
+        AST.getPragmaIncludes(),
+        AST.getSourceManager(),
+        [&](const include_cleaner::SymbolReference &Ref,
+        llvm::ArrayRef<include_cleaner::Header> Providers) {
+
+    std::string Name;
+    switch(Ref.Target.kind()) {
+       case include_cleaner::Symbol::Declaration:
+        Name = cast<NamedDecl>(Ref.Target.declaration())
+            .getDeclName()
+            .getAsString();   
+        break;
+      case include_cleaner::Symbol::Macro:
+        Name = Ref.Target.macro().Name->getName(); 
+        break;
+    }      
+    for (const include_cleaner::Header &H : Providers) {
+      switch (H.kind()) {
+      case include_cleaner::Header::Physical:
+        if (H.physical()->tryGetRealPathName().contains(
+                llvm::StringRef(Inclusion.Written).trim("\"<>"))) {
+          UsedSymbols.insert(Name);
+        }
+        break;
+      case include_cleaner::Header::Standard:
+        if (Inclusion.Written == H.standard().name()) {
+          UsedSymbols.insert(Name);
+        }
+        break;
+      // TODO(bakalova) does the verbatim thing include quotes or not?
+      case include_cleaner::Header::Verbatim:
+        if (Inclusion.Written == H.verbatim()) {
+          UsedSymbols.insert(Name);
+        }
+        break;
+      }
+    }
+  });
+
+    CodeLens Lens;
+    Lens.range = clangd::Range{Position{Inclusion.HashLine, 0}, Position{Inclusion.HashLine, 0}};
+    Command cmd;
+    
+    std::vector<std::string> UsedSymbolsDeduped;
+    for (auto Sym : UsedSymbols) {
+      UsedSymbolsDeduped.push_back(Sym);
+    }
+
+    for (unsigned i = 0; i < 4 && i < UsedSymbolsDeduped.size(); i++) {
+      std::string Name = UsedSymbolsDeduped[i];
+      cmd.title += Name;
+      cmd.title += " | ";
+    }
+    if (UsedSymbols.size() >= 5) {
+      cmd.title += UsedSymbolsDeduped[4];
+      cmd.title += " | ...";
+    }
+    
+    cmd.command = "HelloWorld";
+    cmd.argument = toJSON(S);
+    Lens.command = cmd;
+    Result.push_back(Lens);  
+  }
+  
+  
+  for (auto CodeLens : Result) {
+    llvm::errs() << "CODE LENS: " << CodeLens << "\n";
+  }
+  return Result;
+}
+
 ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
                                 const SymbolIndex *Index, bool AddContext) {
   ReferencesResult Results;
Index: clang-tools-extra/clangd/Protocol.h
===================================================================
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -976,6 +976,12 @@
 bool fromJSON(const llvm::json::Value &, WorkspaceEdit &, llvm::json::Path);
 llvm::json::Value toJSON(const WorkspaceEdit &WE);
 
+struct IncludeSpelling {
+  std::string spelling;
+};
+bool fromJSON(const llvm::json::Value &, IncludeSpelling &, llvm::json::Path);
+llvm::json::Value toJSON(const IncludeSpelling &IS);
+
 /// Arguments for the 'applyTweak' command. The server sends these commands as a
 /// response to the textDocument/codeAction request. The client can later send a
 /// command back to the server if the user requests to execute a particular code
@@ -1876,6 +1882,19 @@
 llvm::json::Value toJSON(const ASTNode &);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const ASTNode &);
 
+struct CodeLensParams {
+  TextDocumentIdentifier textDocument;
+};
+bool fromJSON(const llvm::json::Value &, CodeLensParams &,
+              llvm::json::Path);
+
+struct CodeLens {
+  Range range;
+  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,17 @@
   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);
+}
+
+bool fromJSON(const llvm::json::Value &Params, IncludeSpelling &R, llvm::json::Path P) {
+  llvm::json::ObjectMapper O(Params, P);
+  return O && O.map("spelling", R.spelling);
+}
+
 bool fromJSON(const llvm::json::Value &Params, DidSaveTextDocumentParams &R,
               llvm::json::Path P) {
   llvm::json::ObjectMapper O(Params, P);
@@ -613,6 +624,22 @@
   };
 }
 
+llvm::json::Value toJSON(const IncludeSpelling &IS) {
+  return llvm::json::Object{
+    {"spelling", IS.spelling}
+  };
+}
+
+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;
+}
+
 llvm::json::Value toJSON(DiagnosticTag Tag) { return static_cast<int>(Tag); }
 
 llvm::json::Value toJSON(const CodeDescription &D) {
Index: clang-tools-extra/clangd/Hover.cpp
===================================================================
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -15,6 +15,8 @@
 #include "ParsedAST.h"
 #include "Selection.h"
 #include "SourceCode.h"
+#include "clang-include-cleaner/Analysis.h"
+#include "clang-include-cleaner/Types.h"
 #include "index/SymbolCollector.h"
 #include "support/Markup.h"
 #include "clang/AST/ASTContext.h"
@@ -1084,8 +1086,67 @@
   return Candidates.front();
 }
 
+std::vector<include_cleaner::SymbolReference>
+collectMacroReferences(ParsedAST &AST) {
+  const auto &SM = AST.getSourceManager();
+  //  FIXME: !!this is a hacky way to collect macro references.
+  std::vector<include_cleaner::SymbolReference> Macros;
+  auto &PP = AST.getPreprocessor();
+  for (const syntax::Token &Tok :
+       AST.getTokens().spelledTokens(SM.getMainFileID())) {
+    auto Macro = locateMacroAt(Tok, PP);
+    if (!Macro)
+      continue;
+    if (auto DefLoc = Macro->Info->getDefinitionLoc(); DefLoc.isValid())
+      Macros.push_back(
+          {Tok.location(),
+           include_cleaner::Macro{/*Name=*/PP.getIdentifierInfo(Tok.text(SM)),
+                                  DefLoc},
+           include_cleaner::RefType::Explicit});
+  }
+  return Macros;
+}
+
 } // namespace
 
+void maybeAddHeaderProvider(ParsedAST &AST, HoverInfo &HI, SourceLocation CurLoc) {
+  llvm::errs() << "CALLED ADD HEADER PROVIDER\n";
+  include_cleaner::walkUsed(AST.getLocalTopLevelDecls(),
+      collectMacroReferences(AST),
+      AST.getPragmaIncludes(),
+      AST.getSourceManager(),
+      [&](const include_cleaner::SymbolReference &Ref,
+      llvm::ArrayRef<include_cleaner::Header> Providers) {
+        if (Ref.RefLocation != CurLoc) {
+          return;  
+        }
+        StringRef ProviderName;
+        if (!Providers.empty()) {
+          include_cleaner::Header FirstProvider = Providers[0];
+          // TODO(bakalova) switch on provider type
+          switch(FirstProvider.kind()) {
+            case include_cleaner::Header::Physical:
+              ProviderName = FirstProvider.physical()->tryGetRealPathName();
+              llvm::errs() << "PHYSICAL PROVIDER: " << ProviderName << "\n";
+              break;
+            case include_cleaner::Header::Standard:
+              ProviderName = FirstProvider.standard().name();
+              llvm::errs() << "STANDARD PROVIDER: " << ProviderName << "\n";
+              break;
+            case include_cleaner::Header::Verbatim:
+              ProviderName = FirstProvider.verbatim();
+              llvm::errs() << "VERBATIM PROVIDER: " << ProviderName << "\n";
+              break;
+          }
+          HI.Documentation += "\n\n";
+          HI.Documentation += "Provided by `";
+          HI.Documentation += ProviderName;
+          HI.Documentation += "`.";
+          llvm::errs() << "DOC: " << HI.Documentation << "\n";
+        }
+  });
+}
+
 std::optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
                                   const format::FormatStyle &Style,
                                   const SymbolIndex *Index) {
@@ -1168,6 +1229,7 @@
         if (!HI->Value)
           HI->Value = printExprValue(N, AST.getASTContext());
         maybeAddCalleeArgInfo(N, *HI, PP);
+        maybeAddHeaderProvider(AST, *HI, *CurLoc);
       } else if (const Expr *E = N->ASTNode.get<Expr>()) {
         HI = getHoverContents(N, E, AST, PP, Index);
       } else if (const Attr *A = N->ASTNode.get<Attr>()) {
Index: clang-tools-extra/clangd/ClangdServer.h
===================================================================
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -305,6 +305,8 @@
   void findReferences(PathRef File, Position Pos, uint32_t Limit,
                       bool AddContainer, Callback<ReferencesResult> CB);
 
+  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>);
 
+  void onCodeLens(const CodeLensParams &Params, Callback<std::vector<CodeLens>> Reply);
+  void onCommandShowUsedSymbols(const IncludeSpelling &Spelling, Callback<llvm::json::Value> 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
@@ -71,6 +71,7 @@
 
 const llvm::StringLiteral ApplyFixCommand = "clangd.applyFix";
 const llvm::StringLiteral ApplyTweakCommand = "clangd.applyTweak";
+const llvm::StringLiteral ApplyShowUsedSymbols = "HelloWorld";
 
 /// Transforms a tweak into a code action that would apply it if executed.
 /// EXPECTS: T.prepare() was called and returned true.
@@ -586,6 +587,7 @@
       {"clangdInlayHintsProvider", true},
       {"inlayHintProvider", true},
       {"foldingRangeProvider", true},
+      {"codeLensProvider", true},
   };
 
   {
@@ -736,6 +738,14 @@
   applyEdit(WE, "Fix applied.", std::move(Reply));
 }
 
+void ClangdLSPServer::onCommandShowUsedSymbols(const IncludeSpelling &Spelling, Callback<llvm::json::Value> Reply) {
+  llvm::errs() << "ONCOMMAND SHOW USED SYMBOLS TRIGGERED\n";
+  llvm::json::Value Response = llvm::json::Object{
+    {"response", "Hello to you as well!!!"}
+  };
+  return Reply(Response);
+}
+
 void ClangdLSPServer::onCommandApplyTweak(const TweakArgs &Args,
                                           Callback<llvm::json::Value> Reply) {
   auto Action = [this, Reply = std::move(Reply)](
@@ -1399,6 +1409,12 @@
                          });
 }
 
+void ClangdLSPServer::onCodeLens(const CodeLensParams &Params,
+    Callback<std::vector<CodeLens>> Reply) {
+  llvm::errs() << "TRIGGERED CODE LENS: " << Params.textDocument.uri.file() << "\n";
+  Server->findCodeLens(Params.textDocument.uri.file(), std::move(Reply));
+}
+
 void ClangdLSPServer::onGoToType(const TextDocumentPositionParams &Params,
                                  Callback<std::vector<Location>> Reply) {
   Server->findType(
@@ -1589,6 +1605,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);
@@ -1622,6 +1639,7 @@
   Bind.method("textDocument/foldingRange", this, &ClangdLSPServer::onFoldingRange);
   Bind.command(ApplyFixCommand, this, &ClangdLSPServer::onCommandApplyEdit);
   Bind.command(ApplyTweakCommand, this, &ClangdLSPServer::onCommandApplyTweak);
+  Bind.command(ApplyShowUsedSymbols, this, &ClangdLSPServer::onCommandShowUsedSymbols);
 
   ApplyWorkspaceEdit = Bind.outgoingMethod("workspace/applyEdit");
   PublishDiagnostics = Bind.outgoingNotification("textDocument/publishDiagnostics");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to