#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/NestedNameSpecifier.h"
// Come up with a presentation for an anonymous entity.
if (isa<NamespaceDecl>(ND))
return "(anonymous namespace)";
- if (auto *Cls = llvm::dyn_cast<RecordDecl>(&ND))
+ if (auto *Cls = llvm::dyn_cast<RecordDecl>(&ND)) {
+ if (Cls->isLambda())
+ return "(lambda)";
return ("(anonymous " + Cls->getKindName() + ")").str();
+ }
if (isa<EnumDecl>(ND))
return "(anonymous enum)";
return "(anonymous)";
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/Index/IndexSymbol.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
std::string getNamespaceScope(const Decl *D) {
const DeclContext *DC = D->getDeclContext();
- if (const TypeDecl *TD = dyn_cast<TypeDecl>(DC))
+ if (const TagDecl *TD = dyn_cast<TagDecl>(DC))
return getNamespaceScope(TD);
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
return getNamespaceScope(FD);
+ if (const NamespaceDecl *NSD = dyn_cast<NamespaceDecl>(DC)) {
+ // Skip inline/anon namespaces.
+ if (NSD->isInline() || NSD->isAnonymousNamespace())
+ return getNamespaceScope(NSD);
+ }
if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC))
- return ND->getQualifiedNameAsString();
+ return printQualifiedName(*ND);
return "";
}
HoverInfo getHoverContents(QualType T, ASTContext &ASTCtx,
const SymbolIndex *Index) {
HoverInfo HI;
- llvm::raw_string_ostream OS(HI.Name);
- PrintingPolicy Policy = printingPolicyForDecls(ASTCtx.getPrintingPolicy());
- T.print(OS, Policy);
- OS.flush();
if (const auto *D = T->getAsTagDecl()) {
+ HI.Name = printName(ASTCtx, *D);
HI.Kind = index::getSymbolInfo(D).Kind;
enhanceFromIndex(HI, D, Index);
}
+
+ if (HI.Name.empty()) {
+ // Builtin types
+ llvm::raw_string_ostream OS(HI.Name);
+ PrintingPolicy Policy = printingPolicyForDecls(ASTCtx.getPrintingPolicy());
+ T.print(OS, Policy);
+ }
return HI;
}
}}
)cpp",
[](HoverInfo &HI) {
- HI.NamespaceScope = "ns1::(anonymous)::";
+ HI.NamespaceScope = "ns1::";
HI.LocalScope = "(anonymous struct)::";
HI.Name = "bar";
HI.Kind = index::SymbolKind::Field;
}
)cpp",
[](HoverInfo &HI) {
- HI.Name = "class (lambda)";
+ HI.Name = "(lambda)";
HI.Kind = index::SymbolKind::Class;
}},
// auto on template instantiation
}
)cpp",
[](HoverInfo &HI) {
- HI.Name = "class Foo<int>";
+ HI.Name = "Foo<int>";
HI.Kind = index::SymbolKind::Class;
}},
// auto on specialized template
}
)cpp",
[](HoverInfo &HI) {
- HI.Name = "class Foo<int>";
+ HI.Name = "Foo<int>";
HI.Kind = index::SymbolKind::Class;
}},
HI.NamespaceScope = "";
HI.LocalScope = "boom::";
}},
+ {
+ R"cpp(// Should not print inline or anon namespaces.
+ namespace ns {
+ inline namespace in_ns {
+ namespace a {
+ namespace {
+ namespace b {
+ inline namespace in_ns2 {
+ class Foo {};
+ } // in_ns2
+ } // b
+ } // anon
+ } // a
+ } // in_ns
+ } // ns
+ void foo() {
+ ns::a::b::[[F^oo]] x;
+ (void)x;
+ }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "Foo";
+ HI.Kind = index::SymbolKind::Class;
+ HI.NamespaceScope = "ns::a::b::";
+ HI.Definition = "class Foo {}";
+ }},
+ {
+ R"cpp(
+ template <typename T> class Foo {};
+ class X;
+ void foo() {
+ [[^auto]] x = Foo<X>();
+ }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "Foo<X>";
+ HI.Kind = index::SymbolKind::Class;
+ }},
};
for (const auto &Case : Cases) {
SCOPED_TRACE(Case.Code);
[](HoverInfo &HI) {
HI.Name = "foo";
HI.Kind = index::SymbolKind::Variable;
- HI.NamespaceScope = "ns::(anonymous)::";
+ HI.NamespaceScope = "ns::";
HI.Type = "int";
HI.Definition = "int foo";
}},
}
)cpp",
[](HoverInfo &HI) {
- HI.Name = "class std::initializer_list<int>";
+ HI.Name = "initializer_list<int>";
HI.Kind = index::SymbolKind::Class;
}},
{
}
)cpp",
[](HoverInfo &HI) {
- HI.Name = "struct Bar";
+ HI.Name = "Bar";
HI.Kind = index::SymbolKind::Struct;
}},
{
}
)cpp",
[](HoverInfo &HI) {
- HI.Name = "struct Bar";
+ HI.Name = "Bar";
HI.Kind = index::SymbolKind::Struct;
}},
{
}
)cpp",
[](HoverInfo &HI) {
- HI.Name = "struct Bar";
+ HI.Name = "Bar";
HI.Kind = index::SymbolKind::Struct;
}},
{
}
)cpp",
[](HoverInfo &HI) {
- HI.Name = "struct Bar";
+ HI.Name = "Bar";
HI.Kind = index::SymbolKind::Struct;
}},
{
}
)cpp",
[](HoverInfo &HI) {
- HI.Name = "struct Bar";
+ HI.Name = "Bar";
HI.Kind = index::SymbolKind::Struct;
}},
{
}
)cpp",
[](HoverInfo &HI) {
- HI.Name = "struct Bar";
+ HI.Name = "Bar";
HI.Kind = index::SymbolKind::Struct;
}},
{
}
)cpp",
[](HoverInfo &HI) {
- HI.Name = "struct Bar";
+ HI.Name = "Bar";
HI.Kind = index::SymbolKind::Struct;
}},
{
}
)cpp",
[](HoverInfo &HI) {
- HI.Name = "struct Bar";
+ HI.Name = "Bar";
HI.Kind = index::SymbolKind::Struct;
}},
{
^[[auto]] y = cls_type();
)cpp",
[](HoverInfo &HI) {
- HI.Name = "struct cls";
+ HI.Name = "cls";
HI.Kind = index::SymbolKind::Struct;
}},
{
^[[auto]] z = templ<int>();
)cpp",
[](HoverInfo &HI) {
- HI.Name = "struct templ<int>";
+ HI.Name = "templ<int>";
HI.Kind = index::SymbolKind::Struct;
}},
};