xref: /src/contrib/llvm-project/clang/lib/Tooling/Syntax/Tree.cpp (revision fcaf7f8644a9988098ac6be2165bce3ea4786e91)
122989816SDimitry Andric //===- Tree.cpp -----------------------------------------------*- C++ -*-=====//
222989816SDimitry Andric //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
622989816SDimitry Andric //
722989816SDimitry Andric //===----------------------------------------------------------------------===//
822989816SDimitry Andric #include "clang/Tooling/Syntax/Tree.h"
922989816SDimitry Andric #include "clang/Basic/TokenKinds.h"
1022989816SDimitry Andric #include "clang/Tooling/Syntax/Nodes.h"
116f8fc217SDimitry Andric #include "llvm/ADT/BitVector.h"
124b4fe385SDimitry Andric #include "llvm/Support/raw_ostream.h"
1322989816SDimitry Andric #include "llvm/Support/Casting.h"
14706b4fc4SDimitry Andric #include <cassert>
1522989816SDimitry Andric 
1622989816SDimitry Andric using namespace clang;
1722989816SDimitry Andric 
18706b4fc4SDimitry Andric namespace {
traverse(const syntax::Node * N,llvm::function_ref<void (const syntax::Node *)> Visit)19706b4fc4SDimitry Andric static void traverse(const syntax::Node *N,
20706b4fc4SDimitry Andric                      llvm::function_ref<void(const syntax::Node *)> Visit) {
21706b4fc4SDimitry Andric   if (auto *T = dyn_cast<syntax::Tree>(N)) {
22b60736ecSDimitry Andric     for (const syntax::Node &C : T->getChildren())
23b60736ecSDimitry Andric       traverse(&C, Visit);
24706b4fc4SDimitry Andric   }
25706b4fc4SDimitry Andric   Visit(N);
26706b4fc4SDimitry Andric }
traverse(syntax::Node * N,llvm::function_ref<void (syntax::Node *)> Visit)27706b4fc4SDimitry Andric static void traverse(syntax::Node *N,
28706b4fc4SDimitry Andric                      llvm::function_ref<void(syntax::Node *)> Visit) {
29706b4fc4SDimitry Andric   traverse(static_cast<const syntax::Node *>(N), [&](const syntax::Node *N) {
30706b4fc4SDimitry Andric     Visit(const_cast<syntax::Node *>(N));
31706b4fc4SDimitry Andric   });
32706b4fc4SDimitry Andric }
33706b4fc4SDimitry Andric } // namespace
34706b4fc4SDimitry Andric 
Leaf(syntax::TokenManager::Key K)354b4fe385SDimitry Andric syntax::Leaf::Leaf(syntax::TokenManager::Key K) : Node(NodeKind::Leaf), K(K) {}
3622989816SDimitry Andric 
Node(NodeKind Kind)3722989816SDimitry Andric syntax::Node::Node(NodeKind Kind)
38b60736ecSDimitry Andric     : Parent(nullptr), NextSibling(nullptr), PreviousSibling(nullptr),
39b60736ecSDimitry Andric       Kind(static_cast<unsigned>(Kind)), Role(0), Original(false),
40b60736ecSDimitry Andric       CanModify(false) {
41cfca06d7SDimitry Andric   this->setRole(NodeRole::Detached);
42cfca06d7SDimitry Andric }
43706b4fc4SDimitry Andric 
isDetached() const44b60736ecSDimitry Andric bool syntax::Node::isDetached() const {
45b60736ecSDimitry Andric   return getRole() == NodeRole::Detached;
46b60736ecSDimitry Andric }
4722989816SDimitry Andric 
setRole(NodeRole NR)48cfca06d7SDimitry Andric void syntax::Node::setRole(NodeRole NR) {
49cfca06d7SDimitry Andric   this->Role = static_cast<unsigned>(NR);
50cfca06d7SDimitry Andric }
51cfca06d7SDimitry Andric 
appendChildLowLevel(Node * Child,NodeRole Role)52b60736ecSDimitry Andric void syntax::Tree::appendChildLowLevel(Node *Child, NodeRole Role) {
53b60736ecSDimitry Andric   assert(Child->getRole() == NodeRole::Detached);
54b60736ecSDimitry Andric   assert(Role != NodeRole::Detached);
55b60736ecSDimitry Andric 
56b60736ecSDimitry Andric   Child->setRole(Role);
57b60736ecSDimitry Andric   appendChildLowLevel(Child);
58b60736ecSDimitry Andric }
59b60736ecSDimitry Andric 
appendChildLowLevel(Node * Child)60b60736ecSDimitry Andric void syntax::Tree::appendChildLowLevel(Node *Child) {
61b60736ecSDimitry Andric   assert(Child->Parent == nullptr);
62b60736ecSDimitry Andric   assert(Child->NextSibling == nullptr);
63b60736ecSDimitry Andric   assert(Child->PreviousSibling == nullptr);
64b60736ecSDimitry Andric   assert(Child->getRole() != NodeRole::Detached);
65b60736ecSDimitry Andric 
66b60736ecSDimitry Andric   Child->Parent = this;
67b60736ecSDimitry Andric   if (this->LastChild) {
68b60736ecSDimitry Andric     Child->PreviousSibling = this->LastChild;
69b60736ecSDimitry Andric     this->LastChild->NextSibling = Child;
70b60736ecSDimitry Andric   } else
71b60736ecSDimitry Andric     this->FirstChild = Child;
72b60736ecSDimitry Andric 
73b60736ecSDimitry Andric   this->LastChild = Child;
74b60736ecSDimitry Andric }
7522989816SDimitry Andric 
prependChildLowLevel(Node * Child,NodeRole Role)7622989816SDimitry Andric void syntax::Tree::prependChildLowLevel(Node *Child, NodeRole Role) {
77b60736ecSDimitry Andric   assert(Child->getRole() == NodeRole::Detached);
7822989816SDimitry Andric   assert(Role != NodeRole::Detached);
7922989816SDimitry Andric 
80cfca06d7SDimitry Andric   Child->setRole(Role);
81cfca06d7SDimitry Andric   prependChildLowLevel(Child);
82cfca06d7SDimitry Andric }
83cfca06d7SDimitry Andric 
prependChildLowLevel(Node * Child)84cfca06d7SDimitry Andric void syntax::Tree::prependChildLowLevel(Node *Child) {
85cfca06d7SDimitry Andric   assert(Child->Parent == nullptr);
86cfca06d7SDimitry Andric   assert(Child->NextSibling == nullptr);
87b60736ecSDimitry Andric   assert(Child->PreviousSibling == nullptr);
88b60736ecSDimitry Andric   assert(Child->getRole() != NodeRole::Detached);
89cfca06d7SDimitry Andric 
9022989816SDimitry Andric   Child->Parent = this;
91b60736ecSDimitry Andric   if (this->FirstChild) {
9222989816SDimitry Andric     Child->NextSibling = this->FirstChild;
93b60736ecSDimitry Andric     this->FirstChild->PreviousSibling = Child;
94b60736ecSDimitry Andric   } else
95b60736ecSDimitry Andric     this->LastChild = Child;
96b60736ecSDimitry Andric 
9722989816SDimitry Andric   this->FirstChild = Child;
9822989816SDimitry Andric }
9922989816SDimitry Andric 
replaceChildRangeLowLevel(Node * Begin,Node * End,Node * New)100b60736ecSDimitry Andric void syntax::Tree::replaceChildRangeLowLevel(Node *Begin, Node *End,
101706b4fc4SDimitry Andric                                              Node *New) {
102b60736ecSDimitry Andric   assert((!Begin || Begin->Parent == this) &&
103b60736ecSDimitry Andric          "`Begin` is not a child of `this`.");
104b60736ecSDimitry Andric   assert((!End || End->Parent == this) && "`End` is not a child of `this`.");
105b60736ecSDimitry Andric   assert(canModify() && "Cannot modify `this`.");
106706b4fc4SDimitry Andric 
107706b4fc4SDimitry Andric #ifndef NDEBUG
108b60736ecSDimitry Andric   for (auto *N = New; N; N = N->NextSibling) {
109706b4fc4SDimitry Andric     assert(N->Parent == nullptr);
110b60736ecSDimitry Andric     assert(N->getRole() != NodeRole::Detached && "Roles must be set");
111846a2208SDimitry Andric     // FIXME: validate the role.
112706b4fc4SDimitry Andric   }
113b60736ecSDimitry Andric 
114b60736ecSDimitry Andric   auto Reachable = [](Node *From, Node *N) {
115b60736ecSDimitry Andric     if (!N)
116b60736ecSDimitry Andric       return true;
117b60736ecSDimitry Andric     for (auto *It = From; It; It = It->NextSibling)
118b60736ecSDimitry Andric       if (It == N)
119b60736ecSDimitry Andric         return true;
120b60736ecSDimitry Andric     return false;
121b60736ecSDimitry Andric   };
122b60736ecSDimitry Andric   assert(Reachable(FirstChild, Begin) && "`Begin` is not reachable.");
123b60736ecSDimitry Andric   assert(Reachable(Begin, End) && "`End` is not after `Begin`.");
124706b4fc4SDimitry Andric #endif
125706b4fc4SDimitry Andric 
126b60736ecSDimitry Andric   if (!New && Begin == End)
127b60736ecSDimitry Andric     return;
128b60736ecSDimitry Andric 
129b60736ecSDimitry Andric   // Mark modification.
130b60736ecSDimitry Andric   for (auto *T = this; T && T->Original; T = T->Parent)
131b60736ecSDimitry Andric     T->Original = false;
132b60736ecSDimitry Andric 
133b60736ecSDimitry Andric   // Save the node before the range to be removed. Later we insert the `New`
134b60736ecSDimitry Andric   // range after this node.
135b60736ecSDimitry Andric   auto *BeforeBegin = Begin ? Begin->PreviousSibling : LastChild;
136b60736ecSDimitry Andric 
137706b4fc4SDimitry Andric   // Detach old nodes.
138b60736ecSDimitry Andric   for (auto *N = Begin; N != End;) {
139706b4fc4SDimitry Andric     auto *Next = N->NextSibling;
140706b4fc4SDimitry Andric 
141cfca06d7SDimitry Andric     N->setRole(NodeRole::Detached);
142706b4fc4SDimitry Andric     N->Parent = nullptr;
143706b4fc4SDimitry Andric     N->NextSibling = nullptr;
144b60736ecSDimitry Andric     N->PreviousSibling = nullptr;
145706b4fc4SDimitry Andric     if (N->Original)
146b60736ecSDimitry Andric       traverse(N, [](Node *C) { C->Original = false; });
147706b4fc4SDimitry Andric 
148706b4fc4SDimitry Andric     N = Next;
149706b4fc4SDimitry Andric   }
150706b4fc4SDimitry Andric 
151b60736ecSDimitry Andric   // Attach new range.
152b60736ecSDimitry Andric   auto *&NewFirst = BeforeBegin ? BeforeBegin->NextSibling : FirstChild;
153b60736ecSDimitry Andric   auto *&NewLast = End ? End->PreviousSibling : LastChild;
154706b4fc4SDimitry Andric 
155b60736ecSDimitry Andric   if (!New) {
156b60736ecSDimitry Andric     NewFirst = End;
157b60736ecSDimitry Andric     NewLast = BeforeBegin;
158b60736ecSDimitry Andric     return;
159b60736ecSDimitry Andric   }
160b60736ecSDimitry Andric 
161b60736ecSDimitry Andric   New->PreviousSibling = BeforeBegin;
162b60736ecSDimitry Andric   NewFirst = New;
163b60736ecSDimitry Andric 
164b60736ecSDimitry Andric   Node *LastInNew;
165b60736ecSDimitry Andric   for (auto *N = New; N != nullptr; N = N->NextSibling) {
166b60736ecSDimitry Andric     LastInNew = N;
167706b4fc4SDimitry Andric     N->Parent = this;
168706b4fc4SDimitry Andric   }
169b60736ecSDimitry Andric   LastInNew->NextSibling = End;
170b60736ecSDimitry Andric   NewLast = LastInNew;
171706b4fc4SDimitry Andric }
172706b4fc4SDimitry Andric 
17322989816SDimitry Andric namespace {
dumpNode(raw_ostream & OS,const syntax::Node * N,const syntax::TokenManager & TM,llvm::BitVector IndentMask)174b60736ecSDimitry Andric static void dumpNode(raw_ostream &OS, const syntax::Node *N,
1754b4fe385SDimitry Andric                      const syntax::TokenManager &TM, llvm::BitVector IndentMask) {
176b60736ecSDimitry Andric   auto DumpExtraInfo = [&OS](const syntax::Node *N) {
177b60736ecSDimitry Andric     if (N->getRole() != syntax::NodeRole::Unknown)
178b60736ecSDimitry Andric       OS << " " << N->getRole();
179706b4fc4SDimitry Andric     if (!N->isOriginal())
180b60736ecSDimitry Andric       OS << " synthesized";
181706b4fc4SDimitry Andric     if (!N->canModify())
182b60736ecSDimitry Andric       OS << " unmodifiable";
183b60736ecSDimitry Andric   };
184706b4fc4SDimitry Andric 
185b60736ecSDimitry Andric   assert(N);
186b60736ecSDimitry Andric   if (const auto *L = dyn_cast<syntax::Leaf>(N)) {
187b60736ecSDimitry Andric     OS << "'";
1884b4fe385SDimitry Andric     OS << TM.getText(L->getTokenKey());
189b60736ecSDimitry Andric     OS << "'";
190b60736ecSDimitry Andric     DumpExtraInfo(N);
19122989816SDimitry Andric     OS << "\n";
19222989816SDimitry Andric     return;
19322989816SDimitry Andric   }
19422989816SDimitry Andric 
195b60736ecSDimitry Andric   const auto *T = cast<syntax::Tree>(N);
196b60736ecSDimitry Andric   OS << T->getKind();
197b60736ecSDimitry Andric   DumpExtraInfo(N);
198b60736ecSDimitry Andric   OS << "\n";
19922989816SDimitry Andric 
200b60736ecSDimitry Andric   for (const syntax::Node &It : T->getChildren()) {
2016f8fc217SDimitry Andric     for (unsigned Idx = 0; Idx < IndentMask.size(); ++Idx) {
2026f8fc217SDimitry Andric       if (IndentMask[Idx])
20322989816SDimitry Andric         OS << "| ";
20422989816SDimitry Andric       else
20522989816SDimitry Andric         OS << "  ";
20622989816SDimitry Andric     }
207b60736ecSDimitry Andric     if (!It.getNextSibling()) {
20822989816SDimitry Andric       OS << "`-";
20922989816SDimitry Andric       IndentMask.push_back(false);
21022989816SDimitry Andric     } else {
21122989816SDimitry Andric       OS << "|-";
21222989816SDimitry Andric       IndentMask.push_back(true);
21322989816SDimitry Andric     }
2144b4fe385SDimitry Andric     dumpNode(OS, &It, TM, IndentMask);
21522989816SDimitry Andric     IndentMask.pop_back();
21622989816SDimitry Andric   }
21722989816SDimitry Andric }
21822989816SDimitry Andric } // namespace
21922989816SDimitry Andric 
dump(const TokenManager & TM) const2204b4fe385SDimitry Andric std::string syntax::Node::dump(const TokenManager &TM) const {
22122989816SDimitry Andric   std::string Str;
22222989816SDimitry Andric   llvm::raw_string_ostream OS(Str);
2234b4fe385SDimitry Andric   dumpNode(OS, this, TM, /*IndentMask=*/{});
22422989816SDimitry Andric   return std::move(OS.str());
22522989816SDimitry Andric }
22622989816SDimitry Andric 
dumpTokens(const TokenManager & TM) const2274b4fe385SDimitry Andric std::string syntax::Node::dumpTokens(const TokenManager &TM) const {
22822989816SDimitry Andric   std::string Storage;
22922989816SDimitry Andric   llvm::raw_string_ostream OS(Storage);
23022989816SDimitry Andric   traverse(this, [&](const syntax::Node *N) {
231b60736ecSDimitry Andric     if (const auto *L = dyn_cast<syntax::Leaf>(N)) {
2324b4fe385SDimitry Andric       OS << TM.getText(L->getTokenKey());
233706b4fc4SDimitry Andric       OS << " ";
234b60736ecSDimitry Andric     }
23522989816SDimitry Andric   });
23677fc4c14SDimitry Andric   return Storage;
23722989816SDimitry Andric }
23822989816SDimitry Andric 
assertInvariants() const239706b4fc4SDimitry Andric void syntax::Node::assertInvariants() const {
240706b4fc4SDimitry Andric #ifndef NDEBUG
241706b4fc4SDimitry Andric   if (isDetached())
242b60736ecSDimitry Andric     assert(getParent() == nullptr);
243706b4fc4SDimitry Andric   else
244b60736ecSDimitry Andric     assert(getParent() != nullptr);
245706b4fc4SDimitry Andric 
246b60736ecSDimitry Andric   const auto *T = dyn_cast<Tree>(this);
247706b4fc4SDimitry Andric   if (!T)
248706b4fc4SDimitry Andric     return;
249b60736ecSDimitry Andric   for (const Node &C : T->getChildren()) {
250706b4fc4SDimitry Andric     if (T->isOriginal())
251b60736ecSDimitry Andric       assert(C.isOriginal());
252b60736ecSDimitry Andric     assert(!C.isDetached());
253b60736ecSDimitry Andric     assert(C.getParent() == T);
254b60736ecSDimitry Andric     const auto *Next = C.getNextSibling();
255b60736ecSDimitry Andric     assert(!Next || &C == Next->getPreviousSibling());
256b60736ecSDimitry Andric     if (!C.getNextSibling())
257b60736ecSDimitry Andric       assert(&C == T->getLastChild() &&
258b60736ecSDimitry Andric              "Last child is reachable by advancing from the first child.");
259706b4fc4SDimitry Andric   }
260b60736ecSDimitry Andric 
261b60736ecSDimitry Andric   const auto *L = dyn_cast<List>(T);
262b60736ecSDimitry Andric   if (!L)
263b60736ecSDimitry Andric     return;
264b60736ecSDimitry Andric   for (const Node &C : T->getChildren()) {
265b60736ecSDimitry Andric     assert(C.getRole() == NodeRole::ListElement ||
266b60736ecSDimitry Andric            C.getRole() == NodeRole::ListDelimiter);
267b60736ecSDimitry Andric     if (C.getRole() == NodeRole::ListDelimiter) {
268b60736ecSDimitry Andric       assert(isa<Leaf>(C));
2694b4fe385SDimitry Andric       // FIXME: re-enable it when there is way to retrieve token kind in Leaf.
2704b4fe385SDimitry Andric       // assert(cast<Leaf>(C).getToken()->kind() == L->getDelimiterTokenKind());
271b60736ecSDimitry Andric     }
272b60736ecSDimitry Andric   }
273b60736ecSDimitry Andric 
274706b4fc4SDimitry Andric #endif
275706b4fc4SDimitry Andric }
276706b4fc4SDimitry Andric 
assertInvariantsRecursive() const277706b4fc4SDimitry Andric void syntax::Node::assertInvariantsRecursive() const {
278706b4fc4SDimitry Andric #ifndef NDEBUG
279706b4fc4SDimitry Andric   traverse(this, [&](const syntax::Node *N) { N->assertInvariants(); });
280706b4fc4SDimitry Andric #endif
281706b4fc4SDimitry Andric }
282706b4fc4SDimitry Andric 
findFirstLeaf() const283b60736ecSDimitry Andric const syntax::Leaf *syntax::Tree::findFirstLeaf() const {
284b60736ecSDimitry Andric   for (const Node &C : getChildren()) {
285b60736ecSDimitry Andric     if (const auto *L = dyn_cast<syntax::Leaf>(&C))
286706b4fc4SDimitry Andric       return L;
287b60736ecSDimitry Andric     if (const auto *L = cast<syntax::Tree>(C).findFirstLeaf())
288706b4fc4SDimitry Andric       return L;
289706b4fc4SDimitry Andric   }
290706b4fc4SDimitry Andric   return nullptr;
291706b4fc4SDimitry Andric }
292706b4fc4SDimitry Andric 
findLastLeaf() const293b60736ecSDimitry Andric const syntax::Leaf *syntax::Tree::findLastLeaf() const {
294b60736ecSDimitry Andric   for (const auto *C = getLastChild(); C; C = C->getPreviousSibling()) {
295b60736ecSDimitry Andric     if (const auto *L = dyn_cast<syntax::Leaf>(C))
296b60736ecSDimitry Andric       return L;
297b60736ecSDimitry Andric     if (const auto *L = cast<syntax::Tree>(C)->findLastLeaf())
298b60736ecSDimitry Andric       return L;
29922989816SDimitry Andric   }
30022989816SDimitry Andric   return nullptr;
30122989816SDimitry Andric }
302b60736ecSDimitry Andric 
findChild(NodeRole R) const303b60736ecSDimitry Andric const syntax::Node *syntax::Tree::findChild(NodeRole R) const {
304b60736ecSDimitry Andric   for (const Node &C : getChildren()) {
305b60736ecSDimitry Andric     if (C.getRole() == R)
306b60736ecSDimitry Andric       return &C;
307b60736ecSDimitry Andric   }
308b60736ecSDimitry Andric   return nullptr;
309b60736ecSDimitry Andric }
310b60736ecSDimitry Andric 
311b60736ecSDimitry Andric std::vector<syntax::List::ElementAndDelimiter<syntax::Node>>
getElementsAsNodesAndDelimiters()312b60736ecSDimitry Andric syntax::List::getElementsAsNodesAndDelimiters() {
313b60736ecSDimitry Andric   if (!getFirstChild())
314b60736ecSDimitry Andric     return {};
315b60736ecSDimitry Andric 
316b60736ecSDimitry Andric   std::vector<syntax::List::ElementAndDelimiter<Node>> Children;
317b60736ecSDimitry Andric   syntax::Node *ElementWithoutDelimiter = nullptr;
318b60736ecSDimitry Andric   for (Node &C : getChildren()) {
319b60736ecSDimitry Andric     switch (C.getRole()) {
320b60736ecSDimitry Andric     case syntax::NodeRole::ListElement: {
321b60736ecSDimitry Andric       if (ElementWithoutDelimiter) {
322b60736ecSDimitry Andric         Children.push_back({ElementWithoutDelimiter, nullptr});
323b60736ecSDimitry Andric       }
324b60736ecSDimitry Andric       ElementWithoutDelimiter = &C;
325b60736ecSDimitry Andric       break;
326b60736ecSDimitry Andric     }
327b60736ecSDimitry Andric     case syntax::NodeRole::ListDelimiter: {
328b60736ecSDimitry Andric       Children.push_back({ElementWithoutDelimiter, cast<syntax::Leaf>(&C)});
329b60736ecSDimitry Andric       ElementWithoutDelimiter = nullptr;
330b60736ecSDimitry Andric       break;
331b60736ecSDimitry Andric     }
332b60736ecSDimitry Andric     default:
333b60736ecSDimitry Andric       llvm_unreachable(
334b60736ecSDimitry Andric           "A list can have only elements and delimiters as children.");
335b60736ecSDimitry Andric     }
336b60736ecSDimitry Andric   }
337b60736ecSDimitry Andric 
338b60736ecSDimitry Andric   switch (getTerminationKind()) {
339b60736ecSDimitry Andric   case syntax::List::TerminationKind::Separated: {
340b60736ecSDimitry Andric     Children.push_back({ElementWithoutDelimiter, nullptr});
341b60736ecSDimitry Andric     break;
342b60736ecSDimitry Andric   }
343b60736ecSDimitry Andric   case syntax::List::TerminationKind::Terminated:
344b60736ecSDimitry Andric   case syntax::List::TerminationKind::MaybeTerminated: {
345b60736ecSDimitry Andric     if (ElementWithoutDelimiter) {
346b60736ecSDimitry Andric       Children.push_back({ElementWithoutDelimiter, nullptr});
347b60736ecSDimitry Andric     }
348b60736ecSDimitry Andric     break;
349b60736ecSDimitry Andric   }
350b60736ecSDimitry Andric   }
351b60736ecSDimitry Andric 
352b60736ecSDimitry Andric   return Children;
353b60736ecSDimitry Andric }
354b60736ecSDimitry Andric 
355b60736ecSDimitry Andric // Almost the same implementation of `getElementsAsNodesAndDelimiters` but
356b60736ecSDimitry Andric // ignoring delimiters
getElementsAsNodes()357b60736ecSDimitry Andric std::vector<syntax::Node *> syntax::List::getElementsAsNodes() {
358b60736ecSDimitry Andric   if (!getFirstChild())
359b60736ecSDimitry Andric     return {};
360b60736ecSDimitry Andric 
361b60736ecSDimitry Andric   std::vector<syntax::Node *> Children;
362b60736ecSDimitry Andric   syntax::Node *ElementWithoutDelimiter = nullptr;
363b60736ecSDimitry Andric   for (Node &C : getChildren()) {
364b60736ecSDimitry Andric     switch (C.getRole()) {
365b60736ecSDimitry Andric     case syntax::NodeRole::ListElement: {
366b60736ecSDimitry Andric       if (ElementWithoutDelimiter) {
367b60736ecSDimitry Andric         Children.push_back(ElementWithoutDelimiter);
368b60736ecSDimitry Andric       }
369b60736ecSDimitry Andric       ElementWithoutDelimiter = &C;
370b60736ecSDimitry Andric       break;
371b60736ecSDimitry Andric     }
372b60736ecSDimitry Andric     case syntax::NodeRole::ListDelimiter: {
373b60736ecSDimitry Andric       Children.push_back(ElementWithoutDelimiter);
374b60736ecSDimitry Andric       ElementWithoutDelimiter = nullptr;
375b60736ecSDimitry Andric       break;
376b60736ecSDimitry Andric     }
377b60736ecSDimitry Andric     default:
378b60736ecSDimitry Andric       llvm_unreachable("A list has only elements or delimiters.");
379b60736ecSDimitry Andric     }
380b60736ecSDimitry Andric   }
381b60736ecSDimitry Andric 
382b60736ecSDimitry Andric   switch (getTerminationKind()) {
383b60736ecSDimitry Andric   case syntax::List::TerminationKind::Separated: {
384b60736ecSDimitry Andric     Children.push_back(ElementWithoutDelimiter);
385b60736ecSDimitry Andric     break;
386b60736ecSDimitry Andric   }
387b60736ecSDimitry Andric   case syntax::List::TerminationKind::Terminated:
388b60736ecSDimitry Andric   case syntax::List::TerminationKind::MaybeTerminated: {
389b60736ecSDimitry Andric     if (ElementWithoutDelimiter) {
390b60736ecSDimitry Andric       Children.push_back(ElementWithoutDelimiter);
391b60736ecSDimitry Andric     }
392b60736ecSDimitry Andric     break;
393b60736ecSDimitry Andric   }
394b60736ecSDimitry Andric   }
395b60736ecSDimitry Andric 
396b60736ecSDimitry Andric   return Children;
397b60736ecSDimitry Andric }
398b60736ecSDimitry Andric 
getDelimiterTokenKind() const399b60736ecSDimitry Andric clang::tok::TokenKind syntax::List::getDelimiterTokenKind() const {
400b60736ecSDimitry Andric   switch (this->getKind()) {
401b60736ecSDimitry Andric   case NodeKind::NestedNameSpecifier:
402b60736ecSDimitry Andric     return clang::tok::coloncolon;
403b60736ecSDimitry Andric   case NodeKind::CallArguments:
404b60736ecSDimitry Andric   case NodeKind::ParameterDeclarationList:
405b60736ecSDimitry Andric   case NodeKind::DeclaratorList:
406b60736ecSDimitry Andric     return clang::tok::comma;
407b60736ecSDimitry Andric   default:
408b60736ecSDimitry Andric     llvm_unreachable("This is not a subclass of List, thus "
409b60736ecSDimitry Andric                      "getDelimiterTokenKind() cannot be called");
410b60736ecSDimitry Andric   }
411b60736ecSDimitry Andric }
412b60736ecSDimitry Andric 
getTerminationKind() const413b60736ecSDimitry Andric syntax::List::TerminationKind syntax::List::getTerminationKind() const {
414b60736ecSDimitry Andric   switch (this->getKind()) {
415b60736ecSDimitry Andric   case NodeKind::NestedNameSpecifier:
416b60736ecSDimitry Andric     return TerminationKind::Terminated;
417b60736ecSDimitry Andric   case NodeKind::CallArguments:
418b60736ecSDimitry Andric   case NodeKind::ParameterDeclarationList:
419b60736ecSDimitry Andric   case NodeKind::DeclaratorList:
420b60736ecSDimitry Andric     return TerminationKind::Separated;
421b60736ecSDimitry Andric   default:
422b60736ecSDimitry Andric     llvm_unreachable("This is not a subclass of List, thus "
423b60736ecSDimitry Andric                      "getTerminationKind() cannot be called");
424b60736ecSDimitry Andric   }
425b60736ecSDimitry Andric }
426b60736ecSDimitry Andric 
canBeEmpty() const427b60736ecSDimitry Andric bool syntax::List::canBeEmpty() const {
428b60736ecSDimitry Andric   switch (this->getKind()) {
429b60736ecSDimitry Andric   case NodeKind::NestedNameSpecifier:
430b60736ecSDimitry Andric     return false;
431b60736ecSDimitry Andric   case NodeKind::CallArguments:
432b60736ecSDimitry Andric     return true;
433b60736ecSDimitry Andric   case NodeKind::ParameterDeclarationList:
434b60736ecSDimitry Andric     return true;
435b60736ecSDimitry Andric   case NodeKind::DeclaratorList:
436b60736ecSDimitry Andric     return true;
437b60736ecSDimitry Andric   default:
438b60736ecSDimitry Andric     llvm_unreachable("This is not a subclass of List, thus canBeEmpty() "
439b60736ecSDimitry Andric                      "cannot be called");
440b60736ecSDimitry Andric   }
441b60736ecSDimitry Andric }
442