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