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.
|
// Otherwise the target declaration is the right one.
|
||||||
AddResultDecl(D);
|
AddResultDecl(D);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,11 @@ using ::testing::UnorderedElementsAreArray;
|
||||||
MATCHER_P2(FileRange, File, Range, "") {
|
MATCHER_P2(FileRange, File, Range, "") {
|
||||||
return Location{URIForFile::canonicalize(File, testRoot()), Range} == arg;
|
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
|
// Extracts ranges from an annotated example, and constructs a matcher for a
|
||||||
// highlight set. Ranges should be named $read/$write as appropriate.
|
// highlight set. Ranges should be named $read/$write as appropriate.
|
||||||
|
@ -945,15 +950,77 @@ TEST(LocateSymbol, TextualDependent) {
|
||||||
Sym("uniqueMethodName", Header.range("BarLoc"), llvm::None)));
|
Sym("uniqueMethodName", Header.range("BarLoc"), llvm::None)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LocateSymbol, TemplateTypedefs) {
|
TEST(LocateSymbol, Alias) {
|
||||||
auto T = Annotations(R"cpp(
|
const char *Tests[] = {
|
||||||
template <class T> struct function {};
|
R"cpp(
|
||||||
template <class T> using callback = function<T()>;
|
template <class T> struct function {};
|
||||||
|
template <class T> using [[callback]] = function<T()>;
|
||||||
|
|
||||||
c^allback<int> foo;
|
c^allback<int> foo;
|
||||||
)cpp");
|
)cpp",
|
||||||
auto AST = TestTU::withCode(T.code()).build();
|
|
||||||
EXPECT_THAT(locateSymbolAt(AST, T.point()), ElementsAre(Sym("callback")));
|
// 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) {
|
TEST(LocateSymbol, RelPathsInCompileCommand) {
|
||||||
|
|
Loading…
Reference in New Issue