xref: /openbsd-src/gnu/llvm/clang/lib/Tooling/Syntax/Tree.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===- Tree.cpp -----------------------------------------------*- C++ -*-=====//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick #include "clang/Tooling/Syntax/Tree.h"
9e5dd7070Spatrick #include "clang/Basic/TokenKinds.h"
10e5dd7070Spatrick #include "clang/Tooling/Syntax/Nodes.h"
11*12c85518Srobert #include "llvm/ADT/BitVector.h"
12*12c85518Srobert #include "llvm/Support/raw_ostream.h"
13e5dd7070Spatrick #include "llvm/Support/Casting.h"
14e5dd7070Spatrick #include <cassert>
15e5dd7070Spatrick 
16e5dd7070Spatrick using namespace clang;
17e5dd7070Spatrick 
18e5dd7070Spatrick namespace {
traverse(const syntax::Node * N,llvm::function_ref<void (const syntax::Node *)> Visit)19e5dd7070Spatrick static void traverse(const syntax::Node *N,
20e5dd7070Spatrick                      llvm::function_ref<void(const syntax::Node *)> Visit) {
21e5dd7070Spatrick   if (auto *T = dyn_cast<syntax::Tree>(N)) {
22a9ac8606Spatrick     for (const syntax::Node &C : T->getChildren())
23a9ac8606Spatrick       traverse(&C, Visit);
24e5dd7070Spatrick   }
25e5dd7070Spatrick   Visit(N);
26e5dd7070Spatrick }
traverse(syntax::Node * N,llvm::function_ref<void (syntax::Node *)> Visit)27e5dd7070Spatrick static void traverse(syntax::Node *N,
28e5dd7070Spatrick                      llvm::function_ref<void(syntax::Node *)> Visit) {
29e5dd7070Spatrick   traverse(static_cast<const syntax::Node *>(N), [&](const syntax::Node *N) {
30e5dd7070Spatrick     Visit(const_cast<syntax::Node *>(N));
31e5dd7070Spatrick   });
32e5dd7070Spatrick }
33e5dd7070Spatrick } // namespace
34e5dd7070Spatrick 
Leaf(syntax::TokenManager::Key K)35*12c85518Srobert syntax::Leaf::Leaf(syntax::TokenManager::Key K) : Node(NodeKind::Leaf), K(K) {}
36e5dd7070Spatrick 
Node(NodeKind Kind)37e5dd7070Spatrick syntax::Node::Node(NodeKind Kind)
38a9ac8606Spatrick     : Parent(nullptr), NextSibling(nullptr), PreviousSibling(nullptr),
39a9ac8606Spatrick       Kind(static_cast<unsigned>(Kind)), Role(0), Original(false),
40a9ac8606Spatrick       CanModify(false) {
41ec727ea7Spatrick   this->setRole(NodeRole::Detached);
42ec727ea7Spatrick }
43e5dd7070Spatrick 
isDetached() const44a9ac8606Spatrick bool syntax::Node::isDetached() const {
45a9ac8606Spatrick   return getRole() == NodeRole::Detached;
46a9ac8606Spatrick }
47e5dd7070Spatrick 
setRole(NodeRole NR)48ec727ea7Spatrick void syntax::Node::setRole(NodeRole NR) {
49ec727ea7Spatrick   this->Role = static_cast<unsigned>(NR);
50ec727ea7Spatrick }
51ec727ea7Spatrick 
appendChildLowLevel(Node * Child,NodeRole Role)52a9ac8606Spatrick void syntax::Tree::appendChildLowLevel(Node *Child, NodeRole Role) {
53a9ac8606Spatrick   assert(Child->getRole() == NodeRole::Detached);
54a9ac8606Spatrick   assert(Role != NodeRole::Detached);
55a9ac8606Spatrick 
56a9ac8606Spatrick   Child->setRole(Role);
57a9ac8606Spatrick   appendChildLowLevel(Child);
58a9ac8606Spatrick }
59a9ac8606Spatrick 
appendChildLowLevel(Node * Child)60a9ac8606Spatrick void syntax::Tree::appendChildLowLevel(Node *Child) {
61a9ac8606Spatrick   assert(Child->Parent == nullptr);
62a9ac8606Spatrick   assert(Child->NextSibling == nullptr);
63a9ac8606Spatrick   assert(Child->PreviousSibling == nullptr);
64a9ac8606Spatrick   assert(Child->getRole() != NodeRole::Detached);
65a9ac8606Spatrick 
66a9ac8606Spatrick   Child->Parent = this;
67a9ac8606Spatrick   if (this->LastChild) {
68a9ac8606Spatrick     Child->PreviousSibling = this->LastChild;
69a9ac8606Spatrick     this->LastChild->NextSibling = Child;
70a9ac8606Spatrick   } else
71a9ac8606Spatrick     this->FirstChild = Child;
72a9ac8606Spatrick 
73a9ac8606Spatrick   this->LastChild = Child;
74a9ac8606Spatrick }
75e5dd7070Spatrick 
prependChildLowLevel(Node * Child,NodeRole Role)76e5dd7070Spatrick void syntax::Tree::prependChildLowLevel(Node *Child, NodeRole Role) {
77a9ac8606Spatrick   assert(Child->getRole() == NodeRole::Detached);
78e5dd7070Spatrick   assert(Role != NodeRole::Detached);
79e5dd7070Spatrick 
80ec727ea7Spatrick   Child->setRole(Role);
81ec727ea7Spatrick   prependChildLowLevel(Child);
82ec727ea7Spatrick }
83ec727ea7Spatrick 
prependChildLowLevel(Node * Child)84ec727ea7Spatrick void syntax::Tree::prependChildLowLevel(Node *Child) {
85ec727ea7Spatrick   assert(Child->Parent == nullptr);
86ec727ea7Spatrick   assert(Child->NextSibling == nullptr);
87a9ac8606Spatrick   assert(Child->PreviousSibling == nullptr);
88a9ac8606Spatrick   assert(Child->getRole() != NodeRole::Detached);
89ec727ea7Spatrick 
90e5dd7070Spatrick   Child->Parent = this;
91a9ac8606Spatrick   if (this->FirstChild) {
92e5dd7070Spatrick     Child->NextSibling = this->FirstChild;
93a9ac8606Spatrick     this->FirstChild->PreviousSibling = Child;
94a9ac8606Spatrick   } else
95a9ac8606Spatrick     this->LastChild = Child;
96a9ac8606Spatrick 
97e5dd7070Spatrick   this->FirstChild = Child;
98e5dd7070Spatrick }
99e5dd7070Spatrick 
replaceChildRangeLowLevel(Node * Begin,Node * End,Node * New)100a9ac8606Spatrick void syntax::Tree::replaceChildRangeLowLevel(Node *Begin, Node *End,
101e5dd7070Spatrick                                              Node *New) {
102a9ac8606Spatrick   assert((!Begin || Begin->Parent == this) &&
103a9ac8606Spatrick          "`Begin` is not a child of `this`.");
104a9ac8606Spatrick   assert((!End || End->Parent == this) && "`End` is not a child of `this`.");
105a9ac8606Spatrick   assert(canModify() && "Cannot modify `this`.");
106e5dd7070Spatrick 
107e5dd7070Spatrick #ifndef NDEBUG
108a9ac8606Spatrick   for (auto *N = New; N; N = N->NextSibling) {
109e5dd7070Spatrick     assert(N->Parent == nullptr);
110a9ac8606Spatrick     assert(N->getRole() != NodeRole::Detached && "Roles must be set");
111*12c85518Srobert     // FIXME: validate the role.
112e5dd7070Spatrick   }
113a9ac8606Spatrick 
114a9ac8606Spatrick   auto Reachable = [](Node *From, Node *N) {
115a9ac8606Spatrick     if (!N)
116a9ac8606Spatrick       return true;
117a9ac8606Spatrick     for (auto *It = From; It; It = It->NextSibling)
118a9ac8606Spatrick       if (It == N)
119a9ac8606Spatrick         return true;
120a9ac8606Spatrick     return false;
121a9ac8606Spatrick   };
122a9ac8606Spatrick   assert(Reachable(FirstChild, Begin) && "`Begin` is not reachable.");
123a9ac8606Spatrick   assert(Reachable(Begin, End) && "`End` is not after `Begin`.");
124e5dd7070Spatrick #endif
125e5dd7070Spatrick 
126a9ac8606Spatrick   if (!New && Begin == End)
127a9ac8606Spatrick     return;
128a9ac8606Spatrick 
129a9ac8606Spatrick   // Mark modification.
130a9ac8606Spatrick   for (auto *T = this; T && T->Original; T = T->Parent)
131a9ac8606Spatrick     T->Original = false;
132a9ac8606Spatrick 
133a9ac8606Spatrick   // Save the node before the range to be removed. Later we insert the `New`
134a9ac8606Spatrick   // range after this node.
135a9ac8606Spatrick   auto *BeforeBegin = Begin ? Begin->PreviousSibling : LastChild;
136a9ac8606Spatrick 
137e5dd7070Spatrick   // Detach old nodes.
138a9ac8606Spatrick   for (auto *N = Begin; N != End;) {
139e5dd7070Spatrick     auto *Next = N->NextSibling;
140e5dd7070Spatrick 
141ec727ea7Spatrick     N->setRole(NodeRole::Detached);
142e5dd7070Spatrick     N->Parent = nullptr;
143e5dd7070Spatrick     N->NextSibling = nullptr;
144a9ac8606Spatrick     N->PreviousSibling = nullptr;
145e5dd7070Spatrick     if (N->Original)
146a9ac8606Spatrick       traverse(N, [](Node *C) { C->Original = false; });
147e5dd7070Spatrick 
148e5dd7070Spatrick     N = Next;
149e5dd7070Spatrick   }
150e5dd7070Spatrick 
151a9ac8606Spatrick   // Attach new range.
152a9ac8606Spatrick   auto *&NewFirst = BeforeBegin ? BeforeBegin->NextSibling : FirstChild;
153a9ac8606Spatrick   auto *&NewLast = End ? End->PreviousSibling : LastChild;
154e5dd7070Spatrick 
155a9ac8606Spatrick   if (!New) {
156a9ac8606Spatrick     NewFirst = End;
157a9ac8606Spatrick     NewLast = BeforeBegin;
158a9ac8606Spatrick     return;
159a9ac8606Spatrick   }
160a9ac8606Spatrick 
161a9ac8606Spatrick   New->PreviousSibling = BeforeBegin;
162a9ac8606Spatrick   NewFirst = New;
163a9ac8606Spatrick 
164a9ac8606Spatrick   Node *LastInNew;
165a9ac8606Spatrick   for (auto *N = New; N != nullptr; N = N->NextSibling) {
166a9ac8606Spatrick     LastInNew = N;
167e5dd7070Spatrick     N->Parent = this;
168e5dd7070Spatrick   }
169a9ac8606Spatrick   LastInNew->NextSibling = End;
170a9ac8606Spatrick   NewLast = LastInNew;
171e5dd7070Spatrick }
172e5dd7070Spatrick 
173e5dd7070Spatrick namespace {
dumpNode(raw_ostream & OS,const syntax::Node * N,const syntax::TokenManager & TM,llvm::BitVector IndentMask)174a9ac8606Spatrick static void dumpNode(raw_ostream &OS, const syntax::Node *N,
175*12c85518Srobert                      const syntax::TokenManager &TM, llvm::BitVector IndentMask) {
176a9ac8606Spatrick   auto DumpExtraInfo = [&OS](const syntax::Node *N) {
177a9ac8606Spatrick     if (N->getRole() != syntax::NodeRole::Unknown)
178a9ac8606Spatrick       OS << " " << N->getRole();
179e5dd7070Spatrick     if (!N->isOriginal())
180a9ac8606Spatrick       OS << " synthesized";
181e5dd7070Spatrick     if (!N->canModify())
182a9ac8606Spatrick       OS << " unmodifiable";
183a9ac8606Spatrick   };
184e5dd7070Spatrick 
185a9ac8606Spatrick   assert(N);
186a9ac8606Spatrick   if (const auto *L = dyn_cast<syntax::Leaf>(N)) {
187a9ac8606Spatrick     OS << "'";
188*12c85518Srobert     OS << TM.getText(L->getTokenKey());
189a9ac8606Spatrick     OS << "'";
190a9ac8606Spatrick     DumpExtraInfo(N);
191e5dd7070Spatrick     OS << "\n";
192e5dd7070Spatrick     return;
193e5dd7070Spatrick   }
194e5dd7070Spatrick 
195a9ac8606Spatrick   const auto *T = cast<syntax::Tree>(N);
196a9ac8606Spatrick   OS << T->getKind();
197a9ac8606Spatrick   DumpExtraInfo(N);
198a9ac8606Spatrick   OS << "\n";
199e5dd7070Spatrick 
200a9ac8606Spatrick   for (const syntax::Node &It : T->getChildren()) {
201*12c85518Srobert     for (unsigned Idx = 0; Idx < IndentMask.size(); ++Idx) {
202*12c85518Srobert       if (IndentMask[Idx])
203e5dd7070Spatrick         OS << "| ";
204e5dd7070Spatrick       else
205e5dd7070Spatrick         OS << "  ";
206e5dd7070Spatrick     }
207a9ac8606Spatrick     if (!It.getNextSibling()) {
208e5dd7070Spatrick       OS << "`-";
209e5dd7070Spatrick       IndentMask.push_back(false);
210e5dd7070Spatrick     } else {
211e5dd7070Spatrick       OS << "|-";
212e5dd7070Spatrick       IndentMask.push_back(true);
213e5dd7070Spatrick     }
214*12c85518Srobert     dumpNode(OS, &It, TM, IndentMask);
215e5dd7070Spatrick     IndentMask.pop_back();
216e5dd7070Spatrick   }
217e5dd7070Spatrick }
218e5dd7070Spatrick } // namespace
219e5dd7070Spatrick 
dump(const TokenManager & TM) const220*12c85518Srobert std::string syntax::Node::dump(const TokenManager &TM) const {
221e5dd7070Spatrick   std::string Str;
222e5dd7070Spatrick   llvm::raw_string_ostream OS(Str);
223*12c85518Srobert   dumpNode(OS, this, TM, /*IndentMask=*/{});
224e5dd7070Spatrick   return std::move(OS.str());
225e5dd7070Spatrick }
226e5dd7070Spatrick 
dumpTokens(const TokenManager & TM) const227*12c85518Srobert std::string syntax::Node::dumpTokens(const TokenManager &TM) const {
228e5dd7070Spatrick   std::string Storage;
229e5dd7070Spatrick   llvm::raw_string_ostream OS(Storage);
230e5dd7070Spatrick   traverse(this, [&](const syntax::Node *N) {
231a9ac8606Spatrick     if (const auto *L = dyn_cast<syntax::Leaf>(N)) {
232*12c85518Srobert       OS << TM.getText(L->getTokenKey());
233e5dd7070Spatrick       OS << " ";
234a9ac8606Spatrick     }
235e5dd7070Spatrick   });
236*12c85518Srobert   return Storage;
237e5dd7070Spatrick }
238e5dd7070Spatrick 
assertInvariants() const239e5dd7070Spatrick void syntax::Node::assertInvariants() const {
240e5dd7070Spatrick #ifndef NDEBUG
241e5dd7070Spatrick   if (isDetached())
242a9ac8606Spatrick     assert(getParent() == nullptr);
243e5dd7070Spatrick   else
244a9ac8606Spatrick     assert(getParent() != nullptr);
245e5dd7070Spatrick 
246a9ac8606Spatrick   const auto *T = dyn_cast<Tree>(this);
247e5dd7070Spatrick   if (!T)
248e5dd7070Spatrick     return;
249a9ac8606Spatrick   for (const Node &C : T->getChildren()) {
250e5dd7070Spatrick     if (T->isOriginal())
251a9ac8606Spatrick       assert(C.isOriginal());
252a9ac8606Spatrick     assert(!C.isDetached());
253a9ac8606Spatrick     assert(C.getParent() == T);
254a9ac8606Spatrick     const auto *Next = C.getNextSibling();
255a9ac8606Spatrick     assert(!Next || &C == Next->getPreviousSibling());
256a9ac8606Spatrick     if (!C.getNextSibling())
257a9ac8606Spatrick       assert(&C == T->getLastChild() &&
258a9ac8606Spatrick              "Last child is reachable by advancing from the first child.");
259e5dd7070Spatrick   }
260a9ac8606Spatrick 
261a9ac8606Spatrick   const auto *L = dyn_cast<List>(T);
262a9ac8606Spatrick   if (!L)
263a9ac8606Spatrick     return;
264a9ac8606Spatrick   for (const Node &C : T->getChildren()) {
265a9ac8606Spatrick     assert(C.getRole() == NodeRole::ListElement ||
266a9ac8606Spatrick            C.getRole() == NodeRole::ListDelimiter);
267a9ac8606Spatrick     if (C.getRole() == NodeRole::ListDelimiter) {
268a9ac8606Spatrick       assert(isa<Leaf>(C));
269*12c85518Srobert       // FIXME: re-enable it when there is way to retrieve token kind in Leaf.
270*12c85518Srobert       // assert(cast<Leaf>(C).getToken()->kind() == L->getDelimiterTokenKind());
271a9ac8606Spatrick     }
272a9ac8606Spatrick   }
273a9ac8606Spatrick 
274e5dd7070Spatrick #endif
275e5dd7070Spatrick }
276e5dd7070Spatrick 
assertInvariantsRecursive() const277e5dd7070Spatrick void syntax::Node::assertInvariantsRecursive() const {
278e5dd7070Spatrick #ifndef NDEBUG
279e5dd7070Spatrick   traverse(this, [&](const syntax::Node *N) { N->assertInvariants(); });
280e5dd7070Spatrick #endif
281e5dd7070Spatrick }
282e5dd7070Spatrick 
findFirstLeaf() const283a9ac8606Spatrick const syntax::Leaf *syntax::Tree::findFirstLeaf() const {
284a9ac8606Spatrick   for (const Node &C : getChildren()) {
285a9ac8606Spatrick     if (const auto *L = dyn_cast<syntax::Leaf>(&C))
286e5dd7070Spatrick       return L;
287a9ac8606Spatrick     if (const auto *L = cast<syntax::Tree>(C).findFirstLeaf())
288e5dd7070Spatrick       return L;
289e5dd7070Spatrick   }
290e5dd7070Spatrick   return nullptr;
291e5dd7070Spatrick }
292e5dd7070Spatrick 
findLastLeaf() const293a9ac8606Spatrick const syntax::Leaf *syntax::Tree::findLastLeaf() const {
294a9ac8606Spatrick   for (const auto *C = getLastChild(); C; C = C->getPreviousSibling()) {
295a9ac8606Spatrick     if (const auto *L = dyn_cast<syntax::Leaf>(C))
296a9ac8606Spatrick       return L;
297a9ac8606Spatrick     if (const auto *L = cast<syntax::Tree>(C)->findLastLeaf())
298a9ac8606Spatrick       return L;
299e5dd7070Spatrick   }
300e5dd7070Spatrick   return nullptr;
301e5dd7070Spatrick }
302a9ac8606Spatrick 
findChild(NodeRole R) const303a9ac8606Spatrick const syntax::Node *syntax::Tree::findChild(NodeRole R) const {
304a9ac8606Spatrick   for (const Node &C : getChildren()) {
305a9ac8606Spatrick     if (C.getRole() == R)
306a9ac8606Spatrick       return &C;
307a9ac8606Spatrick   }
308a9ac8606Spatrick   return nullptr;
309a9ac8606Spatrick }
310a9ac8606Spatrick 
311a9ac8606Spatrick std::vector<syntax::List::ElementAndDelimiter<syntax::Node>>
getElementsAsNodesAndDelimiters()312a9ac8606Spatrick syntax::List::getElementsAsNodesAndDelimiters() {
313a9ac8606Spatrick   if (!getFirstChild())
314a9ac8606Spatrick     return {};
315a9ac8606Spatrick 
316a9ac8606Spatrick   std::vector<syntax::List::ElementAndDelimiter<Node>> Children;
317a9ac8606Spatrick   syntax::Node *ElementWithoutDelimiter = nullptr;
318a9ac8606Spatrick   for (Node &C : getChildren()) {
319a9ac8606Spatrick     switch (C.getRole()) {
320a9ac8606Spatrick     case syntax::NodeRole::ListElement: {
321a9ac8606Spatrick       if (ElementWithoutDelimiter) {
322a9ac8606Spatrick         Children.push_back({ElementWithoutDelimiter, nullptr});
323a9ac8606Spatrick       }
324a9ac8606Spatrick       ElementWithoutDelimiter = &C;
325a9ac8606Spatrick       break;
326a9ac8606Spatrick     }
327a9ac8606Spatrick     case syntax::NodeRole::ListDelimiter: {
328a9ac8606Spatrick       Children.push_back({ElementWithoutDelimiter, cast<syntax::Leaf>(&C)});
329a9ac8606Spatrick       ElementWithoutDelimiter = nullptr;
330a9ac8606Spatrick       break;
331a9ac8606Spatrick     }
332a9ac8606Spatrick     default:
333a9ac8606Spatrick       llvm_unreachable(
334a9ac8606Spatrick           "A list can have only elements and delimiters as children.");
335a9ac8606Spatrick     }
336a9ac8606Spatrick   }
337a9ac8606Spatrick 
338a9ac8606Spatrick   switch (getTerminationKind()) {
339a9ac8606Spatrick   case syntax::List::TerminationKind::Separated: {
340a9ac8606Spatrick     Children.push_back({ElementWithoutDelimiter, nullptr});
341a9ac8606Spatrick     break;
342a9ac8606Spatrick   }
343a9ac8606Spatrick   case syntax::List::TerminationKind::Terminated:
344a9ac8606Spatrick   case syntax::List::TerminationKind::MaybeTerminated: {
345a9ac8606Spatrick     if (ElementWithoutDelimiter) {
346a9ac8606Spatrick       Children.push_back({ElementWithoutDelimiter, nullptr});
347a9ac8606Spatrick     }
348a9ac8606Spatrick     break;
349a9ac8606Spatrick   }
350a9ac8606Spatrick   }
351a9ac8606Spatrick 
352a9ac8606Spatrick   return Children;
353a9ac8606Spatrick }
354a9ac8606Spatrick 
355a9ac8606Spatrick // Almost the same implementation of `getElementsAsNodesAndDelimiters` but
356a9ac8606Spatrick // ignoring delimiters
getElementsAsNodes()357a9ac8606Spatrick std::vector<syntax::Node *> syntax::List::getElementsAsNodes() {
358a9ac8606Spatrick   if (!getFirstChild())
359a9ac8606Spatrick     return {};
360a9ac8606Spatrick 
361a9ac8606Spatrick   std::vector<syntax::Node *> Children;
362a9ac8606Spatrick   syntax::Node *ElementWithoutDelimiter = nullptr;
363a9ac8606Spatrick   for (Node &C : getChildren()) {
364a9ac8606Spatrick     switch (C.getRole()) {
365a9ac8606Spatrick     case syntax::NodeRole::ListElement: {
366a9ac8606Spatrick       if (ElementWithoutDelimiter) {
367a9ac8606Spatrick         Children.push_back(ElementWithoutDelimiter);
368a9ac8606Spatrick       }
369a9ac8606Spatrick       ElementWithoutDelimiter = &C;
370a9ac8606Spatrick       break;
371a9ac8606Spatrick     }
372a9ac8606Spatrick     case syntax::NodeRole::ListDelimiter: {
373a9ac8606Spatrick       Children.push_back(ElementWithoutDelimiter);
374a9ac8606Spatrick       ElementWithoutDelimiter = nullptr;
375a9ac8606Spatrick       break;
376a9ac8606Spatrick     }
377a9ac8606Spatrick     default:
378a9ac8606Spatrick       llvm_unreachable("A list has only elements or delimiters.");
379a9ac8606Spatrick     }
380a9ac8606Spatrick   }
381a9ac8606Spatrick 
382a9ac8606Spatrick   switch (getTerminationKind()) {
383a9ac8606Spatrick   case syntax::List::TerminationKind::Separated: {
384a9ac8606Spatrick     Children.push_back(ElementWithoutDelimiter);
385a9ac8606Spatrick     break;
386a9ac8606Spatrick   }
387a9ac8606Spatrick   case syntax::List::TerminationKind::Terminated:
388a9ac8606Spatrick   case syntax::List::TerminationKind::MaybeTerminated: {
389a9ac8606Spatrick     if (ElementWithoutDelimiter) {
390a9ac8606Spatrick       Children.push_back(ElementWithoutDelimiter);
391a9ac8606Spatrick     }
392a9ac8606Spatrick     break;
393a9ac8606Spatrick   }
394a9ac8606Spatrick   }
395a9ac8606Spatrick 
396a9ac8606Spatrick   return Children;
397a9ac8606Spatrick }
398a9ac8606Spatrick 
getDelimiterTokenKind() const399a9ac8606Spatrick clang::tok::TokenKind syntax::List::getDelimiterTokenKind() const {
400a9ac8606Spatrick   switch (this->getKind()) {
401a9ac8606Spatrick   case NodeKind::NestedNameSpecifier:
402a9ac8606Spatrick     return clang::tok::coloncolon;
403a9ac8606Spatrick   case NodeKind::CallArguments:
404a9ac8606Spatrick   case NodeKind::ParameterDeclarationList:
405a9ac8606Spatrick   case NodeKind::DeclaratorList:
406a9ac8606Spatrick     return clang::tok::comma;
407a9ac8606Spatrick   default:
408a9ac8606Spatrick     llvm_unreachable("This is not a subclass of List, thus "
409a9ac8606Spatrick                      "getDelimiterTokenKind() cannot be called");
410a9ac8606Spatrick   }
411a9ac8606Spatrick }
412a9ac8606Spatrick 
getTerminationKind() const413a9ac8606Spatrick syntax::List::TerminationKind syntax::List::getTerminationKind() const {
414a9ac8606Spatrick   switch (this->getKind()) {
415a9ac8606Spatrick   case NodeKind::NestedNameSpecifier:
416a9ac8606Spatrick     return TerminationKind::Terminated;
417a9ac8606Spatrick   case NodeKind::CallArguments:
418a9ac8606Spatrick   case NodeKind::ParameterDeclarationList:
419a9ac8606Spatrick   case NodeKind::DeclaratorList:
420a9ac8606Spatrick     return TerminationKind::Separated;
421a9ac8606Spatrick   default:
422a9ac8606Spatrick     llvm_unreachable("This is not a subclass of List, thus "
423a9ac8606Spatrick                      "getTerminationKind() cannot be called");
424a9ac8606Spatrick   }
425a9ac8606Spatrick }
426a9ac8606Spatrick 
canBeEmpty() const427a9ac8606Spatrick bool syntax::List::canBeEmpty() const {
428a9ac8606Spatrick   switch (this->getKind()) {
429a9ac8606Spatrick   case NodeKind::NestedNameSpecifier:
430a9ac8606Spatrick     return false;
431a9ac8606Spatrick   case NodeKind::CallArguments:
432a9ac8606Spatrick     return true;
433a9ac8606Spatrick   case NodeKind::ParameterDeclarationList:
434a9ac8606Spatrick     return true;
435a9ac8606Spatrick   case NodeKind::DeclaratorList:
436a9ac8606Spatrick     return true;
437a9ac8606Spatrick   default:
438a9ac8606Spatrick     llvm_unreachable("This is not a subclass of List, thus canBeEmpty() "
439a9ac8606Spatrick                      "cannot be called");
440a9ac8606Spatrick   }
441a9ac8606Spatrick }
442