Coverage Report

Created: 2020-09-15 12:33

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