18adc4d1eSSam McCall //===-- DumpASTTests.cpp --------------------------------------------------===// 28adc4d1eSSam McCall // 38adc4d1eSSam McCall // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 48adc4d1eSSam McCall // See https://llvm.org/LICENSE.txt for license information. 58adc4d1eSSam McCall // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68adc4d1eSSam McCall // 78adc4d1eSSam McCall //===----------------------------------------------------------------------===// 88adc4d1eSSam McCall 98adc4d1eSSam McCall #include "Annotations.h" 108adc4d1eSSam McCall #include "DumpAST.h" 118adc4d1eSSam McCall #include "TestTU.h" 124d006520SSam McCall #include "clang/AST/ASTTypeTraits.h" 138adc4d1eSSam McCall #include "llvm/Support/ScopedPrinter.h" 148adc4d1eSSam McCall #include "gmock/gmock.h" 158adc4d1eSSam McCall #include "gtest/gtest.h" 168adc4d1eSSam McCall 178adc4d1eSSam McCall namespace clang { 188adc4d1eSSam McCall namespace clangd { 198adc4d1eSSam McCall namespace { 2081dae18dSChristian Kandeler using testing::Contains; 2181dae18dSChristian Kandeler using testing::Not; 228adc4d1eSSam McCall using testing::SizeIs; 238adc4d1eSSam McCall 248edfc2f8SChristian Kühnel MATCHER_P(withDetail, str, "") { return arg.detail == str; } 2581dae18dSChristian Kandeler 268adc4d1eSSam McCall TEST(DumpASTTests, BasicInfo) { 278adc4d1eSSam McCall std::pair</*Code=*/std::string, /*Expected=*/std::string> Cases[] = { 288adc4d1eSSam McCall {R"cpp( 298adc4d1eSSam McCall float root(int *x) { 308adc4d1eSSam McCall return *x + 1; 318adc4d1eSSam McCall } 328adc4d1eSSam McCall )cpp", 338adc4d1eSSam McCall R"( 348adc4d1eSSam McCall declaration: Function - root 358adc4d1eSSam McCall type: FunctionProto 368adc4d1eSSam McCall type: Builtin - float 378adc4d1eSSam McCall declaration: ParmVar - x 388adc4d1eSSam McCall type: Pointer 398adc4d1eSSam McCall type: Builtin - int 408adc4d1eSSam McCall statement: Compound 418adc4d1eSSam McCall statement: Return 428adc4d1eSSam McCall expression: ImplicitCast - IntegralToFloating 438adc4d1eSSam McCall expression: BinaryOperator - + 448adc4d1eSSam McCall expression: ImplicitCast - LValueToRValue 458adc4d1eSSam McCall expression: UnaryOperator - * 468adc4d1eSSam McCall expression: ImplicitCast - LValueToRValue 478adc4d1eSSam McCall expression: DeclRef - x 488adc4d1eSSam McCall expression: IntegerLiteral - 1 498adc4d1eSSam McCall )"}, 508adc4d1eSSam McCall {R"cpp( 518adc4d1eSSam McCall namespace root { 52*db93ef14Scor3ntin struct S { static const int x = 0; ~S(); }; 53*db93ef14Scor3ntin int y = S::x + root::S().x; 54*db93ef14Scor3ntin } 55*db93ef14Scor3ntin )cpp", 56*db93ef14Scor3ntin R"( 57*db93ef14Scor3ntin declaration: Namespace - root 58*db93ef14Scor3ntin declaration: CXXRecord - S 59*db93ef14Scor3ntin declaration: Var - x 60*db93ef14Scor3ntin type: Qualified - const 61*db93ef14Scor3ntin type: Builtin - int 62*db93ef14Scor3ntin expression: IntegerLiteral - 0 63*db93ef14Scor3ntin declaration: CXXDestructor 64*db93ef14Scor3ntin type: Record - S 65*db93ef14Scor3ntin type: FunctionProto 66*db93ef14Scor3ntin type: Builtin - void 67*db93ef14Scor3ntin declaration: CXXConstructor 68*db93ef14Scor3ntin declaration: CXXConstructor 69*db93ef14Scor3ntin declaration: Var - y 70*db93ef14Scor3ntin type: Builtin - int 71*db93ef14Scor3ntin expression: ExprWithCleanups 72*db93ef14Scor3ntin expression: BinaryOperator - + 73*db93ef14Scor3ntin expression: ImplicitCast - LValueToRValue 74*db93ef14Scor3ntin expression: DeclRef - x 75*db93ef14Scor3ntin specifier: TypeSpec 76*db93ef14Scor3ntin type: Record - S 77*db93ef14Scor3ntin expression: ImplicitCast - LValueToRValue 78*db93ef14Scor3ntin expression: Member - x 79*db93ef14Scor3ntin expression: CXXBindTemporary 80*db93ef14Scor3ntin expression: CXXTemporaryObject - S 81*db93ef14Scor3ntin type: Elaborated 82*db93ef14Scor3ntin specifier: Namespace - root:: 83*db93ef14Scor3ntin type: Record - S 84*db93ef14Scor3ntin )"}, 85*db93ef14Scor3ntin {R"cpp( 86*db93ef14Scor3ntin namespace root { 878adc4d1eSSam McCall struct S { static const int x = 0; }; 888adc4d1eSSam McCall int y = S::x + root::S().x; 898adc4d1eSSam McCall } 908adc4d1eSSam McCall )cpp", 918adc4d1eSSam McCall R"( 928adc4d1eSSam McCall declaration: Namespace - root 938adc4d1eSSam McCall declaration: CXXRecord - S 948adc4d1eSSam McCall declaration: Var - x 958adc4d1eSSam McCall type: Qualified - const 968adc4d1eSSam McCall type: Builtin - int 978adc4d1eSSam McCall expression: IntegerLiteral - 0 988adc4d1eSSam McCall declaration: CXXConstructor 998adc4d1eSSam McCall declaration: CXXConstructor 1008adc4d1eSSam McCall declaration: CXXConstructor 1018adc4d1eSSam McCall declaration: CXXDestructor 1028adc4d1eSSam McCall declaration: Var - y 1038adc4d1eSSam McCall type: Builtin - int 1048adc4d1eSSam McCall expression: BinaryOperator - + 1058adc4d1eSSam McCall expression: ImplicitCast - LValueToRValue 1068adc4d1eSSam McCall expression: DeclRef - x 1078adc4d1eSSam McCall specifier: TypeSpec 1088adc4d1eSSam McCall type: Record - S 1098adc4d1eSSam McCall expression: ImplicitCast - LValueToRValue 1108adc4d1eSSam McCall expression: Member - x 1118adc4d1eSSam McCall expression: CXXTemporaryObject - S 1128adc4d1eSSam McCall type: Elaborated 1138adc4d1eSSam McCall specifier: Namespace - root:: 1148adc4d1eSSam McCall type: Record - S 1158adc4d1eSSam McCall )"}, 1168adc4d1eSSam McCall {R"cpp( 1179e83d0bcSSam McCall namespace root { 1189e83d0bcSSam McCall template <typename T> int tmpl() { 1199e83d0bcSSam McCall (void)tmpl<unsigned>(); 1208adc4d1eSSam McCall return T::value; 1218adc4d1eSSam McCall } 1229e83d0bcSSam McCall } 1238adc4d1eSSam McCall )cpp", 1248adc4d1eSSam McCall R"( 1259e83d0bcSSam McCall declaration: Namespace - root 1269e83d0bcSSam McCall declaration: FunctionTemplate - tmpl 1278adc4d1eSSam McCall declaration: TemplateTypeParm - T 1289e83d0bcSSam McCall declaration: Function - tmpl 1298adc4d1eSSam McCall type: FunctionProto 1308adc4d1eSSam McCall type: Builtin - int 1318adc4d1eSSam McCall statement: Compound 1328adc4d1eSSam McCall expression: CStyleCast - ToVoid 1338adc4d1eSSam McCall type: Builtin - void 1348adc4d1eSSam McCall expression: Call 1358adc4d1eSSam McCall expression: ImplicitCast - FunctionToPointerDecay 1369e83d0bcSSam McCall expression: DeclRef - tmpl 1378adc4d1eSSam McCall template argument: Type 1388adc4d1eSSam McCall type: Builtin - unsigned int 1398adc4d1eSSam McCall statement: Return 1408adc4d1eSSam McCall expression: DependentScopeDeclRef - value 1418adc4d1eSSam McCall specifier: TypeSpec 1428adc4d1eSSam McCall type: TemplateTypeParm - T 1438adc4d1eSSam McCall )"}, 1448adc4d1eSSam McCall {R"cpp( 1458adc4d1eSSam McCall struct Foo { char operator+(int); }; 1468adc4d1eSSam McCall char root = Foo() + 42; 1478adc4d1eSSam McCall )cpp", 1488adc4d1eSSam McCall R"( 1498adc4d1eSSam McCall declaration: Var - root 1508adc4d1eSSam McCall type: Builtin - char 1518adc4d1eSSam McCall expression: ExprWithCleanups 1528adc4d1eSSam McCall expression: CXXOperatorCall 1538adc4d1eSSam McCall expression: ImplicitCast - FunctionToPointerDecay 1548adc4d1eSSam McCall expression: DeclRef - operator+ 1558adc4d1eSSam McCall expression: MaterializeTemporary - lvalue 1568adc4d1eSSam McCall expression: CXXTemporaryObject - Foo 15715f3cd6bSMatheus Izvekov type: Elaborated 1588adc4d1eSSam McCall type: Record - Foo 1598adc4d1eSSam McCall expression: IntegerLiteral - 42 1608adc4d1eSSam McCall )"}, 1619e83d0bcSSam McCall {R"cpp( 1629e83d0bcSSam McCall struct Bar { 1639e83d0bcSSam McCall int x; 1649e83d0bcSSam McCall int root() const { 1659e83d0bcSSam McCall return x; 1669e83d0bcSSam McCall } 1679e83d0bcSSam McCall }; 1689e83d0bcSSam McCall )cpp", 1699e83d0bcSSam McCall R"( 1709e83d0bcSSam McCall declaration: CXXMethod - root 1719e83d0bcSSam McCall type: FunctionProto 1729e83d0bcSSam McCall type: Builtin - int 1739e83d0bcSSam McCall statement: Compound 1749e83d0bcSSam McCall statement: Return 1759e83d0bcSSam McCall expression: ImplicitCast - LValueToRValue 1769e83d0bcSSam McCall expression: Member - x 1779e83d0bcSSam McCall expression: CXXThis - const, implicit 1789e83d0bcSSam McCall )"}, 1798adc4d1eSSam McCall }; 1808adc4d1eSSam McCall for (const auto &Case : Cases) { 1818adc4d1eSSam McCall ParsedAST AST = TestTU::withCode(Case.first).build(); 1829e83d0bcSSam McCall auto Node = dumpAST(DynTypedNode::create(findUnqualifiedDecl(AST, "root")), 1838adc4d1eSSam McCall AST.getTokens(), AST.getASTContext()); 1848adc4d1eSSam McCall EXPECT_EQ(llvm::StringRef(Case.second).trim(), 1858adc4d1eSSam McCall llvm::StringRef(llvm::to_string(Node)).trim()); 1868adc4d1eSSam McCall } 1878adc4d1eSSam McCall } 1888adc4d1eSSam McCall 1898adc4d1eSSam McCall TEST(DumpASTTests, Range) { 1908adc4d1eSSam McCall Annotations Case("$var[[$type[[int]] x]];"); 1918adc4d1eSSam McCall ParsedAST AST = TestTU::withCode(Case.code()).build(); 1928adc4d1eSSam McCall auto Node = dumpAST(DynTypedNode::create(findDecl(AST, "x")), AST.getTokens(), 1938adc4d1eSSam McCall AST.getASTContext()); 1948adc4d1eSSam McCall EXPECT_EQ(Node.range, Case.range("var")); 1958adc4d1eSSam McCall ASSERT_THAT(Node.children, SizeIs(1)) << "Expected one child typeloc"; 1968adc4d1eSSam McCall EXPECT_EQ(Node.children.front().range, Case.range("type")); 1978adc4d1eSSam McCall } 1988adc4d1eSSam McCall 19981dae18dSChristian Kandeler TEST(DumpASTTests, NoRange) { 20081dae18dSChristian Kandeler auto TU = TestTU::withHeaderCode("void funcFromHeader();"); 20181dae18dSChristian Kandeler TU.Code = "int varFromSource;"; 20281dae18dSChristian Kandeler ParsedAST AST = TU.build(); 20381dae18dSChristian Kandeler auto Node = dumpAST( 20481dae18dSChristian Kandeler DynTypedNode::create(*AST.getASTContext().getTranslationUnitDecl()), 20581dae18dSChristian Kandeler AST.getTokens(), AST.getASTContext()); 2068edfc2f8SChristian Kühnel ASSERT_THAT(Node.children, Contains(withDetail("varFromSource"))); 2078edfc2f8SChristian Kühnel ASSERT_THAT(Node.children, Not(Contains(withDetail("funcFromHeader")))); 20881dae18dSChristian Kandeler EXPECT_THAT(Node.arcana, testing::StartsWith("TranslationUnitDecl ")); 209b8df4093SKazu Hirata ASSERT_FALSE(Node.range) << "Expected no range for translation unit"; 21081dae18dSChristian Kandeler } 21181dae18dSChristian Kandeler 2128adc4d1eSSam McCall TEST(DumpASTTests, Arcana) { 2138adc4d1eSSam McCall ParsedAST AST = TestTU::withCode("int x;").build(); 2148adc4d1eSSam McCall auto Node = dumpAST(DynTypedNode::create(findDecl(AST, "x")), AST.getTokens(), 2158adc4d1eSSam McCall AST.getASTContext()); 2168adc4d1eSSam McCall EXPECT_THAT(Node.arcana, testing::StartsWith("VarDecl ")); 2178adc4d1eSSam McCall EXPECT_THAT(Node.arcana, testing::EndsWith(" 'int'")); 2188adc4d1eSSam McCall ASSERT_THAT(Node.children, SizeIs(1)) << "Expected one child typeloc"; 2198adc4d1eSSam McCall EXPECT_THAT(Node.children.front().arcana, testing::StartsWith("QualType ")); 2208adc4d1eSSam McCall } 2218adc4d1eSSam McCall 2229d1dada5SNathan Ridge TEST(DumpASTTests, UnbalancedBraces) { 2239d1dada5SNathan Ridge // Test that we don't crash while trying to compute a source range for the 2249d1dada5SNathan Ridge // node whose ending brace is missing, and also that the source range is 2259d1dada5SNathan Ridge // not empty. 2269d1dada5SNathan Ridge Annotations Case("/*error-ok*/ $func[[int main() {]]"); 2279d1dada5SNathan Ridge ParsedAST AST = TestTU::withCode(Case.code()).build(); 2289d1dada5SNathan Ridge auto Node = dumpAST(DynTypedNode::create(findDecl(AST, "main")), 2299d1dada5SNathan Ridge AST.getTokens(), AST.getASTContext()); 2309d1dada5SNathan Ridge ASSERT_EQ(Node.range, Case.range("func")); 2319d1dada5SNathan Ridge } 2329d1dada5SNathan Ridge 2338adc4d1eSSam McCall } // namespace 2348adc4d1eSSam McCall } // namespace clangd 2358adc4d1eSSam McCall } // namespace clang 236