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

Rename function.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D147044

Files:
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/IncludeCleaner.cpp
  clang-tools-extra/clangd/IncludeCleaner.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/XRefsTests.cpp

Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -43,6 +43,10 @@
 using ::testing::UnorderedElementsAreArray;
 using ::testing::UnorderedPointwise;
 
+std::string guard(llvm::StringRef Code) {
+  return "#pragma once\n" + Code.str();
+}
+
 MATCHER_P2(FileRange, File, Range, "") {
   return Location{URIForFile::canonicalize(File, testRoot()), Range} == arg;
 }
@@ -2293,6 +2297,50 @@
     checkFindRefs(Test);
 }
 
+TEST(FindReferences, UsedSymbolsFromInclude) {
+  const char *Tests[] = {
+      R"cpp([[#include ^"bar.h"]]
+        #include <vector>
+        int fstBar = [[bar1]]();
+        int sndBar = [[bar2]]();
+        [[Bar]] bar;
+        int macroBar = [[BAR]];
+        std::vector<int> vec;
+      )cpp",
+
+      R"cpp([[#in^clude <vector>]]
+        std::[[vector]]<int> vec;
+      )cpp"};
+  for (const char *Test : Tests) {
+    Annotations T(Test);
+    auto TU = TestTU::withCode(T.code());
+    TU.ExtraArgs.push_back("-std=c++20");
+    TU.AdditionalFiles["bar.h"] = guard(R"cpp(
+      #define BAR 5
+      int bar1();
+      int bar2();
+      class Bar {};            
+    )cpp");
+    TU.AdditionalFiles["system/vector"] = guard(R"cpp(
+      namespace std {
+        template<typename>
+        class vector{};
+      }
+    )cpp");
+    TU.ExtraArgs.push_back("-isystem" + testPath("system"));
+
+    auto AST = TU.build();
+    std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
+    for (const auto &R : T.ranges())
+      ExpectedLocations.push_back(AllOf(rangeIs(R), attrsAre(0u)));
+    for (const auto &P : T.points()) 
+      EXPECT_THAT(findReferences(AST, P, 0).References,
+                  UnorderedElementsAreArray(ExpectedLocations))
+          << "Failed for Refs at " << P << "\n"
+          << Test;
+  }
+}
+
 TEST(FindReferences, NeedsIndexForSymbols) {
   const char *Header = "int foo();";
   Annotations Main("int main() { [[f^oo]](); }");
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"
@@ -48,6 +51,7 @@
 #include "clang/Index/IndexingAction.h"
 #include "clang/Index/IndexingOptions.h"
 #include "clang/Index/USRGeneration.h"
+#include "clang/Lex/Lexer.h"
 #include "clang/Tooling/Syntax/Tokens.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.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,6 +1317,63 @@
 }
 } // namespace
 
+ReferencesResult maybeFindIncludeReferences(ParsedAST &AST, Position Pos,
+                                            URIForFile URIMainFile) {
+  ReferencesResult Results;
+  const SourceManager &SM = AST.getSourceManager();
+  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 Provider =
+              firstMatchedProvider(ConvertedMainFileIncludes, Providers);
+          if (!Provider)
+            return;
+
+          // Check if the referenced include matches this provider.
+          if (ReferencedInclude.match(*Provider).empty())
+            return;
+
+          auto Loc = SM.getFileLoc(Ref.RefLocation);
+          // File locations can be outside of the main file if macro is
+          // expanded through an #include.
+          while (SM.getFileID(Loc) != SM.getMainFileID())
+            Loc = SM.getIncludeLoc(SM.getFileID(Loc));
+
+          ReferencesResult::Reference Result;
+          const auto *Token = AST.getTokens().spelledTokenAt(Loc);
+          Result.Loc.range =
+              Range{sourceLocToPosition(SM, Token->location()),
+                    sourceLocToPosition(SM, Token->endLocation())};
+          Result.Loc.uri = URIMainFile;
+          Results.References.push_back(std::move(Result));
+        });
+    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));
+  }
+  return Results;
+}
+
 ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
                                 const SymbolIndex *Index, bool AddContext) {
   ReferencesResult Results;
@@ -1324,6 +1386,10 @@
     return {};
   }
 
+  Results = maybeFindIncludeReferences(AST, Pos, URIMainFile);
+  if (!Results.References.empty())
+    return Results;
+
   llvm::DenseSet<SymbolID> IDsToQuery, OverriddenMethods;
 
   const auto *IdentifierAtCursor =
Index: clang-tools-extra/clangd/IncludeCleaner.h
===================================================================
--- clang-tools-extra/clangd/IncludeCleaner.h
+++ clang-tools-extra/clangd/IncludeCleaner.h
@@ -81,6 +81,11 @@
 
 std::vector<include_cleaner::SymbolReference>
 collectMacroReferences(ParsedAST &AST);
+
+/// Find the first provider in the list that is matched by the includes.
+std::optional<include_cleaner::Header>
+firstMatchedProvider(const include_cleaner::Includes &Includes,
+                     llvm::ArrayRef<include_cleaner::Header> Providers);
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/IncludeCleaner.cpp
===================================================================
--- clang-tools-extra/clangd/IncludeCleaner.cpp
+++ clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -432,5 +432,15 @@
   return Result;
 }
 
+std::optional<include_cleaner::Header>
+firstMatchedProvider(const include_cleaner::Includes &Includes,
+                       llvm::ArrayRef<include_cleaner::Header> Providers) {
+  for (const auto &H : Providers) {
+    if (!Includes.match(H).empty())
+      return H;
+  }
+  // No match for this provider in the includes list.
+  return {};
+}
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/Hover.cpp
===================================================================
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -1172,20 +1172,16 @@
             UsedSymbols.find(Ref.Target) != UsedSymbols.end())
           return;
 
-        for (const include_cleaner::Header &H : Providers) {
-          auto MatchingIncludes = ConvertedMainFileIncludes.match(H);
-          // No match for this provider in the main file.
-          if (MatchingIncludes.empty())
-            continue;
-
-          // Check if the hovered include matches this provider.
-          if (!HoveredInclude.match(H).empty())
-            UsedSymbols.insert(Ref.Target);
-
-          // Don't look for rest of the providers once we've found a match
-          // in the main file.
-          break;
-        }
+        auto Provider =
+            firstMatchedProvider(ConvertedMainFileIncludes, Providers);
+        if (!Provider)
+          return;
+
+        // Check if the hovered include matches this provider.
+        if (HoveredInclude.match(*Provider).empty())
+          return;
+
+        UsedSymbols.insert(Ref.Target);
       });
 
   for (const auto &UsedSymbolDecl : UsedSymbols)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to