1 //===- Mutations.cpp ------------------------------------------*- C++ -*-=====//
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
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"
23 using namespace clang
;
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
{
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
);
40 auto *P
= Anchor
->getParent();
41 P
->replaceChildRangeLowLevel(Anchor
->getNextSibling(),
42 Anchor
->getNextSibling(), New
);
44 P
->assertInvariants();
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());
57 New
->Role
= Old
->Role
;
58 auto *P
= Old
->getParent();
59 P
->replaceChildRangeLowLevel(Old
, Old
->getNextSibling(), New
);
61 P
->assertInvariants();
64 /// Completely remove the node from its parent.
65 static void remove(syntax::Node
*N
) {
67 assert(N
->Parent
!= nullptr);
68 assert(N
->canModify());
70 auto *P
= N
->getParent();
71 P
->replaceChildRangeLowLevel(N
, N
->getNextSibling(),
74 P
->assertInvariants();
75 N
->assertInvariants();
79 void syntax::removeStatement(syntax::Arena
&A
, TokenBufferTokenManager
&TBTM
,
80 syntax::Statement
*S
) {
82 assert(S
->canModify());
84 if (isa
<CompoundStatement
>(S
->getParent())) {
85 // A child of CompoundStatement can just be safely removed.
86 MutationsImpl::remove(S
);
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.
93 MutationsImpl::replace(S
, createEmptyStatement(A
, TBTM
));