diff --git a/clang-tools-extra/clangd/Hover.h b/clang-tools-extra/clangd/Hover.h --- a/clang-tools-extra/clangd/Hover.h +++ b/clang-tools-extra/clangd/Hover.h @@ -31,6 +31,8 @@ /// The pretty-printed parameter type, e.g. "int", or "typename" (in /// TemplateParameters), might be None for macro parameters. llvm::Optional Type; + /// CanonicalType + llvm::Optional CanonicalType; /// None for unnamed parameters. llvm::Optional Name; /// None if no default is provided. @@ -65,8 +67,12 @@ /// Pretty-printed variable type. /// Set only for variables. llvm::Optional Type; + /// CanonicalType + llvm::Optional CanonicalType; /// Set for functions and lambdas. llvm::Optional ReturnType; + /// Canonical retuen type + llvm::Optional CanonicalReturnType; /// Set for functions, lambdas and macros with parameters. llvm::Optional> Parameters; /// Set for all templates(function, class, variable). diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -138,7 +138,8 @@ return LangOpts.ObjC ? "objective-c" : "cpp"; } -std::string printType(QualType QT, const PrintingPolicy &PP) { +std::string printType(QualType QT, const PrintingPolicy &PP, + bool Canonical = false) { // 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,6 +156,9 @@ OS << TT->getDecl()->getKindName() << " "; } OS.flush(); + if (Canonical && !QT.isNull()) { + QT = QT.getCanonicalType(); + } QT.print(OS, PP); return Result; } @@ -167,15 +171,15 @@ } std::string printType(const NonTypeTemplateParmDecl *NTTP, - const PrintingPolicy &PP) { - std::string Res = printType(NTTP->getType(), PP); + const PrintingPolicy &PP, bool Canonical = false) { + std::string Res = printType(NTTP->getType(), PP, Canonical); if (NTTP->isParameterPack()) Res += "..."; return Res; } std::string printType(const TemplateTemplateParmDecl *TTP, - const PrintingPolicy &PP) { + const PrintingPolicy &PP, bool Canonical = false) { std::string Res; llvm::raw_string_ostream OS(Res); OS << "template <"; @@ -186,9 +190,9 @@ if (const auto *TTP = dyn_cast(Param)) OS << printType(TTP); else if (const auto *NTTP = dyn_cast(Param)) - OS << printType(NTTP, PP); + OS << printType(NTTP, PP, Canonical); else if (const auto *TTPD = dyn_cast(Param)) - OS << printType(TTPD, PP); + OS << printType(TTPD, PP, Canonical); } // FIXME: TemplateTemplateParameter doesn't store the info on whether this // param was a "typename" or "class". @@ -214,6 +218,7 @@ P.Default = TTP->getDefaultArgument().getAsString(PP); } else if (const auto *NTTP = dyn_cast(Param)) { P.Type = printType(NTTP, PP); + P.CanonicalType = printType(NTTP, PP, true); if (IdentifierInfo *II = NTTP->getIdentifier()) P.Name = II->getName().str(); @@ -225,6 +230,7 @@ } } else if (const auto *TTPD = dyn_cast(Param)) { P.Type = printType(TTPD, PP); + P.CanonicalType = printType(TTPD, PP, true); if (!TTPD->getName().empty()) P.Name = TTPD->getNameAsString(); @@ -330,6 +336,7 @@ const PrintingPolicy &PP) { HoverInfo::Param Out; Out.Type = printType(PVD->getType(), PP); + Out.CanonicalType = printType(PVD->getType(), PP, true); if (!PVD->getName().empty()) Out.Name = PVD->getNameAsString(); if (const Expr *DefArg = getDefaultArg(PVD)) { @@ -357,10 +364,12 @@ return; HI.ReturnType = printType(FD->getReturnType(), PP); + HI.CanonicalReturnType = printType(FD->getReturnType(), PP, true); QualType QT = FD->getType(); if (const VarDecl *VD = llvm::dyn_cast(D)) // Lambdas QT = VD->getType().getDesugaredType(D->getASTContext()); HI.Type = printType(QT, PP); + HI.CanonicalType = printType(QT, PP, true); // FIXME: handle variadics. } @@ -588,12 +597,17 @@ // Fill in types and params. if (const FunctionDecl *FD = getUnderlyingFunction(D)) fillFunctionTypeAndParams(HI, D, FD, PP); - else if (const auto *VD = dyn_cast(D)) + else if (const auto *VD = dyn_cast(D)) { HI.Type = printType(VD->getType(), PP); - else if (const auto *TTP = dyn_cast(D)) + HI.CanonicalType = printType(VD->getType(), PP, true); + } else if (const auto *TTP = dyn_cast(D)) { HI.Type = TTP->wasDeclaredWithTypename() ? "typename" : "class"; - else if (const auto *TTP = dyn_cast(D)) + HI.CanonicalType = HI.Type; + } else if (const auto *TTP = dyn_cast(D)) { HI.Type = printType(TTP, PP); + HI.CanonicalType = printType(TTP, PP, true); + } + // Fill in value with evaluated initializer if possible. if (const auto *Var = dyn_cast(D)) { @@ -727,6 +741,7 @@ // evaluatable. if (auto Val = printExprValue(E, AST.getASTContext())) { HI.Type = printType(E->getType(), PP); + HI.CanonicalType = printType(E->getType(), PP, true); HI.Value = *Val; HI.Name = std::string(getNameForExpr(E)); return HI; @@ -1057,7 +1072,11 @@ // Parameters: // - `bool param1` // - `int param2 = 5` - Output.addParagraph().appendText("→ ").appendCode(*ReturnType); + std::string ReturnTypeStr = *ReturnType; + if (CanonicalReturnType && CanonicalReturnType != ReturnType) { + ReturnTypeStr += llvm::formatv(" (aka '{0}')", *CanonicalReturnType); + } + Output.addParagraph().appendText("→ ").appendCode(ReturnTypeStr); if (Parameters && !Parameters->empty()) { Output.addParagraph().appendText("Parameters: "); markup::BulletList &L = Output.addBulletList(); @@ -1069,7 +1088,11 @@ } } } else if (Type) { - Output.addParagraph().appendText("Type: ").appendCode(*Type); + std::string TypeStr = *Type; + if (CanonicalType && CanonicalType != Type) { + TypeStr += llvm::formatv(" (aka '{0}')", *CanonicalType); + } + Output.addParagraph().appendText("Type: ").appendCode(TypeStr); } if (Value) { @@ -1102,8 +1125,15 @@ } if (CalleeArgInfo->Name) OS << "as " << CalleeArgInfo->Name; - if (CallPassType->Converted && CalleeArgInfo->Type) - OS << " (converted to " << CalleeArgInfo->Type << ")"; + if (CallPassType->Converted && CalleeArgInfo->Type) { + std::string ConvertedTypeStr = *CalleeArgInfo->Type; + if (CalleeArgInfo->CanonicalType && + CalleeArgInfo->CanonicalType != CalleeArgInfo->Type) { + ConvertedTypeStr += + llvm::formatv(" aka '{0}'", *CalleeArgInfo->CanonicalType); + } + OS << " (converted to " << ConvertedTypeStr << ")"; + } Output.addParagraph().appendText(OS.str()); } @@ -1221,6 +1251,8 @@ OS << llvm::join(Output, " "); if (P.Default) OS << " = " << *P.Default; + if (P.CanonicalType && P.CanonicalType != P.Type) + OS << llvm::formatv(" (aka '{0}')", *P.CanonicalType); return OS; } diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -46,7 +46,9 @@ HI.Documentation = "Best foo ever."; HI.Definition = "void foo()"; HI.ReturnType = "void"; + HI.CanonicalReturnType = "void"; HI.Type = "void ()"; + HI.CanonicalType = "void ()"; HI.Parameters.emplace(); }}, // Inside namespace @@ -63,7 +65,9 @@ HI.Documentation = "Best foo ever."; HI.Definition = "void foo()"; HI.ReturnType = "void"; + HI.CanonicalReturnType = "void"; HI.Type = "void ()"; + HI.CanonicalType = "void ()"; HI.Parameters.emplace(); }}, // Field @@ -82,6 +86,7 @@ HI.Kind = index::SymbolKind::Field; HI.Definition = "char bar"; HI.Type = "char"; + HI.CanonicalType = "char"; HI.Offset = 0; HI.Size = 1; HI.Padding = 7; @@ -101,6 +106,7 @@ HI.Kind = index::SymbolKind::Field; HI.Definition = "char bar"; HI.Type = "char"; + HI.CanonicalType = "char"; HI.Size = 1; HI.Padding = 15; HI.AccessSpecifier = "public"; @@ -119,6 +125,7 @@ HI.Kind = index::SymbolKind::Field; HI.Definition = "int x : 1"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.AccessSpecifier = "public"; }}, // Local to class method. @@ -138,6 +145,7 @@ HI.Kind = index::SymbolKind::Variable; HI.Definition = "int bar"; HI.Type = "int"; + HI.CanonicalType = "int"; }}, // Anon namespace and local scope. {R"cpp( @@ -154,6 +162,7 @@ HI.Kind = index::SymbolKind::Field; HI.Definition = "char bar"; HI.Type = "char"; + HI.CanonicalType = "char"; HI.Offset = 0; HI.Size = 1; HI.AccessSpecifier = "public"; @@ -180,6 +189,7 @@ HI.Kind = index::SymbolKind::Variable; HI.Definition = "Foo foo = Foo(5)"; HI.Type = "Foo"; + HI.CanonicalType = "Foo"; }}, // Implicit template instantiation {R"cpp( @@ -212,11 +222,16 @@ class Foo {})cpp"; HI.TemplateParameters = { {std::string("template class"), + std::string("template 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("typename"), std::string("typename"), llvm::None, + std::string("char")}, + {std::string("int"), std::string("int"), llvm::None, + std::string("0")}, + {std::string("bool"), std::string("bool"), std::string("Q"), + std::string("false")}, + {std::string("class..."), std::string("class..."), + std::string("Ts"), llvm::None}, }; }}, // Function template @@ -238,7 +253,9 @@ HI.Kind = index::SymbolKind::Function; HI.Definition = "template <> void foo>()"; HI.ReturnType = "void"; + HI.CanonicalReturnType = "void"; HI.Type = "void ()"; + HI.CanonicalType = "void ()"; HI.Parameters.emplace(); }}, // Function decl @@ -256,10 +273,13 @@ HI.Kind = index::SymbolKind::Function; HI.Definition = "Foo foo(int, bool T = false)"; HI.ReturnType = "Foo"; + HI.CanonicalReturnType = "Foo"; HI.Type = "Foo (int, bool)"; + HI.CanonicalType = "Foo (int, bool)"; HI.Parameters = { - {std::string("int"), llvm::None, llvm::None}, - {std::string("bool"), std::string("T"), std::string("false")}, + {std::string("int"), std::string("int"), llvm::None, llvm::None}, + {std::string("bool"), std::string("bool"), std::string("T"), + std::string("false")}, }; }}, // Pointers to lambdas @@ -277,10 +297,14 @@ HI.Kind = index::SymbolKind::Variable; HI.Definition = "auto *c = &b"; HI.Type = "(lambda) **"; + HI.CanonicalType = "(lambda) **"; HI.ReturnType = "bool"; + HI.CanonicalReturnType = "bool"; HI.Parameters = { - {std::string("int"), std::string("T"), llvm::None}, - {std::string("bool"), std::string("B"), llvm::None}, + {std::string("int"), std::string("int"), std::string("T"), + llvm::None}, + {std::string("bool"), std::string("bool"), std::string("B"), + llvm::None}, }; return HI; }}, @@ -298,10 +322,14 @@ HI.Kind = index::SymbolKind::Parameter; HI.Definition = "decltype(lamb) &bar"; HI.Type = "decltype(lamb) &"; + HI.CanonicalType = "(lambda) &"; HI.ReturnType = "bool"; + HI.CanonicalReturnType = "bool"; HI.Parameters = { - {std::string("int"), std::string("T"), llvm::None}, - {std::string("bool"), std::string("B"), llvm::None}, + {std::string("int"), std::string("int"), std::string("T"), + llvm::None}, + {std::string("bool"), std::string("bool"), std::string("B"), + llvm::None}, }; return HI; }}, @@ -319,10 +347,14 @@ HI.Kind = index::SymbolKind::Parameter; HI.Definition = "decltype(lamb) bar"; HI.Type = "class (lambda)"; + HI.CanonicalType = "class (lambda)"; HI.ReturnType = "bool"; + HI.CanonicalReturnType = "bool"; HI.Parameters = { - {std::string("int"), std::string("T"), llvm::None}, - {std::string("bool"), std::string("B"), llvm::None}, + {std::string("int"), std::string("int"), std::string("T"), + llvm::None}, + {std::string("bool"), std::string("bool"), std::string("B"), + llvm::None}, }; HI.Value = "false"; return HI; @@ -342,10 +374,14 @@ HI.Kind = index::SymbolKind::Variable; HI.Definition = "auto lamb = [&bar](int T, bool B) -> bool {}"; HI.Type = "class (lambda)"; + HI.CanonicalType = "class (lambda)"; HI.ReturnType = "bool"; + HI.CanonicalReturnType = "bool"; HI.Parameters = { - {std::string("int"), std::string("T"), llvm::None}, - {std::string("bool"), std::string("B"), llvm::None}, + {std::string("int"), std::string("int"), std::string("T"), + llvm::None}, + {std::string("bool"), std::string("bool"), std::string("B"), + llvm::None}, }; return HI; }}, @@ -362,6 +398,7 @@ HI.Kind = index::SymbolKind::Variable; HI.Definition = "int test"; HI.Type = "int"; + HI.CanonicalType = "int"; }}, // Partially-specialized class template. (formerly type-parameter-0-0) {R"cpp( @@ -498,6 +535,7 @@ HI.Definition = "int bar = add(1, 2)"; HI.Kind = index::SymbolKind::Variable; HI.Type = "int"; + HI.CanonicalType = "int"; HI.NamespaceScope = ""; HI.Value = "3"; }}, @@ -509,6 +547,7 @@ HI.Definition = "int bar = sizeof(char)"; HI.Kind = index::SymbolKind::Variable; HI.Type = "int"; + HI.CanonicalType = "int"; HI.NamespaceScope = ""; HI.Value = "1"; }}, @@ -523,6 +562,7 @@ HI.Definition = "int bar = Add<1, 2>::result"; HI.Kind = index::SymbolKind::Variable; HI.Type = "int"; + HI.CanonicalType = "int"; HI.NamespaceScope = ""; HI.Value = "3"; }}, @@ -537,6 +577,7 @@ HI.Definition = "GREEN = 5"; HI.Kind = index::SymbolKind::EnumConstant; HI.Type = "enum Color"; + HI.CanonicalType = "enum Color"; HI.Value = "5"; // Numeric on the enumerator name, no hex as small. }}, {R"cpp( @@ -550,6 +591,7 @@ HI.Definition = "Color x = RED"; HI.Kind = index::SymbolKind::Variable; HI.Type = "enum Color"; + HI.CanonicalType = "enum Color"; HI.Value = "RED (0xffffff85)"; // Symbolic on an expression. }}, {R"cpp( @@ -563,21 +605,25 @@ HI.Definition = "static constexpr int result = a + b"; HI.Kind = index::SymbolKind::StaticProperty; HI.Type = "const int"; + HI.CanonicalType = "const int"; 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 ()"; + HI.CanonicalType = "int ()"; + HI.ReturnType = "my_int"; + HI.CanonicalReturnType = "int"; HI.Parameters.emplace(); HI.NamespaceScope = ""; HI.Value = "42 (0x2a)"; @@ -590,6 +636,7 @@ HI.Definition = "const char *bar = \"1234\""; HI.Kind = index::SymbolKind::Variable; HI.Type = "const char *"; + HI.CanonicalType = "const char *"; HI.NamespaceScope = ""; HI.Value = "&\"1234\"[0]"; }}, @@ -608,6 +655,7 @@ HI.Definition = "int name"; HI.Kind = index::SymbolKind::Parameter; HI.Type = "int"; + HI.CanonicalType = "int"; HI.NamespaceScope = ""; HI.LocalScope = "boom::"; }}, @@ -680,6 +728,7 @@ HI.Definition = "typename T = int"; HI.LocalScope = "foo::"; HI.Type = "typename"; + HI.CanonicalType = "typename"; HI.AccessSpecifier = "public"; }}, {// TemplateTemplate Type Parameter @@ -693,6 +742,7 @@ HI.Definition = "template class T"; HI.LocalScope = "foo::"; HI.Type = "template class"; + HI.CanonicalType = "template class"; HI.AccessSpecifier = "public"; }}, {// NonType Template Parameter @@ -706,6 +756,7 @@ HI.Definition = "int T = 5"; HI.LocalScope = "foo::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.AccessSpecifier = "public"; }}, @@ -721,7 +772,9 @@ HI.LocalScope = "X::"; HI.Documentation = "Trivial accessor for `Y`."; HI.Type = "float ()"; + HI.CanonicalType = "float ()"; HI.ReturnType = "float"; + HI.CanonicalReturnType = "float"; HI.Parameters.emplace(); HI.AccessSpecifier = "public"; }}, @@ -737,10 +790,13 @@ HI.LocalScope = "X::"; HI.Documentation = "Trivial setter for `Y`."; HI.Type = "void (float)"; + HI.CanonicalType = "void (float)"; HI.ReturnType = "void"; + HI.CanonicalReturnType = "void"; HI.Parameters.emplace(); HI.Parameters->emplace_back(); HI.Parameters->back().Type = "float"; + HI.Parameters->back().CanonicalType = "float"; HI.Parameters->back().Name = "v"; HI.AccessSpecifier = "public"; }}, @@ -756,10 +812,13 @@ HI.LocalScope = "X::"; HI.Documentation = "Trivial setter for `Y`."; HI.Type = "X &(float)"; + HI.CanonicalType = "X &(float)"; HI.ReturnType = "X &"; + HI.CanonicalReturnType = "X &"; HI.Parameters.emplace(); HI.Parameters->emplace_back(); HI.Parameters->back().Type = "float"; + HI.Parameters->back().CanonicalType = "float"; HI.Parameters->back().Name = "v"; HI.AccessSpecifier = "public"; }}, @@ -776,10 +835,13 @@ HI.LocalScope = "X::"; HI.Documentation = "Trivial setter for `Y`."; HI.Type = "void (float)"; + HI.CanonicalType = "void (float)"; HI.ReturnType = "void"; + HI.CanonicalReturnType = "void"; HI.Parameters.emplace(); HI.Parameters->emplace_back(); HI.Parameters->back().Type = "float"; + HI.Parameters->back().CanonicalType = "float"; HI.Parameters->back().Name = "v"; HI.AccessSpecifier = "public"; }}, @@ -794,6 +856,7 @@ HI.NamespaceScope = ""; HI.Definition = "X x"; HI.Type = "struct X"; + HI.CanonicalType = "struct X"; }}, {// Don't crash on null types. R"cpp(auto [^[[x]]] = 1; /*error-ok*/)cpp", @@ -803,6 +866,7 @@ HI.NamespaceScope = ""; HI.Definition = ""; HI.Type = "NULL TYPE"; + HI.CanonicalType = "NULL TYPE"; // Bindings are in theory public members of an anonymous struct. HI.AccessSpecifier = "public"; }}, @@ -822,6 +886,7 @@ HI.LocalScope = "code::"; HI.Value = "2"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.CalleeArgInfo.emplace(); HI.CalleeArgInfo->Name = "arg_b"; HI.CalleeArgInfo->Type = "int &"; @@ -849,6 +914,7 @@ HI.LocalScope = "code::"; HI.Value = "1"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.CalleeArgInfo.emplace(); HI.CalleeArgInfo->Name = "arg_a"; HI.CalleeArgInfo->Type = "int"; @@ -870,6 +936,7 @@ HI.Definition = "int xx"; HI.LocalScope = "Foo::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.AccessSpecifier = "public"; }}, {R"cpp( @@ -885,6 +952,7 @@ HI.Definition = "int yy"; HI.LocalScope = "Foo::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.AccessSpecifier = "public"; }}, {// No crash on InitListExpr. @@ -900,6 +968,7 @@ HI.Name = "expression"; HI.Kind = index::SymbolKind::Unknown; HI.Type = "int[10]"; + HI.CanonicalType = "int[10]"; HI.Value = "{1}"; }}}; for (const auto &Case : Cases) { @@ -926,7 +995,9 @@ EXPECT_EQ(H->Documentation, Expected.Documentation); EXPECT_EQ(H->Definition, Expected.Definition); EXPECT_EQ(H->Type, Expected.Type); + EXPECT_EQ(H->CanonicalType, Expected.CanonicalType); EXPECT_EQ(H->ReturnType, Expected.ReturnType); + EXPECT_EQ(H->CanonicalReturnType, Expected.CanonicalReturnType); EXPECT_EQ(H->Parameters, Expected.Parameters); EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters); EXPECT_EQ(H->SymRange, Expected.SymRange); @@ -1118,6 +1189,7 @@ HI.NamespaceScope = ""; HI.LocalScope = "main::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.Definition = "int bonjour"; }}, { @@ -1135,6 +1207,7 @@ HI.NamespaceScope = ""; HI.LocalScope = "s::method::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.Definition = "int bonjour"; }}, { @@ -1194,11 +1267,13 @@ HI.Kind = index::SymbolKind::Function; HI.NamespaceScope = ""; HI.Type = "void (int)"; + HI.CanonicalType = "void (int)"; HI.Definition = "void foo(int)"; HI.Documentation = "Function definition via pointer"; HI.ReturnType = "void"; + HI.CanonicalReturnType = "void"; HI.Parameters = { - {std::string("int"), llvm::None, llvm::None}, + {std::string("int"), std::string("int"), llvm::None, llvm::None}, }; }}, { @@ -1213,11 +1288,13 @@ HI.Kind = index::SymbolKind::Function; HI.NamespaceScope = ""; HI.Type = "int (int)"; + HI.CanonicalType = "int (int)"; HI.Definition = "int foo(int)"; HI.Documentation = "Function declaration via call"; HI.ReturnType = "int"; + HI.CanonicalReturnType = "int"; HI.Parameters = { - {std::string("int"), llvm::None, llvm::None}, + {std::string("int"), std::string("int"), llvm::None, llvm::None}, }; }}, { @@ -1234,6 +1311,7 @@ HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.Definition = "int x"; }}, { @@ -1250,6 +1328,7 @@ HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.Definition = "int x = 5"; }}, { @@ -1265,6 +1344,7 @@ HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.Definition = "static int x"; }}, { @@ -1280,6 +1360,7 @@ HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.Definition = "int x"; }}, { @@ -1295,6 +1376,7 @@ HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.Definition = "int x"; // FIXME: Initializer for x is a DesignatedInitListExpr, hence it is // of struct type and omitted. @@ -1312,6 +1394,7 @@ HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.Definition = "int x"; }}, { @@ -1328,8 +1411,10 @@ HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; HI.Type = "int ()"; + HI.CanonicalType = "int ()"; HI.Definition = "int x()"; HI.ReturnType = "int"; + HI.CanonicalReturnType = "int"; HI.Parameters = std::vector{}; }}, { @@ -1345,8 +1430,10 @@ HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; HI.Type = "int ()"; + HI.CanonicalType = "int ()"; HI.Definition = "static int x()"; HI.ReturnType = "int"; + HI.CanonicalReturnType = "int"; HI.Parameters = std::vector{}; }}, { @@ -1405,6 +1492,7 @@ HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = "ns::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.Definition = "int foo"; }}, { @@ -1465,9 +1553,11 @@ HI.Kind = index::SymbolKind::Function; HI.NamespaceScope = ""; HI.Type = "void ()"; + HI.CanonicalType = "void ()"; HI.Definition = "void foo()"; HI.Documentation = "Function declaration"; HI.ReturnType = "void"; + HI.CanonicalReturnType = "void"; HI.Parameters = std::vector{}; }}, { @@ -1501,6 +1591,7 @@ HI.NamespaceScope = ""; HI.LocalScope = "Hello::"; HI.Type = "enum Hello"; + HI.CanonicalType = "enum Hello"; HI.Definition = "ONE"; HI.Value = "0"; }}, @@ -1520,6 +1611,7 @@ // FIXME: This should be `(anon enum)::` HI.LocalScope = ""; HI.Type = "enum (unnamed)"; + HI.CanonicalType = "enum (unnamed)"; HI.Definition = "ONE"; HI.Value = "0"; }}, @@ -1535,6 +1627,7 @@ HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = ""; HI.Type = "int"; + HI.CanonicalType = "int"; HI.Definition = "static int hey = 10"; HI.Documentation = "Global variable"; // FIXME: Value shouldn't be set in this case @@ -1554,6 +1647,7 @@ HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = "ns1::"; HI.Type = "long long"; + HI.CanonicalType = "long long"; HI.Definition = "static long long hey = -36637162602497"; HI.Value = "-36637162602497 (0xffffdeadbeefffff)"; // needs 64 bits }}, @@ -1572,6 +1666,7 @@ HI.NamespaceScope = ""; HI.LocalScope = "(anonymous struct)::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.Definition = "int hello"; }}, { @@ -1587,9 +1682,11 @@ HI.Kind = index::SymbolKind::Function; HI.NamespaceScope = ""; HI.Type = "int ()"; + HI.CanonicalType = "int ()"; HI.Definition = "template <> int foo()"; HI.Documentation = "Templated function"; HI.ReturnType = "int"; + HI.CanonicalReturnType = "int"; HI.Parameters = std::vector{}; // FIXME: We should populate template parameters with arguments in // case of instantiations. @@ -1609,6 +1706,7 @@ HI.NamespaceScope = ""; HI.LocalScope = "outer::(anonymous union)::"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.Definition = "int def"; }}, { @@ -1622,8 +1720,10 @@ HI.Kind = index::SymbolKind::Function; HI.NamespaceScope = ""; HI.Type = "void ()"; + HI.CanonicalType = "void ()"; HI.Definition = "void indexSymbol()"; HI.ReturnType = "void"; + HI.CanonicalReturnType = "void"; HI.Parameters = std::vector{}; HI.Documentation = "comment from index"; }}, @@ -2014,6 +2114,7 @@ HI.NamespaceScope = ""; HI.LocalScope = "test::"; HI.Type = "Test &&"; + HI.CanonicalType = "Test &&"; HI.Definition = "Test &&test = {}"; }}, { @@ -2115,7 +2216,9 @@ HI.Name = "method"; HI.Parameters.emplace(); HI.ReturnType = "int"; + HI.CanonicalReturnType = "int"; HI.Type = "int ()"; + HI.CanonicalType = "int ()"; }}, { R"cpp(// type of nested templates. @@ -2128,6 +2231,7 @@ HI.NamespaceScope = ""; HI.Name = "foo"; HI.Type = "cls>>"; + HI.CanonicalType = "cls>>"; }}, { R"cpp(// type of nested templates. @@ -2151,6 +2255,7 @@ HI.NamespaceScope = ""; HI.Name = "b"; HI.Type = "int"; + HI.CanonicalType = "int"; }}, { R"cpp(// type with decltype @@ -2163,6 +2268,7 @@ HI.NamespaceScope = ""; HI.Name = "b"; HI.Type = "int"; + HI.CanonicalType = "int"; }}, { R"cpp(// type with decltype @@ -2174,6 +2280,7 @@ HI.NamespaceScope = ""; HI.Name = "b"; HI.Type = "int"; + HI.CanonicalType = "int"; }}, { R"cpp(// type with decltype @@ -2187,9 +2294,11 @@ // FIXME: Handle composite types with decltype with a printing // policy. HI.Type = "auto (decltype(a)) -> decltype(a)"; + HI.CanonicalType = "int (int)"; HI.ReturnType = "int"; + HI.CanonicalReturnType = "int"; HI.Parameters = { - {std::string("int"), std::string("x"), llvm::None}}; + {std::string("int"), std::string("int"), std::string("x"), llvm::None}}; }}, { R"cpp(// sizeof expr @@ -2199,6 +2308,7 @@ [](HoverInfo &HI) { HI.Name = "expression"; HI.Type = "unsigned long"; + HI.CanonicalType = "unsigned long"; HI.Value = "1"; }}, { @@ -2209,6 +2319,7 @@ [](HoverInfo &HI) { HI.Name = "expression"; HI.Type = "unsigned long"; + HI.CanonicalType = "unsigned long"; HI.Value = "1"; }}, { @@ -2221,9 +2332,11 @@ HI.Name = "foo"; HI.Kind = index::SymbolKind::Function; HI.Type = "void (const int &)"; + HI.CanonicalType = "void (const int &)"; HI.ReturnType = "void"; + HI.CanonicalReturnType = "void"; HI.Parameters = { - {std::string("const int &"), llvm::None, std::string("T()")}}; + {std::string("const int &"), std::string("const int &"), llvm::None, std::string("T()")}}; HI.Definition = "template <> void foo(const int &)"; HI.NamespaceScope = ""; }}, @@ -2236,6 +2349,7 @@ [](HoverInfo &HI) { HI.Name = "data"; HI.Type = "char"; + HI.CanonicalType = "char"; HI.Kind = index::SymbolKind::Field; HI.LocalScope = "ObjC::"; HI.NamespaceScope = ""; @@ -2387,6 +2501,7 @@ HI.Definition = "int result = 2"; HI.Kind = index::SymbolKind::Variable; HI.Type = "int"; + HI.CanonicalType = "int"; HI.LocalScope = "+[Foo(Private) somePrivateMethod]::"; HI.NamespaceScope = ""; HI.Value = "2"; @@ -2407,6 +2522,7 @@ HI.Definition = "int result = 0"; HI.Kind = index::SymbolKind::Variable; HI.Type = "int"; + HI.CanonicalType = "int"; HI.LocalScope = "-[Foo variadicArgMethod:, ...]::"; HI.NamespaceScope = ""; HI.Value = "0"; @@ -2458,7 +2574,9 @@ EXPECT_EQ(H->Documentation, Expected.Documentation); EXPECT_EQ(H->Definition, Expected.Definition); EXPECT_EQ(H->Type, Expected.Type); + EXPECT_EQ(H->CanonicalType, Expected.CanonicalType); EXPECT_EQ(H->ReturnType, Expected.ReturnType); + EXPECT_EQ(H->CanonicalReturnType, Expected.CanonicalReturnType); EXPECT_EQ(H->Parameters, Expected.Parameters); EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters); EXPECT_EQ(H->SymRange, Expected.SymRange); @@ -2602,11 +2720,14 @@ HI.Kind = index::SymbolKind::Function; HI.Name = "foo"; HI.Type = "type"; + HI.CanonicalType = "c_type"; HI.ReturnType = "ret_type"; + HI.CanonicalReturnType = "can_ret_type"; HI.Parameters.emplace(); HoverInfo::Param P; HI.Parameters->push_back(P); P.Type = "type"; + P.CanonicalType = "can_type"; HI.Parameters->push_back(P); P.Name = "foo"; HI.Parameters->push_back(P); @@ -2617,12 +2738,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) {}", @@ -2634,6 +2755,7 @@ HI.Value = "value"; HI.Name = "foo"; HI.Type = "type"; + HI.CanonicalType = "can_type"; HI.Definition = "def"; HI.Size = 4; HI.Offset = 12; @@ -2641,7 +2763,7 @@ }, R"(field foo -Type: type +Type: type (aka 'can_type') Value = value Offset: 12 bytes Size: 4 bytes (+4 padding) @@ -2664,22 +2786,24 @@ }, { [](HoverInfo &HI) { - HI.Definition = "int method()"; + HI.Definition = "size_t method()"; HI.AccessSpecifier = "protected"; HI.Kind = index::SymbolKind::InstanceMethod; HI.NamespaceScope = ""; HI.LocalScope = "cls::"; HI.Name = "method"; HI.Parameters.emplace(); - HI.ReturnType = "int"; - HI.Type = "int ()"; + HI.ReturnType = "size_t"; + HI.CanonicalReturnType = "unsigned long"; + HI.Type = "size_t ()"; + HI.CanonicalType = "unsigned long ()"; }, R"(instance-method method -→ int +→ size_t (aka 'unsigned long') // In cls -protected: int method())", +protected: size_t method())", }, { [](HoverInfo &HI) { @@ -2702,9 +2826,11 @@ HI.LocalScope = "test::Bar::"; HI.Value = "3"; HI.Type = "int"; + HI.CanonicalType = "int"; HI.CalleeArgInfo.emplace(); HI.CalleeArgInfo->Name = "arg_a"; HI.CalleeArgInfo->Type = "int"; + HI.CalleeArgInfo->CanonicalType = "int"; HI.CalleeArgInfo->Default = "7"; HI.CallPassType.emplace(); HI.CallPassType->PassBy = PassMode::Value; @@ -2754,7 +2880,8 @@ HI.Type = "int"; HI.CalleeArgInfo.emplace(); HI.CalleeArgInfo->Name = "arg_a"; - HI.CalleeArgInfo->Type = "int"; + HI.CalleeArgInfo->Type = "alias_int"; + HI.CalleeArgInfo->CanonicalType = "int"; HI.CalleeArgInfo->Default = "7"; HI.CallPassType.emplace(); HI.CallPassType->PassBy = PassMode::Value; @@ -2764,7 +2891,7 @@ Type: int Value = 3 -Passed as arg_a (converted to int) +Passed as arg_a (converted to alias_int aka 'int') // In test::Bar int foo = 3)",