[clang-tools-extra] a701618 - [clangd] Include the underlying decls in go-to-definition.

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 7 02:40:07 PDT 2020


Author: Haojian Wu
Date: 2020-08-07T11:39:49+02:00
New Revision: a70161808bcd6560e268aecf90138ff68f41fe54

URL: https://github.com/llvm/llvm-project/commit/a70161808bcd6560e268aecf90138ff68f41fe54
DIFF: https://github.com/llvm/llvm-project/commit/a70161808bcd6560e268aecf90138ff68f41fe54.diff

LOG: [clangd] Include the underlying decls in go-to-definition.

Fixes https://github.com/clangd/clangd/issues/277

Reviewed By: sammccall

Differential Revision: https://reviews.llvm.org/D74054

Added: 
    

Modified: 
    clang-tools-extra/clangd/XRefs.cpp
    clang-tools-extra/clangd/unittests/XRefsTests.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp
index 26653aa409d7..b61ff4979320 100644
--- a/clang-tools-extra/clangd/XRefs.cpp
+++ b/clang-tools-extra/clangd/XRefs.cpp
@@ -290,6 +290,18 @@ locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier,
       }
     }
 
+    // Give the underlying decl if navigation is triggered on a non-renaming
+    // alias.
+    if (llvm::isa<UsingDecl>(D)) {
+      // FIXME: address more complicated cases. TargetDecl(... Underlying) gives
+      // all overload candidates, we only want the targeted one if the cursor is
+      // on an using-alias usage, workround it with getDeclAtPosition.
+      llvm::for_each(
+          getDeclAtPosition(AST, CurLoc, DeclRelation::Underlying, NodeKind),
+          [&](const NamedDecl *UD) { AddResultDecl(UD); });
+      continue;
+    }
+
     // Otherwise the target declaration is the right one.
     AddResultDecl(D);
   }

diff  --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
index c9c115fd19d8..686ba023a282 100644
--- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -47,6 +47,11 @@ using ::testing::UnorderedElementsAreArray;
 MATCHER_P2(FileRange, File, Range, "") {
   return Location{URIForFile::canonicalize(File, testRoot()), Range} == arg;
 }
+MATCHER(DeclRange, "") {
+  const LocatedSymbol &Sym = ::testing::get<0>(arg);
+  const Range &Range = ::testing::get<1>(arg);
+  return Sym.PreferredDeclaration.range == Range;
+}
 
 // Extracts ranges from an annotated example, and constructs a matcher for a
 // highlight set. Ranges should be named $read/$write as appropriate.
@@ -945,15 +950,77 @@ TEST(LocateSymbol, TextualDependent) {
                   Sym("uniqueMethodName", Header.range("BarLoc"), llvm::None)));
 }
 
-TEST(LocateSymbol, TemplateTypedefs) {
-  auto T = Annotations(R"cpp(
-    template <class T> struct function {};
-    template <class T> using callback = function<T()>;
+TEST(LocateSymbol, Alias) {
+  const char *Tests[] = {
+    R"cpp(
+      template <class T> struct function {};
+      template <class T> using [[callback]] = function<T()>;
 
-    c^allback<int> foo;
-  )cpp");
-  auto AST = TestTU::withCode(T.code()).build();
-  EXPECT_THAT(locateSymbolAt(AST, T.point()), ElementsAre(Sym("callback")));
+      c^allback<int> foo;
+    )cpp",
+
+    // triggered on non-definition of a renaming alias: should not give any
+    // underlying decls.
+    R"cpp(
+      class Foo {};
+      typedef Foo [[Bar]];
+
+      B^ar b;
+    )cpp",
+    R"cpp(
+      class Foo {};
+      using [[Bar]] = Foo; // definition
+      Ba^r b;
+    )cpp",
+
+    // triggered on the underlying decl of a renaming alias.
+    R"cpp(
+      class [[Foo]];
+      using Bar = Fo^o;
+    )cpp",
+
+    // triggered on definition of a non-renaming alias: should give underlying
+    // decls.
+    R"cpp(
+      namespace ns { class [[Foo]] {}; }
+      using ns::F^oo;
+    )cpp",
+
+    R"cpp(
+      namespace ns { int [[x]](char); int [[x]](double); }
+      using ns::^x;
+    )cpp",
+
+    R"cpp(
+      namespace ns { int [[x]](char); int x(double); }
+      using ns::x;
+      int y = ^x('a');
+    )cpp",
+
+    R"cpp(
+      namespace ns { class [[Foo]] {}; }
+      using ns::Foo;
+      F^oo f;
+    )cpp",
+
+    // other cases that don't matter much.
+    R"cpp(
+      class Foo {};
+      typedef Foo [[Ba^r]];
+    )cpp",
+    R"cpp(
+      class Foo {};
+      using [[B^ar]] = Foo;
+    )cpp",
+  };
+
+  for (const auto* Case : Tests) {
+    SCOPED_TRACE(Case);
+    auto T = Annotations(Case);
+    auto AST = TestTU::withCode(T.code()).build();
+    EXPECT_THAT(locateSymbolAt(AST, T.point()),
+                ::testing::UnorderedPointwise(DeclRange(), T.ranges()));
+  }
 }
 
 TEST(LocateSymbol, RelPathsInCompileCommand) {


        


More information about the cfe-commits mailing list