xref: /freebsd-src/contrib/llvm-project/clang/lib/Tooling/Syntax/Mutations.cpp (revision fcaf7f8644a9988098ac6be2165bce3ea4786e91)
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);
33e8d8bef9SDimitry Andric     assert(Anchor->Parent != nullptr);
34480093f4SDimitry Andric     assert(New->Parent == nullptr);
35480093f4SDimitry Andric     assert(New->NextSibling == nullptr);
36e8d8bef9SDimitry Andric     assert(New->PreviousSibling == nullptr);
37e8d8bef9SDimitry Andric     assert(New->isDetached());
38480093f4SDimitry Andric     assert(Role != NodeRole::Detached);
39480093f4SDimitry Andric 
405ffd83dbSDimitry Andric     New->setRole(Role);
41e8d8bef9SDimitry Andric     auto *P = Anchor->getParent();
42e8d8bef9SDimitry Andric     P->replaceChildRangeLowLevel(Anchor->getNextSibling(),
43e8d8bef9SDimitry 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);
55e8d8bef9SDimitry Andric     assert(New->PreviousSibling == nullptr);
56480093f4SDimitry Andric     assert(New->isDetached());
57480093f4SDimitry Andric 
58480093f4SDimitry Andric     New->Role = Old->Role;
59e8d8bef9SDimitry Andric     auto *P = Old->getParent();
60e8d8bef9SDimitry 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) {
67e8d8bef9SDimitry Andric     assert(N != nullptr);
68e8d8bef9SDimitry Andric     assert(N->Parent != nullptr);
69e8d8bef9SDimitry Andric     assert(N->canModify());
70e8d8bef9SDimitry Andric 
71e8d8bef9SDimitry Andric     auto *P = N->getParent();
72e8d8bef9SDimitry 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 
80*fcaf7f86SDimitry Andric void syntax::removeStatement(syntax::Arena &A, TokenBufferTokenManager &TBTM,
81*fcaf7f86SDimitry Andric                              syntax::Statement *S) {
82480093f4SDimitry Andric   assert(S);
83480093f4SDimitry Andric   assert(S->canModify());
84480093f4SDimitry Andric 
85e8d8bef9SDimitry Andric   if (isa<CompoundStatement>(S->getParent())) {
86480093f4SDimitry Andric     // A child of CompoundStatement can just be safely removed.
87480093f4SDimitry Andric     MutationsImpl::remove(S);
88480093f4SDimitry Andric     return;
89480093f4SDimitry Andric   }
90480093f4SDimitry Andric   // For the rest, we have to replace with an empty statement.
91480093f4SDimitry Andric   if (isa<EmptyStatement>(S))
92480093f4SDimitry Andric     return; // already an empty statement, nothing to do.
93480093f4SDimitry Andric 
94*fcaf7f86SDimitry Andric   MutationsImpl::replace(S, createEmptyStatement(A, TBTM));
95480093f4SDimitry Andric }
96