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