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