Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Tooling/Transformer/RewriteRule.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- Transformer.cpp - Transformer library implementation ---*- 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
9
#include "clang/Tooling/Transformer/RewriteRule.h"
10
#include "clang/AST/ASTTypeTraits.h"
11
#include "clang/AST/Stmt.h"
12
#include "clang/ASTMatchers/ASTMatchFinder.h"
13
#include "clang/ASTMatchers/ASTMatchers.h"
14
#include "clang/Basic/SourceLocation.h"
15
#include "clang/Tooling/Transformer/SourceCode.h"
16
#include "llvm/ADT/Optional.h"
17
#include "llvm/ADT/StringRef.h"
18
#include "llvm/Support/Errc.h"
19
#include "llvm/Support/Error.h"
20
#include <map>
21
#include <string>
22
#include <utility>
23
#include <vector>
24
25
using namespace clang;
26
using namespace transformer;
27
28
using ast_matchers::MatchFinder;
29
using ast_matchers::internal::DynTypedMatcher;
30
31
using MatchResult = MatchFinder::MatchResult;
32
33
const char transformer::RootID[] = "___root___";
34
35
static Expected<SmallVector<transformer::Edit, 1>>
36
125
translateEdits(const MatchResult &Result, ArrayRef<ASTEdit> ASTEdits) {
37
125
  SmallVector<transformer::Edit, 1> Edits;
38
132
  for (const auto &E : ASTEdits) {
39
132
    Expected<CharSourceRange> Range = E.TargetRange(Result);
40
132
    if (!Range)
41
2
      return Range.takeError();
42
130
    llvm::Optional<CharSourceRange> EditRange =
43
130
        tooling::getRangeForEdit(*Range, *Result.Context);
44
    // FIXME: let user specify whether to treat this case as an error or ignore
45
    // it as is currently done. This behavior is problematic in that it hides
46
    // failures from bad ranges. Also, the behavior here differs from
47
    // `flatten`. Here, we abort (without error), whereas flatten, if it hits an
48
    // empty list, does not abort. As a result, `editList({A,B})` is not
49
    // equivalent to `flatten(edit(A), edit(B))`. The former will abort if `A`
50
    // produces a bad range, whereas the latter will simply ignore A.
51
130
    if (!EditRange)
52
2
      return SmallVector<Edit, 0>();
53
128
    auto Replacement = E.Replacement->eval(Result);
54
128
    if (!Replacement)
55
3
      return Replacement.takeError();
56
125
    auto Metadata = E.Metadata(Result);
57
125
    if (!Metadata)
58
0
      return Metadata.takeError();
59
125
    transformer::Edit T;
60
125
    T.Kind = E.Kind;
61
125
    T.Range = *EditRange;
62
125
    T.Replacement = std::move(*Replacement);
63
125
    T.Metadata = std::move(*Metadata);
64
125
    Edits.push_back(std::move(T));
65
125
  }
66
118
  return Edits;
67
125
}
68
69
11
EditGenerator transformer::editList(SmallVector<ASTEdit, 1> Edits) {
70
11
  return [Edits = std::move(Edits)](const MatchResult &Result) {
71
10
    return translateEdits(Result, Edits);
72
10
  };
73
11
}
74
75
78
EditGenerator transformer::edit(ASTEdit Edit) {
76
115
  return [Edit = std::move(Edit)](const MatchResult &Result) {
77
115
    return translateEdits(Result, {Edit});
78
115
  };
79
78
}
80
81
1
EditGenerator transformer::noopEdit(RangeSelector Anchor) {
82
1
  return [Anchor = std::move(Anchor)](const MatchResult &Result)
83
1
             -> Expected<SmallVector<transformer::Edit, 1>> {
84
1
    Expected<CharSourceRange> Range = Anchor(Result);
85
1
    if (!Range)
86
0
      return Range.takeError();
87
    // In case the range is inside a macro expansion, map the location back to a
88
    // "real" source location.
89
1
    SourceLocation Begin =
90
1
        Result.SourceManager->getSpellingLoc(Range->getBegin());
91
1
    Edit E;
92
    // Implicitly, leave `E.Replacement` as the empty string.
93
1
    E.Kind = EditKind::Range;
94
1
    E.Range = CharSourceRange::getCharRange(Begin, Begin);
95
1
    return SmallVector<Edit, 1>{E};
96
1
  };
97
1
}
98
99
EditGenerator
100
5
transformer::flattenVector(SmallVector<EditGenerator, 2> Generators) {
101
5
  if (Generators.size() == 1)
102
0
    return std::move(Generators[0]);
103
5
  return
104
5
      [Gs = std::move(Generators)](
105
5
          const MatchResult &Result) -> llvm::Expected<SmallVector<Edit, 1>> {
106
5
        SmallVector<Edit, 1> AllEdits;
107
12
        for (const auto &G : Gs) {
108
12
          llvm::Expected<SmallVector<Edit, 1>> Edits = G(Result);
109
12
          if (!Edits)
110
0
            return Edits.takeError();
111
12
          AllEdits.append(Edits->begin(), Edits->end());
112
12
        }
113
5
        return AllEdits;
114
5
      };
115
5
}
116
117
86
ASTEdit transformer::changeTo(RangeSelector Target, TextGenerator Replacement) {
118
86
  ASTEdit E;
119
86
  E.TargetRange = std::move(Target);
120
86
  E.Replacement = std::move(Replacement);
121
86
  return E;
122
86
}
123
124
namespace {
125
/// A \c TextGenerator that always returns a fixed string.
126
class SimpleTextGenerator : public MatchComputation<std::string> {
127
  std::string S;
128
129
public:
130
9
  SimpleTextGenerator(std::string S) : S(std::move(S)) {}
131
  llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &,
132
9
                   std::string *Result) const override {
133
9
    Result->append(S);
134
9
    return llvm::Error::success();
135
9
  }
136
0
  std::string toString() const override {
137
0
    return (llvm::Twine("text(\"") + S + "\")").str();
138
0
  }
139
};
140
} // namespace
141
142
9
static TextGenerator makeText(std::string S) {
143
9
  return std::make_shared<SimpleTextGenerator>(std::move(S));
144
9
}
145
146
4
ASTEdit transformer::remove(RangeSelector S) {
147
4
  return change(std::move(S), makeText(""));
148
4
}
149
150
5
static std::string formatHeaderPath(StringRef Header, IncludeFormat Format) {
151
5
  switch (Format) {
152
3
  case transformer::IncludeFormat::Quoted:
153
3
    return Header.str();
154
2
  case transformer::IncludeFormat::Angled:
155
2
    return ("<" + Header + ">").str();
156
5
  }
157
0
  llvm_unreachable("Unknown transformer::IncludeFormat enum");
158
0
}
159
160
ASTEdit transformer::addInclude(RangeSelector Target, StringRef Header,
161
5
                                IncludeFormat Format) {
162
5
  ASTEdit E;
163
5
  E.Kind = EditKind::AddInclude;
164
5
  E.TargetRange = Target;
165
5
  E.Replacement = makeText(formatHeaderPath(Header, Format));
166
5
  return E;
167
5
}
168
169
EditGenerator
170
5
transformer::detail::makeEditGenerator(llvm::SmallVector<ASTEdit, 1> Edits) {
171
5
  return editList(std::move(Edits));
172
5
}
173
174
67
EditGenerator transformer::detail::makeEditGenerator(ASTEdit Edit) {
175
67
  return edit(std::move(Edit));
176
67
}
177
178
RewriteRule transformer::detail::makeRule(DynTypedMatcher M,
179
81
                                          EditGenerator Edits) {
180
81
  RewriteRule R;
181
81
  R.Cases = {{std::move(M), std::move(Edits)}};
182
81
  return R;
183
81
}
184
185
RewriteRule transformer::makeRule(ast_matchers::internal::DynTypedMatcher M,
186
5
                                  std::initializer_list<ASTEdit> Edits) {
187
5
  return detail::makeRule(std::move(M),
188
5
                          detail::makeEditGenerator(std::move(Edits)));
189
5
}
190
191
namespace {
192
193
/// Unconditionally binds the given node set before trying `InnerMatcher` and
194
/// keeps the bound nodes on a successful match.
195
template <typename T>
196
class BindingsMatcher : public ast_matchers::internal::MatcherInterface<T> {
197
  ast_matchers::BoundNodes Nodes;
198
  const ast_matchers::internal::Matcher<T> InnerMatcher;
199
200
public:
201
  explicit BindingsMatcher(ast_matchers::BoundNodes Nodes,
202
                           ast_matchers::internal::Matcher<T> InnerMatcher)
203
10
      : Nodes(std::move(Nodes)), InnerMatcher(std::move(InnerMatcher)) {}
RewriteRule.cpp:(anonymous namespace)::BindingsMatcher<clang::Decl>::BindingsMatcher(clang::ast_matchers::BoundNodes, clang::ast_matchers::internal::Matcher<clang::Decl>)
Line
Count
Source
203
4
      : Nodes(std::move(Nodes)), InnerMatcher(std::move(InnerMatcher)) {}
RewriteRule.cpp:(anonymous namespace)::BindingsMatcher<clang::Stmt>::BindingsMatcher(clang::ast_matchers::BoundNodes, clang::ast_matchers::internal::Matcher<clang::Stmt>)
Line
Count
Source
203
4
      : Nodes(std::move(Nodes)), InnerMatcher(std::move(InnerMatcher)) {}
RewriteRule.cpp:(anonymous namespace)::BindingsMatcher<clang::TypeLoc>::BindingsMatcher(clang::ast_matchers::BoundNodes, clang::ast_matchers::internal::Matcher<clang::TypeLoc>)
Line
Count
Source
203
2
      : Nodes(std::move(Nodes)), InnerMatcher(std::move(InnerMatcher)) {}
204
205
  bool matches(
206
      const T &Node, ast_matchers::internal::ASTMatchFinder *Finder,
207
10
      ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
208
10
    ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
209
10
    for (const auto &N : Nodes.getMap())
210
32
      Result.setBinding(N.first, N.second);
211
10
    if (InnerMatcher.matches(Node, Finder, &Result)) {
212
10
      *Builder = std::move(Result);
213
10
      return true;
214
10
    }
215
0
    return false;
216
10
  }
RewriteRule.cpp:(anonymous namespace)::BindingsMatcher<clang::Decl>::matches(clang::Decl const&, clang::ast_matchers::internal::ASTMatchFinder*, clang::ast_matchers::internal::BoundNodesTreeBuilder*) const
Line
Count
Source
207
4
      ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
208
4
    ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
209
4
    for (const auto &N : Nodes.getMap())
210
13
      Result.setBinding(N.first, N.second);
211
4
    if (InnerMatcher.matches(Node, Finder, &Result)) {
212
4
      *Builder = std::move(Result);
213
4
      return true;
214
4
    }
215
0
    return false;
216
4
  }
RewriteRule.cpp:(anonymous namespace)::BindingsMatcher<clang::Stmt>::matches(clang::Stmt const&, clang::ast_matchers::internal::ASTMatchFinder*, clang::ast_matchers::internal::BoundNodesTreeBuilder*) const
Line
Count
Source
207
4
      ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
208
4
    ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
209
4
    for (const auto &N : Nodes.getMap())
210
13
      Result.setBinding(N.first, N.second);
211
4
    if (InnerMatcher.matches(Node, Finder, &Result)) {
212
4
      *Builder = std::move(Result);
213
4
      return true;
214
4
    }
215
0
    return false;
216
4
  }
RewriteRule.cpp:(anonymous namespace)::BindingsMatcher<clang::TypeLoc>::matches(clang::TypeLoc const&, clang::ast_matchers::internal::ASTMatchFinder*, clang::ast_matchers::internal::BoundNodesTreeBuilder*) const
Line
Count
Source
207
2
      ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
208
2
    ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
209
2
    for (const auto &N : Nodes.getMap())
210
6
      Result.setBinding(N.first, N.second);
211
2
    if (InnerMatcher.matches(Node, Finder, &Result)) {
212
2
      *Builder = std::move(Result);
213
2
      return true;
214
2
    }
215
0
    return false;
216
2
  }
217
};
218
219
/// Matches nodes of type T that have at least one descendant node for which the
220
/// given inner matcher matches.  Will match for each descendant node that
221
/// matches.  Based on ForEachDescendantMatcher, but takes a dynamic matcher,
222
/// instead of a static one, because it is used by RewriteRule, which carries
223
/// (only top-level) dynamic matchers.
224
template <typename T>
225
class DynamicForEachDescendantMatcher
226
    : public ast_matchers::internal::MatcherInterface<T> {
227
  const DynTypedMatcher DescendantMatcher;
228
229
public:
230
  explicit DynamicForEachDescendantMatcher(DynTypedMatcher DescendantMatcher)
231
10
      : DescendantMatcher(std::move(DescendantMatcher)) {}
RewriteRule.cpp:(anonymous namespace)::DynamicForEachDescendantMatcher<clang::Decl>::DynamicForEachDescendantMatcher(clang::ast_matchers::internal::DynTypedMatcher)
Line
Count
Source
231
4
      : DescendantMatcher(std::move(DescendantMatcher)) {}
RewriteRule.cpp:(anonymous namespace)::DynamicForEachDescendantMatcher<clang::Stmt>::DynamicForEachDescendantMatcher(clang::ast_matchers::internal::DynTypedMatcher)
Line
Count
Source
231
4
      : DescendantMatcher(std::move(DescendantMatcher)) {}
RewriteRule.cpp:(anonymous namespace)::DynamicForEachDescendantMatcher<clang::TypeLoc>::DynamicForEachDescendantMatcher(clang::ast_matchers::internal::DynTypedMatcher)
Line
Count
Source
231
2
      : DescendantMatcher(std::move(DescendantMatcher)) {}
232
233
  bool matches(
234
      const T &Node, ast_matchers::internal::ASTMatchFinder *Finder,
235
10
      ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
236
10
    return Finder->matchesDescendantOf(
237
10
        Node, this->DescendantMatcher, Builder,
238
10
        ast_matchers::internal::ASTMatchFinder::BK_All);
239
10
  }
RewriteRule.cpp:(anonymous namespace)::DynamicForEachDescendantMatcher<clang::Decl>::matches(clang::Decl const&, clang::ast_matchers::internal::ASTMatchFinder*, clang::ast_matchers::internal::BoundNodesTreeBuilder*) const
Line
Count
Source
235
4
      ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
236
4
    return Finder->matchesDescendantOf(
237
4
        Node, this->DescendantMatcher, Builder,
238
4
        ast_matchers::internal::ASTMatchFinder::BK_All);
239
4
  }
RewriteRule.cpp:(anonymous namespace)::DynamicForEachDescendantMatcher<clang::Stmt>::matches(clang::Stmt const&, clang::ast_matchers::internal::ASTMatchFinder*, clang::ast_matchers::internal::BoundNodesTreeBuilder*) const
Line
Count
Source
235
4
      ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
236
4
    return Finder->matchesDescendantOf(
237
4
        Node, this->DescendantMatcher, Builder,
238
4
        ast_matchers::internal::ASTMatchFinder::BK_All);
239
4
  }
RewriteRule.cpp:(anonymous namespace)::DynamicForEachDescendantMatcher<clang::TypeLoc>::matches(clang::TypeLoc const&, clang::ast_matchers::internal::ASTMatchFinder*, clang::ast_matchers::internal::BoundNodesTreeBuilder*) const
Line
Count
Source
235
2
      ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
236
2
    return Finder->matchesDescendantOf(
237
2
        Node, this->DescendantMatcher, Builder,
238
2
        ast_matchers::internal::ASTMatchFinder::BK_All);
239
2
  }
240
};
241
242
template <typename T>
243
ast_matchers::internal::Matcher<T>
244
forEachDescendantDynamically(ast_matchers::BoundNodes Nodes,
245
10
                             DynTypedMatcher M) {
246
10
  return ast_matchers::internal::makeMatcher(new BindingsMatcher<T>(
247
10
      std::move(Nodes),
248
10
      ast_matchers::internal::makeMatcher(
249
10
          new DynamicForEachDescendantMatcher<T>(std::move(M)))));
250
10
}
RewriteRule.cpp:clang::ast_matchers::internal::Matcher<clang::Decl> (anonymous namespace)::forEachDescendantDynamically<clang::Decl>(clang::ast_matchers::BoundNodes, clang::ast_matchers::internal::DynTypedMatcher)
Line
Count
Source
245
4
                             DynTypedMatcher M) {
246
4
  return ast_matchers::internal::makeMatcher(new BindingsMatcher<T>(
247
4
      std::move(Nodes),
248
4
      ast_matchers::internal::makeMatcher(
249
4
          new DynamicForEachDescendantMatcher<T>(std::move(M)))));
250
4
}
RewriteRule.cpp:clang::ast_matchers::internal::Matcher<clang::Stmt> (anonymous namespace)::forEachDescendantDynamically<clang::Stmt>(clang::ast_matchers::BoundNodes, clang::ast_matchers::internal::DynTypedMatcher)
Line
Count
Source
245
4
                             DynTypedMatcher M) {
246
4
  return ast_matchers::internal::makeMatcher(new BindingsMatcher<T>(
247
4
      std::move(Nodes),
248
4
      ast_matchers::internal::makeMatcher(
249
4
          new DynamicForEachDescendantMatcher<T>(std::move(M)))));
250
4
}
RewriteRule.cpp:clang::ast_matchers::internal::Matcher<clang::TypeLoc> (anonymous namespace)::forEachDescendantDynamically<clang::TypeLoc>(clang::ast_matchers::BoundNodes, clang::ast_matchers::internal::DynTypedMatcher)
Line
Count
Source
245
2
                             DynTypedMatcher M) {
246
2
  return ast_matchers::internal::makeMatcher(new BindingsMatcher<T>(
247
2
      std::move(Nodes),
248
2
      ast_matchers::internal::makeMatcher(
249
2
          new DynamicForEachDescendantMatcher<T>(std::move(M)))));
250
2
}
251
252
class ApplyRuleCallback : public MatchFinder::MatchCallback {
253
public:
254
10
  ApplyRuleCallback(RewriteRule Rule) : Rule(std::move(Rule)) {}
255
256
  template <typename T>
257
  void registerMatchers(const ast_matchers::BoundNodes &Nodes,
258
10
                        MatchFinder *MF) {
259
10
    for (auto &Matcher : transformer::detail::buildMatchers(Rule))
260
10
      MF->addMatcher(forEachDescendantDynamically<T>(Nodes, Matcher), this);
261
10
  }
RewriteRule.cpp:void (anonymous namespace)::ApplyRuleCallback::registerMatchers<clang::Decl>(clang::ast_matchers::BoundNodes const&, clang::ast_matchers::MatchFinder*)
Line
Count
Source
258
4
                        MatchFinder *MF) {
259
4
    for (auto &Matcher : transformer::detail::buildMatchers(Rule))
260
4
      MF->addMatcher(forEachDescendantDynamically<T>(Nodes, Matcher), this);
261
4
  }
RewriteRule.cpp:void (anonymous namespace)::ApplyRuleCallback::registerMatchers<clang::Stmt>(clang::ast_matchers::BoundNodes const&, clang::ast_matchers::MatchFinder*)
Line
Count
Source
258
4
                        MatchFinder *MF) {
259
4
    for (auto &Matcher : transformer::detail::buildMatchers(Rule))
260
4
      MF->addMatcher(forEachDescendantDynamically<T>(Nodes, Matcher), this);
261
4
  }
RewriteRule.cpp:void (anonymous namespace)::ApplyRuleCallback::registerMatchers<clang::TypeLoc>(clang::ast_matchers::BoundNodes const&, clang::ast_matchers::MatchFinder*)
Line
Count
Source
258
2
                        MatchFinder *MF) {
259
2
    for (auto &Matcher : transformer::detail::buildMatchers(Rule))
260
2
      MF->addMatcher(forEachDescendantDynamically<T>(Nodes, Matcher), this);
261
2
  }
262
263
32
  void run(const MatchFinder::MatchResult &Result) override {
264
32
    if (!Edits)
265
0
      return;
266
32
    size_t I = transformer::detail::findSelectedCase(Result, Rule);
267
32
    auto Transformations = Rule.Cases[I].Edits(Result);
268
32
    if (!Transformations) {
269
0
      Edits = Transformations.takeError();
270
0
      return;
271
0
    }
272
32
    Edits->append(Transformations->begin(), Transformations->end());
273
32
  }
274
275
  RewriteRule Rule;
276
277
  // Initialize to a non-error state.
278
  Expected<SmallVector<Edit, 1>> Edits = SmallVector<Edit, 1>();
279
};
280
} // namespace
281
282
template <typename T>
283
llvm::Expected<SmallVector<clang::transformer::Edit, 1>>
284
rewriteDescendantsImpl(const T &Node, RewriteRule Rule,
285
10
                       const MatchResult &Result) {
286
10
  ApplyRuleCallback Callback(std::move(Rule));
287
10
  MatchFinder Finder;
288
10
  Callback.registerMatchers<T>(Result.Nodes, &Finder);
289
10
  Finder.match(Node, *Result.Context);
290
10
  return std::move(Callback.Edits);
291
10
}
llvm::Expected<llvm::SmallVector<clang::transformer::Edit, 1u> > rewriteDescendantsImpl<clang::Decl>(clang::Decl const&, clang::transformer::RewriteRuleWith<void>, clang::ast_matchers::MatchFinder::MatchResult const&)
Line
Count
Source
285
4
                       const MatchResult &Result) {
286
4
  ApplyRuleCallback Callback(std::move(Rule));
287
4
  MatchFinder Finder;
288
4
  Callback.registerMatchers<T>(Result.Nodes, &Finder);
289
4
  Finder.match(Node, *Result.Context);
290
4
  return std::move(Callback.Edits);
291
4
}
llvm::Expected<llvm::SmallVector<clang::transformer::Edit, 1u> > rewriteDescendantsImpl<clang::Stmt>(clang::Stmt const&, clang::transformer::RewriteRuleWith<void>, clang::ast_matchers::MatchFinder::MatchResult const&)
Line
Count
Source
285
4
                       const MatchResult &Result) {
286
4
  ApplyRuleCallback Callback(std::move(Rule));
287
4
  MatchFinder Finder;
288
4
  Callback.registerMatchers<T>(Result.Nodes, &Finder);
289
4
  Finder.match(Node, *Result.Context);
290
4
  return std::move(Callback.Edits);
291
4
}
llvm::Expected<llvm::SmallVector<clang::transformer::Edit, 1u> > rewriteDescendantsImpl<clang::TypeLoc>(clang::TypeLoc const&, clang::transformer::RewriteRuleWith<void>, clang::ast_matchers::MatchFinder::MatchResult const&)
Line
Count
Source
285
2
                       const MatchResult &Result) {
286
2
  ApplyRuleCallback Callback(std::move(Rule));
287
2
  MatchFinder Finder;
288
2
  Callback.registerMatchers<T>(Result.Nodes, &Finder);
289
2
  Finder.match(Node, *Result.Context);
290
2
  return std::move(Callback.Edits);
291
2
}
292
293
llvm::Expected<SmallVector<clang::transformer::Edit, 1>>
294
transformer::detail::rewriteDescendants(const Decl &Node, RewriteRule Rule,
295
1
                                        const MatchResult &Result) {
296
1
  return rewriteDescendantsImpl(Node, std::move(Rule), Result);
297
1
}
298
299
llvm::Expected<SmallVector<clang::transformer::Edit, 1>>
300
transformer::detail::rewriteDescendants(const Stmt &Node, RewriteRule Rule,
301
1
                                        const MatchResult &Result) {
302
1
  return rewriteDescendantsImpl(Node, std::move(Rule), Result);
303
1
}
304
305
llvm::Expected<SmallVector<clang::transformer::Edit, 1>>
306
transformer::detail::rewriteDescendants(const TypeLoc &Node, RewriteRule Rule,
307
1
                                        const MatchResult &Result) {
308
1
  return rewriteDescendantsImpl(Node, std::move(Rule), Result);
309
1
}
310
311
llvm::Expected<SmallVector<clang::transformer::Edit, 1>>
312
transformer::detail::rewriteDescendants(const DynTypedNode &DNode,
313
                                        RewriteRule Rule,
314
8
                                        const MatchResult &Result) {
315
8
  if (const auto *Node = DNode.get<Decl>())
316
3
    return rewriteDescendantsImpl(*Node, std::move(Rule), Result);
317
5
  if (const auto *Node = DNode.get<Stmt>())
318
3
    return rewriteDescendantsImpl(*Node, std::move(Rule), Result);
319
2
  if (const auto *Node = DNode.get<TypeLoc>())
320
1
    return rewriteDescendantsImpl(*Node, std::move(Rule), Result);
321
322
1
  return llvm::make_error<llvm::StringError>(
323
1
      llvm::errc::invalid_argument,
324
1
      "type unsupported for recursive rewriting, Kind=" +
325
1
          DNode.getNodeKind().asStringRef());
326
2
}
327
328
EditGenerator transformer::rewriteDescendants(std::string NodeId,
329
8
                                              RewriteRule Rule) {
330
8
  return [NodeId = std::move(NodeId),
331
8
          Rule = std::move(Rule)](const MatchResult &Result)
332
8
             -> llvm::Expected<SmallVector<clang::transformer::Edit, 1>> {
333
8
    const ast_matchers::BoundNodes::IDToNodeMap &NodesMap =
334
8
        Result.Nodes.getMap();
335
8
    auto It = NodesMap.find(NodeId);
336
8
    if (It == NodesMap.end())
337
1
      return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
338
1
                                                 "ID not bound: " + NodeId);
339
7
    return detail::rewriteDescendants(It->second, std::move(Rule), Result);
340
8
  };
341
8
}
342
343
void transformer::addInclude(RewriteRuleBase &Rule, StringRef Header,
344
2
                             IncludeFormat Format) {
345
2
  for (auto &Case : Rule.Cases)
346
2
    Case.Edits = flatten(std::move(Case.Edits), addInclude(Header, Format));
347
2
}
348
349
#ifndef NDEBUG
350
// Filters for supported matcher kinds. FIXME: Explicitly list the allowed kinds
351
// (all node matcher types except for `QualType` and `Type`), rather than just
352
// banning `QualType` and `Type`.
353
92
static bool hasValidKind(const DynTypedMatcher &M) {
354
92
  return !M.canConvertTo<QualType>();
355
92
}
356
#endif
357
358
// Binds each rule's matcher to a unique (and deterministic) tag based on
359
// `TagBase` and the id paired with the case. All of the returned matchers have
360
// their traversal kind explicitly set, either based on a pre-set kind or to the
361
// provided `DefaultTraversalKind`.
362
static std::vector<DynTypedMatcher> taggedMatchers(
363
    StringRef TagBase,
364
    const SmallVectorImpl<std::pair<size_t, RewriteRule::Case>> &Cases,
365
86
    TraversalKind DefaultTraversalKind) {
366
86
  std::vector<DynTypedMatcher> Matchers;
367
86
  Matchers.reserve(Cases.size());
368
92
  for (const auto &Case : Cases) {
369
92
    std::string Tag = (TagBase + Twine(Case.first)).str();
370
    // HACK: Many matchers are not bindable, so ensure that tryBind will work.
371
92
    DynTypedMatcher BoundMatcher(Case.second.Matcher);
372
92
    BoundMatcher.setAllowBind(true);
373
92
    auto M = *BoundMatcher.tryBind(Tag);
374
92
    Matchers.push_back(!M.getTraversalKind()
375
92
                           ? 
M.withTraversalKind(DefaultTraversalKind)82
376
92
                           : 
std::move(M)10
);
377
92
  }
378
86
  return Matchers;
379
86
}
380
381
// Simply gathers the contents of the various rules into a single rule. The
382
// actual work to combine these into an ordered choice is deferred to matcher
383
// registration.
384
template <>
385
RewriteRuleWith<void>
386
4
transformer::applyFirst(ArrayRef<RewriteRuleWith<void>> Rules) {
387
4
  RewriteRule R;
388
4
  for (auto &Rule : Rules)
389
9
    R.Cases.append(Rule.Cases.begin(), Rule.Cases.end());
390
4
  return R;
391
4
}
392
393
std::vector<DynTypedMatcher>
394
84
transformer::detail::buildMatchers(const RewriteRuleBase &Rule) {
395
  // Map the cases into buckets of matchers -- one for each "root" AST kind,
396
  // which guarantees that they can be combined in a single anyOf matcher. Each
397
  // case is paired with an identifying number that is converted to a string id
398
  // in `taggedMatchers`.
399
84
  std::map<ASTNodeKind,
400
84
           SmallVector<std::pair<size_t, RewriteRuleBase::Case>, 1>>
401
84
      Buckets;
402
84
  const SmallVectorImpl<RewriteRule::Case> &Cases = Rule.Cases;
403
176
  for (int I = 0, N = Cases.size(); I < N; 
++I92
) {
404
92
    assert(hasValidKind(Cases[I].Matcher) &&
405
92
           "Matcher must be non-(Qual)Type node matcher");
406
0
    Buckets[Cases[I].Matcher.getSupportedKind()].emplace_back(I, Cases[I]);
407
92
  }
408
409
  // Each anyOf explicitly controls the traversal kind. The anyOf itself is set
410
  // to `TK_AsIs` to ensure no nodes are skipped, thereby deferring to the kind
411
  // of the branches. Then, each branch is either left as is, if the kind is
412
  // already set, or explicitly set to `TK_AsIs`. We choose this setting because
413
  // it is the default interpretation of matchers.
414
84
  std::vector<DynTypedMatcher> Matchers;
415
86
  for (const auto &Bucket : Buckets) {
416
86
    DynTypedMatcher M = DynTypedMatcher::constructVariadic(
417
86
        DynTypedMatcher::VO_AnyOf, Bucket.first,
418
86
        taggedMatchers("Tag", Bucket.second, TK_AsIs));
419
86
    M.setAllowBind(true);
420
    // `tryBind` is guaranteed to succeed, because `AllowBind` was set to true.
421
86
    Matchers.push_back(M.tryBind(RootID)->withTraversalKind(TK_AsIs));
422
86
  }
423
84
  return Matchers;
424
84
}
425
426
0
DynTypedMatcher transformer::detail::buildMatcher(const RewriteRuleBase &Rule) {
427
0
  std::vector<DynTypedMatcher> Ms = buildMatchers(Rule);
428
0
  assert(Ms.size() == 1 && "Cases must have compatible matchers.");
429
0
  return Ms[0];
430
0
}
431
432
0
SourceLocation transformer::detail::getRuleMatchLoc(const MatchResult &Result) {
433
0
  auto &NodesMap = Result.Nodes.getMap();
434
0
  auto Root = NodesMap.find(RootID);
435
0
  assert(Root != NodesMap.end() && "Transformation failed: missing root node.");
436
0
  llvm::Optional<CharSourceRange> RootRange = tooling::getRangeForEdit(
437
0
      CharSourceRange::getTokenRange(Root->second.getSourceRange()),
438
0
      *Result.Context);
439
0
  if (RootRange)
440
0
    return RootRange->getBegin();
441
  // The match doesn't have a coherent range, so fall back to the expansion
442
  // location as the "beginning" of the match.
443
0
  return Result.SourceManager->getExpansionLoc(
444
0
      Root->second.getSourceRange().getBegin());
445
0
}
446
447
// Finds the case that was "selected" -- that is, whose matcher triggered the
448
// `MatchResult`.
449
size_t transformer::detail::findSelectedCase(const MatchResult &Result,
450
131
                                             const RewriteRuleBase &Rule) {
451
131
  if (Rule.Cases.size() == 1)
452
120
    return 0;
453
454
11
  auto &NodesMap = Result.Nodes.getMap();
455
17
  for (size_t i = 0, N = Rule.Cases.size(); i < N; 
++i6
) {
456
17
    std::string Tag = ("Tag" + Twine(i)).str();
457
17
    if (NodesMap.find(Tag) != NodesMap.end())
458
11
      return i;
459
17
  }
460
0
  llvm_unreachable("No tag found for this rule.");
461
0
}