Path: blob/main/contrib/llvm-project/clang/lib/Tooling/Syntax/Mutations.cpp
35271 views
//===- Mutations.cpp ------------------------------------------*- C++ -*-=====//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7#include "clang/Tooling/Syntax/Mutations.h"8#include "clang/Basic/LLVM.h"9#include "clang/Basic/SourceLocation.h"10#include "clang/Lex/Token.h"11#include "clang/Tooling/Core/Replacement.h"12#include "clang/Tooling/Syntax/BuildTree.h"13#include "clang/Tooling/Syntax/Nodes.h"14#include "clang/Tooling/Syntax/Tokens.h"15#include "clang/Tooling/Syntax/Tree.h"16#include "llvm/ADT/ArrayRef.h"17#include "llvm/ADT/STLExtras.h"18#include "llvm/Support/Casting.h"19#include <cassert>20#include <string>2122using namespace clang;2324// This class has access to the internals of tree nodes. Its sole purpose is to25// define helpers that allow implementing the high-level mutation operations.26class syntax::MutationsImpl {27public:28/// Add a new node with a specified role.29static void addAfter(syntax::Node *Anchor, syntax::Node *New, NodeRole Role) {30assert(Anchor != nullptr);31assert(Anchor->Parent != nullptr);32assert(New->Parent == nullptr);33assert(New->NextSibling == nullptr);34assert(New->PreviousSibling == nullptr);35assert(New->isDetached());36assert(Role != NodeRole::Detached);3738New->setRole(Role);39auto *P = Anchor->getParent();40P->replaceChildRangeLowLevel(Anchor->getNextSibling(),41Anchor->getNextSibling(), New);4243P->assertInvariants();44}4546/// Replace the node, keeping the role.47static void replace(syntax::Node *Old, syntax::Node *New) {48assert(Old != nullptr);49assert(Old->Parent != nullptr);50assert(Old->canModify());51assert(New->Parent == nullptr);52assert(New->NextSibling == nullptr);53assert(New->PreviousSibling == nullptr);54assert(New->isDetached());5556New->Role = Old->Role;57auto *P = Old->getParent();58P->replaceChildRangeLowLevel(Old, Old->getNextSibling(), New);5960P->assertInvariants();61}6263/// Completely remove the node from its parent.64static void remove(syntax::Node *N) {65assert(N != nullptr);66assert(N->Parent != nullptr);67assert(N->canModify());6869auto *P = N->getParent();70P->replaceChildRangeLowLevel(N, N->getNextSibling(),71/*New=*/nullptr);7273P->assertInvariants();74N->assertInvariants();75}76};7778void syntax::removeStatement(syntax::Arena &A, TokenBufferTokenManager &TBTM,79syntax::Statement *S) {80assert(S);81assert(S->canModify());8283if (isa<CompoundStatement>(S->getParent())) {84// A child of CompoundStatement can just be safely removed.85MutationsImpl::remove(S);86return;87}88// For the rest, we have to replace with an empty statement.89if (isa<EmptyStatement>(S))90return; // already an empty statement, nothing to do.9192MutationsImpl::replace(S, createEmptyStatement(A, TBTM));93}949596