xref: /llvm-project/clang-tools-extra/clangd/unittests/DumpASTTests.cpp (revision db93ef14aef9c572e02bc842762bc4d0278148f9)
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