1af582c9bSEduardo Caldas //===- TreeTest.cpp ---------------------------------------------*- C++ -*-===//
2af582c9bSEduardo Caldas //
3af582c9bSEduardo Caldas // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4af582c9bSEduardo Caldas // See https://llvm.org/LICENSE.txt for license information.
5af582c9bSEduardo Caldas // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6af582c9bSEduardo Caldas //
7af582c9bSEduardo Caldas //===----------------------------------------------------------------------===//
8af582c9bSEduardo Caldas
9af582c9bSEduardo Caldas #include "clang/Tooling/Syntax/Tree.h"
10af582c9bSEduardo Caldas #include "TreeTestBase.h"
11d4934eb5SSam McCall #include "clang/Basic/SourceManager.h"
12af582c9bSEduardo Caldas #include "clang/Tooling/Syntax/BuildTree.h"
13c3c08bfdSEduardo Caldas #include "clang/Tooling/Syntax/Nodes.h"
14c3c08bfdSEduardo Caldas #include "llvm/ADT/STLExtras.h"
15af582c9bSEduardo Caldas #include "gtest/gtest.h"
16af582c9bSEduardo Caldas
17af582c9bSEduardo Caldas using namespace clang;
18af582c9bSEduardo Caldas using namespace clang::syntax;
19af582c9bSEduardo Caldas
20af582c9bSEduardo Caldas namespace {
21d4934eb5SSam McCall using testing::ElementsAre;
22af582c9bSEduardo Caldas
23af582c9bSEduardo Caldas class TreeTest : public SyntaxTreeTest {
24af582c9bSEduardo Caldas private:
createTree(ArrayRef<const Node * > Children)25af582c9bSEduardo Caldas Tree *createTree(ArrayRef<const Node *> Children) {
26af582c9bSEduardo Caldas std::vector<std::pair<Node *, NodeRole>> ChildrenWithRoles;
27af582c9bSEduardo Caldas ChildrenWithRoles.reserve(Children.size());
28af582c9bSEduardo Caldas for (const auto *Child : Children) {
2966bcb143SEduardo Caldas ChildrenWithRoles.push_back(std::make_pair(
30*263dcf45SHaojian Wu deepCopyExpandingMacros(*Arena, *TM, Child), NodeRole::Unknown));
31af582c9bSEduardo Caldas }
32af582c9bSEduardo Caldas return clang::syntax::createTree(*Arena, ChildrenWithRoles,
33af582c9bSEduardo Caldas NodeKind::UnknownExpression);
34af582c9bSEduardo Caldas }
35af582c9bSEduardo Caldas
36af582c9bSEduardo Caldas // Generate Forests by combining `Children` into `ParentCount` Trees.
37af582c9bSEduardo Caldas //
38af582c9bSEduardo Caldas // We do this recursively.
39af582c9bSEduardo Caldas std::vector<std::vector<const Tree *>>
generateAllForests(ArrayRef<const Node * > Children,unsigned ParentCount)40af582c9bSEduardo Caldas generateAllForests(ArrayRef<const Node *> Children, unsigned ParentCount) {
41af582c9bSEduardo Caldas assert(ParentCount > 0);
42af582c9bSEduardo Caldas // If there is only one Parent node, then combine `Children` under
43af582c9bSEduardo Caldas // this Parent.
44af582c9bSEduardo Caldas if (ParentCount == 1)
45af582c9bSEduardo Caldas return {{createTree(Children)}};
46af582c9bSEduardo Caldas
47af582c9bSEduardo Caldas // Otherwise, combine `ChildrenCount` children under the last parent and
48af582c9bSEduardo Caldas // solve the smaller problem without these children and this parent. Do this
49af582c9bSEduardo Caldas // for every `ChildrenCount` and combine the results.
50af582c9bSEduardo Caldas std::vector<std::vector<const Tree *>> AllForests;
51af582c9bSEduardo Caldas for (unsigned ChildrenCount = 0; ChildrenCount <= Children.size();
52af582c9bSEduardo Caldas ++ChildrenCount) {
53af582c9bSEduardo Caldas auto *LastParent = createTree(Children.take_back(ChildrenCount));
54af582c9bSEduardo Caldas for (auto &Forest : generateAllForests(Children.drop_back(ChildrenCount),
55af582c9bSEduardo Caldas ParentCount - 1)) {
56af582c9bSEduardo Caldas Forest.push_back(LastParent);
57af582c9bSEduardo Caldas AllForests.push_back(Forest);
58af582c9bSEduardo Caldas }
59af582c9bSEduardo Caldas }
60af582c9bSEduardo Caldas return AllForests;
61af582c9bSEduardo Caldas }
62af582c9bSEduardo Caldas
63af582c9bSEduardo Caldas protected:
64af582c9bSEduardo Caldas // Generates all trees with a `Base` of `Node`s and `NodeCountPerLayer`
65af582c9bSEduardo Caldas // `Node`s per layer. An example of Tree with `Base` = {`(`, `)`} and
66af582c9bSEduardo Caldas // `NodeCountPerLayer` = {2, 2}:
67af582c9bSEduardo Caldas // Tree
68af582c9bSEduardo Caldas // |-Tree
69af582c9bSEduardo Caldas // `-Tree
70af582c9bSEduardo Caldas // |-Tree
71af582c9bSEduardo Caldas // | `-'('
72af582c9bSEduardo Caldas // `-Tree
73af582c9bSEduardo Caldas // `-')'
74af582c9bSEduardo Caldas std::vector<const Tree *>
generateAllTreesWithShape(ArrayRef<const Node * > Base,ArrayRef<unsigned> NodeCountPerLayer)75af582c9bSEduardo Caldas generateAllTreesWithShape(ArrayRef<const Node *> Base,
76af582c9bSEduardo Caldas ArrayRef<unsigned> NodeCountPerLayer) {
77af582c9bSEduardo Caldas // We compute the solution per layer. A layer is a collection of bases,
78af582c9bSEduardo Caldas // where each base has the same number of nodes, given by
79af582c9bSEduardo Caldas // `NodeCountPerLayer`.
80af582c9bSEduardo Caldas auto GenerateNextLayer = [this](ArrayRef<std::vector<const Node *>> Layer,
81af582c9bSEduardo Caldas unsigned NextLayerNodeCount) {
82af582c9bSEduardo Caldas std::vector<std::vector<const Node *>> NextLayer;
83af582c9bSEduardo Caldas for (const auto &Base : Layer) {
84af582c9bSEduardo Caldas for (const auto &NextBase :
85af582c9bSEduardo Caldas generateAllForests(Base, NextLayerNodeCount)) {
86af582c9bSEduardo Caldas NextLayer.push_back(
87af582c9bSEduardo Caldas std::vector<const Node *>(NextBase.begin(), NextBase.end()));
88af582c9bSEduardo Caldas }
89af582c9bSEduardo Caldas }
90af582c9bSEduardo Caldas return NextLayer;
91af582c9bSEduardo Caldas };
92af582c9bSEduardo Caldas
93af582c9bSEduardo Caldas std::vector<std::vector<const Node *>> Layer = {Base};
94af582c9bSEduardo Caldas for (auto NodeCount : NodeCountPerLayer)
95af582c9bSEduardo Caldas Layer = GenerateNextLayer(Layer, NodeCount);
96af582c9bSEduardo Caldas
97af582c9bSEduardo Caldas std::vector<const Tree *> AllTrees;
98af582c9bSEduardo Caldas AllTrees.reserve(Layer.size());
99af582c9bSEduardo Caldas for (const auto &Base : Layer)
100af582c9bSEduardo Caldas AllTrees.push_back(createTree(Base));
101af582c9bSEduardo Caldas
102af582c9bSEduardo Caldas return AllTrees;
103af582c9bSEduardo Caldas }
104af582c9bSEduardo Caldas };
105af582c9bSEduardo Caldas
106d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P(TreeTests, TreeTest,
107d4d80a29SBenjamin Kramer ::testing::ValuesIn(allTestClangConfigs()) );
108af582c9bSEduardo Caldas
TEST_P(TreeTest,FirstLeaf)109af582c9bSEduardo Caldas TEST_P(TreeTest, FirstLeaf) {
110af582c9bSEduardo Caldas buildTree("", GetParam());
111*263dcf45SHaojian Wu std::vector<const Node *> Leafs = {createLeaf(*Arena, *TM, tok::l_paren),
112*263dcf45SHaojian Wu createLeaf(*Arena, *TM, tok::r_paren)};
113af582c9bSEduardo Caldas for (const auto *Tree : generateAllTreesWithShape(Leafs, {3u})) {
114af582c9bSEduardo Caldas ASSERT_TRUE(Tree->findFirstLeaf() != nullptr);
115*263dcf45SHaojian Wu EXPECT_EQ(TM->getToken(Tree->findFirstLeaf()->getTokenKey())->kind(), tok::l_paren);
116af582c9bSEduardo Caldas }
117af582c9bSEduardo Caldas }
118af582c9bSEduardo Caldas
TEST_P(TreeTest,LastLeaf)119af582c9bSEduardo Caldas TEST_P(TreeTest, LastLeaf) {
120af582c9bSEduardo Caldas buildTree("", GetParam());
121*263dcf45SHaojian Wu std::vector<const Node *> Leafs = {createLeaf(*Arena, *TM, tok::l_paren),
122*263dcf45SHaojian Wu createLeaf(*Arena, *TM, tok::r_paren)};
123af582c9bSEduardo Caldas for (const auto *Tree : generateAllTreesWithShape(Leafs, {3u})) {
124af582c9bSEduardo Caldas ASSERT_TRUE(Tree->findLastLeaf() != nullptr);
125*263dcf45SHaojian Wu EXPECT_EQ(TM->getToken(Tree->findLastLeaf()->getTokenKey())->kind(), tok::r_paren);
126af582c9bSEduardo Caldas }
127af582c9bSEduardo Caldas }
128af582c9bSEduardo Caldas
TEST_F(TreeTest,Iterators)129d4934eb5SSam McCall TEST_F(TreeTest, Iterators) {
130d4934eb5SSam McCall buildTree("", allTestClangConfigs().front());
131*263dcf45SHaojian Wu std::vector<Node *> Children = {createLeaf(*Arena, *TM, tok::identifier, "a"),
132*263dcf45SHaojian Wu createLeaf(*Arena, *TM, tok::identifier, "b"),
133*263dcf45SHaojian Wu createLeaf(*Arena, *TM, tok::identifier, "c")};
134d4934eb5SSam McCall auto *Tree = syntax::createTree(*Arena,
135d4934eb5SSam McCall {{Children[0], NodeRole::LeftHandSide},
136d4934eb5SSam McCall {Children[1], NodeRole::OperatorToken},
137d4934eb5SSam McCall {Children[2], NodeRole::RightHandSide}},
138d4934eb5SSam McCall NodeKind::TranslationUnit);
139d4934eb5SSam McCall const auto *ConstTree = Tree;
140d4934eb5SSam McCall
141d4934eb5SSam McCall auto Range = Tree->getChildren();
142d4934eb5SSam McCall EXPECT_THAT(Range, ElementsAre(role(NodeRole::LeftHandSide),
143d4934eb5SSam McCall role(NodeRole::OperatorToken),
144d4934eb5SSam McCall role(NodeRole::RightHandSide)));
145d4934eb5SSam McCall
146d4934eb5SSam McCall auto ConstRange = ConstTree->getChildren();
147d4934eb5SSam McCall EXPECT_THAT(ConstRange, ElementsAre(role(NodeRole::LeftHandSide),
148d4934eb5SSam McCall role(NodeRole::OperatorToken),
149d4934eb5SSam McCall role(NodeRole::RightHandSide)));
150d4934eb5SSam McCall
151d4934eb5SSam McCall // FIXME: mutate and observe no invalidation. Mutations are private for now...
152d4934eb5SSam McCall auto It = Range.begin();
153d4934eb5SSam McCall auto CIt = ConstRange.begin();
154d4934eb5SSam McCall static_assert(std::is_same<decltype(*It), syntax::Node &>::value,
155d4934eb5SSam McCall "mutable range");
156d4934eb5SSam McCall static_assert(std::is_same<decltype(*CIt), const syntax::Node &>::value,
157d4934eb5SSam McCall "const range");
158d4934eb5SSam McCall
159d4934eb5SSam McCall for (unsigned I = 0; I < 3; ++I) {
160d4934eb5SSam McCall EXPECT_EQ(It, CIt);
161d4934eb5SSam McCall EXPECT_TRUE(It);
162d4934eb5SSam McCall EXPECT_TRUE(CIt);
163d4934eb5SSam McCall EXPECT_EQ(It.asPointer(), Children[I]);
164d4934eb5SSam McCall EXPECT_EQ(CIt.asPointer(), Children[I]);
165d4934eb5SSam McCall EXPECT_EQ(&*It, Children[I]);
166d4934eb5SSam McCall EXPECT_EQ(&*CIt, Children[I]);
167d4934eb5SSam McCall ++It;
168d4934eb5SSam McCall ++CIt;
169d4934eb5SSam McCall }
170d4934eb5SSam McCall EXPECT_EQ(It, CIt);
171d4934eb5SSam McCall EXPECT_EQ(It, Tree::ChildIterator());
172d4934eb5SSam McCall EXPECT_EQ(CIt, Tree::ConstChildIterator());
173d4934eb5SSam McCall EXPECT_FALSE(It);
174d4934eb5SSam McCall EXPECT_FALSE(CIt);
175d4934eb5SSam McCall EXPECT_EQ(nullptr, It.asPointer());
176d4934eb5SSam McCall EXPECT_EQ(nullptr, CIt.asPointer());
177d4934eb5SSam McCall }
178d4934eb5SSam McCall
179c3c08bfdSEduardo Caldas class ListTest : public SyntaxTreeTest {
180c3c08bfdSEduardo Caldas private:
dumpQuotedTokensOrNull(const Node * N)181c3c08bfdSEduardo Caldas std::string dumpQuotedTokensOrNull(const Node *N) {
182c3c08bfdSEduardo Caldas return N ? "'" +
183*263dcf45SHaojian Wu StringRef(N->dumpTokens(*TM))
184c3c08bfdSEduardo Caldas .trim()
185c3c08bfdSEduardo Caldas .str() +
186c3c08bfdSEduardo Caldas "'"
187c3c08bfdSEduardo Caldas : "null";
188c3c08bfdSEduardo Caldas }
189c3c08bfdSEduardo Caldas
190c3c08bfdSEduardo Caldas protected:
191c3c08bfdSEduardo Caldas std::string
dumpElementsAndDelimiters(ArrayRef<List::ElementAndDelimiter<Node>> EDs)192c3c08bfdSEduardo Caldas dumpElementsAndDelimiters(ArrayRef<List::ElementAndDelimiter<Node>> EDs) {
193c3c08bfdSEduardo Caldas std::string Storage;
194c3c08bfdSEduardo Caldas llvm::raw_string_ostream OS(Storage);
195c3c08bfdSEduardo Caldas
196c3c08bfdSEduardo Caldas OS << "[";
197c3c08bfdSEduardo Caldas
198c3c08bfdSEduardo Caldas llvm::interleaveComma(
199c3c08bfdSEduardo Caldas EDs, OS, [&OS, this](const List::ElementAndDelimiter<Node> &ED) {
200c3c08bfdSEduardo Caldas OS << "(" << dumpQuotedTokensOrNull(ED.element) << ", "
201c3c08bfdSEduardo Caldas << dumpQuotedTokensOrNull(ED.delimiter) << ")";
202c3c08bfdSEduardo Caldas });
203c3c08bfdSEduardo Caldas
204c3c08bfdSEduardo Caldas OS << "]";
205c3c08bfdSEduardo Caldas
20608eb614eSLogan Smith return Storage;
207c3c08bfdSEduardo Caldas }
208c3c08bfdSEduardo Caldas
dumpNodes(ArrayRef<Node * > Nodes)209c3c08bfdSEduardo Caldas std::string dumpNodes(ArrayRef<Node *> Nodes) {
210c3c08bfdSEduardo Caldas std::string Storage;
211c3c08bfdSEduardo Caldas llvm::raw_string_ostream OS(Storage);
212c3c08bfdSEduardo Caldas
213c3c08bfdSEduardo Caldas OS << "[";
214c3c08bfdSEduardo Caldas
215c3c08bfdSEduardo Caldas llvm::interleaveComma(Nodes, OS, [&OS, this](const Node *N) {
216c3c08bfdSEduardo Caldas OS << dumpQuotedTokensOrNull(N);
217c3c08bfdSEduardo Caldas });
218c3c08bfdSEduardo Caldas
219c3c08bfdSEduardo Caldas OS << "]";
220c3c08bfdSEduardo Caldas
22108eb614eSLogan Smith return Storage;
222c3c08bfdSEduardo Caldas }
223c3c08bfdSEduardo Caldas };
224c3c08bfdSEduardo Caldas
225d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P(TreeTests, ListTest,
226d4d80a29SBenjamin Kramer ::testing::ValuesIn(allTestClangConfigs()) );
227c3c08bfdSEduardo Caldas
228c3c08bfdSEduardo Caldas /// "a, b, c" <=> [("a", ","), ("b", ","), ("c", null)]
TEST_P(ListTest,List_Separated_WellFormed)229c3c08bfdSEduardo Caldas TEST_P(ListTest, List_Separated_WellFormed) {
230c3c08bfdSEduardo Caldas buildTree("", GetParam());
231c3c08bfdSEduardo Caldas
232c3c08bfdSEduardo Caldas // "a, b, c"
233c3c08bfdSEduardo Caldas auto *List = dyn_cast<syntax::List>(syntax::createTree(
234c3c08bfdSEduardo Caldas *Arena,
235c3c08bfdSEduardo Caldas {
236*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "a"), NodeRole::ListElement},
237*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::comma), NodeRole::ListDelimiter},
238*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "b"), NodeRole::ListElement},
239*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::comma), NodeRole::ListDelimiter},
240*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "c"), NodeRole::ListElement},
241c3c08bfdSEduardo Caldas },
242c3c08bfdSEduardo Caldas NodeKind::CallArguments));
243c3c08bfdSEduardo Caldas
244c3c08bfdSEduardo Caldas EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
245c3c08bfdSEduardo Caldas "[('a', ','), ('b', ','), ('c', null)]");
246c3c08bfdSEduardo Caldas EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', 'b', 'c']");
247c3c08bfdSEduardo Caldas }
248c3c08bfdSEduardo Caldas
249c3c08bfdSEduardo Caldas /// "a, , c" <=> [("a", ","), (null, ","), ("c", null)]
TEST_P(ListTest,List_Separated_MissingElement)250c3c08bfdSEduardo Caldas TEST_P(ListTest, List_Separated_MissingElement) {
251c3c08bfdSEduardo Caldas buildTree("", GetParam());
252c3c08bfdSEduardo Caldas
253c3c08bfdSEduardo Caldas // "a, , c"
254c3c08bfdSEduardo Caldas auto *List = dyn_cast<syntax::List>(syntax::createTree(
255c3c08bfdSEduardo Caldas *Arena,
256c3c08bfdSEduardo Caldas {
257*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "a"), NodeRole::ListElement},
258*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::comma), NodeRole::ListDelimiter},
259*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::comma), NodeRole::ListDelimiter},
260*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "c"), NodeRole::ListElement},
261c3c08bfdSEduardo Caldas },
262c3c08bfdSEduardo Caldas NodeKind::CallArguments));
263c3c08bfdSEduardo Caldas
264c3c08bfdSEduardo Caldas EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
265c3c08bfdSEduardo Caldas "[('a', ','), (null, ','), ('c', null)]");
266c3c08bfdSEduardo Caldas EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', null, 'c']");
267c3c08bfdSEduardo Caldas }
268c3c08bfdSEduardo Caldas
269c3c08bfdSEduardo Caldas /// "a, b c" <=> [("a", ","), ("b", null), ("c", null)]
TEST_P(ListTest,List_Separated_MissingDelimiter)270c3c08bfdSEduardo Caldas TEST_P(ListTest, List_Separated_MissingDelimiter) {
271c3c08bfdSEduardo Caldas buildTree("", GetParam());
272c3c08bfdSEduardo Caldas
273c3c08bfdSEduardo Caldas // "a, b c"
274c3c08bfdSEduardo Caldas auto *List = dyn_cast<syntax::List>(syntax::createTree(
275c3c08bfdSEduardo Caldas *Arena,
276c3c08bfdSEduardo Caldas {
277*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "a"), NodeRole::ListElement},
278*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::comma), NodeRole::ListDelimiter},
279*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "b"), NodeRole::ListElement},
280*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "c"), NodeRole::ListElement},
281c3c08bfdSEduardo Caldas },
282c3c08bfdSEduardo Caldas NodeKind::CallArguments));
283c3c08bfdSEduardo Caldas
284c3c08bfdSEduardo Caldas EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
285c3c08bfdSEduardo Caldas "[('a', ','), ('b', null), ('c', null)]");
286c3c08bfdSEduardo Caldas EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', 'b', 'c']");
287c3c08bfdSEduardo Caldas }
288c3c08bfdSEduardo Caldas
289c3c08bfdSEduardo Caldas /// "a, b," <=> [("a", ","), ("b", ","), (null, null)]
TEST_P(ListTest,List_Separated_MissingLastElement)290c3c08bfdSEduardo Caldas TEST_P(ListTest, List_Separated_MissingLastElement) {
291c3c08bfdSEduardo Caldas buildTree("", GetParam());
292c3c08bfdSEduardo Caldas
293c3c08bfdSEduardo Caldas // "a, b, c"
294c3c08bfdSEduardo Caldas auto *List = dyn_cast<syntax::List>(syntax::createTree(
295c3c08bfdSEduardo Caldas *Arena,
296c3c08bfdSEduardo Caldas {
297*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "a"), NodeRole::ListElement},
298*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::comma), NodeRole::ListDelimiter},
299*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "b"), NodeRole::ListElement},
300*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::comma), NodeRole::ListDelimiter},
301c3c08bfdSEduardo Caldas },
302c3c08bfdSEduardo Caldas NodeKind::CallArguments));
303c3c08bfdSEduardo Caldas
304c3c08bfdSEduardo Caldas EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
305c3c08bfdSEduardo Caldas "[('a', ','), ('b', ','), (null, null)]");
306c3c08bfdSEduardo Caldas EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', 'b', null]");
307c3c08bfdSEduardo Caldas }
308c3c08bfdSEduardo Caldas
309c3c08bfdSEduardo Caldas /// "a:: b:: c::" <=> [("a", "::"), ("b", "::"), ("c", "::")]
TEST_P(ListTest,List_Terminated_WellFormed)310c3c08bfdSEduardo Caldas TEST_P(ListTest, List_Terminated_WellFormed) {
311c3c08bfdSEduardo Caldas if (!GetParam().isCXX()) {
312c3c08bfdSEduardo Caldas return;
313c3c08bfdSEduardo Caldas }
314c3c08bfdSEduardo Caldas buildTree("", GetParam());
315c3c08bfdSEduardo Caldas
316c3c08bfdSEduardo Caldas // "a:: b:: c::"
317c3c08bfdSEduardo Caldas auto *List = dyn_cast<syntax::List>(syntax::createTree(
318c3c08bfdSEduardo Caldas *Arena,
319c3c08bfdSEduardo Caldas {
320*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "a"), NodeRole::ListElement},
321*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::coloncolon), NodeRole::ListDelimiter},
322*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "b"), NodeRole::ListElement},
323*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::coloncolon), NodeRole::ListDelimiter},
324*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "c"), NodeRole::ListElement},
325*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::coloncolon), NodeRole::ListDelimiter},
326c3c08bfdSEduardo Caldas },
327c3c08bfdSEduardo Caldas NodeKind::NestedNameSpecifier));
328c3c08bfdSEduardo Caldas
329c3c08bfdSEduardo Caldas EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
330c3c08bfdSEduardo Caldas "[('a', '::'), ('b', '::'), ('c', '::')]");
331c3c08bfdSEduardo Caldas EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', 'b', 'c']");
332c3c08bfdSEduardo Caldas }
333c3c08bfdSEduardo Caldas
334c3c08bfdSEduardo Caldas /// "a:: :: c::" <=> [("a", "::"), (null, "::"), ("c", "::")]
TEST_P(ListTest,List_Terminated_MissingElement)335c3c08bfdSEduardo Caldas TEST_P(ListTest, List_Terminated_MissingElement) {
336c3c08bfdSEduardo Caldas if (!GetParam().isCXX()) {
337c3c08bfdSEduardo Caldas return;
338c3c08bfdSEduardo Caldas }
339c3c08bfdSEduardo Caldas buildTree("", GetParam());
340c3c08bfdSEduardo Caldas
341c3c08bfdSEduardo Caldas // "a:: b:: c::"
342c3c08bfdSEduardo Caldas auto *List = dyn_cast<syntax::List>(syntax::createTree(
343c3c08bfdSEduardo Caldas *Arena,
344c3c08bfdSEduardo Caldas {
345*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "a"), NodeRole::ListElement},
346*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::coloncolon), NodeRole::ListDelimiter},
347*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::coloncolon), NodeRole::ListDelimiter},
348*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "c"), NodeRole::ListElement},
349*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::coloncolon), NodeRole::ListDelimiter},
350c3c08bfdSEduardo Caldas },
351c3c08bfdSEduardo Caldas NodeKind::NestedNameSpecifier));
352c3c08bfdSEduardo Caldas
353c3c08bfdSEduardo Caldas EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
354c3c08bfdSEduardo Caldas "[('a', '::'), (null, '::'), ('c', '::')]");
355c3c08bfdSEduardo Caldas EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', null, 'c']");
356c3c08bfdSEduardo Caldas }
357c3c08bfdSEduardo Caldas
358c3c08bfdSEduardo Caldas /// "a:: b c::" <=> [("a", "::"), ("b", null), ("c", "::")]
TEST_P(ListTest,List_Terminated_MissingDelimiter)359c3c08bfdSEduardo Caldas TEST_P(ListTest, List_Terminated_MissingDelimiter) {
360c3c08bfdSEduardo Caldas if (!GetParam().isCXX()) {
361c3c08bfdSEduardo Caldas return;
362c3c08bfdSEduardo Caldas }
363c3c08bfdSEduardo Caldas buildTree("", GetParam());
364c3c08bfdSEduardo Caldas
365c3c08bfdSEduardo Caldas // "a:: b c::"
366c3c08bfdSEduardo Caldas auto *List = dyn_cast<syntax::List>(syntax::createTree(
367c3c08bfdSEduardo Caldas *Arena,
368c3c08bfdSEduardo Caldas {
369*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "a"), NodeRole::ListElement},
370*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::coloncolon), NodeRole::ListDelimiter},
371*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "b"), NodeRole::ListElement},
372*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "c"), NodeRole::ListElement},
373*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::coloncolon), NodeRole::ListDelimiter},
374c3c08bfdSEduardo Caldas },
375c3c08bfdSEduardo Caldas NodeKind::NestedNameSpecifier));
376c3c08bfdSEduardo Caldas
377c3c08bfdSEduardo Caldas EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
378c3c08bfdSEduardo Caldas "[('a', '::'), ('b', null), ('c', '::')]");
379c3c08bfdSEduardo Caldas EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', 'b', 'c']");
380c3c08bfdSEduardo Caldas }
381c3c08bfdSEduardo Caldas
382c3c08bfdSEduardo Caldas /// "a:: b:: c" <=> [("a", "::"), ("b", "::"), ("c", null)]
TEST_P(ListTest,List_Terminated_MissingLastDelimiter)383c3c08bfdSEduardo Caldas TEST_P(ListTest, List_Terminated_MissingLastDelimiter) {
384c3c08bfdSEduardo Caldas if (!GetParam().isCXX()) {
385c3c08bfdSEduardo Caldas return;
386c3c08bfdSEduardo Caldas }
387c3c08bfdSEduardo Caldas buildTree("", GetParam());
388c3c08bfdSEduardo Caldas
389c3c08bfdSEduardo Caldas // "a:: b:: c"
390c3c08bfdSEduardo Caldas auto *List = dyn_cast<syntax::List>(syntax::createTree(
391c3c08bfdSEduardo Caldas *Arena,
392c3c08bfdSEduardo Caldas {
393*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "a"), NodeRole::ListElement},
394*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::coloncolon), NodeRole::ListDelimiter},
395*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "b"), NodeRole::ListElement},
396*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::coloncolon), NodeRole::ListDelimiter},
397*263dcf45SHaojian Wu {createLeaf(*Arena, *TM, tok::identifier, "c"), NodeRole::ListElement},
398c3c08bfdSEduardo Caldas },
399c3c08bfdSEduardo Caldas NodeKind::NestedNameSpecifier));
400c3c08bfdSEduardo Caldas
401c3c08bfdSEduardo Caldas EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
402c3c08bfdSEduardo Caldas "[('a', '::'), ('b', '::'), ('c', null)]");
403c3c08bfdSEduardo Caldas EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', 'b', 'c']");
404c3c08bfdSEduardo Caldas }
405c3c08bfdSEduardo Caldas
406af582c9bSEduardo Caldas } // namespace
407