diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -556,12 +556,7 @@ HoverInfo HI; if (const auto *D = T->getAsTagDecl()) { - HI.Name = printName(ASTCtx, *D); - HI.Kind = index::getSymbolInfo(D).Kind; - - const auto *CommentD = getDeclForComment(D); - HI.Documentation = getDeclComment(ASTCtx, *CommentD); - enhanceFromIndex(HI, *CommentD, Index); + return getHoverContents(D, Index); } else { // Builtin types auto Policy = printingPolicyForDecls(ASTCtx.getPrintingPolicy()); diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -667,15 +667,45 @@ return {}; } - const syntax::Token *TouchedIdentifier = - syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens()); - if (TouchedIdentifier) - if (auto Macro = - locateMacroReferent(*TouchedIdentifier, AST, *MainFilePath)) - // Don't look at the AST or index if we have a macro result. - // (We'd just return declarations referenced from the macro's - // expansion.) - return {*std::move(Macro)}; + const syntax::Token *TouchedIdentifier = nullptr; + auto TokensTouchingCursor = + syntax::spelledTokensTouching(*CurLoc, AST.getTokens()); + for (const syntax::Token &Tok : TokensTouchingCursor) { + if (Tok.kind() == tok::identifier) { + if (auto Macro = locateMacroReferent(Tok, AST, *MainFilePath)) + // Don't look at the AST or index if we have a macro result. + // (We'd just return declarations referenced from the macro's + // expansion.) + return {*std::move(Macro)}; + + TouchedIdentifier = &Tok; + break; + } + + if (Tok.kind() == tok::kw_auto || Tok.kind() == tok::kw_decltype) { + if (auto Deduced = getDeducedType(AST.getASTContext(), Tok.location())) { + Deduced = Deduced->getNonReferenceType(); + const NamedDecl *D = Deduced->getTypePtr()->getAsTagDecl(); + if (!D) + continue; + + D = getPreferredDecl(D); + auto Loc = makeLocation(AST.getASTContext(), nameLocation(*D, SM), + *MainFilePath); + if (!Loc) + continue; + + LocatedSymbol LocSym; + LocSym.Name = printName(AST.getASTContext(), *D); + LocSym.PreferredDeclaration = *Loc; + if (const NamedDecl *Def = getDefinition(D)) + LocSym.Definition = makeLocation( + AST.getASTContext(), nameLocation(*Def, SM), *MainFilePath); + + return {std::move(LocSym)}; + } + } + } ASTNodeKind NodeKind; auto ASTResults = locateASTReferent(*CurLoc, TouchedIdentifier, AST, diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -388,6 +388,9 @@ [](HoverInfo &HI) { HI.Name = "(lambda)"; HI.Kind = index::SymbolKind::Class; + HI.NamespaceScope = ""; + HI.LocalScope = "foo::"; + HI.Definition = "class {}"; }}, // auto on template instantiation {R"cpp( @@ -399,6 +402,8 @@ [](HoverInfo &HI) { HI.Name = "Foo"; HI.Kind = index::SymbolKind::Class; + HI.NamespaceScope = ""; + HI.Definition = "template <> class Foo {}"; }}, // auto on specialized template {R"cpp( @@ -411,6 +416,8 @@ [](HoverInfo &HI) { HI.Name = "Foo"; HI.Kind = index::SymbolKind::Class; + HI.NamespaceScope = ""; + HI.Definition = "template <> class Foo {}"; }}, // macro @@ -584,6 +591,8 @@ [](HoverInfo &HI) { HI.Name = "Foo"; HI.Kind = index::SymbolKind::Class; + HI.NamespaceScope = ""; + HI.Definition = "template <> class Foo {}"; }}, {// Falls back to primary template, when the type is not instantiated. R"cpp( @@ -1593,6 +1602,8 @@ [](HoverInfo &HI) { HI.Name = "initializer_list"; HI.Kind = index::SymbolKind::Class; + HI.NamespaceScope = "std::"; + HI.Definition = "template <> class initializer_list {}"; }}, { R"cpp(// User defined conversion to auto @@ -1651,6 +1662,8 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.NamespaceScope = ""; + HI.Definition = "struct Bar {}"; HI.Documentation = "auto function return with trailing type"; }}, { @@ -1663,6 +1676,8 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.NamespaceScope = ""; + HI.Definition = "struct Bar {}"; HI.Documentation = "trailing return type"; }}, { @@ -1675,6 +1690,8 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.NamespaceScope = ""; + HI.Definition = "struct Bar {}"; HI.Documentation = "auto in function return"; }}, { @@ -1688,6 +1705,8 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.NamespaceScope = ""; + HI.Definition = "struct Bar {}"; HI.Documentation = "auto& in function return"; }}, { @@ -1701,6 +1720,8 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.NamespaceScope = ""; + HI.Definition = "struct Bar {}"; HI.Documentation = "auto* in function return"; }}, { @@ -1714,6 +1735,8 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.NamespaceScope = ""; + HI.Definition = "struct Bar {}"; HI.Documentation = "const auto& in function return"; }}, { @@ -1726,6 +1749,8 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.NamespaceScope = ""; + HI.Definition = "struct Bar {}"; HI.Documentation = "decltype(auto) in function return"; }}, { @@ -1791,6 +1816,8 @@ [](HoverInfo &HI) { HI.Name = "Bar"; HI.Kind = index::SymbolKind::Struct; + HI.NamespaceScope = ""; + HI.Definition = "struct Bar {}"; HI.Documentation = "decltype of function with trailing return type."; }}, @@ -1837,10 +1864,12 @@ [](HoverInfo &HI) { HI.Name = "cls"; HI.Kind = index::SymbolKind::Struct; + HI.NamespaceScope = ""; + HI.Definition = "struct cls {}"; HI.Documentation = "auto on alias"; }}, { - R"cpp(// auto on alias + R"cpp(// auto on template template struct templ {}; ^[[auto]] z = templ(); @@ -1848,7 +1877,9 @@ [](HoverInfo &HI) { HI.Name = "templ"; HI.Kind = index::SymbolKind::Struct; - HI.Documentation = "auto on alias"; + HI.NamespaceScope = ""; + HI.Definition = "template <> struct templ {}"; + HI.Documentation = "auto on template"; }}, { R"cpp(// should not crash. diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -624,6 +624,140 @@ struct Fo^o {}; )cpp", + R"cpp(// auto builtin type (not supported) + au^to x = 42; + )cpp", + + R"cpp(// auto on lambda + auto x = [[[]]]{}; + au^to y = x; + )cpp", + + R"cpp(// auto on struct + namespace ns1 { + struct [[S1]] {}; + } // namespace ns1 + + au^to x = ns1::S1{}; + )cpp", + + R"cpp(// decltype on struct + namespace ns1 { + struct [[S1]] {}; + } // namespace ns1 + + ns1::S1 i; + decl^type(i) j; + )cpp", + + R"cpp(// decltype(auto) on struct + namespace ns1 { + struct [[S1]] {}; + } // namespace ns1 + + ns1::S1 i; + ns1::S1& j = i; + decl^type(auto) k = j; + )cpp", + + R"cpp(// auto on template class + template class [[Foo]] {}; + + au^to x = Foo(); + )cpp", + + R"cpp(// auto on template class with forward declared class + template class [[Foo]] {}; + class X; + + au^to x = Foo(); + )cpp", + + R"cpp(// auto on specialized template class + template class Foo {}; + template<> class [[Foo]] {}; + + au^to x = Foo(); + )cpp", + + R"cpp(// auto on initializer list. + namespace std + { + template + class [[initializer_list]] {}; + } + + au^to i = {1,2}; + )cpp", + + R"cpp(// auto function return with trailing type + struct [[Bar]] {}; + au^to test() -> decltype(Bar()) { + return Bar(); + } + )cpp", + + R"cpp(// decltype in trailing return type + struct [[Bar]] {}; + auto test() -> decl^type(Bar()) { + return Bar(); + } + )cpp", + + R"cpp(// auto in function return + struct [[Bar]] {}; + au^to test() { + return Bar(); + } + )cpp", + + R"cpp(// auto& in function return + struct [[Bar]] {}; + au^to& test() { + static Bar x; + return x; + } + )cpp", + + R"cpp(// auto* in function return + struct [[Bar]] {}; + au^to* test() { + Bar* x; + return x; + } + )cpp", + + R"cpp(// const auto& in function return + struct [[Bar]] {}; + const au^to& test() { + static Bar x; + return x; + } + )cpp", + + R"cpp(// decltype(auto) in function return + struct [[Bar]] {}; + decl^type(auto) test() { + return Bar(); + } + )cpp", + + R"cpp(// decltype of function with trailing return type. + struct [[Bar]] {}; + auto test() -> decltype(Bar()) { + return Bar(); + } + void foo() { + decl^type(test()) i = test(); + } + )cpp", + + R"cpp(// auto on alias + struct [[cls]] {}; + typedef cls cls_type; + au^to y = cls_type(); + )cpp", + R"cpp(// Override specifier jumps to overridden method class Y { virtual void $decl[[a]]() = 0; }; class X : Y { void a() ^override {} };