hokein updated this revision to Diff 225398.
hokein marked 14 inline comments as done.
hokein added a comment.

address comments:

- remove the confusing IsDeclRef
- use getQualifier from AST.h


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68977

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/FindTarget.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.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
@@ -2277,7 +2277,8 @@
       if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
         Names.push_back(ND->getQualifiedNameAsString());
     }
-    EXPECT_THAT(Names, UnorderedElementsAreArray(C.ExpectedDecls));
+    EXPECT_THAT(Names, UnorderedElementsAreArray(C.ExpectedDecls))
+        << File.code();
   }
 }
 
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -520,8 +520,28 @@
     findExplicitReferences(Func.getBody(), [&Refs](ReferenceLoc R) {
       Refs.push_back(std::move(R));
     });
+    return dumpReferences(std::move(Refs), Code, AST.getSourceManager());
+  }
+
+  /// Similar to annotateReferencesInFoo, but finds all references in the main
+  /// AST.
+  AllRefs annotateReferencesInMainAST(llvm::StringRef Code) {
+    TestTU TU;
+    TU.Code = Code;
 
-    auto &SM = AST.getSourceManager();
+    auto AST = TU.build();
+    std::vector<ReferenceLoc> Refs;
+    for (const auto *ToplLevelDecl : AST.getLocalTopLevelDecls()) {
+      findExplicitReferences(ToplLevelDecl, [&Refs](ReferenceLoc R) {
+        Refs.push_back(std::move(R));
+      });
+    }
+    return dumpReferences(std::move(Refs), Code, AST.getSourceManager());
+  }
+
+private:
+  AllRefs dumpReferences(std::vector<ReferenceLoc> Refs, llvm::StringRef Code,
+                         const SourceManager &SM) {
     llvm::sort(Refs, [&](const ReferenceLoc &L, const ReferenceLoc &R) {
       return SM.isBeforeInTranslationUnit(L.NameLoc, R.NameLoc);
     });
@@ -600,59 +620,67 @@
           }
         )cpp",
            "0: targets = {ns}\n"
-           "1: targets = {ns::global}, qualifier = 'ns::'\n"},
+           "1: targets = {ns::global}, qualifier = 'ns::', decl\n"},
           // Simple types.
           {R"cpp(
          struct Struct { int a; };
          using Typedef = int;
          void foo() {
-           $0^Struct x;
-           $1^Typedef y;
-           static_cast<$2^Struct*>(0);
+           $0^Struct $1^x;
+           $2^Typedef $3^y;
+           static_cast<$4^Struct*>(0);
          }
        )cpp",
            "0: targets = {Struct}\n"
-           "1: targets = {Typedef}\n"
-           "2: targets = {Struct}\n"},
+           "1: targets = {x}, decl\n"
+           "2: targets = {Typedef}\n"
+           "3: targets = {y}, decl\n"
+           "4: targets = {Struct}\n"},
           // Name qualifiers.
           {R"cpp(
          namespace a { namespace b { struct S { typedef int type; }; } }
          void foo() {
-           $0^a::$1^b::$2^S x;
-           using namespace $3^a::$4^b;
-           $5^S::$6^type y;
+           $0^a::$1^b::$2^S $3^x;
+           using namespace $4^a::$5^b;
+           $6^S::$7^type $8^y;
          }
         )cpp",
            "0: targets = {a}\n"
            "1: targets = {a::b}, qualifier = 'a::'\n"
            "2: targets = {a::b::S}, qualifier = 'a::b::'\n"
-           "3: targets = {a}\n"
-           "4: targets = {a::b}, qualifier = 'a::'\n"
-           "5: targets = {a::b::S}\n"
-           "6: targets = {a::b::S::type}, qualifier = 'struct S::'\n"},
+           "3: targets = {x}, decl\n"
+           "4: targets = {a}\n"
+           "5: targets = {a::b}, qualifier = 'a::'\n"
+           "6: targets = {a::b::S}\n"
+           "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
+           "8: targets = {y}, decl\n"},
           // Simple templates.
           {R"cpp(
           template <class T> struct vector { using value_type = T; };
           template <> struct vector<bool> { using value_type = bool; };
           void foo() {
-            $0^vector<int> vi;
-            $1^vector<bool> vb;
+            $0^vector<int> $1^vi;
+            $2^vector<bool> $3^vb;
           }
         )cpp",
            "0: targets = {vector<int>}\n"
-           "1: targets = {vector<bool>}\n"},
+           "1: targets = {vi}, decl\n"
+           "2: targets = {vector<bool>}\n"
+           "3: targets = {vb}, decl\n"},
           // Template type aliases.
           {R"cpp(
             template <class T> struct vector { using value_type = T; };
             template <> struct vector<bool> { using value_type = bool; };
             template <class T> using valias = vector<T>;
             void foo() {
-              $0^valias<int> vi;
-              $1^valias<bool> vb;
+              $0^valias<int> $1^vi;
+              $2^valias<bool> $3^vb;
             }
           )cpp",
            "0: targets = {valias}\n"
-           "1: targets = {valias}\n"},
+           "1: targets = {vi}, decl\n"
+           "2: targets = {valias}\n"
+           "3: targets = {vb}, decl\n"},
           // MemberExpr should know their using declaration.
           {R"cpp(
             struct X { void func(int); }
@@ -694,13 +722,14 @@
             };
 
             void foo() {
-              for (int x : $0^vector()) {
-                $1^x = 10;
+              for (int $0^x : $1^vector()) {
+                $2^x = 10;
               }
             }
         )cpp",
-           "0: targets = {vector}\n"
-           "1: targets = {x}\n"},
+           "0: targets = {x}, decl\n"
+           "1: targets = {vector}\n"
+           "2: targets = {x}\n"},
           // Handle UnresolvedLookupExpr.
           {R"cpp(
             namespace ns1 { void func(char*); }
@@ -736,39 +765,42 @@
             void foo() {
               static_cast<$0^T>(0);
               $1^T();
-              $2^T t;
+              $2^T $3^t;
             }
         )cpp",
            "0: targets = {T}\n"
            "1: targets = {T}\n"
-           "2: targets = {T}\n"},
+           "2: targets = {T}\n"
+           "3: targets = {t}, decl\n"},
           // Non-type template parameters.
           {R"cpp(
             template <int I>
             void foo() {
-              int x = $0^I;
+              int $0^x = $1^I;
             }
         )cpp",
-           "0: targets = {I}\n"},
+           "0: targets = {x}, decl\n"
+           "1: targets = {I}\n"},
           // Template template parameters.
           {R"cpp(
             template <class T> struct vector {};
 
             template <template<class> class TT, template<class> class ...TP>
             void foo() {
-              $0^TT<int> x;
-              $1^foo<$2^TT>();
-              $3^foo<$4^vector>()
-              $5^foo<$6^TP...>();
+              $0^TT<int> $1^x;
+              $2^foo<$3^TT>();
+              $4^foo<$5^vector>()
+              $6^foo<$7^TP...>();
             }
         )cpp",
            "0: targets = {TT}\n"
-           "1: targets = {foo}\n"
-           "2: targets = {TT}\n"
-           "3: targets = {foo}\n"
-           "4: targets = {vector}\n"
-           "5: targets = {foo}\n"
-           "6: targets = {TP}\n"},
+           "1: targets = {x}, decl\n"
+           "2: targets = {foo}\n"
+           "3: targets = {TT}\n"
+           "4: targets = {foo}\n"
+           "5: targets = {vector}\n"
+           "6: targets = {foo}\n"
+           "7: targets = {TP}\n"},
           // Non-type template parameters with declarations.
           {R"cpp(
             int func();
@@ -776,13 +808,14 @@
 
             template <int(*FuncParam)()>
             void foo() {
-              $0^wrapper<$1^func> w;
-              $2^FuncParam();
+              $0^wrapper<$1^func> $2^w;
+              $3^FuncParam();
             }
         )cpp",
            "0: targets = {wrapper<&func>}\n"
            "1: targets = {func}\n"
-           "2: targets = {FuncParam}\n"},
+           "2: targets = {w}, decl\n"
+           "3: targets = {FuncParam}\n"},
       };
 
   for (const auto &C : Cases) {
@@ -796,6 +829,70 @@
   }
 }
 
+TEST_F(FindExplicitReferencesTest, DeclReference) {
+  std::pair</*Code*/ llvm::StringRef, /*References*/ llvm::StringRef> Cases[] =
+      {
+          // simple declarations.
+          {R"cpp(
+             class $0^Foo { $1^Foo(); $2^~$3^Foo(); int $4^field; };
+             int $5^Var;
+             void $6^Fun() {}
+             enum $7^E { $8^ABC };
+             typedef int $9^INT;
+             using $10^INT2 = int;
+             template<typename $11^T>
+             // FIXME: the duplicated locations are from FunctionTemplateDecl and
+             // the underlying FunctionDecl. we should report just one.
+             void $12^$13^F() {}
+           )cpp",
+           "0: targets = {Foo}, decl\n"
+           "1: targets = {Foo::Foo}, decl\n"
+           "2: targets = {Foo::~Foo}, decl\n"
+           "3: targets = {Foo}\n"
+           "4: targets = {Foo::field}, decl\n"
+           "5: targets = {Var}, decl\n"
+           "6: targets = {Fun}, decl\n"
+           "7: targets = {E}, decl\n"
+           "8: targets = {ABC}, decl\n"
+           "9: targets = {INT}, decl\n"
+           "10: targets = {INT2}, decl\n"
+           "11: targets = {T}, decl\n"
+           "12: targets = {F}, decl\n"
+           "13: targets = {F}, decl\n"},
+          // declarations with qualifiers.
+          {R"cpp(
+             namespace $0^ns {
+             class $1^Foo {
+               void $2^method();
+             };
+             void $3^func();
+             }
+             void $4^ns::$5^Foo::$6^method() {}
+             void $7^ns::$8^func() {}
+           )cpp",
+           "0: targets = {ns}, decl\n"
+           "1: targets = {ns::Foo}, decl\n"
+           "2: targets = {ns::Foo::method}, decl\n"
+           "3: targets = {ns::func}, decl\n"
+           "4: targets = {ns}\n"
+           "5: targets = {ns::Foo}, qualifier = 'ns::'\n"
+           "6: targets = {ns::Foo::method}, qualifier = 'ns::class Foo::', "
+           "decl\n"
+           "7: targets = {ns}\n"
+           "8: targets = {ns::func}, qualifier = 'ns::', decl\n"},
+      };
+
+  for (const auto &C : Cases) {
+    llvm::StringRef ExpectedCode = C.first;
+    llvm::StringRef ExpectedRefs = C.second;
+
+    auto Actual =
+        annotateReferencesInMainAST(llvm::Annotations(ExpectedCode).code());
+    EXPECT_EQ(ExpectedCode, Actual.AnnotatedCode);
+    EXPECT_EQ(ExpectedRefs, Actual.DumpedReferences) << ExpectedCode;
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/XRefs.cpp
===================================================================
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -1307,7 +1307,8 @@
   llvm::DenseSet<const Decl *> DeclRefs;
   findExplicitReferences(FD, [&](ReferenceLoc Ref) {
     for (const Decl *D : Ref.Targets) {
-      if (!index::isFunctionLocalSymbol(D) && !D->isTemplateParameter())
+      if (!index::isFunctionLocalSymbol(D) && !D->isTemplateParameter() &&
+          !Ref.IsDecl)
         DeclRefs.insert(D);
     }
   });
Index: clang-tools-extra/clangd/FindTarget.h
===================================================================
--- clang-tools-extra/clangd/FindTarget.h
+++ clang-tools-extra/clangd/FindTarget.h
@@ -86,6 +86,8 @@
   NestedNameSpecifierLoc Qualifier;
   /// Start location of the last name part, i.e. 'foo' in 'ns::foo<int>'.
   SourceLocation NameLoc;
+  /// True if the reference is a declaration or definition;
+  bool IsDecl = false;
   // FIXME: add info about template arguments.
   /// A list of targets referenced by this name. Normally this has a single
   /// element, but multiple is also possible, e.g. in case of using declarations
Index: clang-tools-extra/clangd/FindTarget.cpp
===================================================================
--- clang-tools-extra/clangd/FindTarget.cpp
+++ clang-tools-extra/clangd/FindTarget.cpp
@@ -417,22 +417,32 @@
     llvm::Optional<ReferenceLoc> Ref;
 
     void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
+      // We want to keep it as non-declarations references, as the
+      // "using namespace" declaration doesn't have a name.
       Ref = ReferenceLoc{D->getQualifierLoc(),
                          D->getIdentLocation(),
+                         /*IsDecl=*/false,
                          {D->getNominatedNamespaceAsWritten()}};
     }
 
     void VisitUsingDecl(const UsingDecl *D) {
-      Ref = ReferenceLoc{D->getQualifierLoc(), D->getLocation(),
-                         explicitReferenceTargets(DynTypedNode::create(*D),
-                                                  DeclRelation::Underlying)};
+      Ref =
+          ReferenceLoc{D->getQualifierLoc(), D->getLocation(), /*IsDecl=*/true,
+                       explicitReferenceTargets(DynTypedNode::create(*D),
+                                                DeclRelation::Underlying)};
     }
 
     void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
       Ref = ReferenceLoc{D->getQualifierLoc(),
                          D->getTargetNameLoc(),
+                         /*IsDecl=*/true,
                          {D->getAliasedNamespace()}};
     }
+
+    void VisitNamedDecl(const NamedDecl *ND) {
+      Ref = ReferenceLoc{
+          getQualifierLoc(*ND), ND->getLocation(), /*IsDecl=*/true, {ND}};
+    }
   };
 
   Visitor V;
@@ -446,18 +456,22 @@
     llvm::Optional<ReferenceLoc> Ref;
 
     void VisitDeclRefExpr(const DeclRefExpr *E) {
-      Ref = ReferenceLoc{
-          E->getQualifierLoc(), E->getNameInfo().getLoc(), {E->getFoundDecl()}};
+      Ref = ReferenceLoc{E->getQualifierLoc(),
+                         E->getNameInfo().getLoc(),
+                         /*IsDecl=*/false,
+                         {E->getFoundDecl()}};
     }
 
     void VisitMemberExpr(const MemberExpr *E) {
       Ref = ReferenceLoc{E->getQualifierLoc(),
                          E->getMemberNameInfo().getLoc(),
+                         /*IsDecl=*/false,
                          {E->getFoundDecl()}};
     }
 
     void VisitOverloadExpr(const OverloadExpr *E) {
       Ref = ReferenceLoc{E->getQualifierLoc(), E->getNameInfo().getLoc(),
+                         /*IsDecl=*/false,
                          llvm::SmallVector<const NamedDecl *, 1>(
                              E->decls().begin(), E->decls().end())};
     }
@@ -483,13 +497,17 @@
     }
 
     void VisitTagTypeLoc(TagTypeLoc L) {
-      Ref =
-          ReferenceLoc{NestedNameSpecifierLoc(), L.getNameLoc(), {L.getDecl()}};
+      Ref = ReferenceLoc{NestedNameSpecifierLoc(),
+                         L.getNameLoc(),
+                         /*IsDecl=*/false,
+                         {L.getDecl()}};
     }
 
     void VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc L) {
-      Ref =
-          ReferenceLoc{NestedNameSpecifierLoc(), L.getNameLoc(), {L.getDecl()}};
+      Ref = ReferenceLoc{NestedNameSpecifierLoc(),
+                         L.getNameLoc(),
+                         /*IsDecl=*/false,
+                         {L.getDecl()}};
     }
 
     void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) {
@@ -502,14 +520,14 @@
       //    2. 'vector<int>' with mask 'Underlying'.
       //  we want to return only #1 in this case.
       Ref = ReferenceLoc{
-          NestedNameSpecifierLoc(), L.getTemplateNameLoc(),
+          NestedNameSpecifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false,
           explicitReferenceTargets(DynTypedNode::create(L.getType()),
                                    DeclRelation::Alias)};
     }
     void VisitDeducedTemplateSpecializationTypeLoc(
         DeducedTemplateSpecializationTypeLoc L) {
       Ref = ReferenceLoc{
-          NestedNameSpecifierLoc(), L.getNameLoc(),
+          NestedNameSpecifierLoc(), L.getNameLoc(), /*IsDecl=*/false,
           explicitReferenceTargets(DynTypedNode::create(L.getType()),
                                    DeclRelation::Alias)};
     }
@@ -517,19 +535,21 @@
     void VisitDependentTemplateSpecializationTypeLoc(
         DependentTemplateSpecializationTypeLoc L) {
       Ref = ReferenceLoc{
-          L.getQualifierLoc(), L.getTemplateNameLoc(),
+          L.getQualifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false,
           explicitReferenceTargets(DynTypedNode::create(L.getType()))};
     }
 
     void VisitDependentNameTypeLoc(DependentNameTypeLoc L) {
       Ref = ReferenceLoc{
-          L.getQualifierLoc(), L.getNameLoc(),
+          L.getQualifierLoc(), L.getNameLoc(), /*IsDecl=*/false,
           explicitReferenceTargets(DynTypedNode::create(L.getType()))};
     }
 
     void VisitTypedefTypeLoc(TypedefTypeLoc L) {
-      Ref = ReferenceLoc{
-          NestedNameSpecifierLoc(), L.getNameLoc(), {L.getTypedefNameDecl()}};
+      Ref = ReferenceLoc{NestedNameSpecifierLoc(),
+                         L.getNameLoc(),
+                         /*IsDecl=*/false,
+                         {L.getTypedefNameDecl()}};
     }
   };
 
@@ -575,6 +595,7 @@
     case TemplateArgument::TemplateExpansion:
       reportReference(ReferenceLoc{A.getTemplateQualifierLoc(),
                                    A.getTemplateNameLoc(),
+                                   /*IsDecl=*/false,
                                    {A.getArgument()
                                         .getAsTemplateOrTemplatePattern()
                                         .getAsTemplateDecl()}},
@@ -631,7 +652,7 @@
     if (auto *E = N.get<Expr>())
       return refInExpr(E);
     if (auto *NNSL = N.get<NestedNameSpecifierLoc>())
-      return ReferenceLoc{NNSL->getPrefix(), NNSL->getLocalBeginLoc(),
+      return ReferenceLoc{NNSL->getPrefix(), NNSL->getLocalBeginLoc(), false,
                           explicitReferenceTargets(DynTypedNode::create(
                               *NNSL->getNestedNameSpecifier()))};
     if (const TypeLoc *TL = N.get<TypeLoc>())
@@ -642,6 +663,7 @@
       assert(CCI->isAnyMemberInitializer());
       return ReferenceLoc{NestedNameSpecifierLoc(),
                           CCI->getMemberLocation(),
+                          /*IsDecl=*/false,
                           {CCI->getAnyMember()}};
     }
     // We do not have location information for other nodes (QualType, etc)
@@ -727,6 +749,8 @@
                                                 PrintingPolicy(LangOptions()));
     OS << "'";
   }
+  if (R.IsDecl)
+    OS << ", decl";
   return OS;
 }
 
Index: clang-tools-extra/clangd/AST.h
===================================================================
--- clang-tools-extra/clangd/AST.h
+++ clang-tools-extra/clangd/AST.h
@@ -98,6 +98,12 @@
 ///   explicit specialization.
 bool isExplicitTemplateSpecialization(const NamedDecl *D);
 
+/// Returns a nested name specifier loc of \p ND if it was present in the
+/// source, e.g.
+///     void ns::something::foo() -> returns 'ns::something'
+///     void foo() -> returns null
+NestedNameSpecifierLoc getQualifierLoc(const NamedDecl &ND);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/AST.cpp
===================================================================
--- clang-tools-extra/clangd/AST.cpp
+++ clang-tools-extra/clangd/AST.cpp
@@ -99,20 +99,16 @@
   return QName;
 }
 
-static bool isAnonymous(const DeclarationName &N) {
-  return N.isIdentifier() && !N.getAsIdentifierInfo();
-}
-
-/// Returns a nested name specifier of \p ND if it was present in the source,
-/// e.g.
-///     void ns::something::foo() -> returns 'ns::something'
-///     void foo() -> returns null
-static NestedNameSpecifier *getQualifier(const NamedDecl &ND) {
+NestedNameSpecifierLoc getQualifierLoc(const NamedDecl &ND) {
   if (auto *V = llvm::dyn_cast<DeclaratorDecl>(&ND))
-    return V->getQualifier();
+    return V->getQualifierLoc();
   if (auto *T = llvm::dyn_cast<TagDecl>(&ND))
-    return T->getQualifier();
-  return nullptr;
+    return T->getQualifierLoc();
+  return NestedNameSpecifierLoc();
+}
+
+static bool isAnonymous(const DeclarationName &N) {
+  return N.isIdentifier() && !N.getAsIdentifierInfo();
 }
 
 std::string printName(const ASTContext &Ctx, const NamedDecl &ND) {
@@ -141,7 +137,7 @@
   }
 
   // Print nested name qualifier if it was written in the source code.
-  if (auto *Qualifier = getQualifier(ND))
+  if (auto *Qualifier = getQualifierLoc(ND).getNestedNameSpecifier())
     Qualifier->print(Out, PP);
   // Print the name itself.
   ND.getDeclName().print(Out, PP);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to