1 //===- Mutations.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/Mutations.h" 9 #include "clang/Basic/LLVM.h" 10 #include "clang/Tooling/Syntax/BuildTree.h" 11 #include "clang/Tooling/Syntax/Nodes.h" 12 #include "clang/Tooling/Syntax/Tree.h" 13 #include <cassert> 14 15 using namespace clang; 16 17 // This class has access to the internals of tree nodes. Its sole purpose is to 18 // define helpers that allow implementing the high-level mutation operations. 19 class syntax::MutationsImpl { 20 public: 21 /// Add a new node with a specified role. 22 static void addAfter(syntax::Node *Anchor, syntax::Node *New, NodeRole Role) { 23 assert(Anchor != nullptr); 24 assert(Anchor->Parent != nullptr); 25 assert(New->Parent == nullptr); 26 assert(New->NextSibling == nullptr); 27 assert(New->PreviousSibling == nullptr); 28 assert(New->isDetached()); 29 assert(Role != NodeRole::Detached); 30 31 New->setRole(Role); 32 auto *P = Anchor->getParent(); 33 P->replaceChildRangeLowLevel(Anchor->getNextSibling(), 34 Anchor->getNextSibling(), New); 35 36 P->assertInvariants(); 37 } 38 39 /// Replace the node, keeping the role. 40 static void replace(syntax::Node *Old, syntax::Node *New) { 41 assert(Old != nullptr); 42 assert(Old->Parent != nullptr); 43 assert(Old->canModify()); 44 assert(New->Parent == nullptr); 45 assert(New->NextSibling == nullptr); 46 assert(New->PreviousSibling == nullptr); 47 assert(New->isDetached()); 48 49 New->Role = Old->Role; 50 auto *P = Old->getParent(); 51 P->replaceChildRangeLowLevel(Old, Old->getNextSibling(), New); 52 53 P->assertInvariants(); 54 } 55 56 /// Completely remove the node from its parent. 57 static void remove(syntax::Node *N) { 58 assert(N != nullptr); 59 assert(N->Parent != nullptr); 60 assert(N->canModify()); 61 62 auto *P = N->getParent(); 63 P->replaceChildRangeLowLevel(N, N->getNextSibling(), 64 /*New=*/nullptr); 65 66 P->assertInvariants(); 67 N->assertInvariants(); 68 } 69 }; 70 71 void syntax::removeStatement(syntax::Arena &A, TokenBufferTokenManager &TBTM, 72 syntax::Statement *S) { 73 assert(S); 74 assert(S->canModify()); 75 76 if (isa<CompoundStatement>(S->getParent())) { 77 // A child of CompoundStatement can just be safely removed. 78 MutationsImpl::remove(S); 79 return; 80 } 81 // For the rest, we have to replace with an empty statement. 82 if (isa<EmptyStatement>(S)) 83 return; // already an empty statement, nothing to do. 84 85 MutationsImpl::replace(S, createEmptyStatement(A, TBTM)); 86 } 87