Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Tooling/Syntax/Mutations.cpp
35271 views
1
//===- Mutations.cpp ------------------------------------------*- C++ -*-=====//
2
//
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
6
//
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"
20
#include <cassert>
21
#include <string>
22
23
using namespace clang;
24
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 {
28
public:
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);
38
39
New->setRole(Role);
40
auto *P = Anchor->getParent();
41
P->replaceChildRangeLowLevel(Anchor->getNextSibling(),
42
Anchor->getNextSibling(), New);
43
44
P->assertInvariants();
45
}
46
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());
56
57
New->Role = Old->Role;
58
auto *P = Old->getParent();
59
P->replaceChildRangeLowLevel(Old, Old->getNextSibling(), New);
60
61
P->assertInvariants();
62
}
63
64
/// Completely remove the node from its parent.
65
static void remove(syntax::Node *N) {
66
assert(N != nullptr);
67
assert(N->Parent != nullptr);
68
assert(N->canModify());
69
70
auto *P = N->getParent();
71
P->replaceChildRangeLowLevel(N, N->getNextSibling(),
72
/*New=*/nullptr);
73
74
P->assertInvariants();
75
N->assertInvariants();
76
}
77
};
78
79
void syntax::removeStatement(syntax::Arena &A, TokenBufferTokenManager &TBTM,
80
syntax::Statement *S) {
81
assert(S);
82
assert(S->canModify());
83
84
if (isa<CompoundStatement>(S->getParent())) {
85
// A child of CompoundStatement can just be safely removed.
86
MutationsImpl::remove(S);
87
return;
88
}
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.
92
93
MutationsImpl::replace(S, createEmptyStatement(A, TBTM));
94
}
95
96