diff --git a/clang-tools-extra/clangd/AST.h b/clang-tools-extra/clangd/AST.h --- a/clang-tools-extra/clangd/AST.h +++ b/clang-tools-extra/clangd/AST.h @@ -111,6 +111,11 @@ /// void foo() -> returns null NestedNameSpecifierLoc getQualifierLoc(const NamedDecl &ND); +// Returns a type corresponding to a declaration of that type. +// Unlike the method on ASTContext, attempts to preserve the type as-written +// (i.e. vector rather than vector. +QualType declaredType(const TypeDecl *D); + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -246,6 +246,12 @@ printNamespaceScope(Context) ); } +QualType declaredType(const TypeDecl *D) { + if (const auto *CTSD = llvm::dyn_cast(D)) + if (const auto *TSI = CTSD->getTypeAsWritten()) + return TSI->getType(); + return D->getASTContext().getTypeDeclType(D); +} } // namespace clangd } // namespace clang 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 @@ -414,12 +414,12 @@ static std::string getLocalScope(const Decl *D) { std::vector Scopes; const DeclContext *DC = D->getDeclContext(); - auto GetName = [](const Decl *D) { - const NamedDecl *ND = dyn_cast(D); - std::string Name = ND->getNameAsString(); - // FIXME(sammccall): include template params/specialization args?. - if (!Name.empty()) - return Name; + auto GetName = [](const TypeDecl *D) { + if (!D->getDeclName().isEmpty()) { + PrintingPolicy Policy = D->getASTContext().getPrintingPolicy(); + Policy.SuppressScope = true; + return declaredType(D).getAsString(Policy); + } if (auto RD = dyn_cast(D)) return ("(anonymous " + RD->getKindName() + ")").str(); return std::string(""); @@ -566,6 +566,51 @@ Req, [&](const Symbol &S) { Hover.Documentation = S.Documentation; }); } +// Populates Type, ReturnType, and Parameters for function-like decls. +static void fillFunctionTypeAndParams(HoverInfo &HI, const Decl *D, + const FunctionDecl *FD, + const PrintingPolicy &Policy) { + HI.Parameters.emplace(); + for (const ParmVarDecl *PVD : FD->parameters()) { + HI.Parameters->emplace_back(); + auto &P = HI.Parameters->back(); + if (!PVD->getType().isNull()) { + P.Type.emplace(); + llvm::raw_string_ostream OS(*P.Type); + PVD->getType().print(OS, Policy); + } else { + std::string Param; + llvm::raw_string_ostream OS(Param); + PVD->dump(OS); + OS.flush(); + elog("Got param with null type: {0}", Param); + } + if (!PVD->getName().empty()) + P.Name = PVD->getNameAsString(); + if (PVD->hasDefaultArg()) { + P.Default.emplace(); + llvm::raw_string_ostream Out(*P.Default); + PVD->getDefaultArg()->printPretty(Out, nullptr, Policy); + } + } + + if (const auto* CCD = llvm::dyn_cast(FD)) { + // Constructor's "return type" is the class type. + HI.ReturnType = declaredType(CCD->getParent()).getAsString(Policy); + // Don't provide any type for the constructor itself. + } else if (const auto* CDD = llvm::dyn_cast(FD)){ + HI.ReturnType = "void"; + } else { + HI.ReturnType = FD->getReturnType().getAsString(Policy); + + QualType FunctionType = FD->getType(); + if (const VarDecl *VD = llvm::dyn_cast(D)) // Lambdas + FunctionType = VD->getType().getDesugaredType(D->getASTContext()); + HI.Type = FunctionType.getAsString(Policy); + } + // FIXME: handle variadics. +} + /// Generate a \p Hover object given the declaration \p D. static HoverInfo getHoverContents(const Decl *D, const SymbolIndex *Index) { HoverInfo HI; @@ -601,45 +646,7 @@ // Fill in types and params. if (const FunctionDecl *FD = getUnderlyingFunction(D)) { - HI.ReturnType.emplace(); - { - llvm::raw_string_ostream OS(*HI.ReturnType); - FD->getReturnType().print(OS, Policy); - } - - HI.Parameters.emplace(); - for (const ParmVarDecl *PVD : FD->parameters()) { - HI.Parameters->emplace_back(); - auto &P = HI.Parameters->back(); - if (!PVD->getType().isNull()) { - P.Type.emplace(); - llvm::raw_string_ostream OS(*P.Type); - PVD->getType().print(OS, Policy); - } else { - std::string Param; - llvm::raw_string_ostream OS(Param); - PVD->dump(OS); - OS.flush(); - elog("Got param with null type: {0}", Param); - } - if (!PVD->getName().empty()) - P.Name = PVD->getNameAsString(); - if (PVD->hasDefaultArg()) { - P.Default.emplace(); - llvm::raw_string_ostream Out(*P.Default); - PVD->getDefaultArg()->printPretty(Out, nullptr, Policy); - } - } - - HI.Type.emplace(); - llvm::raw_string_ostream TypeOS(*HI.Type); - // Lambdas - if (const VarDecl *VD = llvm::dyn_cast(D)) - VD->getType().getDesugaredType(D->getASTContext()).print(TypeOS, Policy); - // Functions - else - FD->getType().print(TypeOS, Policy); - // FIXME: handle variadics. + fillFunctionTypeAndParams(HI, D, FD, Policy); } else if (const auto *VD = dyn_cast(D)) { HI.Type.emplace(); llvm::raw_string_ostream OS(*HI.Type); 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 @@ -910,16 +910,15 @@ }}, // Constructor of partially-specialized class template {R"cpp( - template struct X; + template struct X; template struct X{ [[^X]](); }; )cpp", [](HoverInfo &HI) { HI.NamespaceScope = ""; HI.Name = "X"; - HI.LocalScope = "X::"; // FIXME: Should be X:: + HI.LocalScope = "X::"; // FIXME: X:: HI.Kind = SymbolKind::Constructor; - HI.Type = "void ()"; // FIXME: Should be None - HI.ReturnType = "void"; // FIXME: Should be None or X + HI.ReturnType = "X"; HI.Definition = "X()"; HI.Parameters.emplace(); }}, @@ -1020,8 +1019,8 @@ HI.Type = "enum Color"; HI.Value = "1"; }}, - // FIXME: We should use the Decl referenced, even if it comes from an - // implicit instantiation. + // FIXME: We should use the Decl referenced, even if from an implicit + // instantiation. Then the scope would be Add<1, 2> and the value 3. {R"cpp( template struct Add { static constexpr int result = a + b; @@ -1034,7 +1033,7 @@ HI.Kind = SymbolKind::Property; HI.Type = "const int"; HI.NamespaceScope = ""; - HI.LocalScope = "Add::"; + HI.LocalScope = "Add::"; }}, {R"cpp( const char *[[ba^r]] = "1234";