87 lines · cpp
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-exception6//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 15using namespace clang;16 17// This class has access to the internals of tree nodes. Its sole purpose is to18// define helpers that allow implementing the high-level mutation operations.19class syntax::MutationsImpl {20public: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 71void 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