xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Tooling/Syntax/Tree.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===- Tree.cpp -----------------------------------------------*- C++ -*-=====//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg #include "clang/Tooling/Syntax/Tree.h"
97330f729Sjoerg #include "clang/Basic/TokenKinds.h"
107330f729Sjoerg #include "clang/Tooling/Syntax/Nodes.h"
117330f729Sjoerg #include "llvm/ADT/ArrayRef.h"
127330f729Sjoerg #include "llvm/ADT/STLExtras.h"
137330f729Sjoerg #include "llvm/Support/Casting.h"
14*e038c9c4Sjoerg #include <cassert>
157330f729Sjoerg 
167330f729Sjoerg using namespace clang;
177330f729Sjoerg 
18*e038c9c4Sjoerg namespace {
traverse(const syntax::Node * N,llvm::function_ref<void (const syntax::Node *)> Visit)19*e038c9c4Sjoerg static void traverse(const syntax::Node *N,
20*e038c9c4Sjoerg                      llvm::function_ref<void(const syntax::Node *)> Visit) {
21*e038c9c4Sjoerg   if (auto *T = dyn_cast<syntax::Tree>(N)) {
22*e038c9c4Sjoerg     for (const syntax::Node &C : T->getChildren())
23*e038c9c4Sjoerg       traverse(&C, Visit);
24*e038c9c4Sjoerg   }
25*e038c9c4Sjoerg   Visit(N);
26*e038c9c4Sjoerg }
traverse(syntax::Node * N,llvm::function_ref<void (syntax::Node *)> Visit)27*e038c9c4Sjoerg static void traverse(syntax::Node *N,
28*e038c9c4Sjoerg                      llvm::function_ref<void(syntax::Node *)> Visit) {
29*e038c9c4Sjoerg   traverse(static_cast<const syntax::Node *>(N), [&](const syntax::Node *N) {
30*e038c9c4Sjoerg     Visit(const_cast<syntax::Node *>(N));
31*e038c9c4Sjoerg   });
32*e038c9c4Sjoerg }
33*e038c9c4Sjoerg } // namespace
347330f729Sjoerg 
Arena(SourceManager & SourceMgr,const LangOptions & LangOpts,const TokenBuffer & Tokens)35*e038c9c4Sjoerg syntax::Arena::Arena(SourceManager &SourceMgr, const LangOptions &LangOpts,
36*e038c9c4Sjoerg                      const TokenBuffer &Tokens)
37*e038c9c4Sjoerg     : SourceMgr(SourceMgr), LangOpts(LangOpts), Tokens(Tokens) {}
38*e038c9c4Sjoerg 
getTokenBuffer() const39*e038c9c4Sjoerg const syntax::TokenBuffer &syntax::Arena::getTokenBuffer() const {
407330f729Sjoerg   return Tokens;
417330f729Sjoerg }
427330f729Sjoerg 
43*e038c9c4Sjoerg std::pair<FileID, ArrayRef<syntax::Token>>
lexBuffer(std::unique_ptr<llvm::MemoryBuffer> Input)447330f729Sjoerg syntax::Arena::lexBuffer(std::unique_ptr<llvm::MemoryBuffer> Input) {
457330f729Sjoerg   auto FID = SourceMgr.createFileID(std::move(Input));
467330f729Sjoerg   auto It = ExtraTokens.try_emplace(FID, tokenize(FID, SourceMgr, LangOpts));
477330f729Sjoerg   assert(It.second && "duplicate FileID");
487330f729Sjoerg   return {FID, It.first->second};
497330f729Sjoerg }
507330f729Sjoerg 
Leaf(const syntax::Token * Tok)517330f729Sjoerg syntax::Leaf::Leaf(const syntax::Token *Tok) : Node(NodeKind::Leaf), Tok(Tok) {
527330f729Sjoerg   assert(Tok != nullptr);
537330f729Sjoerg }
547330f729Sjoerg 
Node(NodeKind Kind)55*e038c9c4Sjoerg syntax::Node::Node(NodeKind Kind)
56*e038c9c4Sjoerg     : Parent(nullptr), NextSibling(nullptr), PreviousSibling(nullptr),
57*e038c9c4Sjoerg       Kind(static_cast<unsigned>(Kind)), Role(0), Original(false),
58*e038c9c4Sjoerg       CanModify(false) {
59*e038c9c4Sjoerg   this->setRole(NodeRole::Detached);
607330f729Sjoerg }
617330f729Sjoerg 
isDetached() const62*e038c9c4Sjoerg bool syntax::Node::isDetached() const {
63*e038c9c4Sjoerg   return getRole() == NodeRole::Detached;
64*e038c9c4Sjoerg }
657330f729Sjoerg 
setRole(NodeRole NR)66*e038c9c4Sjoerg void syntax::Node::setRole(NodeRole NR) {
67*e038c9c4Sjoerg   this->Role = static_cast<unsigned>(NR);
68*e038c9c4Sjoerg }
697330f729Sjoerg 
appendChildLowLevel(Node * Child,NodeRole Role)70*e038c9c4Sjoerg void syntax::Tree::appendChildLowLevel(Node *Child, NodeRole Role) {
71*e038c9c4Sjoerg   assert(Child->getRole() == NodeRole::Detached);
727330f729Sjoerg   assert(Role != NodeRole::Detached);
737330f729Sjoerg 
74*e038c9c4Sjoerg   Child->setRole(Role);
75*e038c9c4Sjoerg   appendChildLowLevel(Child);
76*e038c9c4Sjoerg }
77*e038c9c4Sjoerg 
appendChildLowLevel(Node * Child)78*e038c9c4Sjoerg void syntax::Tree::appendChildLowLevel(Node *Child) {
79*e038c9c4Sjoerg   assert(Child->Parent == nullptr);
80*e038c9c4Sjoerg   assert(Child->NextSibling == nullptr);
81*e038c9c4Sjoerg   assert(Child->PreviousSibling == nullptr);
82*e038c9c4Sjoerg   assert(Child->getRole() != NodeRole::Detached);
83*e038c9c4Sjoerg 
847330f729Sjoerg   Child->Parent = this;
85*e038c9c4Sjoerg   if (this->LastChild) {
86*e038c9c4Sjoerg     Child->PreviousSibling = this->LastChild;
87*e038c9c4Sjoerg     this->LastChild->NextSibling = Child;
88*e038c9c4Sjoerg   } else
89*e038c9c4Sjoerg     this->FirstChild = Child;
90*e038c9c4Sjoerg 
91*e038c9c4Sjoerg   this->LastChild = Child;
92*e038c9c4Sjoerg }
93*e038c9c4Sjoerg 
prependChildLowLevel(Node * Child,NodeRole Role)94*e038c9c4Sjoerg void syntax::Tree::prependChildLowLevel(Node *Child, NodeRole Role) {
95*e038c9c4Sjoerg   assert(Child->getRole() == NodeRole::Detached);
96*e038c9c4Sjoerg   assert(Role != NodeRole::Detached);
97*e038c9c4Sjoerg 
98*e038c9c4Sjoerg   Child->setRole(Role);
99*e038c9c4Sjoerg   prependChildLowLevel(Child);
100*e038c9c4Sjoerg }
101*e038c9c4Sjoerg 
prependChildLowLevel(Node * Child)102*e038c9c4Sjoerg void syntax::Tree::prependChildLowLevel(Node *Child) {
103*e038c9c4Sjoerg   assert(Child->Parent == nullptr);
104*e038c9c4Sjoerg   assert(Child->NextSibling == nullptr);
105*e038c9c4Sjoerg   assert(Child->PreviousSibling == nullptr);
106*e038c9c4Sjoerg   assert(Child->getRole() != NodeRole::Detached);
107*e038c9c4Sjoerg 
108*e038c9c4Sjoerg   Child->Parent = this;
109*e038c9c4Sjoerg   if (this->FirstChild) {
1107330f729Sjoerg     Child->NextSibling = this->FirstChild;
111*e038c9c4Sjoerg     this->FirstChild->PreviousSibling = Child;
112*e038c9c4Sjoerg   } else
113*e038c9c4Sjoerg     this->LastChild = Child;
114*e038c9c4Sjoerg 
1157330f729Sjoerg   this->FirstChild = Child;
1167330f729Sjoerg }
1177330f729Sjoerg 
replaceChildRangeLowLevel(Node * Begin,Node * End,Node * New)118*e038c9c4Sjoerg void syntax::Tree::replaceChildRangeLowLevel(Node *Begin, Node *End,
119*e038c9c4Sjoerg                                              Node *New) {
120*e038c9c4Sjoerg   assert((!Begin || Begin->Parent == this) &&
121*e038c9c4Sjoerg          "`Begin` is not a child of `this`.");
122*e038c9c4Sjoerg   assert((!End || End->Parent == this) && "`End` is not a child of `this`.");
123*e038c9c4Sjoerg   assert(canModify() && "Cannot modify `this`.");
124*e038c9c4Sjoerg 
125*e038c9c4Sjoerg #ifndef NDEBUG
126*e038c9c4Sjoerg   for (auto *N = New; N; N = N->NextSibling) {
127*e038c9c4Sjoerg     assert(N->Parent == nullptr);
128*e038c9c4Sjoerg     assert(N->getRole() != NodeRole::Detached && "Roles must be set");
129*e038c9c4Sjoerg     // FIXME: sanity-check the role.
1307330f729Sjoerg   }
1317330f729Sjoerg 
132*e038c9c4Sjoerg   auto Reachable = [](Node *From, Node *N) {
133*e038c9c4Sjoerg     if (!N)
134*e038c9c4Sjoerg       return true;
135*e038c9c4Sjoerg     for (auto *It = From; It; It = It->NextSibling)
136*e038c9c4Sjoerg       if (It == N)
137*e038c9c4Sjoerg         return true;
138*e038c9c4Sjoerg     return false;
139*e038c9c4Sjoerg   };
140*e038c9c4Sjoerg   assert(Reachable(FirstChild, Begin) && "`Begin` is not reachable.");
141*e038c9c4Sjoerg   assert(Reachable(Begin, End) && "`End` is not after `Begin`.");
142*e038c9c4Sjoerg #endif
143*e038c9c4Sjoerg 
144*e038c9c4Sjoerg   if (!New && Begin == End)
145*e038c9c4Sjoerg     return;
146*e038c9c4Sjoerg 
147*e038c9c4Sjoerg   // Mark modification.
148*e038c9c4Sjoerg   for (auto *T = this; T && T->Original; T = T->Parent)
149*e038c9c4Sjoerg     T->Original = false;
150*e038c9c4Sjoerg 
151*e038c9c4Sjoerg   // Save the node before the range to be removed. Later we insert the `New`
152*e038c9c4Sjoerg   // range after this node.
153*e038c9c4Sjoerg   auto *BeforeBegin = Begin ? Begin->PreviousSibling : LastChild;
154*e038c9c4Sjoerg 
155*e038c9c4Sjoerg   // Detach old nodes.
156*e038c9c4Sjoerg   for (auto *N = Begin; N != End;) {
157*e038c9c4Sjoerg     auto *Next = N->NextSibling;
158*e038c9c4Sjoerg 
159*e038c9c4Sjoerg     N->setRole(NodeRole::Detached);
160*e038c9c4Sjoerg     N->Parent = nullptr;
161*e038c9c4Sjoerg     N->NextSibling = nullptr;
162*e038c9c4Sjoerg     N->PreviousSibling = nullptr;
163*e038c9c4Sjoerg     if (N->Original)
164*e038c9c4Sjoerg       traverse(N, [](Node *C) { C->Original = false; });
165*e038c9c4Sjoerg 
166*e038c9c4Sjoerg     N = Next;
1677330f729Sjoerg   }
168*e038c9c4Sjoerg 
169*e038c9c4Sjoerg   // Attach new range.
170*e038c9c4Sjoerg   auto *&NewFirst = BeforeBegin ? BeforeBegin->NextSibling : FirstChild;
171*e038c9c4Sjoerg   auto *&NewLast = End ? End->PreviousSibling : LastChild;
172*e038c9c4Sjoerg 
173*e038c9c4Sjoerg   if (!New) {
174*e038c9c4Sjoerg     NewFirst = End;
175*e038c9c4Sjoerg     NewLast = BeforeBegin;
176*e038c9c4Sjoerg     return;
177*e038c9c4Sjoerg   }
178*e038c9c4Sjoerg 
179*e038c9c4Sjoerg   New->PreviousSibling = BeforeBegin;
180*e038c9c4Sjoerg   NewFirst = New;
181*e038c9c4Sjoerg 
182*e038c9c4Sjoerg   Node *LastInNew;
183*e038c9c4Sjoerg   for (auto *N = New; N != nullptr; N = N->NextSibling) {
184*e038c9c4Sjoerg     LastInNew = N;
185*e038c9c4Sjoerg     N->Parent = this;
186*e038c9c4Sjoerg   }
187*e038c9c4Sjoerg   LastInNew->NextSibling = End;
188*e038c9c4Sjoerg   NewLast = LastInNew;
189*e038c9c4Sjoerg }
190*e038c9c4Sjoerg 
191*e038c9c4Sjoerg namespace {
dumpLeaf(raw_ostream & OS,const syntax::Leaf * L,const SourceManager & SM)192*e038c9c4Sjoerg static void dumpLeaf(raw_ostream &OS, const syntax::Leaf *L,
193*e038c9c4Sjoerg                      const SourceManager &SM) {
194*e038c9c4Sjoerg   assert(L);
195*e038c9c4Sjoerg   const auto *Token = L->getToken();
196*e038c9c4Sjoerg   assert(Token);
197*e038c9c4Sjoerg   // Handle 'eof' separately, calling text() on it produces an empty string.
198*e038c9c4Sjoerg   if (Token->kind() == tok::eof)
199*e038c9c4Sjoerg     OS << "<eof>";
200*e038c9c4Sjoerg   else
201*e038c9c4Sjoerg     OS << Token->text(SM);
202*e038c9c4Sjoerg }
203*e038c9c4Sjoerg 
dumpNode(raw_ostream & OS,const syntax::Node * N,const SourceManager & SM,std::vector<bool> IndentMask)204*e038c9c4Sjoerg static void dumpNode(raw_ostream &OS, const syntax::Node *N,
205*e038c9c4Sjoerg                      const SourceManager &SM, std::vector<bool> IndentMask) {
206*e038c9c4Sjoerg   auto DumpExtraInfo = [&OS](const syntax::Node *N) {
207*e038c9c4Sjoerg     if (N->getRole() != syntax::NodeRole::Unknown)
208*e038c9c4Sjoerg       OS << " " << N->getRole();
209*e038c9c4Sjoerg     if (!N->isOriginal())
210*e038c9c4Sjoerg       OS << " synthesized";
211*e038c9c4Sjoerg     if (!N->canModify())
212*e038c9c4Sjoerg       OS << " unmodifiable";
213*e038c9c4Sjoerg   };
214*e038c9c4Sjoerg 
215*e038c9c4Sjoerg   assert(N);
216*e038c9c4Sjoerg   if (const auto *L = dyn_cast<syntax::Leaf>(N)) {
217*e038c9c4Sjoerg     OS << "'";
218*e038c9c4Sjoerg     dumpLeaf(OS, L, SM);
219*e038c9c4Sjoerg     OS << "'";
220*e038c9c4Sjoerg     DumpExtraInfo(N);
2217330f729Sjoerg     OS << "\n";
2227330f729Sjoerg     return;
2237330f729Sjoerg   }
2247330f729Sjoerg 
225*e038c9c4Sjoerg   const auto *T = cast<syntax::Tree>(N);
226*e038c9c4Sjoerg   OS << T->getKind();
227*e038c9c4Sjoerg   DumpExtraInfo(N);
228*e038c9c4Sjoerg   OS << "\n";
2297330f729Sjoerg 
230*e038c9c4Sjoerg   for (const syntax::Node &It : T->getChildren()) {
2317330f729Sjoerg     for (bool Filled : IndentMask) {
2327330f729Sjoerg       if (Filled)
2337330f729Sjoerg         OS << "| ";
2347330f729Sjoerg       else
2357330f729Sjoerg         OS << "  ";
2367330f729Sjoerg     }
237*e038c9c4Sjoerg     if (!It.getNextSibling()) {
2387330f729Sjoerg       OS << "`-";
2397330f729Sjoerg       IndentMask.push_back(false);
2407330f729Sjoerg     } else {
2417330f729Sjoerg       OS << "|-";
2427330f729Sjoerg       IndentMask.push_back(true);
2437330f729Sjoerg     }
244*e038c9c4Sjoerg     dumpNode(OS, &It, SM, IndentMask);
2457330f729Sjoerg     IndentMask.pop_back();
2467330f729Sjoerg   }
2477330f729Sjoerg }
2487330f729Sjoerg } // namespace
2497330f729Sjoerg 
dump(const SourceManager & SM) const250*e038c9c4Sjoerg std::string syntax::Node::dump(const SourceManager &SM) const {
2517330f729Sjoerg   std::string Str;
2527330f729Sjoerg   llvm::raw_string_ostream OS(Str);
253*e038c9c4Sjoerg   dumpNode(OS, this, SM, /*IndentMask=*/{});
2547330f729Sjoerg   return std::move(OS.str());
2557330f729Sjoerg }
2567330f729Sjoerg 
dumpTokens(const SourceManager & SM) const257*e038c9c4Sjoerg std::string syntax::Node::dumpTokens(const SourceManager &SM) const {
2587330f729Sjoerg   std::string Storage;
2597330f729Sjoerg   llvm::raw_string_ostream OS(Storage);
2607330f729Sjoerg   traverse(this, [&](const syntax::Node *N) {
261*e038c9c4Sjoerg     if (const auto *L = dyn_cast<syntax::Leaf>(N)) {
262*e038c9c4Sjoerg       dumpLeaf(OS, L, SM);
263*e038c9c4Sjoerg       OS << " ";
264*e038c9c4Sjoerg     }
2657330f729Sjoerg   });
2667330f729Sjoerg   return OS.str();
2677330f729Sjoerg }
2687330f729Sjoerg 
assertInvariants() const269*e038c9c4Sjoerg void syntax::Node::assertInvariants() const {
270*e038c9c4Sjoerg #ifndef NDEBUG
271*e038c9c4Sjoerg   if (isDetached())
272*e038c9c4Sjoerg     assert(getParent() == nullptr);
273*e038c9c4Sjoerg   else
274*e038c9c4Sjoerg     assert(getParent() != nullptr);
275*e038c9c4Sjoerg 
276*e038c9c4Sjoerg   const auto *T = dyn_cast<Tree>(this);
277*e038c9c4Sjoerg   if (!T)
278*e038c9c4Sjoerg     return;
279*e038c9c4Sjoerg   for (const Node &C : T->getChildren()) {
280*e038c9c4Sjoerg     if (T->isOriginal())
281*e038c9c4Sjoerg       assert(C.isOriginal());
282*e038c9c4Sjoerg     assert(!C.isDetached());
283*e038c9c4Sjoerg     assert(C.getParent() == T);
284*e038c9c4Sjoerg     const auto *Next = C.getNextSibling();
285*e038c9c4Sjoerg     assert(!Next || &C == Next->getPreviousSibling());
286*e038c9c4Sjoerg     if (!C.getNextSibling())
287*e038c9c4Sjoerg       assert(&C == T->getLastChild() &&
288*e038c9c4Sjoerg              "Last child is reachable by advancing from the first child.");
289*e038c9c4Sjoerg   }
290*e038c9c4Sjoerg 
291*e038c9c4Sjoerg   const auto *L = dyn_cast<List>(T);
292*e038c9c4Sjoerg   if (!L)
293*e038c9c4Sjoerg     return;
294*e038c9c4Sjoerg   for (const Node &C : T->getChildren()) {
295*e038c9c4Sjoerg     assert(C.getRole() == NodeRole::ListElement ||
296*e038c9c4Sjoerg            C.getRole() == NodeRole::ListDelimiter);
297*e038c9c4Sjoerg     if (C.getRole() == NodeRole::ListDelimiter) {
298*e038c9c4Sjoerg       assert(isa<Leaf>(C));
299*e038c9c4Sjoerg       assert(cast<Leaf>(C).getToken()->kind() == L->getDelimiterTokenKind());
300*e038c9c4Sjoerg     }
301*e038c9c4Sjoerg   }
302*e038c9c4Sjoerg 
303*e038c9c4Sjoerg #endif
304*e038c9c4Sjoerg }
305*e038c9c4Sjoerg 
assertInvariantsRecursive() const306*e038c9c4Sjoerg void syntax::Node::assertInvariantsRecursive() const {
307*e038c9c4Sjoerg #ifndef NDEBUG
308*e038c9c4Sjoerg   traverse(this, [&](const syntax::Node *N) { N->assertInvariants(); });
309*e038c9c4Sjoerg #endif
310*e038c9c4Sjoerg }
311*e038c9c4Sjoerg 
findFirstLeaf() const312*e038c9c4Sjoerg const syntax::Leaf *syntax::Tree::findFirstLeaf() const {
313*e038c9c4Sjoerg   for (const Node &C : getChildren()) {
314*e038c9c4Sjoerg     if (const auto *L = dyn_cast<syntax::Leaf>(&C))
315*e038c9c4Sjoerg       return L;
316*e038c9c4Sjoerg     if (const auto *L = cast<syntax::Tree>(C).findFirstLeaf())
317*e038c9c4Sjoerg       return L;
3187330f729Sjoerg   }
3197330f729Sjoerg   return nullptr;
3207330f729Sjoerg }
321*e038c9c4Sjoerg 
findLastLeaf() const322*e038c9c4Sjoerg const syntax::Leaf *syntax::Tree::findLastLeaf() const {
323*e038c9c4Sjoerg   for (const auto *C = getLastChild(); C; C = C->getPreviousSibling()) {
324*e038c9c4Sjoerg     if (const auto *L = dyn_cast<syntax::Leaf>(C))
325*e038c9c4Sjoerg       return L;
326*e038c9c4Sjoerg     if (const auto *L = cast<syntax::Tree>(C)->findLastLeaf())
327*e038c9c4Sjoerg       return L;
328*e038c9c4Sjoerg   }
329*e038c9c4Sjoerg   return nullptr;
330*e038c9c4Sjoerg }
331*e038c9c4Sjoerg 
findChild(NodeRole R) const332*e038c9c4Sjoerg const syntax::Node *syntax::Tree::findChild(NodeRole R) const {
333*e038c9c4Sjoerg   for (const Node &C : getChildren()) {
334*e038c9c4Sjoerg     if (C.getRole() == R)
335*e038c9c4Sjoerg       return &C;
336*e038c9c4Sjoerg   }
337*e038c9c4Sjoerg   return nullptr;
338*e038c9c4Sjoerg }
339*e038c9c4Sjoerg 
340*e038c9c4Sjoerg std::vector<syntax::List::ElementAndDelimiter<syntax::Node>>
getElementsAsNodesAndDelimiters()341*e038c9c4Sjoerg syntax::List::getElementsAsNodesAndDelimiters() {
342*e038c9c4Sjoerg   if (!getFirstChild())
343*e038c9c4Sjoerg     return {};
344*e038c9c4Sjoerg 
345*e038c9c4Sjoerg   std::vector<syntax::List::ElementAndDelimiter<Node>> Children;
346*e038c9c4Sjoerg   syntax::Node *ElementWithoutDelimiter = nullptr;
347*e038c9c4Sjoerg   for (Node &C : getChildren()) {
348*e038c9c4Sjoerg     switch (C.getRole()) {
349*e038c9c4Sjoerg     case syntax::NodeRole::ListElement: {
350*e038c9c4Sjoerg       if (ElementWithoutDelimiter) {
351*e038c9c4Sjoerg         Children.push_back({ElementWithoutDelimiter, nullptr});
352*e038c9c4Sjoerg       }
353*e038c9c4Sjoerg       ElementWithoutDelimiter = &C;
354*e038c9c4Sjoerg       break;
355*e038c9c4Sjoerg     }
356*e038c9c4Sjoerg     case syntax::NodeRole::ListDelimiter: {
357*e038c9c4Sjoerg       Children.push_back({ElementWithoutDelimiter, cast<syntax::Leaf>(&C)});
358*e038c9c4Sjoerg       ElementWithoutDelimiter = nullptr;
359*e038c9c4Sjoerg       break;
360*e038c9c4Sjoerg     }
361*e038c9c4Sjoerg     default:
362*e038c9c4Sjoerg       llvm_unreachable(
363*e038c9c4Sjoerg           "A list can have only elements and delimiters as children.");
364*e038c9c4Sjoerg     }
365*e038c9c4Sjoerg   }
366*e038c9c4Sjoerg 
367*e038c9c4Sjoerg   switch (getTerminationKind()) {
368*e038c9c4Sjoerg   case syntax::List::TerminationKind::Separated: {
369*e038c9c4Sjoerg     Children.push_back({ElementWithoutDelimiter, nullptr});
370*e038c9c4Sjoerg     break;
371*e038c9c4Sjoerg   }
372*e038c9c4Sjoerg   case syntax::List::TerminationKind::Terminated:
373*e038c9c4Sjoerg   case syntax::List::TerminationKind::MaybeTerminated: {
374*e038c9c4Sjoerg     if (ElementWithoutDelimiter) {
375*e038c9c4Sjoerg       Children.push_back({ElementWithoutDelimiter, nullptr});
376*e038c9c4Sjoerg     }
377*e038c9c4Sjoerg     break;
378*e038c9c4Sjoerg   }
379*e038c9c4Sjoerg   }
380*e038c9c4Sjoerg 
381*e038c9c4Sjoerg   return Children;
382*e038c9c4Sjoerg }
383*e038c9c4Sjoerg 
384*e038c9c4Sjoerg // Almost the same implementation of `getElementsAsNodesAndDelimiters` but
385*e038c9c4Sjoerg // ignoring delimiters
getElementsAsNodes()386*e038c9c4Sjoerg std::vector<syntax::Node *> syntax::List::getElementsAsNodes() {
387*e038c9c4Sjoerg   if (!getFirstChild())
388*e038c9c4Sjoerg     return {};
389*e038c9c4Sjoerg 
390*e038c9c4Sjoerg   std::vector<syntax::Node *> Children;
391*e038c9c4Sjoerg   syntax::Node *ElementWithoutDelimiter = nullptr;
392*e038c9c4Sjoerg   for (Node &C : getChildren()) {
393*e038c9c4Sjoerg     switch (C.getRole()) {
394*e038c9c4Sjoerg     case syntax::NodeRole::ListElement: {
395*e038c9c4Sjoerg       if (ElementWithoutDelimiter) {
396*e038c9c4Sjoerg         Children.push_back(ElementWithoutDelimiter);
397*e038c9c4Sjoerg       }
398*e038c9c4Sjoerg       ElementWithoutDelimiter = &C;
399*e038c9c4Sjoerg       break;
400*e038c9c4Sjoerg     }
401*e038c9c4Sjoerg     case syntax::NodeRole::ListDelimiter: {
402*e038c9c4Sjoerg       Children.push_back(ElementWithoutDelimiter);
403*e038c9c4Sjoerg       ElementWithoutDelimiter = nullptr;
404*e038c9c4Sjoerg       break;
405*e038c9c4Sjoerg     }
406*e038c9c4Sjoerg     default:
407*e038c9c4Sjoerg       llvm_unreachable("A list has only elements or delimiters.");
408*e038c9c4Sjoerg     }
409*e038c9c4Sjoerg   }
410*e038c9c4Sjoerg 
411*e038c9c4Sjoerg   switch (getTerminationKind()) {
412*e038c9c4Sjoerg   case syntax::List::TerminationKind::Separated: {
413*e038c9c4Sjoerg     Children.push_back(ElementWithoutDelimiter);
414*e038c9c4Sjoerg     break;
415*e038c9c4Sjoerg   }
416*e038c9c4Sjoerg   case syntax::List::TerminationKind::Terminated:
417*e038c9c4Sjoerg   case syntax::List::TerminationKind::MaybeTerminated: {
418*e038c9c4Sjoerg     if (ElementWithoutDelimiter) {
419*e038c9c4Sjoerg       Children.push_back(ElementWithoutDelimiter);
420*e038c9c4Sjoerg     }
421*e038c9c4Sjoerg     break;
422*e038c9c4Sjoerg   }
423*e038c9c4Sjoerg   }
424*e038c9c4Sjoerg 
425*e038c9c4Sjoerg   return Children;
426*e038c9c4Sjoerg }
427*e038c9c4Sjoerg 
getDelimiterTokenKind() const428*e038c9c4Sjoerg clang::tok::TokenKind syntax::List::getDelimiterTokenKind() const {
429*e038c9c4Sjoerg   switch (this->getKind()) {
430*e038c9c4Sjoerg   case NodeKind::NestedNameSpecifier:
431*e038c9c4Sjoerg     return clang::tok::coloncolon;
432*e038c9c4Sjoerg   case NodeKind::CallArguments:
433*e038c9c4Sjoerg   case NodeKind::ParameterDeclarationList:
434*e038c9c4Sjoerg   case NodeKind::DeclaratorList:
435*e038c9c4Sjoerg     return clang::tok::comma;
436*e038c9c4Sjoerg   default:
437*e038c9c4Sjoerg     llvm_unreachable("This is not a subclass of List, thus "
438*e038c9c4Sjoerg                      "getDelimiterTokenKind() cannot be called");
439*e038c9c4Sjoerg   }
440*e038c9c4Sjoerg }
441*e038c9c4Sjoerg 
getTerminationKind() const442*e038c9c4Sjoerg syntax::List::TerminationKind syntax::List::getTerminationKind() const {
443*e038c9c4Sjoerg   switch (this->getKind()) {
444*e038c9c4Sjoerg   case NodeKind::NestedNameSpecifier:
445*e038c9c4Sjoerg     return TerminationKind::Terminated;
446*e038c9c4Sjoerg   case NodeKind::CallArguments:
447*e038c9c4Sjoerg   case NodeKind::ParameterDeclarationList:
448*e038c9c4Sjoerg   case NodeKind::DeclaratorList:
449*e038c9c4Sjoerg     return TerminationKind::Separated;
450*e038c9c4Sjoerg   default:
451*e038c9c4Sjoerg     llvm_unreachable("This is not a subclass of List, thus "
452*e038c9c4Sjoerg                      "getTerminationKind() cannot be called");
453*e038c9c4Sjoerg   }
454*e038c9c4Sjoerg }
455*e038c9c4Sjoerg 
canBeEmpty() const456*e038c9c4Sjoerg bool syntax::List::canBeEmpty() const {
457*e038c9c4Sjoerg   switch (this->getKind()) {
458*e038c9c4Sjoerg   case NodeKind::NestedNameSpecifier:
459*e038c9c4Sjoerg     return false;
460*e038c9c4Sjoerg   case NodeKind::CallArguments:
461*e038c9c4Sjoerg     return true;
462*e038c9c4Sjoerg   case NodeKind::ParameterDeclarationList:
463*e038c9c4Sjoerg     return true;
464*e038c9c4Sjoerg   case NodeKind::DeclaratorList:
465*e038c9c4Sjoerg     return true;
466*e038c9c4Sjoerg   default:
467*e038c9c4Sjoerg     llvm_unreachable("This is not a subclass of List, thus canBeEmpty() "
468*e038c9c4Sjoerg                      "cannot be called");
469*e038c9c4Sjoerg   }
470*e038c9c4Sjoerg }
471