forked from OSchip/llvm-project
[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
This commit is contained in:
parent
01bc708126
commit
a70161808b
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue