[clang-tools-extra] 3e03d92 - [clangd] Omit default template arguments from type hints

Nathan Ridge via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 6 23:38:17 PDT 2021


Author: Nathan Ridge
Date: 2021-09-07T02:38:27-04:00
New Revision: 3e03d92e2f4ad150469646c1b140ae6abb256c82

URL: https://github.com/llvm/llvm-project/commit/3e03d92e2f4ad150469646c1b140ae6abb256c82
DIFF: https://github.com/llvm/llvm-project/commit/3e03d92e2f4ad150469646c1b140ae6abb256c82.diff

LOG: [clangd] Omit default template arguments from type hints

Differential Revision: https://reviews.llvm.org/D108975

Added: 
    

Modified: 
    clang-tools-extra/clangd/InlayHints.cpp
    clang-tools-extra/clangd/unittests/InlayHintTests.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp
index bea5306daeb7..167f8001d6e4 100644
--- a/clang-tools-extra/clangd/InlayHints.cpp
+++ b/clang-tools-extra/clangd/InlayHints.cpp
@@ -24,7 +24,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
       : Results(Results), AST(AST.getASTContext()),
         MainFileID(AST.getSourceManager().getMainFileID()),
         Resolver(AST.getHeuristicResolver()),
-        TypeHintPolicy(this->AST.getPrintingPolicy()) {
+        TypeHintPolicy(this->AST.getPrintingPolicy()),
+        StructuredBindingPolicy(this->AST.getPrintingPolicy()) {
     bool Invalid = false;
     llvm::StringRef Buf =
         AST.getSourceManager().getBufferData(MainFileID, &Invalid);
@@ -33,14 +34,16 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
     TypeHintPolicy.SuppressScope = true; // keep type names short
     TypeHintPolicy.AnonymousTagLocations =
         false; // do not print lambda locations
-    // Print canonical types. Otherwise, SuppressScope would result in
-    // things like "metafunction<args>::type" being shorted to just "type",
-    // which is useless. This is particularly important for structured
-    // bindings that use the tuple_element protocol, where the non-canonical
-    // types would be "tuple_element<I, A>::type".
-    // Note, for "auto", we would often prefer sugared types, but the AST
-    // doesn't currently retain them in DeducedType anyways.
-    TypeHintPolicy.PrintCanonicalTypes = true;
+
+    // For structured bindings, print canonical types. This is important because
+    // for bindings that use the tuple_element protocol, the non-canonical types
+    // would be "tuple_element<I, A>::type".
+    // For "auto", we often prefer sugared types, but the AST doesn't currently
+    // retain them in DeducedType. However, not setting PrintCanonicalTypes for
+    // "auto" at least allows SuppressDefaultTemplateArgs (set by default) to
+    // have an effect.
+    StructuredBindingPolicy = TypeHintPolicy;
+    StructuredBindingPolicy.PrintCanonicalTypes = true;
   }
 
   bool VisitCXXConstructExpr(CXXConstructExpr *E) {
@@ -98,7 +101,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
     // but show hints for the individual bindings.
     if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
       for (auto *Binding : DD->bindings()) {
-        addTypeHint(Binding->getLocation(), Binding->getType(), ": ");
+        addTypeHint(Binding->getLocation(), Binding->getType(), ": ",
+                    StructuredBindingPolicy);
       }
       return true;
     }
@@ -327,11 +331,16 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
   }
 
   void addTypeHint(SourceRange R, QualType T, llvm::StringRef Prefix) {
+    addTypeHint(R, T, Prefix, TypeHintPolicy);
+  }
+
+  void addTypeHint(SourceRange R, QualType T, llvm::StringRef Prefix,
+                   const PrintingPolicy &Policy) {
     // Do not print useless "NULL TYPE" hint.
     if (!T.getTypePtrOrNull())
       return;
 
-    std::string TypeName = T.getAsString(TypeHintPolicy);
+    std::string TypeName = T.getAsString(Policy);
     if (TypeName.length() < TypeNameLimit)
       addInlayHint(R, InlayHintKind::TypeHint, std::string(Prefix) + TypeName);
   }
@@ -341,7 +350,14 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
   FileID MainFileID;
   StringRef MainFileBuf;
   const HeuristicResolver *Resolver;
+  // We want to suppress default template arguments, but otherwise print
+  // canonical types. Unfortunately, they're conflicting policies so we can't
+  // have both. For regular types, suppressing template arguments is more
+  // important, whereas printing canonical types is crucial for structured
+  // bindings, so we use two separate policies. (See the constructor where
+  // the policies are initialized for more details.)
   PrintingPolicy TypeHintPolicy;
+  PrintingPolicy StructuredBindingPolicy;
 
   static const size_t TypeNameLimit = 32;
 };

diff  --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
index 62930d1f42b1..cda2ba41e264 100644
--- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -602,6 +602,16 @@ TEST(TypeHints, LongTypeName) {
   )cpp");
 }
 
+TEST(TypeHints, DefaultTemplateArgs) {
+  assertTypeHints(R"cpp(
+    template <typename, typename = int>
+    struct A {};
+    A<float> foo();
+    auto $var[[var]] = foo();
+  )cpp",
+                  ExpectedHint{": A<float>", "var"});
+}
+
 // FIXME: Low-hanging fruit where we could omit a type hint:
 //  - auto x = TypeName(...);
 //  - auto x = (TypeName) (...);


        


More information about the cfe-commits mailing list