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

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D145075

Files:
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/Hover.h

Index: clang-tools-extra/clangd/Hover.h
===================================================================
--- clang-tools-extra/clangd/Hover.h
+++ clang-tools-extra/clangd/Hover.h
@@ -18,6 +18,14 @@
 namespace clang {
 namespace clangd {
 
+struct UsedSymbol {
+  std::string Name;
+  Position Pos;
+};
+inline bool operator<(const UsedSymbol &FstSym, const UsedSymbol &SndSym) {
+  return FstSym.Name < SndSym.Name;
+}
+
 /// Contains detailed information about a Symbol. Especially useful when
 /// generating hover responses. It can be rendered as a hover panel, or
 /// embedding clients can use the structured information to provide their own
@@ -96,6 +104,8 @@
   // Set when symbol is inside function call. Contains information extracted
   // from the callee definition about the argument this is passed as.
   std::optional<Param> CalleeArgInfo;
+
+  std::optional<std::set<UsedSymbol>> UsedSymbols;
   struct PassType {
     // How the variable is passed to callee.
     enum PassMode { Ref, ConstRef, Value };
Index: clang-tools-extra/clangd/Hover.cpp
===================================================================
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -13,8 +13,10 @@
 #include "Config.h"
 #include "FindTarget.h"
 #include "ParsedAST.h"
+#include "Protocol.h"
 #include "Selection.h"
 #include "SourceCode.h"
+#include "clang-include-cleaner/Analysis.h"
 #include "index/SymbolCollector.h"
 #include "support/Markup.h"
 #include "clang/AST/ASTContext.h"
@@ -1084,6 +1086,81 @@
   return Candidates.front();
 }
 
+// FIXME(bakalova): Remove after merging https://reviews.llvm.org/D143496
+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;
+}
+
+void addUsedSymbols(const Inclusion &Inc, ParsedAST &AST,
+                    const std::vector<include_cleaner::SymbolReference> &Macros,
+                    HoverInfo &HI) {
+  const SourceManager &SM = AST.getSourceManager();
+  std::set<UsedSymbol> UsedSymbols;
+  include_cleaner::walkUsed(
+      AST.getLocalTopLevelDecls(), Macros, AST.getPragmaIncludes(), SM,
+      [&](const include_cleaner::SymbolReference &Ref,
+          llvm::ArrayRef<include_cleaner::Header> Providers) {
+        if (Ref.RT != include_cleaner::RefType::Explicit ||
+             !Ref.RefLocation.isFileID() ||
+            !SM.isWrittenInMainFile(SM.getSpellingLoc(Ref.RefLocation)) 
+           ) {
+          return;
+        }
+        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;
+        }
+
+        Position Pos = sourceLocToPosition(SM, Ref.RefLocation);
+        for (const include_cleaner::Header &H : Providers) {
+          switch (H.kind()) {
+          case include_cleaner::Header::Physical:
+            if (H.physical()->tryGetRealPathName() == Inc.Resolved) {
+              UsedSymbols.insert({Name, Pos});
+            }
+            break;
+          case include_cleaner::Header::Standard:
+            if (Inc.Written == H.standard().name()) {
+              UsedSymbols.insert({Name, Pos});
+            }
+            break;
+          case include_cleaner::Header::Verbatim:
+            if (Inc.Written == H.verbatim()) {
+              UsedSymbols.insert({Name, Pos});
+            }
+            break;
+          }
+        }
+      });
+
+  if (!UsedSymbols.empty()) {
+    HI.UsedSymbols = std::optional<std::set<UsedSymbol>>{std::move(UsedSymbols)};
+  }
+}
 } // namespace
 
 std::optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
@@ -1103,6 +1180,7 @@
   if (TokensTouchingCursor.empty())
     return std::nullopt;
 
+  const auto &Macros = collectMacroReferences(AST);
   // Show full header file path if cursor is on include directive.
   for (const auto &Inc : AST.getIncludeStructure().MainFileIncludes) {
     if (Inc.Resolved.empty() || Inc.HashLine != Pos.line)
@@ -1113,6 +1191,7 @@
     HI.Definition =
         URIForFile::canonicalize(Inc.Resolved, AST.tuPath()).file().str();
     HI.DefinitionLanguage = "";
+    addUsedSymbols(Inc, AST, Macros, HI);
     return HI;
   }
 
@@ -1313,6 +1392,25 @@
     Output.addCodeBlock(Buffer, DefinitionLanguage);
   }
 
+  if (UsedSymbols) {
+    Output.addRuler();
+    markup::Paragraph &Title = Output.addParagraph();
+    Title.appendText("Provides symbols used in this file:");
+    markup::BulletList &BL = Output.addBulletList();
+    
+    for (const auto &Sym : *UsedSymbols) {
+      markup::Document &D = BL.addItem();
+      markup::Paragraph &P = D.addParagraph();
+      P.appendCode(Sym.Name);
+      P.appendSpace();
+      P.appendText("[Ln: ");
+      P.appendText(std::to_string(Sym.Pos.line));
+      P.appendText(", Col: ");
+      P.appendText(std::to_string(Sym.Pos.character));
+      P.appendText("]");
+    }
+  }
+
   return Output;
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to