1//===- SynthesisTest.cpp --------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file tests synthesis API for syntax trees.
10//
11//===----------------------------------------------------------------------===//
12
13#include "TreeTestBase.h"
14#include "clang/Tooling/Syntax/BuildTree.h"
15#include "clang/Tooling/Syntax/Nodes.h"
16#include "gtest/gtest.h"
17
18using namespace clang;
19using namespace clang::syntax;
20
21namespace {
22
23class SynthesisTest : public SyntaxTreeTest {
24protected:
25 ::testing::AssertionResult treeDumpEqual(syntax::Node *Root, StringRef Dump) {
26 if (!Root)
27 return ::testing::AssertionFailure()
28 << "Root was not built successfully.";
29
30 auto Actual = StringRef(Root->dump(SM: *TM)).trim().str();
31 auto Expected = Dump.trim().str();
32 // EXPECT_EQ shows the diff between the two strings if they are different.
33 EXPECT_EQ(Expected, Actual);
34 if (Actual != Expected) {
35 return ::testing::AssertionFailure();
36 }
37 return ::testing::AssertionSuccess();
38 }
39};
40
41INSTANTIATE_TEST_SUITE_P(
42 SynthesisTests, SynthesisTest, ::testing::ValuesIn(allTestClangConfigs()),
43 [](const testing::TestParamInfo<TestClangConfig> &Info) {
44 return Info.param.toShortString();
45 });
46
47TEST_P(SynthesisTest, Leaf_Punctuation) {
48 buildTree("", GetParam());
49
50 auto *Leaf = createLeaf(A&: *Arena, TBTM&: *TM, K: tok::comma);
51
52 EXPECT_TRUE(treeDumpEqual(Leaf, R"txt(
53',' Detached synthesized
54 )txt"));
55}
56
57TEST_P(SynthesisTest, Leaf_Punctuation_CXX) {
58 if (!GetParam().isCXX())
59 return;
60
61 buildTree("", GetParam());
62
63 auto *Leaf = createLeaf(A&: *Arena, TBTM&: *TM, K: tok::coloncolon);
64
65 EXPECT_TRUE(treeDumpEqual(Leaf, R"txt(
66'::' Detached synthesized
67 )txt"));
68}
69
70TEST_P(SynthesisTest, Leaf_Keyword) {
71 buildTree("", GetParam());
72
73 auto *Leaf = createLeaf(A&: *Arena, TBTM&: *TM, K: tok::kw_if);
74
75 EXPECT_TRUE(treeDumpEqual(Leaf, R"txt(
76'if' Detached synthesized
77 )txt"));
78}
79
80TEST_P(SynthesisTest, Leaf_Keyword_CXX11) {
81 if (!GetParam().isCXX11OrLater())
82 return;
83
84 buildTree("", GetParam());
85
86 auto *Leaf = createLeaf(A&: *Arena, TBTM&: *TM, K: tok::kw_nullptr);
87
88 EXPECT_TRUE(treeDumpEqual(Leaf, R"txt(
89'nullptr' Detached synthesized
90 )txt"));
91}
92
93TEST_P(SynthesisTest, Leaf_Identifier) {
94 buildTree("", GetParam());
95
96 auto *Leaf = createLeaf(A&: *Arena, TBTM&: *TM, K: tok::identifier, Spelling: "a");
97
98 EXPECT_TRUE(treeDumpEqual(Leaf, R"txt(
99'a' Detached synthesized
100 )txt"));
101}
102
103TEST_P(SynthesisTest, Leaf_Number) {
104 buildTree("", GetParam());
105
106 auto *Leaf = createLeaf(A&: *Arena, TBTM&: *TM, K: tok::numeric_constant, Spelling: "1");
107
108 EXPECT_TRUE(treeDumpEqual(Leaf, R"txt(
109'1' Detached synthesized
110 )txt"));
111}
112
113TEST_P(SynthesisTest, Tree_Empty) {
114 buildTree("", GetParam());
115
116 auto *Tree = createTree(*Arena, {}, NodeKind::UnknownExpression);
117
118 EXPECT_TRUE(treeDumpEqual(Tree, R"txt(
119UnknownExpression Detached synthesized
120 )txt"));
121}
122
123TEST_P(SynthesisTest, Tree_Flat) {
124 buildTree("", GetParam());
125
126 auto *LeafLParen = createLeaf(A&: *Arena, TBTM&: *TM, K: tok::l_paren);
127 auto *LeafRParen = createLeaf(A&: *Arena, TBTM&: *TM, K: tok::r_paren);
128 auto *TreeParen = createTree(*Arena,
129 {{LeafLParen, NodeRole::LeftHandSide},
130 {LeafRParen, NodeRole::RightHandSide}},
131 NodeKind::ParenExpression);
132
133 EXPECT_TRUE(treeDumpEqual(TreeParen, R"txt(
134ParenExpression Detached synthesized
135|-'(' LeftHandSide synthesized
136`-')' RightHandSide synthesized
137 )txt"));
138}
139
140TEST_P(SynthesisTest, Tree_OfTree) {
141 buildTree("", GetParam());
142
143 auto *Leaf1 = createLeaf(A&: *Arena, TBTM&: *TM, K: tok::numeric_constant, Spelling: "1");
144 auto *Int1 = createTree(*Arena, {{Leaf1, NodeRole::LiteralToken}},
145 NodeKind::IntegerLiteralExpression);
146
147 auto *LeafPlus = createLeaf(A&: *Arena, TBTM&: *TM, K: tok::plus);
148
149 auto *Leaf2 = createLeaf(A&: *Arena, TBTM&: *TM, K: tok::numeric_constant, Spelling: "2");
150 auto *Int2 = createTree(*Arena, {{Leaf2, NodeRole::LiteralToken}},
151 NodeKind::IntegerLiteralExpression);
152
153 auto *TreeBinaryOperator = createTree(*Arena,
154 {{Int1, NodeRole::LeftHandSide},
155 {LeafPlus, NodeRole::OperatorToken},
156 {Int2, NodeRole::RightHandSide}},
157 NodeKind::BinaryOperatorExpression);
158
159 EXPECT_TRUE(treeDumpEqual(TreeBinaryOperator, R"txt(
160BinaryOperatorExpression Detached synthesized
161|-IntegerLiteralExpression LeftHandSide synthesized
162| `-'1' LiteralToken synthesized
163|-'+' OperatorToken synthesized
164`-IntegerLiteralExpression RightHandSide synthesized
165 `-'2' LiteralToken synthesized
166 )txt"));
167}
168
169TEST_P(SynthesisTest, DeepCopy_Synthesized) {
170 buildTree("", GetParam());
171
172 auto *LeafContinue = createLeaf(A&: *Arena, TBTM&: *TM, K: tok::kw_continue);
173 auto *LeafSemiColon = createLeaf(A&: *Arena, TBTM&: *TM, K: tok::semi);
174 auto *StatementContinue = createTree(*Arena,
175 {{LeafContinue, NodeRole::LiteralToken},
176 {LeafSemiColon, NodeRole::Unknown}},
177 NodeKind::ContinueStatement);
178
179 auto *Copy = deepCopyExpandingMacros(*Arena, *TM, StatementContinue);
180 EXPECT_TRUE(treeDumpEqual(Copy, StatementContinue->dump(*TM)));
181 // FIXME: Test that copy is independent of original, once the Mutations API is
182 // more developed.
183}
184
185TEST_P(SynthesisTest, DeepCopy_Original) {
186 auto *OriginalTree = buildTree("int a;", GetParam());
187
188 auto *Copy = deepCopyExpandingMacros(*Arena, *TM, OriginalTree);
189 EXPECT_TRUE(treeDumpEqual(Copy, R"txt(
190TranslationUnit Detached synthesized
191`-SimpleDeclaration synthesized
192 |-'int' synthesized
193 |-DeclaratorList Declarators synthesized
194 | `-SimpleDeclarator ListElement synthesized
195 | `-'a' synthesized
196 `-';' synthesized
197 )txt"));
198}
199
200TEST_P(SynthesisTest, DeepCopy_Child) {
201 auto *OriginalTree = buildTree("int a;", GetParam());
202
203 auto *Copy =
204 deepCopyExpandingMacros(*Arena, *TM, OriginalTree->getFirstChild());
205 EXPECT_TRUE(treeDumpEqual(Copy, R"txt(
206SimpleDeclaration Detached synthesized
207|-'int' synthesized
208|-DeclaratorList Declarators synthesized
209| `-SimpleDeclarator ListElement synthesized
210| `-'a' synthesized
211`-';' synthesized
212 )txt"));
213}
214
215TEST_P(SynthesisTest, DeepCopy_Macro) {
216 auto *OriginalTree = buildTree(R"cpp(
217#define HALF_IF if (1+
218#define HALF_IF_2 1) {}
219void test() {
220 HALF_IF HALF_IF_2 else {}
221})cpp",
222 GetParam());
223
224 auto *Copy = deepCopyExpandingMacros(*Arena, *TM, OriginalTree);
225
226 // The syntax tree stores already expanded Tokens, we can only see whether the
227 // macro was expanded when computing replacements. The dump does show that
228 // nodes in the copy are `modifiable`.
229 EXPECT_TRUE(treeDumpEqual(Copy, R"txt(
230TranslationUnit Detached synthesized
231`-SimpleDeclaration synthesized
232 |-'void' synthesized
233 |-DeclaratorList Declarators synthesized
234 | `-SimpleDeclarator ListElement synthesized
235 | |-'test' synthesized
236 | `-ParametersAndQualifiers synthesized
237 | |-'(' OpenParen synthesized
238 | `-')' CloseParen synthesized
239 `-CompoundStatement synthesized
240 |-'{' OpenParen synthesized
241 |-IfStatement Statement synthesized
242 | |-'if' IntroducerKeyword synthesized
243 | |-'(' synthesized
244 | |-ExpressionStatement Condition synthesized
245 | | `-BinaryOperatorExpression Expression synthesized
246 | | |-IntegerLiteralExpression LeftHandSide synthesized
247 | | | `-'1' LiteralToken synthesized
248 | | |-'+' OperatorToken synthesized
249 | | `-IntegerLiteralExpression RightHandSide synthesized
250 | | `-'1' LiteralToken synthesized
251 | |-')' synthesized
252 | |-CompoundStatement ThenStatement synthesized
253 | | |-'{' OpenParen synthesized
254 | | `-'}' CloseParen synthesized
255 | |-'else' ElseKeyword synthesized
256 | `-CompoundStatement ElseStatement synthesized
257 | |-'{' OpenParen synthesized
258 | `-'}' CloseParen synthesized
259 `-'}' CloseParen synthesized
260 )txt"));
261}
262
263TEST_P(SynthesisTest, Statement_EmptyStatement) {
264 buildTree("", GetParam());
265
266 auto *S = createEmptyStatement(A&: *Arena, TBTM&: *TM);
267 EXPECT_TRUE(treeDumpEqual(S, R"txt(
268EmptyStatement Detached synthesized
269`-';' synthesized
270 )txt"));
271}
272} // namespace
273

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/unittests/Tooling/Syntax/SynthesisTest.cpp