/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Tooling/Syntax/Mutations.cpp
Line | Count | Source (jump to first uncovered line) |
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/Optional.h" |
19 | | #include "llvm/ADT/STLExtras.h" |
20 | | #include "llvm/Support/Casting.h" |
21 | | #include <cassert> |
22 | | #include <string> |
23 | | |
24 | | using namespace clang; |
25 | | |
26 | | // This class has access to the internals of tree nodes. Its sole purpose is to |
27 | | // define helpers that allow implementing the high-level mutation operations. |
28 | | class syntax::MutationsImpl { |
29 | | public: |
30 | | /// Add a new node with a specified role. |
31 | 0 | static void addAfter(syntax::Node *Anchor, syntax::Node *New, NodeRole Role) { |
32 | 0 | assert(Anchor != nullptr); |
33 | 0 | assert(Anchor->Parent != nullptr); |
34 | 0 | assert(New->Parent == nullptr); |
35 | 0 | assert(New->NextSibling == nullptr); |
36 | 0 | assert(New->PreviousSibling == nullptr); |
37 | 0 | assert(New->isDetached()); |
38 | 0 | assert(Role != NodeRole::Detached); |
39 | 0 |
|
40 | 0 | New->setRole(Role); |
41 | 0 | auto *P = Anchor->getParent(); |
42 | 0 | P->replaceChildRangeLowLevel(Anchor->getNextSibling(), |
43 | 0 | Anchor->getNextSibling(), New); |
44 | 0 |
|
45 | 0 | P->assertInvariants(); |
46 | 0 | } |
47 | | |
48 | | /// Replace the node, keeping the role. |
49 | 14 | static void replace(syntax::Node *Old, syntax::Node *New) { |
50 | 14 | assert(Old != nullptr); |
51 | 0 | assert(Old->Parent != nullptr); |
52 | 0 | assert(Old->canModify()); |
53 | 0 | assert(New->Parent == nullptr); |
54 | 0 | assert(New->NextSibling == nullptr); |
55 | 0 | assert(New->PreviousSibling == nullptr); |
56 | 0 | assert(New->isDetached()); |
57 | | |
58 | 0 | New->Role = Old->Role; |
59 | 14 | auto *P = Old->getParent(); |
60 | 14 | P->replaceChildRangeLowLevel(Old, Old->getNextSibling(), New); |
61 | | |
62 | 14 | P->assertInvariants(); |
63 | 14 | } |
64 | | |
65 | | /// Completely remove the node from its parent. |
66 | 28 | static void remove(syntax::Node *N) { |
67 | 28 | assert(N != nullptr); |
68 | 0 | assert(N->Parent != nullptr); |
69 | 0 | assert(N->canModify()); |
70 | | |
71 | 0 | auto *P = N->getParent(); |
72 | 28 | P->replaceChildRangeLowLevel(N, N->getNextSibling(), |
73 | 28 | /*New=*/nullptr); |
74 | | |
75 | 28 | P->assertInvariants(); |
76 | 28 | N->assertInvariants(); |
77 | 28 | } |
78 | | }; |
79 | | |
80 | 42 | void syntax::removeStatement(syntax::Arena &A, syntax::Statement *S) { |
81 | 42 | assert(S); |
82 | 0 | assert(S->canModify()); |
83 | | |
84 | 42 | if (isa<CompoundStatement>(S->getParent())) { |
85 | | // A child of CompoundStatement can just be safely removed. |
86 | 28 | MutationsImpl::remove(S); |
87 | 28 | return; |
88 | 28 | } |
89 | | // For the rest, we have to replace with an empty statement. |
90 | 14 | if (isa<EmptyStatement>(S)) |
91 | 0 | return; // already an empty statement, nothing to do. |
92 | | |
93 | 14 | MutationsImpl::replace(S, createEmptyStatement(A)); |
94 | 14 | } |