[clang-tools-extra] 6ec0714 - [clangd] More sensible output for constructors/destructors in hover.

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 19 01:43:36 PST 2019


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(


        


More information about the cfe-commits mailing list