lh123 updated this revision to Diff 389921.
lh123 added a comment.

handle `TypeAliasTemplateDecl`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114522/new/

https://reviews.llvm.org/D114522

Files:
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/Hover.h
  clang-tools-extra/clangd/unittests/HoverTests.cpp
  clang/include/clang/AST/ASTDiagnostic.h
  clang/lib/AST/ASTDiagnostic.cpp

Index: clang/lib/AST/ASTDiagnostic.cpp
===================================================================
--- clang/lib/AST/ASTDiagnostic.cpp
+++ clang/lib/AST/ASTDiagnostic.cpp
@@ -26,7 +26,7 @@
 
 // Returns a desugared version of the QualType, and marks ShouldAKA as true
 // whenever we remove significant sugar from the type.
-static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
+QualType clang::Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
   QualifierCollector QC;
 
   while (true) {
Index: clang/include/clang/AST/ASTDiagnostic.h
===================================================================
--- clang/include/clang/AST/ASTDiagnostic.h
+++ clang/include/clang/AST/ASTDiagnostic.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_AST_ASTDIAGNOSTIC_H
 #define LLVM_CLANG_AST_ASTDIAGNOSTIC_H
 
+#include "clang/AST/Type.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticAST.h"
 
@@ -31,6 +32,10 @@
       SmallVectorImpl<char> &Output,
       void *Cookie,
       ArrayRef<intptr_t> QualTypeVals);
+
+  /// Returns a desugared version of the QualType, and marks ShouldAKA as true
+  /// whenever we remove significant sugar from the type.
+  QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA);
 }  // end namespace clang
 
 #endif
Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -45,8 +45,8 @@
          HI.Kind = index::SymbolKind::Function;
          HI.Documentation = "Best foo ever.";
          HI.Definition = "void foo()";
-         HI.ReturnType = "void";
-         HI.Type = "void ()";
+         HI.ReturnType = {"void", llvm::None};
+         HI.Type = {"void ()", llvm::None};
          HI.Parameters.emplace();
        }},
       // Inside namespace
@@ -62,8 +62,8 @@
          HI.Kind = index::SymbolKind::Function;
          HI.Documentation = "Best foo ever.";
          HI.Definition = "void foo()";
-         HI.ReturnType = "void";
-         HI.Type = "void ()";
+         HI.ReturnType = {"void", llvm::None};
+         HI.Type = {"void ()", llvm::None};
          HI.Parameters.emplace();
        }},
       // Field
@@ -81,7 +81,7 @@
          HI.Name = "bar";
          HI.Kind = index::SymbolKind::Field;
          HI.Definition = "char bar";
-         HI.Type = "char";
+         HI.Type = {"char", llvm::None};
          HI.Offset = 0;
          HI.Size = 1;
          HI.Padding = 7;
@@ -100,7 +100,7 @@
          HI.Name = "bar";
          HI.Kind = index::SymbolKind::Field;
          HI.Definition = "char bar";
-         HI.Type = "char";
+         HI.Type = {"char", llvm::None};
          HI.Size = 1;
          HI.Padding = 15;
          HI.AccessSpecifier = "public";
@@ -118,7 +118,7 @@
          HI.Name = "x";
          HI.Kind = index::SymbolKind::Field;
          HI.Definition = "int x : 1";
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
          HI.AccessSpecifier = "public";
        }},
       // Local to class method.
@@ -137,7 +137,7 @@
          HI.Name = "bar";
          HI.Kind = index::SymbolKind::Variable;
          HI.Definition = "int bar";
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
        }},
       // Anon namespace and local scope.
       {R"cpp(
@@ -153,7 +153,7 @@
          HI.Name = "bar";
          HI.Kind = index::SymbolKind::Field;
          HI.Definition = "char bar";
-         HI.Type = "char";
+         HI.Type = {"char", llvm::None};
          HI.Offset = 0;
          HI.Size = 1;
          HI.AccessSpecifier = "public";
@@ -179,7 +179,7 @@
          HI.Name = "foo";
          HI.Kind = index::SymbolKind::Variable;
          HI.Definition = "Foo<int, char, bool> foo = Foo<int, char, bool>(5)";
-         HI.Type = "Foo<int, char, bool>";
+         HI.Type = {"Foo<int, char, bool>", llvm::None};
        }},
       // Implicit template instantiation
       {R"cpp(
@@ -211,12 +211,19 @@
           bool Q = false, class... Ts>
 class Foo {})cpp";
          HI.TemplateParameters = {
-             {std::string("template <typename, bool...> class"),
-              std::string("C"), llvm::None},
-             {std::string("typename"), llvm::None, std::string("char")},
-             {std::string("int"), llvm::None, std::string("0")},
-             {std::string("bool"), std::string("Q"), std::string("false")},
-             {std::string("class..."), std::string("Ts"), llvm::None},
+             {{{std::string("template <typename, bool...> class"), llvm::None}},
+              std::string("C"),
+              llvm::None},
+             {{{std::string("typename"), llvm::None}},
+              llvm::None,
+              std::string("char")},
+             {{{std::string("int"), llvm::None}}, llvm::None, std::string("0")},
+             {{{std::string("bool"), llvm::None}},
+              std::string("Q"),
+              std::string("false")},
+             {{{std::string("class..."), llvm::None}},
+              std::string("Ts"),
+              llvm::None},
          };
        }},
       // Function template
@@ -237,8 +244,8 @@
          HI.Name = "foo";
          HI.Kind = index::SymbolKind::Function;
          HI.Definition = "template <> void foo<Foo, char, 0, false, <>>()";
-         HI.ReturnType = "void";
-         HI.Type = "void ()";
+         HI.ReturnType = {"void", llvm::None};
+         HI.Type = {"void ()", llvm::None};
          HI.Parameters.emplace();
        }},
       // Function decl
@@ -255,11 +262,13 @@
          HI.Name = "foo";
          HI.Kind = index::SymbolKind::Function;
          HI.Definition = "Foo<bool, true, false> foo(int, bool T = false)";
-         HI.ReturnType = "Foo<bool, true, false>";
-         HI.Type = "Foo<bool, true, false> (int, bool)";
+         HI.ReturnType = {"Foo<bool, true, false>", llvm::None};
+         HI.Type = {"Foo<bool, true, false> (int, bool)", llvm::None};
          HI.Parameters = {
-             {std::string("int"), llvm::None, llvm::None},
-             {std::string("bool"), std::string("T"), std::string("false")},
+             {{{std::string("int"), llvm::None}}, llvm::None, llvm::None},
+             {{{std::string("bool"), llvm::None}},
+              std::string("T"),
+              std::string("false")},
          };
        }},
       // Pointers to lambdas
@@ -276,11 +285,13 @@
          HI.Name = "c";
          HI.Kind = index::SymbolKind::Variable;
          HI.Definition = "auto *c = &b";
-         HI.Type = "(lambda) **";
-         HI.ReturnType = "bool";
+         HI.Type = {"(lambda) **", llvm::None};
+         HI.ReturnType = {"bool", llvm::None};
          HI.Parameters = {
-             {std::string("int"), std::string("T"), llvm::None},
-             {std::string("bool"), std::string("B"), llvm::None},
+             {{{std::string("int"), llvm::None}}, std::string("T"), llvm::None},
+             {{{std::string("bool"), llvm::None}},
+              std::string("B"),
+              llvm::None},
          };
          return HI;
        }},
@@ -297,11 +308,13 @@
          HI.Name = "bar";
          HI.Kind = index::SymbolKind::Parameter;
          HI.Definition = "decltype(lamb) &bar";
-         HI.Type = "decltype(lamb) &";
-         HI.ReturnType = "bool";
+         HI.Type = {"decltype(lamb) &", {"(lambda) &"}};
+         HI.ReturnType = {"bool", llvm::None};
          HI.Parameters = {
-             {std::string("int"), std::string("T"), llvm::None},
-             {std::string("bool"), std::string("B"), llvm::None},
+             {{{std::string("int"), llvm::None}}, std::string("T"), llvm::None},
+             {{{std::string("bool"), llvm::None}},
+              std::string("B"),
+              llvm::None},
          };
          return HI;
        }},
@@ -318,11 +331,13 @@
          HI.Name = "bar";
          HI.Kind = index::SymbolKind::Parameter;
          HI.Definition = "decltype(lamb) bar";
-         HI.Type = "class (lambda)";
-         HI.ReturnType = "bool";
+         HI.Type = {"class (lambda)", llvm::None};
+         HI.ReturnType = {"bool", llvm::None};
          HI.Parameters = {
-             {std::string("int"), std::string("T"), llvm::None},
-             {std::string("bool"), std::string("B"), llvm::None},
+             {{{std::string("int"), llvm::None}}, std::string("T"), llvm::None},
+             {{{std::string("bool"), llvm::None}},
+              std::string("B"),
+              llvm::None},
          };
          HI.Value = "false";
          return HI;
@@ -341,11 +356,13 @@
          HI.Name = "lamb";
          HI.Kind = index::SymbolKind::Variable;
          HI.Definition = "auto lamb = [&bar](int T, bool B) -> bool {}";
-         HI.Type = "class (lambda)";
-         HI.ReturnType = "bool";
+         HI.Type = {"class (lambda)", llvm::None};
+         HI.ReturnType = {"bool", llvm::None};
          HI.Parameters = {
-             {std::string("int"), std::string("T"), llvm::None},
-             {std::string("bool"), std::string("B"), llvm::None},
+             {{{std::string("int"), llvm::None}}, std::string("T"), llvm::None},
+             {{{std::string("bool"), llvm::None}},
+              std::string("B"),
+              llvm::None},
          };
          return HI;
        }},
@@ -361,7 +378,7 @@
          HI.Name = "test";
          HI.Kind = index::SymbolKind::Variable;
          HI.Definition = "int test";
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
        }},
       // Partially-specialized class template. (formerly type-parameter-0-0)
       {R"cpp(
@@ -427,6 +444,7 @@
          HI.Name = "auto";
          HI.Kind = index::SymbolKind::TypeAlias;
          HI.Definition = "struct S";
+         HI.Type = {"struct S", llvm::None};
        }},
       // undeduced auto
       {R"cpp(
@@ -450,6 +468,7 @@
          HI.Name = "auto";
          HI.Kind = index::SymbolKind::TypeAlias;
          HI.Definition = "class(lambda)";
+         HI.Type = {"class (lambda)", llvm::None};
        }},
       // auto on template instantiation
       {R"cpp(
@@ -462,6 +481,7 @@
          HI.Name = "auto";
          HI.Kind = index::SymbolKind::TypeAlias;
          HI.Definition = "Foo<int>";
+         HI.Type = {"Foo<int>", llvm::None};
        }},
       // auto on specialized template
       {R"cpp(
@@ -475,6 +495,7 @@
          HI.Name = "auto";
          HI.Kind = index::SymbolKind::TypeAlias;
          HI.Definition = "Foo<int>";
+         HI.Type = {"Foo<int>", llvm::None};
        }},
 
       // macro
@@ -497,7 +518,7 @@
          HI.Name = "bar";
          HI.Definition = "int bar = add(1, 2)";
          HI.Kind = index::SymbolKind::Variable;
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
          HI.NamespaceScope = "";
          HI.Value = "3";
        }},
@@ -508,7 +529,7 @@
          HI.Name = "bar";
          HI.Definition = "int bar = sizeof(char)";
          HI.Kind = index::SymbolKind::Variable;
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
          HI.NamespaceScope = "";
          HI.Value = "1";
        }},
@@ -522,7 +543,7 @@
          HI.Name = "bar";
          HI.Definition = "int bar = Add<1, 2>::result";
          HI.Kind = index::SymbolKind::Variable;
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
          HI.NamespaceScope = "";
          HI.Value = "3";
        }},
@@ -536,7 +557,7 @@
          HI.LocalScope = "Color::";
          HI.Definition = "GREEN = 5";
          HI.Kind = index::SymbolKind::EnumConstant;
-         HI.Type = "enum Color";
+         HI.Type = {"enum Color", llvm::None};
          HI.Value = "5"; // Numeric on the enumerator name, no hex as small.
        }},
       {R"cpp(
@@ -549,7 +570,7 @@
          HI.NamespaceScope = "";
          HI.Definition = "Color x = RED";
          HI.Kind = index::SymbolKind::Variable;
-         HI.Type = "enum Color";
+         HI.Type = {"enum Color", llvm::None};
          HI.Value = "RED (0xffffff85)"; // Symbolic on an expression.
        }},
       {R"cpp(
@@ -562,22 +583,23 @@
          HI.Name = "result";
          HI.Definition = "static constexpr int result = a + b";
          HI.Kind = index::SymbolKind::StaticProperty;
-         HI.Type = "const int";
+         HI.Type = {"const int", llvm::None};
          HI.NamespaceScope = "";
          HI.LocalScope = "Add<1, 2>::";
          HI.Value = "3";
          HI.AccessSpecifier = "public";
        }},
       {R"cpp(
-        constexpr int answer() { return 40 + 2; }
+        using my_int = int;
+        constexpr my_int answer() { return 40 + 2; }
         int x = [[ans^wer]]();
         )cpp",
        [](HoverInfo &HI) {
          HI.Name = "answer";
-         HI.Definition = "constexpr int answer()";
+         HI.Definition = "constexpr my_int answer()";
          HI.Kind = index::SymbolKind::Function;
-         HI.Type = "int ()";
-         HI.ReturnType = "int";
+         HI.Type = {"my_int ()", {"int ()"}};
+         HI.ReturnType = {"my_int", {"int"}};
          HI.Parameters.emplace();
          HI.NamespaceScope = "";
          HI.Value = "42 (0x2a)";
@@ -589,7 +611,7 @@
          HI.Name = "bar";
          HI.Definition = "const char *bar = \"1234\"";
          HI.Kind = index::SymbolKind::Variable;
-         HI.Type = "const char *";
+         HI.Type = {"const char *", llvm::None};
          HI.NamespaceScope = "";
          HI.Value = "&\"1234\"[0]";
        }},
@@ -607,7 +629,7 @@
          HI.Name = "name";
          HI.Definition = "int name";
          HI.Kind = index::SymbolKind::Parameter;
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
          HI.NamespaceScope = "";
          HI.LocalScope = "boom::";
        }},
@@ -649,6 +671,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "Foo<X>";
+            HI.Type = {"Foo<X>", llvm::None};
           }},
       {// Falls back to primary template, when the type is not instantiated.
        R"cpp(
@@ -679,7 +702,7 @@
          HI.NamespaceScope = "";
          HI.Definition = "typename T = int";
          HI.LocalScope = "foo::";
-         HI.Type = "typename";
+         HI.Type = {"typename", llvm::None};
          HI.AccessSpecifier = "public";
        }},
       {// TemplateTemplate Type Parameter
@@ -692,7 +715,7 @@
          HI.NamespaceScope = "";
          HI.Definition = "template <typename> class T";
          HI.LocalScope = "foo::";
-         HI.Type = "template <typename> class";
+         HI.Type = {"template <typename> class", llvm::None};
          HI.AccessSpecifier = "public";
        }},
       {// NonType Template Parameter
@@ -705,7 +728,7 @@
          HI.NamespaceScope = "";
          HI.Definition = "int T = 5";
          HI.LocalScope = "foo::";
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
          HI.AccessSpecifier = "public";
        }},
 
@@ -720,8 +743,8 @@
          HI.Definition = "float y()";
          HI.LocalScope = "X::";
          HI.Documentation = "Trivial accessor for `Y`.";
-         HI.Type = "float ()";
-         HI.ReturnType = "float";
+         HI.Type = {"float ()", llvm::None};
+         HI.ReturnType = {"float", llvm::None};
          HI.Parameters.emplace();
          HI.AccessSpecifier = "public";
        }},
@@ -736,11 +759,11 @@
          HI.Definition = "void setY(float v)";
          HI.LocalScope = "X::";
          HI.Documentation = "Trivial setter for `Y`.";
-         HI.Type = "void (float)";
-         HI.ReturnType = "void";
+         HI.Type = {"void (float)", llvm::None};
+         HI.ReturnType = {"void", llvm::None};
          HI.Parameters.emplace();
          HI.Parameters->emplace_back();
-         HI.Parameters->back().Type = "float";
+         HI.Parameters->back().Type = {"float", llvm::None};
          HI.Parameters->back().Name = "v";
          HI.AccessSpecifier = "public";
        }},
@@ -755,11 +778,11 @@
          HI.Definition = "X &setY(float v)";
          HI.LocalScope = "X::";
          HI.Documentation = "Trivial setter for `Y`.";
-         HI.Type = "X &(float)";
-         HI.ReturnType = "X &";
+         HI.Type = {"X &(float)", llvm::None};
+         HI.ReturnType = {"X &", llvm::None};
          HI.Parameters.emplace();
          HI.Parameters->emplace_back();
-         HI.Parameters->back().Type = "float";
+         HI.Parameters->back().Type = {"float", llvm::None};
          HI.Parameters->back().Name = "v";
          HI.AccessSpecifier = "public";
        }},
@@ -775,11 +798,11 @@
          HI.Definition = "void setY(float v)";
          HI.LocalScope = "X::";
          HI.Documentation = "Trivial setter for `Y`.";
-         HI.Type = "void (float)";
-         HI.ReturnType = "void";
+         HI.Type = {"void (float)", llvm::None};
+         HI.ReturnType = {"void", llvm::None};
          HI.Parameters.emplace();
          HI.Parameters->emplace_back();
-         HI.Parameters->back().Type = "float";
+         HI.Parameters->back().Type = {"float", llvm::None};
          HI.Parameters->back().Name = "v";
          HI.AccessSpecifier = "public";
        }},
@@ -793,7 +816,7 @@
          HI.Kind = index::SymbolKind::Variable;
          HI.NamespaceScope = "";
          HI.Definition = "X x";
-         HI.Type = "struct X";
+         HI.Type = {"struct X", llvm::None};
        }},
       {// Don't crash on null types.
        R"cpp(auto [^[[x]]] = 1; /*error-ok*/)cpp",
@@ -802,7 +825,7 @@
          HI.Kind = index::SymbolKind::Variable;
          HI.NamespaceScope = "";
          HI.Definition = "";
-         HI.Type = "NULL TYPE";
+         HI.Type = {"NULL TYPE", llvm::None};
          // Bindings are in theory public members of an anonymous struct.
          HI.AccessSpecifier = "public";
        }},
@@ -821,10 +844,10 @@
          HI.Definition = "int b = 2";
          HI.LocalScope = "code::";
          HI.Value = "2";
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
          HI.CalleeArgInfo.emplace();
          HI.CalleeArgInfo->Name = "arg_b";
-         HI.CalleeArgInfo->Type = "int &";
+         HI.CalleeArgInfo->Type = {"int &", llvm::None};
          HI.CallPassType.emplace();
          HI.CallPassType->PassBy = PassMode::Ref;
          HI.CallPassType->Converted = false;
@@ -848,10 +871,10 @@
          HI.Definition = "int a = 1";
          HI.LocalScope = "code::";
          HI.Value = "1";
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
          HI.CalleeArgInfo.emplace();
          HI.CalleeArgInfo->Name = "arg_a";
-         HI.CalleeArgInfo->Type = "int";
+         HI.CalleeArgInfo->Type = {"int", llvm::None};
          HI.CalleeArgInfo->Default = "3";
          HI.CallPassType.emplace();
          HI.CallPassType->PassBy = PassMode::Value;
@@ -869,7 +892,7 @@
          HI.NamespaceScope = "";
          HI.Definition = "int xx";
          HI.LocalScope = "Foo::";
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
          HI.AccessSpecifier = "public";
        }},
       {R"cpp(
@@ -884,7 +907,7 @@
          HI.NamespaceScope = "";
          HI.Definition = "int yy";
          HI.LocalScope = "Foo::";
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
          HI.AccessSpecifier = "public";
        }},
       {// No crash on InitListExpr.
@@ -899,8 +922,79 @@
        [](HoverInfo &HI) {
          HI.Name = "expression";
          HI.Kind = index::SymbolKind::Unknown;
-         HI.Type = "int[10]";
+         HI.Type = {"int[10]", llvm::None};
          HI.Value = "{1}";
+       }},
+      {// Canonical type
+       R"cpp(
+          template<typename T>
+          struct TestHover {
+            using Type = T;
+          };
+
+          void code() {
+            TestHover<int>::Type ^[[a]];
+          }
+         )cpp",
+       [](HoverInfo &HI) {
+         HI.Name = "a";
+         HI.NamespaceScope = "";
+         HI.LocalScope = "code::";
+         HI.Definition = "TestHover<int>::Type a";
+         HI.Kind = index::SymbolKind::Variable;
+         HI.Type = {"TestHover<int>::Type", {"int"}};
+       }},
+      {// Canonical template type
+       R"cpp(
+          template<typename T>
+          void ^[[foo]](T arg) {}
+         )cpp",
+       [](HoverInfo &HI) {
+         HI.Name = "foo";
+         HI.Kind = index::SymbolKind::Function;
+         HI.NamespaceScope = "";
+         HI.Definition = "template <typename T> void foo(T arg)";
+         HI.Type = {"void (T)", llvm::None};
+         HI.ReturnType = {"void", llvm::None};
+         HI.Parameters = {{{{std::string("T"), llvm::None}},
+                           std::string("arg"),
+                           llvm::None}};
+         HI.TemplateParameters = {{{{std::string("typename"), llvm::None}},
+                                   std::string("T"),
+                                   llvm::None}};
+       }},
+      {// TypeAlias Template
+       R"cpp(
+          template<typename T>
+          using ^[[alias]] = T;
+         )cpp",
+       [](HoverInfo &HI) {
+         HI.Name = "alias";
+         HI.NamespaceScope = "";
+         HI.LocalScope = "";
+         HI.Kind = index::SymbolKind::TypeAlias;
+         HI.Definition = "template <typename T> using alias = T";
+         HI.Type = {"T", llvm::None};
+         HI.TemplateParameters = {
+             {{{"typename", llvm::None}}, std::string("T"), llvm::None}};
+       }},
+      {// TypeAlias Template
+       R"cpp(
+          template<typename T>
+          using A = T;
+
+          template<typename T>
+          using ^[[AA]] = A<T>;
+         )cpp",
+       [](HoverInfo &HI) {
+         HI.Name = "AA";
+         HI.NamespaceScope = "";
+         HI.LocalScope = "";
+         HI.Kind = index::SymbolKind::TypeAlias;
+         HI.Definition = "template <typename T> using AA = A<T>";
+         HI.Type = {"A<T>", {"type-parameter-0-0"}}; // FIXME: should be 'T'
+         HI.TemplateParameters = {
+             {{{"typename", llvm::None}}, std::string("T"), llvm::None}};
        }}};
   for (const auto &Case : Cases) {
     SCOPED_TRACE(Case.Code);
@@ -1117,7 +1211,7 @@
             HI.Kind = index::SymbolKind::Variable;
             HI.NamespaceScope = "";
             HI.LocalScope = "main::";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.Definition = "int bonjour";
           }},
       {
@@ -1134,7 +1228,7 @@
             HI.Kind = index::SymbolKind::Variable;
             HI.NamespaceScope = "";
             HI.LocalScope = "s::method::";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.Definition = "int bonjour";
           }},
       {
@@ -1193,12 +1287,12 @@
             HI.Name = "foo";
             HI.Kind = index::SymbolKind::Function;
             HI.NamespaceScope = "";
-            HI.Type = "void (int)";
+            HI.Type = {"void (int)", llvm::None};
             HI.Definition = "void foo(int)";
             HI.Documentation = "Function definition via pointer";
-            HI.ReturnType = "void";
+            HI.ReturnType = {"void", llvm::None};
             HI.Parameters = {
-                {std::string("int"), llvm::None, llvm::None},
+                {{{std::string("int"), llvm::None}}, llvm::None, llvm::None},
             };
           }},
       {
@@ -1212,12 +1306,12 @@
             HI.Name = "foo";
             HI.Kind = index::SymbolKind::Function;
             HI.NamespaceScope = "";
-            HI.Type = "int (int)";
+            HI.Type = {"int (int)", llvm::None};
             HI.Definition = "int foo(int)";
             HI.Documentation = "Function declaration via call";
-            HI.ReturnType = "int";
+            HI.ReturnType = {"int", llvm::None};
             HI.Parameters = {
-                {std::string("int"), llvm::None, llvm::None},
+                {{{std::string("int"), llvm::None}}, llvm::None, llvm::None},
             };
           }},
       {
@@ -1233,7 +1327,7 @@
             HI.Kind = index::SymbolKind::Field;
             HI.NamespaceScope = "";
             HI.LocalScope = "Foo::";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.Definition = "int x";
           }},
       {
@@ -1249,7 +1343,7 @@
             HI.Kind = index::SymbolKind::Field;
             HI.NamespaceScope = "";
             HI.LocalScope = "Foo::";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.Definition = "int x = 5";
           }},
       {
@@ -1264,7 +1358,7 @@
             HI.Kind = index::SymbolKind::StaticProperty;
             HI.NamespaceScope = "";
             HI.LocalScope = "Foo::";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.Definition = "static int x";
           }},
       {
@@ -1279,7 +1373,7 @@
             HI.Kind = index::SymbolKind::Field;
             HI.NamespaceScope = "";
             HI.LocalScope = "Foo::";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.Definition = "int x";
           }},
       {
@@ -1294,7 +1388,7 @@
             HI.Kind = index::SymbolKind::Field;
             HI.NamespaceScope = "";
             HI.LocalScope = "Foo::";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.Definition = "int x";
             // FIXME: Initializer for x is a DesignatedInitListExpr, hence it is
             // of struct type and omitted.
@@ -1311,7 +1405,7 @@
             HI.Kind = index::SymbolKind::Field;
             HI.NamespaceScope = "";
             HI.LocalScope = "Foo::";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.Definition = "int x";
           }},
       {
@@ -1327,9 +1421,9 @@
             HI.Kind = index::SymbolKind::InstanceMethod;
             HI.NamespaceScope = "";
             HI.LocalScope = "Foo::";
-            HI.Type = "int ()";
+            HI.Type = {"int ()", llvm::None};
             HI.Definition = "int x()";
-            HI.ReturnType = "int";
+            HI.ReturnType = {"int", llvm::None};
             HI.Parameters = std::vector<HoverInfo::Param>{};
           }},
       {
@@ -1344,9 +1438,9 @@
             HI.Kind = index::SymbolKind::StaticMethod;
             HI.NamespaceScope = "";
             HI.LocalScope = "Foo::";
-            HI.Type = "int ()";
+            HI.Type = {"int ()", llvm::None};
             HI.Definition = "static int x()";
-            HI.ReturnType = "int";
+            HI.ReturnType = {"int", llvm::None};
             HI.Parameters = std::vector<HoverInfo::Param>{};
           }},
       {
@@ -1361,6 +1455,7 @@
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.NamespaceScope = "";
             HI.Definition = "typedef int Foo";
+            HI.Type = {"int", llvm::None};
             HI.Documentation = "Typedef";
             // FIXME: Maybe put underlying type into HI.Type for aliases?
           }},
@@ -1376,6 +1471,7 @@
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.NamespaceScope = "";
             HI.Definition = "typedef struct Bar Foo";
+            HI.Type = {"struct Bar", llvm::None};
             HI.Documentation = "Typedef with embedded definition";
           }},
       {
@@ -1404,7 +1500,7 @@
             HI.Name = "foo";
             HI.Kind = index::SymbolKind::Variable;
             HI.NamespaceScope = "ns::";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.Definition = "int foo";
           }},
       {
@@ -1464,10 +1560,10 @@
             HI.Name = "foo";
             HI.Kind = index::SymbolKind::Function;
             HI.NamespaceScope = "";
-            HI.Type = "void ()";
+            HI.Type = {"void ()", llvm::None};
             HI.Definition = "void foo()";
             HI.Documentation = "Function declaration";
-            HI.ReturnType = "void";
+            HI.ReturnType = {"void", llvm::None};
             HI.Parameters = std::vector<HoverInfo::Param>{};
           }},
       {
@@ -1500,7 +1596,7 @@
             HI.Kind = index::SymbolKind::EnumConstant;
             HI.NamespaceScope = "";
             HI.LocalScope = "Hello::";
-            HI.Type = "enum Hello";
+            HI.Type = {"enum Hello", llvm::None};
             HI.Definition = "ONE";
             HI.Value = "0";
           }},
@@ -1519,7 +1615,7 @@
             HI.NamespaceScope = "";
             // FIXME: This should be `(anon enum)::`
             HI.LocalScope = "";
-            HI.Type = "enum (unnamed)";
+            HI.Type = {"enum (unnamed)", llvm::None};
             HI.Definition = "ONE";
             HI.Value = "0";
           }},
@@ -1534,7 +1630,7 @@
             HI.Name = "hey";
             HI.Kind = index::SymbolKind::Variable;
             HI.NamespaceScope = "";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.Definition = "static int hey = 10";
             HI.Documentation = "Global variable";
             // FIXME: Value shouldn't be set in this case
@@ -1553,7 +1649,7 @@
             HI.Name = "hey";
             HI.Kind = index::SymbolKind::Variable;
             HI.NamespaceScope = "ns1::";
-            HI.Type = "long long";
+            HI.Type = {"long long", llvm::None};
             HI.Definition = "static long long hey = -36637162602497";
             HI.Value = "-36637162602497 (0xffffdeadbeefffff)"; // needs 64 bits
           }},
@@ -1571,7 +1667,7 @@
             HI.Kind = index::SymbolKind::Field;
             HI.NamespaceScope = "";
             HI.LocalScope = "(anonymous struct)::";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.Definition = "int hello";
           }},
       {
@@ -1586,10 +1682,10 @@
             HI.Name = "foo";
             HI.Kind = index::SymbolKind::Function;
             HI.NamespaceScope = "";
-            HI.Type = "int ()";
+            HI.Type = {"int ()", llvm::None};
             HI.Definition = "template <> int foo<int>()";
             HI.Documentation = "Templated function";
-            HI.ReturnType = "int";
+            HI.ReturnType = {"int", llvm::None};
             HI.Parameters = std::vector<HoverInfo::Param>{};
             // FIXME: We should populate template parameters with arguments in
             // case of instantiations.
@@ -1608,7 +1704,7 @@
             HI.Kind = index::SymbolKind::Field;
             HI.NamespaceScope = "";
             HI.LocalScope = "outer::(anonymous union)::";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.Definition = "int def";
           }},
       {
@@ -1621,9 +1717,9 @@
             HI.Name = "indexSymbol";
             HI.Kind = index::SymbolKind::Function;
             HI.NamespaceScope = "";
-            HI.Type = "void ()";
+            HI.Type = {"void ()", llvm::None};
             HI.Definition = "void indexSymbol()";
-            HI.ReturnType = "void";
+            HI.ReturnType = {"void", llvm::None};
             HI.Parameters = std::vector<HoverInfo::Param>{};
             HI.Documentation = "comment from index";
           }},
@@ -1637,6 +1733,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// Simple initialization with const auto
@@ -1648,6 +1745,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// Simple initialization with const auto&
@@ -1659,6 +1757,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// Simple initialization with auto&
@@ -1671,6 +1770,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// Simple initialization with auto*
@@ -1683,6 +1783,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// Simple initialization with auto from pointer
@@ -1695,6 +1796,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int *";
+            HI.Type = {"int *", llvm::None};
           }},
       {
           R"cpp(// Auto with initializer list.
@@ -1711,6 +1813,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "class std::initializer_list<int>";
+            HI.Type = {"class std::initializer_list<int>", llvm::None};
           }},
       {
           R"cpp(// User defined conversion to auto
@@ -1722,6 +1825,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// Simple initialization with decltype(auto)
@@ -1733,6 +1837,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// Simple initialization with const decltype(auto)
@@ -1745,6 +1850,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "const int";
+            HI.Type = {"const int", llvm::None};
           }},
       {
           R"cpp(// Simple initialization with const& decltype(auto)
@@ -1758,6 +1864,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "const int &";
+            HI.Type = {"const int &", llvm::None};
           }},
       {
           R"cpp(// Simple initialization with & decltype(auto)
@@ -1771,6 +1878,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int &";
+            HI.Type = {"int &", llvm::None};
           }},
       {
           R"cpp(// simple trailing return type
@@ -1782,6 +1890,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// auto function return with trailing type
@@ -1794,6 +1903,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "struct Bar";
+            HI.Type = {"struct Bar", llvm::None};
             HI.Documentation = "auto function return with trailing type";
           }},
       {
@@ -1807,6 +1917,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "struct Bar";
+            HI.Type = {"struct Bar", llvm::None};
             HI.Documentation = "trailing return type";
           }},
       {
@@ -1820,6 +1931,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "struct Bar";
+            HI.Type = {"struct Bar", llvm::None};
             HI.Documentation = "auto in function return";
           }},
       {
@@ -1834,6 +1946,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "struct Bar";
+            HI.Type = {"struct Bar", llvm::None};
             HI.Documentation = "auto& in function return";
           }},
       {
@@ -1848,6 +1961,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "struct Bar";
+            HI.Type = {"struct Bar", llvm::None};
             HI.Documentation = "auto* in function return";
           }},
       {
@@ -1862,6 +1976,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "struct Bar";
+            HI.Type = {"struct Bar", llvm::None};
             HI.Documentation = "const auto& in function return";
           }},
       {
@@ -1875,6 +1990,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "struct Bar";
+            HI.Type = {"struct Bar", llvm::None};
             HI.Documentation = "decltype(auto) in function return";
           }},
       {
@@ -1888,6 +2004,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int &";
+            HI.Type = {"int &", llvm::None};
           }},
       {
           R"cpp(// decltype lvalue reference
@@ -1900,6 +2017,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// decltype lvalue reference
@@ -1913,6 +2031,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int &";
+            HI.Type = {"int &", llvm::None};
           }},
       {
           R"cpp(// decltype lvalue reference parenthesis
@@ -1925,6 +2044,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int &";
+            HI.Type = {"int &", llvm::None};
           }},
       {
           R"cpp(// decltype rvalue reference
@@ -1937,6 +2057,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int &&";
+            HI.Type = {"int &&", llvm::None};
           }},
       {
           R"cpp(// decltype rvalue reference function call
@@ -1950,6 +2071,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int &&";
+            HI.Type = {"int &&", llvm::None};
           }},
       {
           R"cpp(// decltype of function with trailing return type.
@@ -1965,6 +2087,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "struct Bar";
+            HI.Type = {"struct Bar", llvm::None};
             HI.Documentation =
                 "decltype of function with trailing return type.";
           }},
@@ -1980,6 +2103,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// decltype of dependent type
@@ -1992,6 +2116,7 @@
             HI.Name = "decltype";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "<dependent type>";
+            HI.Type = {"<dependent type>", llvm::None};
           }},
       {
           R"cpp(// More complicated structured types.
@@ -2002,6 +2127,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// Should not crash when evaluating the initializer.
@@ -2013,7 +2139,7 @@
             HI.Kind = index::SymbolKind::Variable;
             HI.NamespaceScope = "";
             HI.LocalScope = "test::";
-            HI.Type = "Test &&";
+            HI.Type = {"Test &&", llvm::None};
             HI.Definition = "Test &&test = {}";
           }},
       {
@@ -2025,6 +2151,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "int_type";
+            HI.Type = {"int_type", {"int"}};
           }},
       {
           R"cpp(// auto on alias
@@ -2036,6 +2163,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "cls_type";
+            HI.Type = {"cls_type", {"cls"}};
             HI.Documentation = "auto on alias";
           }},
       {
@@ -2048,6 +2176,7 @@
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
             HI.Definition = "templ<int>";
+            HI.Type = {"templ<int>", llvm::None};
             HI.Documentation = "auto on alias";
           }},
       {
@@ -2114,8 +2243,8 @@
             HI.LocalScope = "cls<int>::";
             HI.Name = "method";
             HI.Parameters.emplace();
-            HI.ReturnType = "int";
-            HI.Type = "int ()";
+            HI.ReturnType = {"int", llvm::None};
+            HI.Type = {"int ()", llvm::None};
           }},
       {
           R"cpp(// type of nested templates.
@@ -2127,7 +2256,7 @@
             HI.Kind = index::SymbolKind::Variable;
             HI.NamespaceScope = "";
             HI.Name = "foo";
-            HI.Type = "cls<cls<cls<int>>>";
+            HI.Type = {"cls<cls<cls<int>>>", llvm::None};
           }},
       {
           R"cpp(// type of nested templates.
@@ -2150,7 +2279,7 @@
             HI.Kind = index::SymbolKind::Variable;
             HI.NamespaceScope = "";
             HI.Name = "b";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// type with decltype
@@ -2162,7 +2291,7 @@
             HI.Kind = index::SymbolKind::Variable;
             HI.NamespaceScope = "";
             HI.Name = "b";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// type with decltype
@@ -2173,7 +2302,7 @@
             HI.Kind = index::SymbolKind::Variable;
             HI.NamespaceScope = "";
             HI.Name = "b";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
           }},
       {
           R"cpp(// type with decltype
@@ -2186,10 +2315,12 @@
             HI.Name = "foo";
             // FIXME: Handle composite types with decltype with a printing
             // policy.
-            HI.Type = "auto (decltype(a)) -> decltype(a)";
-            HI.ReturnType = "int";
-            HI.Parameters = {
-                {std::string("int"), std::string("x"), llvm::None}};
+            HI.Type = {"auto (decltype(a)) -> decltype(a)",
+                       {"auto (int) -> int"}};
+            HI.ReturnType = {"int", llvm::None};
+            HI.Parameters = {{{{std::string("int"), llvm::None}},
+                              std::string("x"),
+                              llvm::None}};
           }},
       {
           R"cpp(// sizeof expr
@@ -2198,7 +2329,7 @@
           })cpp",
           [](HoverInfo &HI) {
             HI.Name = "expression";
-            HI.Type = "unsigned long";
+            HI.Type = {"unsigned long", llvm::None};
             HI.Value = "1";
           }},
       {
@@ -2208,7 +2339,7 @@
           })cpp",
           [](HoverInfo &HI) {
             HI.Name = "expression";
-            HI.Type = "unsigned long";
+            HI.Type = {"unsigned long", llvm::None};
             HI.Value = "1";
           }},
       {
@@ -2220,10 +2351,11 @@
           [](HoverInfo &HI) {
             HI.Name = "foo";
             HI.Kind = index::SymbolKind::Function;
-            HI.Type = "void (const int &)";
-            HI.ReturnType = "void";
-            HI.Parameters = {
-                {std::string("const int &"), llvm::None, std::string("T()")}};
+            HI.Type = {"void (const int &)", llvm::None};
+            HI.ReturnType = {"void", llvm::None};
+            HI.Parameters = {{{{std::string("const int &"), llvm::None}},
+                              llvm::None,
+                              std::string("T()")}};
             HI.Definition = "template <> void foo<int>(const int &)";
             HI.NamespaceScope = "";
           }},
@@ -2235,7 +2367,7 @@
           )cpp",
           [](HoverInfo &HI) {
             HI.Name = "data";
-            HI.Type = "char";
+            HI.Type = {"char", llvm::None};
             HI.Kind = index::SymbolKind::Field;
             HI.LocalScope = "ObjC::";
             HI.NamespaceScope = "";
@@ -2283,6 +2415,7 @@
           [](HoverInfo &HI) {
             HI.Name = "this";
             HI.Definition = "ns::Foo *";
+            HI.Type = {"ns::Foo *", llvm::None};
           }},
       {
           R"cpp(// this expr for template class
@@ -2298,6 +2431,7 @@
           [](HoverInfo &HI) {
             HI.Name = "this";
             HI.Definition = "const Foo<T> *";
+            HI.Type = {"const Foo<T> *", llvm::None};
           }},
       {
           R"cpp(// this expr for specialization class
@@ -2314,6 +2448,7 @@
           [](HoverInfo &HI) {
             HI.Name = "this";
             HI.Definition = "Foo<int> *";
+            HI.Type = {"Foo<int> *", llvm::None};
           }},
       {
           R"cpp(// this expr for partial specialization struct
@@ -2330,6 +2465,7 @@
           [](HoverInfo &HI) {
             HI.Name = "this";
             HI.Definition = "const Foo<int, F> *";
+            HI.Type = {"const Foo<int, F> *", llvm::None};
           }},
       {
           R"cpp(
@@ -2386,7 +2522,7 @@
          HI.Name = "result";
          HI.Definition = "int result = 2";
          HI.Kind = index::SymbolKind::Variable;
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
          HI.LocalScope = "+[Foo(Private) somePrivateMethod]::";
          HI.NamespaceScope = "";
          HI.Value = "2";
@@ -2406,7 +2542,7 @@
          HI.Name = "result";
          HI.Definition = "int result = 0";
          HI.Kind = index::SymbolKind::Variable;
-         HI.Type = "int";
+         HI.Type = {"int", llvm::None};
          HI.LocalScope = "-[Foo variadicArgMethod:, ...]::";
          HI.NamespaceScope = "";
          HI.Value = "0";
@@ -2580,8 +2716,11 @@
             HI.Kind = index::SymbolKind::Class;
             HI.Size = 10;
             HI.TemplateParameters = {
-                {std::string("typename"), std::string("T"), llvm::None},
-                {std::string("typename"), std::string("C"),
+                {{{std::string("typename"), llvm::None}},
+                 std::string("T"),
+                 llvm::None},
+                {{{std::string("typename"), llvm::None}},
+                 std::string("C"),
                  std::string("bool")},
             };
             HI.Documentation = "documentation";
@@ -2601,12 +2740,12 @@
           [](HoverInfo &HI) {
             HI.Kind = index::SymbolKind::Function;
             HI.Name = "foo";
-            HI.Type = "type";
-            HI.ReturnType = "ret_type";
+            HI.Type = {"type", {"c_type"}};
+            HI.ReturnType = {"ret_type", {"can_ret_type"}};
             HI.Parameters.emplace();
             HoverInfo::Param P;
             HI.Parameters->push_back(P);
-            P.Type = "type";
+            P.Type = {"type", {"can_type"}};
             HI.Parameters->push_back(P);
             P.Name = "foo";
             HI.Parameters->push_back(P);
@@ -2617,12 +2756,12 @@
           },
           "function foo\n"
           "\n"
-          "→ ret_type\n"
+          "→ ret_type (aka can_ret_type)\n"
           "Parameters:\n"
           "- \n"
-          "- type\n"
-          "- type foo\n"
-          "- type foo = default\n"
+          "- type (aka can_type)\n"
+          "- type foo (aka can_type)\n"
+          "- type foo = default (aka can_type)\n"
           "\n"
           "// In namespace ns\n"
           "ret_type foo(params) {}",
@@ -2633,7 +2772,7 @@
             HI.LocalScope = "test::Bar::";
             HI.Value = "value";
             HI.Name = "foo";
-            HI.Type = "type";
+            HI.Type = {"type", {"can_type"}};
             HI.Definition = "def";
             HI.Size = 4;
             HI.Offset = 12;
@@ -2641,7 +2780,7 @@
           },
           R"(field foo
 
-Type: type
+Type: type (aka can_type)
 Value = value
 Offset: 12 bytes
 Size: 4 bytes (+4 padding)
@@ -2664,22 +2803,22 @@
       },
       {
           [](HoverInfo &HI) {
-            HI.Definition = "int method()";
+            HI.Definition = "size_t method()";
             HI.AccessSpecifier = "protected";
             HI.Kind = index::SymbolKind::InstanceMethod;
             HI.NamespaceScope = "";
             HI.LocalScope = "cls<int>::";
             HI.Name = "method";
             HI.Parameters.emplace();
-            HI.ReturnType = "int";
-            HI.Type = "int ()";
+            HI.ReturnType = {"size_t", {"unsigned long"}};
+            HI.Type = {"size_t ()", {"unsigned long ()"}};
           },
           R"(instance-method method
 
-→ int
+→ size_t (aka unsigned long)
 
 // In cls<int>
-protected: int method())",
+protected: size_t method())",
       },
       {
           [](HoverInfo &HI) {
@@ -2701,10 +2840,10 @@
             HI.Definition = "int foo = 3";
             HI.LocalScope = "test::Bar::";
             HI.Value = "3";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.CalleeArgInfo.emplace();
             HI.CalleeArgInfo->Name = "arg_a";
-            HI.CalleeArgInfo->Type = "int";
+            HI.CalleeArgInfo->Type = {"int", llvm::None};
             HI.CalleeArgInfo->Default = "7";
             HI.CallPassType.emplace();
             HI.CallPassType->PassBy = PassMode::Value;
@@ -2726,10 +2865,10 @@
             HI.Definition = "int foo = 3";
             HI.LocalScope = "test::Bar::";
             HI.Value = "3";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.CalleeArgInfo.emplace();
             HI.CalleeArgInfo->Name = "arg_a";
-            HI.CalleeArgInfo->Type = "int";
+            HI.CalleeArgInfo->Type = {"int", llvm::None};
             HI.CalleeArgInfo->Default = "7";
             HI.CallPassType.emplace();
             HI.CallPassType->PassBy = PassMode::Ref;
@@ -2751,10 +2890,10 @@
             HI.Definition = "int foo = 3";
             HI.LocalScope = "test::Bar::";
             HI.Value = "3";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.CalleeArgInfo.emplace();
             HI.CalleeArgInfo->Name = "arg_a";
-            HI.CalleeArgInfo->Type = "int";
+            HI.CalleeArgInfo->Type = {"alias_int", {"int"}};
             HI.CalleeArgInfo->Default = "7";
             HI.CallPassType.emplace();
             HI.CallPassType->PassBy = PassMode::Value;
@@ -2764,7 +2903,7 @@
 
 Type: int
 Value = 3
-Passed as arg_a (converted to int)
+Passed as arg_a (converted to alias_int)
 
 // In test::Bar
 int foo = 3)",
@@ -2776,10 +2915,10 @@
             HI.Definition = "int foo = 3";
             HI.LocalScope = "test::Bar::";
             HI.Value = "3";
-            HI.Type = "int";
+            HI.Type = {"int", llvm::None};
             HI.CalleeArgInfo.emplace();
             HI.CalleeArgInfo->Name = "arg_a";
-            HI.CalleeArgInfo->Type = "int";
+            HI.CalleeArgInfo->Type = {"int", llvm::None};
             HI.CalleeArgInfo->Default = "7";
             HI.CallPassType.emplace();
             HI.CallPassType->PassBy = PassMode::ConstRef;
Index: clang-tools-extra/clangd/Hover.h
===================================================================
--- clang-tools-extra/clangd/Hover.h
+++ clang-tools-extra/clangd/Hover.h
@@ -22,15 +22,23 @@
 /// embedding clients can use the structured information to provide their own
 /// UI.
 struct HoverInfo {
+  /// Contains pretty-printed type and desugared type
+  struct PrintedType {
+    /// Pretty-printed type
+    std::string Type;
+    /// Desugared type
+    Optional<std::string> AKA;
+  };
+
   /// Represents parameters of a function, a template or a macro.
   /// For example:
   /// - void foo(ParamType Name = DefaultValue)
   /// - #define FOO(Name)
   /// - template <ParamType Name = DefaultType> class Foo {};
   struct Param {
-    /// The pretty-printed parameter type, e.g. "int", or "typename" (in
+    /// The printable parameter type, e.g. "int", or "typename" (in
     /// TemplateParameters), might be None for macro parameters.
-    llvm::Optional<std::string> Type;
+    llvm::Optional<PrintedType> Type;
     /// None for unnamed parameters.
     llvm::Optional<std::string> Name;
     /// None if no default is provided.
@@ -62,11 +70,11 @@
   /// Access specifier for declarations inside class/struct/unions, empty for
   /// others.
   std::string AccessSpecifier;
-  /// Pretty-printed variable type.
+  /// Printable variable type.
   /// Set only for variables.
-  llvm::Optional<std::string> Type;
+  llvm::Optional<PrintedType> Type;
   /// Set for functions and lambdas.
-  llvm::Optional<std::string> ReturnType;
+  llvm::Optional<PrintedType> ReturnType;
   /// Set for functions, lambdas and macros with parameters.
   llvm::Optional<std::vector<Param>> Parameters;
   /// Set for all templates(function, class, variable).
@@ -98,6 +106,11 @@
   markup::Document present() const;
 };
 
+inline bool operator==(const HoverInfo::PrintedType &LHS,
+                       const HoverInfo::PrintedType &RHS) {
+  return std::tie(LHS.Type, LHS.AKA) == std::tie(RHS.Type, RHS.AKA);
+}
+
 inline bool operator==(const HoverInfo::PassType &LHS,
                        const HoverInfo::PassType &RHS) {
   return std::tie(LHS.PassBy, LHS.Converted) ==
@@ -108,6 +121,8 @@
 // FIXME: move to another file so CodeComplete doesn't depend on Hover.
 void parseDocumentation(llvm::StringRef Input, markup::Document &Output);
 
+llvm::raw_ostream &operator<<(llvm::raw_ostream &,
+                              const HoverInfo::PrintedType &);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const HoverInfo::Param &);
 inline bool operator==(const HoverInfo::Param &LHS,
                        const HoverInfo::Param &RHS) {
Index: clang-tools-extra/clangd/Hover.cpp
===================================================================
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -18,6 +18,7 @@
 #include "support/Logger.h"
 #include "support/Markup.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
@@ -138,7 +139,8 @@
   return LangOpts.ObjC ? "objective-c" : "cpp";
 }
 
-std::string printType(QualType QT, const PrintingPolicy &PP) {
+HoverInfo::PrintedType printType(QualType QT, ASTContext &Context,
+                                 const PrintingPolicy &PP) {
   // TypePrinter doesn't resolve decltypes, so resolve them here.
   // FIXME: This doesn't handle composite types that contain a decltype in them.
   // We should rather have a printing policy for that.
@@ -155,45 +157,65 @@
       OS << TT->getDecl()->getKindName() << " ";
   }
   OS.flush();
-  QT.print(OS, PP);
-  return Result;
+  std::string Type = Result + QT.getAsString(PP);
+  llvm::Optional<std::string> AKA;
+  if (!QT.isNull()) {
+    bool ShouldAKA = false;
+    QualType DesugaredTy = clang::Desugar(Context, QT, ShouldAKA);
+    if (ShouldAKA)
+      AKA = Result + DesugaredTy.getAsString(PP);
+  }
+  return {Type, AKA};
 }
 
-std::string printType(const TemplateTypeParmDecl *TTP) {
+HoverInfo::PrintedType printType(const TemplateTypeParmDecl *TTP) {
   std::string Res = TTP->wasDeclaredWithTypename() ? "typename" : "class";
   if (TTP->isParameterPack())
     Res += "...";
-  return Res;
+  return {Res, llvm::None};
 }
 
-std::string printType(const NonTypeTemplateParmDecl *NTTP,
-                      const PrintingPolicy &PP) {
-  std::string Res = printType(NTTP->getType(), PP);
-  if (NTTP->isParameterPack())
-    Res += "...";
-  return Res;
+HoverInfo::PrintedType printType(const NonTypeTemplateParmDecl *NTTP,
+                                 const PrintingPolicy &PP) {
+  auto PrintedType = printType(NTTP->getType(), NTTP->getASTContext(), PP);
+  if (NTTP->isParameterPack()) {
+    PrintedType.Type += "...";
+    if (PrintedType.AKA)
+      *PrintedType.AKA += "...";
+  }
+  return PrintedType;
 }
 
-std::string printType(const TemplateTemplateParmDecl *TTP,
-                      const PrintingPolicy &PP) {
-  std::string Res;
-  llvm::raw_string_ostream OS(Res);
-  OS << "template <";
-  llvm::StringRef Sep = "";
+HoverInfo::PrintedType printType(const TemplateTemplateParmDecl *TTP,
+                                 const PrintingPolicy &PP) {
+  bool ShouldAKA = false;
+  llvm::SmallVector<std::string, 10> TypeParams;
+  llvm::SmallVector<std::string, 10> AKATypeParams;
   for (const Decl *Param : *TTP->getTemplateParameters()) {
-    OS << Sep;
-    Sep = ", ";
+    llvm::Optional<HoverInfo::PrintedType> PType;
     if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
-      OS << printType(TTP);
+      PType = printType(TTP);
     else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param))
-      OS << printType(NTTP, PP);
+      PType = printType(NTTP, PP);
     else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Param))
-      OS << printType(TTPD, PP);
+      PType = printType(TTPD, PP);
+    if (!PType)
+      continue;
+    TypeParams.push_back(PType->Type);
+    if (PType->AKA) {
+      ShouldAKA = true;
+      AKATypeParams.push_back(*PType->AKA);
+    } else
+      AKATypeParams.push_back(PType->Type);
   }
   // FIXME: TemplateTemplateParameter doesn't store the info on whether this
   // param was a "typename" or "class".
-  OS << "> class";
-  return OS.str();
+  const char *FMT = "template <{0}> class";
+  std::string Type = llvm::formatv(FMT, llvm::join(TypeParams, ", "));
+  llvm::Optional<std::string> AKA;
+  if (ShouldAKA)
+    AKA = llvm::formatv(FMT, llvm::join(AKATypeParams, ", "));
+  return {Type, AKA};
 }
 
 std::vector<HoverInfo::Param>
@@ -329,7 +351,7 @@
 HoverInfo::Param toHoverInfoParam(const ParmVarDecl *PVD,
                                   const PrintingPolicy &PP) {
   HoverInfo::Param Out;
-  Out.Type = printType(PVD->getType(), PP);
+  Out.Type = printType(PVD->getType(), PVD->getASTContext(), PP);
   if (!PVD->getName().empty())
     Out.Name = PVD->getNameAsString();
   if (const Expr *DefArg = getDefaultArg(PVD)) {
@@ -356,11 +378,11 @@
       NK == DeclarationName::CXXConversionFunctionName)
     return;
 
-  HI.ReturnType = printType(FD->getReturnType(), PP);
+  HI.ReturnType = printType(FD->getReturnType(), FD->getASTContext(), PP);
   QualType QT = FD->getType();
   if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D)) // Lambdas
     QT = VD->getType().getDesugaredType(D->getASTContext());
-  HI.Type = printType(QT, PP);
+  HI.Type = printType(QT, D->getASTContext(), PP);
   // FIXME: handle variadics.
 }
 
@@ -588,12 +610,19 @@
   // Fill in types and params.
   if (const FunctionDecl *FD = getUnderlyingFunction(D))
     fillFunctionTypeAndParams(HI, D, FD, PP);
-  else if (const auto *VD = dyn_cast<ValueDecl>(D))
-    HI.Type = printType(VD->getType(), PP);
-  else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(D))
-    HI.Type = TTP->wasDeclaredWithTypename() ? "typename" : "class";
-  else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(D))
+  else if (const auto *VD = dyn_cast<ValueDecl>(D)) {
+    HI.Type = printType(VD->getType(), VD->getASTContext(), PP);
+  } else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(D)) {
+    HI.Type = {TTP->wasDeclaredWithTypename() ? "typename" : "class",
+               llvm::None};
+  } else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
     HI.Type = printType(TTP, PP);
+  } else if (const auto *TN = dyn_cast<TypedefNameDecl>(D)) {
+    HI.Type = printType(TN->getUnderlyingType(), TN->getASTContext(), PP);
+  } else if (const auto *TTD = dyn_cast<TypeAliasTemplateDecl>(D)) {
+    HI.Type = printType(TTD->getTemplatedDecl()->getUnderlyingType(),
+                        TTD->getASTContext(), PP);
+  }
 
   // Fill in value with evaluated initializer if possible.
   if (const auto *Var = dyn_cast<VarDecl>(D)) {
@@ -604,7 +633,6 @@
     if (!ECD->getType()->isDependentType())
       HI.Value = toString(ECD->getInitVal(), 10);
   }
-
   HI.Definition = printDefinition(D, PP);
   return HI;
 }
@@ -658,7 +686,9 @@
 
   HoverInfo HI;
   HI.Name = "this";
-  HI.Definition = printType(PrettyThisType, PP);
+  auto PType = printType(PrettyThisType, ASTCtx, PP);
+  HI.Definition = PType.Type;
+  HI.Type = PType;
   return HI;
 }
 
@@ -675,7 +705,9 @@
   if (QT->isUndeducedAutoType()) {
     HI.Definition = "/* not deduced */";
   } else {
-    HI.Definition = printType(QT, PP);
+    auto PType = printType(QT, ASTCtx, PP);
+    HI.Definition = PType.Type;
+    HI.Type = PType;
 
     if (const auto *D = QT->getAsTagDecl()) {
       const auto *CommentD = getDeclForComment(D);
@@ -726,7 +758,7 @@
   // For expressions we currently print the type and the value, iff it is
   // evaluatable.
   if (auto Val = printExprValue(E, AST.getASTContext())) {
-    HI.Type = printType(E->getType(), PP);
+    HI.Type = printType(E->getType(), AST.getASTContext(), PP);
     HI.Value = *Val;
     HI.Name = std::string(getNameForExpr(E));
     return HI;
@@ -1057,7 +1089,10 @@
     // Parameters:
     // - `bool param1`
     // - `int param2 = 5`
-    Output.addParagraph().appendText("→ ").appendCode(*ReturnType);
+    std::string Buffer;
+    llvm::raw_string_ostream OS(Buffer);
+    OS << ReturnType;
+    Output.addParagraph().appendText("→ ").appendCode(OS.str());
     if (Parameters && !Parameters->empty()) {
       Output.addParagraph().appendText("Parameters: ");
       markup::BulletList &L = Output.addBulletList();
@@ -1069,7 +1104,10 @@
       }
     }
   } else if (Type) {
-    Output.addParagraph().appendText("Type: ").appendCode(*Type);
+    std::string Buffer;
+    llvm::raw_string_ostream OS(Buffer);
+    OS << Type;
+    Output.addParagraph().appendText("Type: ").appendCode(OS.str());
   }
 
   if (Value) {
@@ -1103,7 +1141,7 @@
     if (CalleeArgInfo->Name)
       OS << "as " << CalleeArgInfo->Name;
     if (CallPassType->Converted && CalleeArgInfo->Type)
-      OS << " (converted to " << CalleeArgInfo->Type << ")";
+      OS << " (converted to " << CalleeArgInfo->Type->Type << ")";
     Output.addParagraph().appendText(OS.str());
   }
 
@@ -1212,15 +1250,25 @@
 }
 
 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+                              const HoverInfo::PrintedType &T) {
+  OS << T.Type;
+  if (T.AKA)
+    OS << " (aka " << *T.AKA << ")";
+  return OS;
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
                               const HoverInfo::Param &P) {
   std::vector<llvm::StringRef> Output;
   if (P.Type)
-    Output.push_back(*P.Type);
+    Output.push_back(P.Type->Type);
   if (P.Name)
     Output.push_back(*P.Name);
   OS << llvm::join(Output, " ");
   if (P.Default)
     OS << " = " << *P.Default;
+  if (P.Type && P.Type->AKA)
+    OS << llvm::formatv(" (aka {0})", *P.Type->AKA);
   return OS;
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to