1 //===- Tree.cpp -----------------------------------------------*- C++ -*-=====//
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
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 "llvm/Support/Casting.h"
16 using namespace clang
;
19 static void traverse(const syntax::Node
*N
,
20 llvm::function_ref
<void(const syntax::Node
*)> Visit
) {
21 if (auto *T
= dyn_cast
<syntax::Tree
>(N
)) {
22 for (const syntax::Node
&C
: T
->getChildren())
27 static void traverse(syntax::Node
*N
,
28 llvm::function_ref
<void(syntax::Node
*)> Visit
) {
29 traverse(static_cast<const syntax::Node
*>(N
), [&](const syntax::Node
*N
) {
30 Visit(const_cast<syntax::Node
*>(N
));
35 syntax::Leaf::Leaf(syntax::TokenManager::Key K
) : Node(NodeKind::Leaf
), K(K
) {}
37 syntax::Node::Node(NodeKind Kind
)
38 : Parent(nullptr), NextSibling(nullptr), PreviousSibling(nullptr),
39 Kind(static_cast<unsigned>(Kind
)), Role(0), Original(false),
41 this->setRole(NodeRole::Detached
);
44 bool syntax::Node::isDetached() const {
45 return getRole() == NodeRole::Detached
;
48 void syntax::Node::setRole(NodeRole NR
) {
49 this->Role
= static_cast<unsigned>(NR
);
52 void syntax::Tree::appendChildLowLevel(Node
*Child
, NodeRole Role
) {
53 assert(Child
->getRole() == NodeRole::Detached
);
54 assert(Role
!= NodeRole::Detached
);
57 appendChildLowLevel(Child
);
60 void syntax::Tree::appendChildLowLevel(Node
*Child
) {
61 assert(Child
->Parent
== nullptr);
62 assert(Child
->NextSibling
== nullptr);
63 assert(Child
->PreviousSibling
== nullptr);
64 assert(Child
->getRole() != NodeRole::Detached
);
67 if (this->LastChild
) {
68 Child
->PreviousSibling
= this->LastChild
;
69 this->LastChild
->NextSibling
= Child
;
71 this->FirstChild
= Child
;
73 this->LastChild
= Child
;
76 void syntax::Tree::prependChildLowLevel(Node
*Child
, NodeRole Role
) {
77 assert(Child
->getRole() == NodeRole::Detached
);
78 assert(Role
!= NodeRole::Detached
);
81 prependChildLowLevel(Child
);
84 void syntax::Tree::prependChildLowLevel(Node
*Child
) {
85 assert(Child
->Parent
== nullptr);
86 assert(Child
->NextSibling
== nullptr);
87 assert(Child
->PreviousSibling
== nullptr);
88 assert(Child
->getRole() != NodeRole::Detached
);
91 if (this->FirstChild
) {
92 Child
->NextSibling
= this->FirstChild
;
93 this->FirstChild
->PreviousSibling
= Child
;
95 this->LastChild
= Child
;
97 this->FirstChild
= Child
;
100 void syntax::Tree::replaceChildRangeLowLevel(Node
*Begin
, Node
*End
,
102 assert((!Begin
|| Begin
->Parent
== this) &&
103 "`Begin` is not a child of `this`.");
104 assert((!End
|| End
->Parent
== this) && "`End` is not a child of `this`.");
105 assert(canModify() && "Cannot modify `this`.");
108 for (auto *N
= New
; N
; N
= N
->NextSibling
) {
109 assert(N
->Parent
== nullptr);
110 assert(N
->getRole() != NodeRole::Detached
&& "Roles must be set");
111 // FIXME: validate the role.
114 auto Reachable
= [](Node
*From
, Node
*N
) {
117 for (auto *It
= From
; It
; It
= It
->NextSibling
)
122 assert(Reachable(FirstChild
, Begin
) && "`Begin` is not reachable.");
123 assert(Reachable(Begin
, End
) && "`End` is not after `Begin`.");
126 if (!New
&& Begin
== End
)
129 // Mark modification.
130 for (auto *T
= this; T
&& T
->Original
; T
= T
->Parent
)
133 // Save the node before the range to be removed. Later we insert the `New`
134 // range after this node.
135 auto *BeforeBegin
= Begin
? Begin
->PreviousSibling
: LastChild
;
138 for (auto *N
= Begin
; N
!= End
;) {
139 auto *Next
= N
->NextSibling
;
141 N
->setRole(NodeRole::Detached
);
143 N
->NextSibling
= nullptr;
144 N
->PreviousSibling
= nullptr;
146 traverse(N
, [](Node
*C
) { C
->Original
= false; });
152 auto *&NewFirst
= BeforeBegin
? BeforeBegin
->NextSibling
: FirstChild
;
153 auto *&NewLast
= End
? End
->PreviousSibling
: LastChild
;
157 NewLast
= BeforeBegin
;
161 New
->PreviousSibling
= BeforeBegin
;
165 for (auto *N
= New
; N
!= nullptr; N
= N
->NextSibling
) {
169 LastInNew
->NextSibling
= End
;
174 static void dumpNode(raw_ostream
&OS
, const syntax::Node
*N
,
175 const syntax::TokenManager
&TM
, llvm::BitVector IndentMask
) {
176 auto DumpExtraInfo
= [&OS
](const syntax::Node
*N
) {
177 if (N
->getRole() != syntax::NodeRole::Unknown
)
178 OS
<< " " << N
->getRole();
179 if (!N
->isOriginal())
180 OS
<< " synthesized";
182 OS
<< " unmodifiable";
186 if (const auto *L
= dyn_cast
<syntax::Leaf
>(N
)) {
188 OS
<< TM
.getText(L
->getTokenKey());
195 const auto *T
= cast
<syntax::Tree
>(N
);
200 for (const syntax::Node
&It
: T
->getChildren()) {
201 for (unsigned Idx
= 0; Idx
< IndentMask
.size(); ++Idx
) {
207 if (!It
.getNextSibling()) {
209 IndentMask
.push_back(false);
212 IndentMask
.push_back(true);
214 dumpNode(OS
, &It
, TM
, IndentMask
);
215 IndentMask
.pop_back();
220 std::string
syntax::Node::dump(const TokenManager
&TM
) const {
222 llvm::raw_string_ostream
OS(Str
);
223 dumpNode(OS
, this, TM
, /*IndentMask=*/{});
224 return std::move(OS
.str());
227 std::string
syntax::Node::dumpTokens(const TokenManager
&TM
) const {
229 llvm::raw_string_ostream
OS(Storage
);
230 traverse(this, [&](const syntax::Node
*N
) {
231 if (const auto *L
= dyn_cast
<syntax::Leaf
>(N
)) {
232 OS
<< TM
.getText(L
->getTokenKey());
239 void syntax::Node::assertInvariants() const {
242 assert(getParent() == nullptr);
244 assert(getParent() != nullptr);
246 const auto *T
= dyn_cast
<Tree
>(this);
249 for (const Node
&C
: T
->getChildren()) {
251 assert(C
.isOriginal());
252 assert(!C
.isDetached());
253 assert(C
.getParent() == T
);
254 const auto *Next
= C
.getNextSibling();
255 assert(!Next
|| &C
== Next
->getPreviousSibling());
256 if (!C
.getNextSibling())
257 assert(&C
== T
->getLastChild() &&
258 "Last child is reachable by advancing from the first child.");
261 const auto *L
= dyn_cast
<List
>(T
);
264 for (const Node
&C
: T
->getChildren()) {
265 assert(C
.getRole() == NodeRole::ListElement
||
266 C
.getRole() == NodeRole::ListDelimiter
);
267 if (C
.getRole() == NodeRole::ListDelimiter
) {
268 assert(isa
<Leaf
>(C
));
269 // FIXME: re-enable it when there is way to retrieve token kind in Leaf.
270 // assert(cast<Leaf>(C).getToken()->kind() == L->getDelimiterTokenKind());
277 void syntax::Node::assertInvariantsRecursive() const {
279 traverse(this, [&](const syntax::Node
*N
) { N
->assertInvariants(); });
283 const syntax::Leaf
*syntax::Tree::findFirstLeaf() const {
284 for (const Node
&C
: getChildren()) {
285 if (const auto *L
= dyn_cast
<syntax::Leaf
>(&C
))
287 if (const auto *L
= cast
<syntax::Tree
>(C
).findFirstLeaf())
293 const syntax::Leaf
*syntax::Tree::findLastLeaf() const {
294 for (const auto *C
= getLastChild(); C
; C
= C
->getPreviousSibling()) {
295 if (const auto *L
= dyn_cast
<syntax::Leaf
>(C
))
297 if (const auto *L
= cast
<syntax::Tree
>(C
)->findLastLeaf())
303 const syntax::Node
*syntax::Tree::findChild(NodeRole R
) const {
304 for (const Node
&C
: getChildren()) {
305 if (C
.getRole() == R
)
311 std::vector
<syntax::List::ElementAndDelimiter
<syntax::Node
>>
312 syntax::List::getElementsAsNodesAndDelimiters() {
313 if (!getFirstChild())
316 std::vector
<syntax::List::ElementAndDelimiter
<Node
>> Children
;
317 syntax::Node
*ElementWithoutDelimiter
= nullptr;
318 for (Node
&C
: getChildren()) {
319 switch (C
.getRole()) {
320 case syntax::NodeRole::ListElement
: {
321 if (ElementWithoutDelimiter
) {
322 Children
.push_back({ElementWithoutDelimiter
, nullptr});
324 ElementWithoutDelimiter
= &C
;
327 case syntax::NodeRole::ListDelimiter
: {
328 Children
.push_back({ElementWithoutDelimiter
, cast
<syntax::Leaf
>(&C
)});
329 ElementWithoutDelimiter
= nullptr;
334 "A list can have only elements and delimiters as children.");
338 switch (getTerminationKind()) {
339 case syntax::List::TerminationKind::Separated
: {
340 Children
.push_back({ElementWithoutDelimiter
, nullptr});
343 case syntax::List::TerminationKind::Terminated
:
344 case syntax::List::TerminationKind::MaybeTerminated
: {
345 if (ElementWithoutDelimiter
) {
346 Children
.push_back({ElementWithoutDelimiter
, nullptr});
355 // Almost the same implementation of `getElementsAsNodesAndDelimiters` but
356 // ignoring delimiters
357 std::vector
<syntax::Node
*> syntax::List::getElementsAsNodes() {
358 if (!getFirstChild())
361 std::vector
<syntax::Node
*> Children
;
362 syntax::Node
*ElementWithoutDelimiter
= nullptr;
363 for (Node
&C
: getChildren()) {
364 switch (C
.getRole()) {
365 case syntax::NodeRole::ListElement
: {
366 if (ElementWithoutDelimiter
) {
367 Children
.push_back(ElementWithoutDelimiter
);
369 ElementWithoutDelimiter
= &C
;
372 case syntax::NodeRole::ListDelimiter
: {
373 Children
.push_back(ElementWithoutDelimiter
);
374 ElementWithoutDelimiter
= nullptr;
378 llvm_unreachable("A list has only elements or delimiters.");
382 switch (getTerminationKind()) {
383 case syntax::List::TerminationKind::Separated
: {
384 Children
.push_back(ElementWithoutDelimiter
);
387 case syntax::List::TerminationKind::Terminated
:
388 case syntax::List::TerminationKind::MaybeTerminated
: {
389 if (ElementWithoutDelimiter
) {
390 Children
.push_back(ElementWithoutDelimiter
);
399 clang::tok::TokenKind
syntax::List::getDelimiterTokenKind() const {
400 switch (this->getKind()) {
401 case NodeKind::NestedNameSpecifier
:
402 return clang::tok::coloncolon
;
403 case NodeKind::CallArguments
:
404 case NodeKind::ParameterDeclarationList
:
405 case NodeKind::DeclaratorList
:
406 return clang::tok::comma
;
408 llvm_unreachable("This is not a subclass of List, thus "
409 "getDelimiterTokenKind() cannot be called");
413 syntax::List::TerminationKind
syntax::List::getTerminationKind() const {
414 switch (this->getKind()) {
415 case NodeKind::NestedNameSpecifier
:
416 return TerminationKind::Terminated
;
417 case NodeKind::CallArguments
:
418 case NodeKind::ParameterDeclarationList
:
419 case NodeKind::DeclaratorList
:
420 return TerminationKind::Separated
;
422 llvm_unreachable("This is not a subclass of List, thus "
423 "getTerminationKind() cannot be called");
427 bool syntax::List::canBeEmpty() const {
428 switch (this->getKind()) {
429 case NodeKind::NestedNameSpecifier
:
431 case NodeKind::CallArguments
:
433 case NodeKind::ParameterDeclarationList
:
435 case NodeKind::DeclaratorList
:
438 llvm_unreachable("This is not a subclass of List, thus canBeEmpty() "