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