Coverage Report

Created: 2020-11-24 06:42

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