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/D145059

Files:
  clang-tools-extra/clangd/XRefs.cpp

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"
@@ -1310,6 +1312,28 @@
     return printQualifiedName(*ND);
   return {};
 }
+
+// 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;
+}
 } // namespace
 
 ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
@@ -1324,6 +1348,74 @@
     return {};
   }
 
+  // TODO(bakalova) Look closer at the proper directive kind handling.
+  std::vector<Inclusion> Includes = AST.getIncludeStructure().MainFileIncludes;
+  for (auto &Inc : Includes) {
+    if (Inc.Directive != tok::PPKeywordKind::pp_include) {
+      // Ignore non-C++ include directives.
+      continue;
+    }
+    // It is enough to compare line numbers, since one include per line is a
+    // standard.
+    if (Pos.line != Inc.HashLine) {
+      continue;
+    }
+
+    const auto Macros = collectMacroReferences(AST);
+    include_cleaner::walkUsed(
+        AST.getLocalTopLevelDecls(), Macros,
+        AST.getPragmaIncludes(), SM,
+        [&](const include_cleaner::SymbolReference &Ref,
+            llvm::ArrayRef<include_cleaner::Header> Providers) {
+          if (!Ref.RefLocation.isFileID() ||
+          Ref.RT != include_cleaner::RefType::Explicit ||
+              !SM.isWrittenInMainFile(SM.getSpellingLoc(Ref.RefLocation))) {
+            return;
+          }
+          const syntax::Token *Tok =
+              AST.getTokens().spelledTokenAt(Ref.RefLocation);
+          if (Tok == nullptr) {
+            elog("Can't find spelled token at the symbol reference location.");
+            return;
+          }
+          const SourceLocation &RefEndLocation = Tok->endLocation();
+          clangd::Range Range =
+              clangd::Range{sourceLocToPosition(SM, Ref.RefLocation),
+                            sourceLocToPosition(SM, RefEndLocation)};
+          ReferencesResult::Reference Result;
+          Result.Loc.range = Range;
+          Result.Loc.uri = URIMainFile;
+
+          // TODO(bakalova) does this differentiation make any sense in this
+          // context? Possibly not if (Ref.IsDefinition) {
+          //   Result.Attributes |= ReferencesResult::Declaration;
+          //   Result.Attributes |= ReferencesResult::Definition;
+          // }
+          for (const include_cleaner::Header &H : Providers) {
+            switch (H.kind()) {
+            case include_cleaner::Header::Physical:
+              if (H.physical()->tryGetRealPathName() == Inc.Resolved) {
+                Results.References.push_back(std::move(Result));
+              }
+              break;
+            case include_cleaner::Header::Standard:
+              if (Inc.Written == H.standard().name()) {
+                Results.References.push_back(std::move(Result));
+              }
+              break;
+            case include_cleaner::Header::Verbatim:
+              if (Inc.Written == H.verbatim()) {
+                Results.References.push_back(std::move(Result));
+              }
+              break;
+            }
+          }
+        });
+    if (!Results.References.empty()) {
+      return Results;
+    }
+  }
+
   llvm::DenseSet<SymbolID> IDsToQuery, OverriddenMethods;
 
   const auto *IdentifierAtCursor =
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to