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