Author: Sam McCall Date: 2019-11-19T10:43:22+01:00 New Revision: 6ec07140980770fccfcdf53fe43e7425a9f51a7b
URL: https://github.com/llvm/llvm-project/commit/6ec07140980770fccfcdf53fe43e7425a9f51a7b DIFF: https://github.com/llvm/llvm-project/commit/6ec07140980770fccfcdf53fe43e7425a9f51a7b.diff LOG: [clangd] More sensible output for constructors/destructors in hover. Summary: Previously: both had type void() and return type void. Now: neither have a type. Constructors return T, destructors return void. Reviewers: hokein Subscribers: merge_guards_bot, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D70317 Added: Modified: clang-tools-extra/clangd/AST.cpp clang-tools-extra/clangd/AST.h clang-tools-extra/clangd/XRefs.cpp clang-tools-extra/clangd/unittests/XRefsTests.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index af04fbd0d4d4..d04ebcf22a88 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -246,6 +246,12 @@ std::string printType(const QualType QT, const DeclContext & Context){ printNamespaceScope(Context) ); } +QualType declaredType(const TypeDecl *D) { + if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(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/AST.h b/clang-tools-extra/clangd/AST.h index 8f1abdd3297d..b106e06f8d91 100644 --- a/clang-tools-extra/clangd/AST.h +++ b/clang-tools-extra/clangd/AST.h @@ -111,6 +111,11 @@ bool isExplicitTemplateSpecialization(const NamedDecl *D); /// 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<T*> rather than vector<type-parameter-0-0 *>. +QualType declaredType(const TypeDecl *D); + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 9697b8eec19a..ce8e59553622 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -566,6 +566,51 @@ static void enhanceFromIndex(HoverInfo &Hover, const Decl *D, 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<CXXConstructorDecl>(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<CXXDestructorDecl>(FD)){ + HI.ReturnType = "void"; + } else { + HI.ReturnType = FD->getReturnType().getAsString(Policy); + + QualType FunctionType = FD->getType(); + if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(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 @@ static HoverInfo getHoverContents(const Decl *D, const SymbolIndex *Index) { // 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<VarDecl>(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<ValueDecl>(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 index ef420bee01e9..9817ba643894 100644 --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -918,11 +918,20 @@ void foo())cpp"; HI.Name = "X"; HI.LocalScope = "X::"; // FIXME: Should be X<T *>:: HI.Kind = SymbolKind::Constructor; - HI.Type = "void ()"; // FIXME: Should be None - HI.ReturnType = "void"; // FIXME: Should be None or X<T*> + HI.ReturnType = "X<T *>"; HI.Definition = "X()"; HI.Parameters.emplace(); }}, + {"class X { [[^~]]X(); };", // FIXME: Should be [[~X]]() + [](HoverInfo &HI) { + HI.NamespaceScope = ""; + HI.Name = "~X"; + HI.LocalScope = "X::"; + HI.Kind = SymbolKind::Constructor; + HI.ReturnType = "void"; + HI.Definition = "~X()"; + HI.Parameters.emplace(); + }}, // auto on lambda {R"cpp( _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits