1480093f4SDimitry Andric //===- Mutations.cpp ------------------------------------------*- C++ -*-=====// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric #include "clang/Tooling/Syntax/Mutations.h" 9480093f4SDimitry Andric #include "clang/Basic/LLVM.h" 10480093f4SDimitry Andric #include "clang/Basic/SourceLocation.h" 11480093f4SDimitry Andric #include "clang/Lex/Token.h" 12480093f4SDimitry Andric #include "clang/Tooling/Core/Replacement.h" 13480093f4SDimitry Andric #include "clang/Tooling/Syntax/BuildTree.h" 14480093f4SDimitry Andric #include "clang/Tooling/Syntax/Nodes.h" 15480093f4SDimitry Andric #include "clang/Tooling/Syntax/Tokens.h" 16480093f4SDimitry Andric #include "clang/Tooling/Syntax/Tree.h" 17480093f4SDimitry Andric #include "llvm/ADT/ArrayRef.h" 18480093f4SDimitry Andric #include "llvm/ADT/Optional.h" 19480093f4SDimitry Andric #include "llvm/ADT/STLExtras.h" 20480093f4SDimitry Andric #include "llvm/Support/Casting.h" 21480093f4SDimitry Andric #include <cassert> 22480093f4SDimitry Andric #include <string> 23480093f4SDimitry Andric 24480093f4SDimitry Andric using namespace clang; 25480093f4SDimitry Andric 26480093f4SDimitry Andric // This class has access to the internals of tree nodes. Its sole purpose is to 27480093f4SDimitry Andric // define helpers that allow implementing the high-level mutation operations. 28480093f4SDimitry Andric class syntax::MutationsImpl { 29480093f4SDimitry Andric public: 30480093f4SDimitry Andric /// Add a new node with a specified role. 31480093f4SDimitry Andric static void addAfter(syntax::Node *Anchor, syntax::Node *New, NodeRole Role) { 32480093f4SDimitry Andric assert(Anchor != nullptr); 33*e8d8bef9SDimitry Andric assert(Anchor->Parent != nullptr); 34480093f4SDimitry Andric assert(New->Parent == nullptr); 35480093f4SDimitry Andric assert(New->NextSibling == nullptr); 36*e8d8bef9SDimitry Andric assert(New->PreviousSibling == nullptr); 37*e8d8bef9SDimitry Andric assert(New->isDetached()); 38480093f4SDimitry Andric assert(Role != NodeRole::Detached); 39480093f4SDimitry Andric 405ffd83dbSDimitry Andric New->setRole(Role); 41*e8d8bef9SDimitry Andric auto *P = Anchor->getParent(); 42*e8d8bef9SDimitry Andric P->replaceChildRangeLowLevel(Anchor->getNextSibling(), 43*e8d8bef9SDimitry Andric Anchor->getNextSibling(), New); 44480093f4SDimitry Andric 45480093f4SDimitry Andric P->assertInvariants(); 46480093f4SDimitry Andric } 47480093f4SDimitry Andric 48480093f4SDimitry Andric /// Replace the node, keeping the role. 49480093f4SDimitry Andric static void replace(syntax::Node *Old, syntax::Node *New) { 50480093f4SDimitry Andric assert(Old != nullptr); 51480093f4SDimitry Andric assert(Old->Parent != nullptr); 52480093f4SDimitry Andric assert(Old->canModify()); 53480093f4SDimitry Andric assert(New->Parent == nullptr); 54480093f4SDimitry Andric assert(New->NextSibling == nullptr); 55*e8d8bef9SDimitry Andric assert(New->PreviousSibling == nullptr); 56480093f4SDimitry Andric assert(New->isDetached()); 57480093f4SDimitry Andric 58480093f4SDimitry Andric New->Role = Old->Role; 59*e8d8bef9SDimitry Andric auto *P = Old->getParent(); 60*e8d8bef9SDimitry Andric P->replaceChildRangeLowLevel(Old, Old->getNextSibling(), New); 61480093f4SDimitry Andric 62480093f4SDimitry Andric P->assertInvariants(); 63480093f4SDimitry Andric } 64480093f4SDimitry Andric 65480093f4SDimitry Andric /// Completely remove the node from its parent. 66480093f4SDimitry Andric static void remove(syntax::Node *N) { 67*e8d8bef9SDimitry Andric assert(N != nullptr); 68*e8d8bef9SDimitry Andric assert(N->Parent != nullptr); 69*e8d8bef9SDimitry Andric assert(N->canModify()); 70*e8d8bef9SDimitry Andric 71*e8d8bef9SDimitry Andric auto *P = N->getParent(); 72*e8d8bef9SDimitry Andric P->replaceChildRangeLowLevel(N, N->getNextSibling(), 73480093f4SDimitry Andric /*New=*/nullptr); 74480093f4SDimitry Andric 75480093f4SDimitry Andric P->assertInvariants(); 76480093f4SDimitry Andric N->assertInvariants(); 77480093f4SDimitry Andric } 78480093f4SDimitry Andric }; 79480093f4SDimitry Andric 80480093f4SDimitry Andric void syntax::removeStatement(syntax::Arena &A, syntax::Statement *S) { 81480093f4SDimitry Andric assert(S); 82480093f4SDimitry Andric assert(S->canModify()); 83480093f4SDimitry Andric 84*e8d8bef9SDimitry Andric if (isa<CompoundStatement>(S->getParent())) { 85480093f4SDimitry Andric // A child of CompoundStatement can just be safely removed. 86480093f4SDimitry Andric MutationsImpl::remove(S); 87480093f4SDimitry Andric return; 88480093f4SDimitry Andric } 89480093f4SDimitry Andric // For the rest, we have to replace with an empty statement. 90480093f4SDimitry Andric if (isa<EmptyStatement>(S)) 91480093f4SDimitry Andric return; // already an empty statement, nothing to do. 92480093f4SDimitry Andric 93480093f4SDimitry Andric MutationsImpl::replace(S, createEmptyStatement(A)); 94480093f4SDimitry Andric } 95