diff --git a/clang-tools-extra/clangd/AST.h b/clang-tools-extra/clangd/AST.h --- a/clang-tools-extra/clangd/AST.h +++ b/clang-tools-extra/clangd/AST.h @@ -109,6 +109,7 @@ /// Retrieves the deduced type at a given location (auto, decltype). /// It will return the underlying type. +/// If the type is an undeduced auto, returns the type itself. llvm::Optional getDeducedType(ASTContext &, SourceLocation Loc); /// Gets the nested name specifier necessary for spelling \p ND in \p diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -350,8 +350,7 @@ return true; if (auto *AT = D->getType()->getContainedAutoType()) { - if (!AT->getDeducedType().isNull()) - DeducedType = AT->getDeducedType(); + DeducedType = AT->desugar(); } return true; } 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 @@ -27,6 +27,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" @@ -550,29 +551,6 @@ return HI; } -/// Generate a \p Hover object given the type \p T. -HoverInfo getHoverContents(QualType T, ASTContext &ASTCtx, - const SymbolIndex *Index, - bool SuppressScope = false) { - HoverInfo HI; - - if (const auto *D = T->getAsTagDecl()) { - HI.Name = printName(ASTCtx, *D); - HI.Kind = index::getSymbolInfo(D).Kind; - - const auto *CommentD = getDeclForComment(D); - HI.Documentation = getDeclComment(ASTCtx, *CommentD); - enhanceFromIndex(HI, *CommentD, Index); - } else { - // Builtin types - auto Policy = printingPolicyForDecls(ASTCtx.getPrintingPolicy()); - Policy.SuppressTagKeyword = true; - Policy.SuppressScope = SuppressScope; - HI.Name = T.getAsString(Policy); - } - return HI; -} - /// Generate a \p Hover object given the macro \p MacroDecl. HoverInfo getHoverContents(const DefinedMacro &Macro, ParsedAST &AST) { HoverInfo HI; @@ -608,6 +586,52 @@ return HI; } +llvm::Optional getThisExprHoverContents(const CXXThisExpr *CTE, + ASTContext &ASTCtx) { + QualType OriginThisType = CTE->getType()->getPointeeType(); + QualType ClassType = declaredType(OriginThisType->getAsTagDecl()); + // For partial specialization class, origin `this` pointee type will be + // parsed as `InjectedClassNameType`, which will ouput template arguments + // like "type-parameter-0-0". So we retrieve user written class type in this + // case. + QualType PrettyThisType = ASTCtx.getPointerType( + QualType(ClassType.getTypePtr(), OriginThisType.getCVRQualifiers())); + + auto Policy = printingPolicyForDecls(ASTCtx.getPrintingPolicy()); + Policy.SuppressTagKeyword = true; + Policy.SuppressScope = true; + HoverInfo HI; + HI.Name = "this"; + HI.Definition = PrettyThisType.getAsString(Policy); + return HI; +} + +/// Generate a HoverInfo object given the deduced type \p QT +HoverInfo getDeducedTypeHoverContents(QualType QT, const syntax::Token &Tok, + ASTContext &ASTCtx, + const SymbolIndex *Index) { + HoverInfo HI; + // FIXME: distinguish decltype(auto) vs decltype(expr) + HI.Name = tok::getTokenName(Tok.kind()); + HI.Kind = index::SymbolKind::TypeAlias; + + auto PP = printingPolicyForDecls(ASTCtx.getLangOpts()); + + if (QT->isUndeducedAutoType()) { + HI.Definition = "/* not deduced */"; + } else { + HI.Definition = QT.getAsString(PP); + + if (const auto *D = QT->getAsTagDecl()) { + const auto *CommentD = getDeclForComment(D); + HI.Documentation = getDeclComment(ASTCtx, *CommentD); + enhanceFromIndex(HI, *CommentD, Index); + } + } + + return HI; +} + bool isLiteral(const Expr *E) { // Unfortunately there's no common base Literal classes inherits from // (apart from Expr), therefore these exclusions. @@ -641,18 +665,8 @@ HoverInfo HI; // For `this` expr we currently generate hover with pointee type. - if (const CXXThisExpr *CTE = dyn_cast(E)) { - QualType OriginThisType = CTE->getType()->getPointeeType(); - QualType ClassType = declaredType(OriginThisType->getAsTagDecl()); - // For partial specialization class, origin `this` pointee type will be - // parsed as `InjectedClassNameType`, which will ouput template arguments - // like "type-parameter-0-0". So we retrieve user written class type in this - // case. - QualType PrettyThisType = AST.getASTContext().getPointerType( - QualType(ClassType.getTypePtr(), OriginThisType.getCVRQualifiers())); - return getHoverContents(PrettyThisType, AST.getASTContext(), Index, - /*SuppressScope=*/true); - } + if (const CXXThisExpr *CTE = dyn_cast(E)) + return getThisExprHoverContents(CTE, AST.getASTContext()); // For expressions we currently print the type and the value, iff it is // evaluatable. if (auto Val = printExprValue(E, AST.getASTContext())) { @@ -849,10 +863,16 @@ } } else if (Tok.kind() == tok::kw_auto || Tok.kind() == tok::kw_decltype) { if (auto Deduced = getDeducedType(AST.getASTContext(), Tok.location())) { - HI = getHoverContents(*Deduced, AST.getASTContext(), Index); + HI = getDeducedTypeHoverContents(*Deduced, Tok, AST.getASTContext(), + Index); HighlightRange = Tok.range(SM).toCharRange(SM); break; } + + // If we can't find interesting hover information for this + // auto/decltype keyword, return nothing to avoid showing + // irrelevant or incorrect informations. + return llvm::None; } } diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp --- a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp @@ -106,7 +106,7 @@ Inputs.AST->getASTContext(), CachedLocation->getBeginLoc()); // if we can't resolve the type, return an error message - if (DeducedType == llvm::None) + if (DeducedType == llvm::None || (*DeducedType)->isUndeducedAutoType()) return error("Could not deduce type for 'auto' type"); // if it's a lambda expression, return an error message 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 @@ -379,6 +379,30 @@ HI.Definition = "class X {}"; }}, + // auto on structured bindings + {R"cpp( + void foo() { + struct S { int x; float y; }; + [[au^to]] [x, y] = S(); + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "struct S"; + }}, + // undeduced auto + {R"cpp( + template + void foo() { + [[au^to]] x = T{}; + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "/* not deduced */"; + }}, // auto on lambda {R"cpp( void foo() { @@ -386,8 +410,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "(lambda)"; - HI.Kind = index::SymbolKind::Class; + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "class(lambda)"; }}, // auto on template instantiation {R"cpp( @@ -397,8 +422,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "Foo"; - HI.Kind = index::SymbolKind::Class; + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "class Foo"; }}, // auto on specialized template {R"cpp( @@ -409,8 +435,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "Foo"; - HI.Kind = index::SymbolKind::Class; + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "class Foo"; }}, // macro @@ -582,8 +609,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "Foo"; - HI.Kind = index::SymbolKind::Class; + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "class Foo"; }}, {// Falls back to primary template, when the type is not instantiated. R"cpp( @@ -955,20 +983,11 @@ llvm::StringRef Tests[] = { "^int main() {}", "void foo() {^}", - R"cpp(// structured binding. Not supported yet - struct Bar {}; - void foo() { - Bar a[2]; - ^auto [x,y] = a; - } - )cpp", - R"cpp(// Template auto parameter. Nothing (Not useful). - template - void func() { - } - void foo() { - func<1>(); - } + // FIXME: "decltype(auto)" should be a single hover + "decltype(au^to) x = 0;", + // FIXME: not supported yet + R"cpp(// Lambda auto parameter + auto lamb = [](a^uto){}; )cpp", R"cpp(// non-named decls don't get hover. Don't crash! ^static_assert(1, ""); @@ -1545,9 +1564,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "int"; - // FIXME: Should be Builtin/Integral. - HI.Kind = index::SymbolKind::Unknown; + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int"; }}, { R"cpp(// Simple initialization with const auto @@ -1555,14 +1574,22 @@ const ^[[auto]] i = 1; } )cpp", - [](HoverInfo &HI) { HI.Name = "int"; }}, + [](HoverInfo &HI) { + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int"; + }}, { R"cpp(// Simple initialization with const auto& void foo() { const ^[[auto]]& i = 1; } )cpp", - [](HoverInfo &HI) { HI.Name = "int"; }}, + [](HoverInfo &HI) { + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int"; + }}, { R"cpp(// Simple initialization with auto& void foo() { @@ -1570,7 +1597,11 @@ ^[[auto]]& i = x; } )cpp", - [](HoverInfo &HI) { HI.Name = "int"; }}, + [](HoverInfo &HI) { + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int"; + }}, { R"cpp(// Simple initialization with auto* void foo() { @@ -1578,7 +1609,23 @@ ^[[auto]]* i = &a; } )cpp", - [](HoverInfo &HI) { HI.Name = "int"; }}, + [](HoverInfo &HI) { + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int"; + }}, + { + R"cpp(// Simple initialization with auto from pointer + void foo() { + int a = 1; + ^[[auto]] i = &a; + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int *"; + }}, { R"cpp(// Auto with initializer list. namespace std @@ -1591,8 +1638,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "initializer_list"; - HI.Kind = index::SymbolKind::Class; + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "class std::initializer_list"; }}, { R"cpp(// User defined conversion to auto @@ -1600,14 +1648,22 @@ operator ^[[auto]]() const { return 10; } }; )cpp", - [](HoverInfo &HI) { HI.Name = "int"; }}, + [](HoverInfo &HI) { + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int"; + }}, { R"cpp(// Simple initialization with decltype(auto) void foo() { ^[[decltype]](auto) i = 1; } )cpp", - [](HoverInfo &HI) { HI.Name = "int"; }}, + [](HoverInfo &HI) { + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int"; + }}, { R"cpp(// Simple initialization with const decltype(auto) void foo() { @@ -1615,7 +1671,11 @@ ^[[decltype]](auto) i = j; } )cpp", - [](HoverInfo &HI) { HI.Name = "const int"; }}, + [](HoverInfo &HI) { + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "const int"; + }}, { R"cpp(// Simple initialization with const& decltype(auto) void foo() { @@ -1624,7 +1684,11 @@ ^[[decltype]](auto) i = j; } )cpp", - [](HoverInfo &HI) { HI.Name = "const int &"; }}, + [](HoverInfo &HI) { + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "const int &"; + }}, { R"cpp(// Simple initialization with & decltype(auto) void foo() { @@ -1633,14 +1697,22 @@ ^[[decltype]](auto) i = j; } )cpp", - [](HoverInfo &HI) { HI.Name = "int &"; }}, + [](HoverInfo &HI) { + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int &"; + }}, { R"cpp(// simple trailing return type ^[[auto]] main() -> int { return 0; } )cpp", - [](HoverInfo &HI) { HI.Name = "int"; }}, + [](HoverInfo &HI) { + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int"; + }}, { R"cpp(// auto function return with trailing type struct Bar {}; @@ -1649,8 +1721,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "Bar"; - HI.Kind = index::SymbolKind::Struct; + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "struct Bar"; HI.Documentation = "auto function return with trailing type"; }}, { @@ -1661,8 +1734,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "Bar"; - HI.Kind = index::SymbolKind::Struct; + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "struct Bar"; HI.Documentation = "trailing return type"; }}, { @@ -1673,8 +1747,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "Bar"; - HI.Kind = index::SymbolKind::Struct; + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "struct Bar"; HI.Documentation = "auto in function return"; }}, { @@ -1686,8 +1761,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "Bar"; - HI.Kind = index::SymbolKind::Struct; + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "struct Bar"; HI.Documentation = "auto& in function return"; }}, { @@ -1699,8 +1775,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "Bar"; - HI.Kind = index::SymbolKind::Struct; + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "struct Bar"; HI.Documentation = "auto* in function return"; }}, { @@ -1712,8 +1789,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "Bar"; - HI.Kind = index::SymbolKind::Struct; + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "struct Bar"; HI.Documentation = "const auto& in function return"; }}, { @@ -1724,8 +1802,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "Bar"; - HI.Kind = index::SymbolKind::Struct; + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "struct Bar"; HI.Documentation = "decltype(auto) in function return"; }}, { @@ -1735,7 +1814,11 @@ return (a); } )cpp", - [](HoverInfo &HI) { HI.Name = "int &"; }}, + [](HoverInfo &HI) { + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int &"; + }}, { R"cpp(// decltype lvalue reference void foo() { @@ -1743,7 +1826,11 @@ ^[[decltype]](I) J = I; } )cpp", - [](HoverInfo &HI) { HI.Name = "int"; }}, + [](HoverInfo &HI) { + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int"; + }}, { R"cpp(// decltype lvalue reference void foo() { @@ -1752,7 +1839,11 @@ ^[[decltype]](K) J = I; } )cpp", - [](HoverInfo &HI) { HI.Name = "int &"; }}, + [](HoverInfo &HI) { + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int &"; + }}, { R"cpp(// decltype lvalue reference parenthesis void foo() { @@ -1760,7 +1851,11 @@ ^[[decltype]]((I)) J = I; } )cpp", - [](HoverInfo &HI) { HI.Name = "int &"; }}, + [](HoverInfo &HI) { + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int &"; + }}, { R"cpp(// decltype rvalue reference void foo() { @@ -1768,7 +1863,11 @@ ^[[decltype]](static_cast(I)) J = static_cast(I); } )cpp", - [](HoverInfo &HI) { HI.Name = "int &&"; }}, + [](HoverInfo &HI) { + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int &&"; + }}, { R"cpp(// decltype rvalue reference function call int && bar(); @@ -1777,7 +1876,11 @@ ^[[decltype]](bar()) J = bar(); } )cpp", - [](HoverInfo &HI) { HI.Name = "int &&"; }}, + [](HoverInfo &HI) { + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int &&"; + }}, { R"cpp(// decltype of function with trailing return type. struct Bar {}; @@ -1789,8 +1892,9 @@ } )cpp", [](HoverInfo &HI) { - HI.Name = "Bar"; - HI.Kind = index::SymbolKind::Struct; + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "struct Bar"; HI.Documentation = "decltype of function with trailing return type."; }}, @@ -1802,13 +1906,33 @@ ^[[decltype]](J) K = J; } )cpp", - [](HoverInfo &HI) { HI.Name = "int"; }}, + [](HoverInfo &HI) { + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int"; + }}, + { + R"cpp(// decltype of dependent type + template + struct X { + using Y = ^[[decltype]](T::Z); + }; + )cpp", + [](HoverInfo &HI) { + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = ""; + }}, { R"cpp(// More complicated structured types. int bar(); ^[[auto]] (*foo)() = bar; )cpp", - [](HoverInfo &HI) { HI.Name = "int"; }}, + [](HoverInfo &HI) { + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int"; + }}, { R"cpp(// Should not crash when evaluating the initializer. struct Test {}; @@ -1827,7 +1951,11 @@ typedef int int_type; ^[[auto]] x = int_type(); )cpp", - [](HoverInfo &HI) { HI.Name = "int"; }}, + [](HoverInfo &HI) { + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "int"; + }}, { R"cpp(// auto on alias struct cls {}; @@ -1835,8 +1963,9 @@ ^[[auto]] y = cls_type(); )cpp", [](HoverInfo &HI) { - HI.Name = "cls"; - HI.Kind = index::SymbolKind::Struct; + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "struct cls"; HI.Documentation = "auto on alias"; }}, { @@ -1846,10 +1975,60 @@ ^[[auto]] z = templ(); )cpp", [](HoverInfo &HI) { - HI.Name = "templ"; - HI.Kind = index::SymbolKind::Struct; + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "struct templ"; HI.Documentation = "auto on alias"; }}, + { + R"cpp(// Undeduced auto declaration + template + void foo() { + ^[[auto]] x = T(); + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "/* not deduced */"; + }}, + { + R"cpp(// Undeduced auto return type + template + ^[[auto]] foo() { + return T(); + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "/* not deduced */"; + }}, + { + R"cpp(// Template auto parameter + template<[[a^uto]] T> + void func() { + } + )cpp", + [](HoverInfo &HI) { + // FIXME: not sure this is what we want, but this + // is what we currently get with getDeducedType + HI.Name = "auto"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "/* not deduced */"; + }}, + { + R"cpp(// Undeduced decltype(auto) return type + template + ^[[decltype]](auto) foo() { + return T(); + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "decltype"; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "/* not deduced */"; + }}, { R"cpp(// should not crash. template struct cls { @@ -2030,7 +2209,10 @@ }; } )cpp", - [](HoverInfo &HI) { HI.Name = "Foo *"; }}, + [](HoverInfo &HI) { + HI.Name = "this"; + HI.Definition = "Foo *"; + }}, { R"cpp(// this expr for template class namespace ns { @@ -2042,7 +2224,10 @@ }; } )cpp", - [](HoverInfo &HI) { HI.Name = "const Foo *"; }}, + [](HoverInfo &HI) { + HI.Name = "this"; + HI.Definition = "const Foo *"; + }}, { R"cpp(// this expr for specialization class namespace ns { @@ -2055,7 +2240,10 @@ }; } )cpp", - [](HoverInfo &HI) { HI.Name = "Foo *"; }}, + [](HoverInfo &HI) { + HI.Name = "this"; + HI.Definition = "Foo *"; + }}, { R"cpp(// this expr for partial specialization struct namespace ns { @@ -2068,7 +2256,10 @@ }; } )cpp", - [](HoverInfo &HI) { HI.Name = "const Foo *"; }}, + [](HoverInfo &HI) { + HI.Name = "this"; + HI.Definition = "const Foo *"; + }}, }; // Create a tiny index, so tests above can verify documentation is fetched. @@ -2119,7 +2310,7 @@ Annotations T(R"cpp( template class X {}; void foo() { - au^to t = X(); + auto t = X(); X^ w; (void)w; })cpp"); @@ -2250,17 +2441,17 @@ HI.NamespaceScope = "ns::"; HI.Definition = "ret_type foo(params) {}"; }, - R"(function foo - -→ ret_type -Parameters: -- -- type -- type foo -- type foo = default - -// In namespace ns -ret_type foo(params) {})", + "function foo\n" + "\n" + "→ ret_type\n" + "Parameters:\n" + "- \n" + "- type\n" + "- type foo\n" + "- type foo = default\n" + "\n" + "// In namespace ns\n" + "ret_type foo(params) {}", }, { [](HoverInfo &HI) { @@ -2540,15 +2731,16 @@ HI.Value = "val"; HI.Definition = "def"; - llvm::StringRef ExpectedMarkdown = R"md(### variable `foo` - ---- -Value = `val` - ---- -```cpp -def -```)md"; + llvm::StringRef ExpectedMarkdown = // + "### variable `foo` \n" + "\n" + "---\n" + "Value = `val` \n" + "\n" + "---\n" + "```cpp\n" + "def\n" + "```"; EXPECT_EQ(HI.present().asMarkdown(), ExpectedMarkdown); llvm::StringRef ExpectedPlaintext = R"pt(variable foo