RewriteRule.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- RewriteRule.h - RewriteRule class ----------------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file
  15. /// Defines the RewriteRule class and related functions for creating,
  16. /// modifying and interpreting RewriteRules.
  17. ///
  18. //===----------------------------------------------------------------------===//
  19. #ifndef LLVM_CLANG_TOOLING_TRANSFORMER_REWRITERULE_H
  20. #define LLVM_CLANG_TOOLING_TRANSFORMER_REWRITERULE_H
  21. #include "clang/ASTMatchers/ASTMatchFinder.h"
  22. #include "clang/ASTMatchers/ASTMatchers.h"
  23. #include "clang/ASTMatchers/ASTMatchersInternal.h"
  24. #include "clang/Tooling/Refactoring/AtomicChange.h"
  25. #include "clang/Tooling/Transformer/MatchConsumer.h"
  26. #include "clang/Tooling/Transformer/RangeSelector.h"
  27. #include "llvm/ADT/Any.h"
  28. #include "llvm/ADT/STLExtras.h"
  29. #include "llvm/ADT/SmallVector.h"
  30. #include "llvm/Support/Error.h"
  31. #include <functional>
  32. #include <string>
  33. #include <utility>
  34. namespace clang {
  35. namespace transformer {
  36. // Specifies how to interpret an edit.
  37. enum class EditKind {
  38. // Edits a source range in the file.
  39. Range,
  40. // Inserts an include in the file. The `Replacement` field is the name of the
  41. // newly included file.
  42. AddInclude,
  43. };
  44. /// A concrete description of a source edit, represented by a character range in
  45. /// the source to be replaced and a corresponding replacement string.
  46. struct Edit {
  47. EditKind Kind = EditKind::Range;
  48. CharSourceRange Range;
  49. std::string Replacement;
  50. std::string Note;
  51. llvm::Any Metadata;
  52. };
  53. /// Format of the path in an include directive -- angle brackets or quotes.
  54. enum class IncludeFormat {
  55. Quoted,
  56. Angled,
  57. };
  58. /// Maps a match result to a list of concrete edits (with possible
  59. /// failure). This type is a building block of rewrite rules, but users will
  60. /// generally work in terms of `ASTEdit`s (below) rather than directly in terms
  61. /// of `EditGenerator`.
  62. using EditGenerator = MatchConsumer<llvm::SmallVector<Edit, 1>>;
  63. template <typename T> using Generator = std::shared_ptr<MatchComputation<T>>;
  64. using TextGenerator = Generator<std::string>;
  65. using AnyGenerator = MatchConsumer<llvm::Any>;
  66. // Description of a source-code edit, expressed in terms of an AST node.
  67. // Includes: an ID for the (bound) node, a selector for source related to the
  68. // node, a replacement and, optionally, an explanation for the edit.
  69. //
  70. // * Target: the source code impacted by the rule. This identifies an AST node,
  71. // or part thereof (\c Part), whose source range indicates the extent of the
  72. // replacement applied by the replacement term. By default, the extent is the
  73. // node matched by the pattern term (\c NodePart::Node). Target's are typed
  74. // (\c Kind), which guides the determination of the node extent.
  75. //
  76. // * Replacement: a function that produces a replacement string for the target,
  77. // based on the match result.
  78. //
  79. // * Note: (optional) a note specifically for this edit, potentially referencing
  80. // elements of the match. This will be displayed to the user, where possible;
  81. // for example, in clang-tidy diagnostics. Use of notes should be rare --
  82. // explanations of the entire rewrite should be set in the rule
  83. // (`RewriteRule::Explanation`) instead. Notes serve the rare cases wherein
  84. // edit-specific diagnostics are required.
  85. //
  86. // `ASTEdit` should be built using the `change` convenience functions. For
  87. // example,
  88. // \code
  89. // changeTo(name(fun), cat("Frodo"))
  90. // \endcode
  91. // Or, if we use Stencil for the TextGenerator:
  92. // \code
  93. // using stencil::cat;
  94. // changeTo(statement(thenNode), cat("{", thenNode, "}"))
  95. // changeTo(callArgs(call), cat(x, ",", y))
  96. // \endcode
  97. // Or, if you are changing the node corresponding to the rule's matcher, you can
  98. // use the single-argument override of \c change:
  99. // \code
  100. // changeTo(cat("different_expr"))
  101. // \endcode
  102. struct ASTEdit {
  103. EditKind Kind = EditKind::Range;
  104. RangeSelector TargetRange;
  105. TextGenerator Replacement;
  106. TextGenerator Note;
  107. // Not all transformations will want or need to attach metadata and therefore
  108. // should not be required to do so.
  109. AnyGenerator Metadata = [](const ast_matchers::MatchFinder::MatchResult &)
  110. -> llvm::Expected<llvm::Any> {
  111. return llvm::Expected<llvm::Any>(llvm::Any());
  112. };
  113. };
  114. /// Generates a single (specified) edit.
  115. EditGenerator edit(ASTEdit E);
  116. /// Lifts a list of `ASTEdit`s into an `EditGenerator`.
  117. ///
  118. /// The `EditGenerator` will return an empty vector if any of the edits apply to
  119. /// portions of the source that are ineligible for rewriting (certain
  120. /// interactions with macros, for example) and it will fail if any invariants
  121. /// are violated relating to bound nodes in the match. However, it does not
  122. /// fail in the case of conflicting edits -- conflict handling is left to
  123. /// clients. We recommend use of the \c AtomicChange or \c Replacements classes
  124. /// for assistance in detecting such conflicts.
  125. EditGenerator editList(llvm::SmallVector<ASTEdit, 1> Edits);
  126. /// Generates no edits.
  127. inline EditGenerator noEdits() { return editList({}); }
  128. /// Generates a single, no-op edit anchored at the start location of the
  129. /// specified range. A `noopEdit` may be preferred over `noEdits` to associate a
  130. /// diagnostic `Explanation` with the rule.
  131. EditGenerator noopEdit(RangeSelector Anchor);
  132. /// Generates a single, no-op edit with the associated note anchored at the
  133. /// start location of the specified range.
  134. ASTEdit note(RangeSelector Anchor, TextGenerator Note);
  135. /// Version of `ifBound` specialized to `ASTEdit`.
  136. inline EditGenerator ifBound(std::string ID, ASTEdit TrueEdit,
  137. ASTEdit FalseEdit) {
  138. return ifBound(std::move(ID), edit(std::move(TrueEdit)),
  139. edit(std::move(FalseEdit)));
  140. }
  141. /// Version of `ifBound` that has no "False" branch. If the node is not bound,
  142. /// then no edits are produced.
  143. inline EditGenerator ifBound(std::string ID, ASTEdit TrueEdit) {
  144. return ifBound(std::move(ID), edit(std::move(TrueEdit)), noEdits());
  145. }
  146. /// Flattens a list of generators into a single generator whose elements are the
  147. /// concatenation of the results of the argument generators.
  148. EditGenerator flattenVector(SmallVector<EditGenerator, 2> Generators);
  149. namespace detail {
  150. /// Helper function to construct an \c EditGenerator. Overloaded for common
  151. /// cases so that user doesn't need to specify which factory function to
  152. /// use. This pattern gives benefits similar to implicit constructors, while
  153. /// maintaing a higher degree of explicitness.
  154. inline EditGenerator injectEdits(ASTEdit E) { return edit(std::move(E)); }
  155. inline EditGenerator injectEdits(EditGenerator G) { return G; }
  156. } // namespace detail
  157. template <typename... Ts> EditGenerator flatten(Ts &&...Edits) {
  158. return flattenVector({detail::injectEdits(std::forward<Ts>(Edits))...});
  159. }
  160. // Every rewrite rule is triggered by a match against some AST node.
  161. // Transformer guarantees that this ID is bound to the triggering node whenever
  162. // a rewrite rule is applied.
  163. extern const char RootID[];
  164. /// Replaces a portion of the source text with \p Replacement.
  165. ASTEdit changeTo(RangeSelector Target, TextGenerator Replacement);
  166. /// DEPRECATED: use \c changeTo.
  167. inline ASTEdit change(RangeSelector Target, TextGenerator Replacement) {
  168. return changeTo(std::move(Target), std::move(Replacement));
  169. }
  170. /// Replaces the entirety of a RewriteRule's match with \p Replacement. For
  171. /// example, to replace a function call, one could write:
  172. /// \code
  173. /// makeRule(callExpr(callee(functionDecl(hasName("foo")))),
  174. /// changeTo(cat("bar()")))
  175. /// \endcode
  176. inline ASTEdit changeTo(TextGenerator Replacement) {
  177. return changeTo(node(RootID), std::move(Replacement));
  178. }
  179. /// DEPRECATED: use \c changeTo.
  180. inline ASTEdit change(TextGenerator Replacement) {
  181. return changeTo(std::move(Replacement));
  182. }
  183. /// Inserts \p Replacement before \p S, leaving the source selected by \S
  184. /// unchanged.
  185. inline ASTEdit insertBefore(RangeSelector S, TextGenerator Replacement) {
  186. return changeTo(before(std::move(S)), std::move(Replacement));
  187. }
  188. /// Inserts \p Replacement after \p S, leaving the source selected by \S
  189. /// unchanged.
  190. inline ASTEdit insertAfter(RangeSelector S, TextGenerator Replacement) {
  191. return changeTo(after(std::move(S)), std::move(Replacement));
  192. }
  193. /// Removes the source selected by \p S.
  194. ASTEdit remove(RangeSelector S);
  195. /// Adds an include directive for the given header to the file of `Target`. The
  196. /// particular location specified by `Target` is ignored.
  197. ASTEdit addInclude(RangeSelector Target, StringRef Header,
  198. IncludeFormat Format = IncludeFormat::Quoted);
  199. /// Adds an include directive for the given header to the file associated with
  200. /// `RootID`. If `RootID` matches inside a macro expansion, will add the
  201. /// directive to the file in which the macro was expanded (as opposed to the
  202. /// file in which the macro is defined).
  203. inline ASTEdit addInclude(StringRef Header,
  204. IncludeFormat Format = IncludeFormat::Quoted) {
  205. return addInclude(expansion(node(RootID)), Header, Format);
  206. }
  207. // FIXME: If `Metadata` returns an `llvm::Expected<T>` the `AnyGenerator` will
  208. // construct an `llvm::Expected<llvm::Any>` where no error is present but the
  209. // `llvm::Any` holds the error. This is unlikely but potentially surprising.
  210. // Perhaps the `llvm::Expected` should be unwrapped, or perhaps this should be a
  211. // compile-time error. No solution here is perfect.
  212. //
  213. // Note: This function template accepts any type callable with a MatchResult
  214. // rather than a `std::function` because the return-type needs to be deduced. If
  215. // it accepted a `std::function<R(MatchResult)>`, lambdas or other callable
  216. // types would not be able to deduce `R`, and users would be forced to specify
  217. // explicitly the type they intended to return by wrapping the lambda at the
  218. // call-site.
  219. template <typename Callable>
  220. inline ASTEdit withMetadata(ASTEdit Edit, Callable Metadata) {
  221. Edit.Metadata =
  222. [Gen = std::move(Metadata)](
  223. const ast_matchers::MatchFinder::MatchResult &R) -> llvm::Any {
  224. return Gen(R);
  225. };
  226. return Edit;
  227. }
  228. /// Assuming that the inner range is enclosed by the outer range, creates
  229. /// precision edits to remove the parts of the outer range that are not included
  230. /// in the inner range.
  231. inline EditGenerator shrinkTo(RangeSelector outer, RangeSelector inner) {
  232. return editList({remove(enclose(before(outer), before(inner))),
  233. remove(enclose(after(inner), after(outer)))});
  234. }
  235. /// Description of a source-code transformation.
  236. //
  237. // A *rewrite rule* describes a transformation of source code. A simple rule
  238. // contains each of the following components:
  239. //
  240. // * Matcher: the pattern term, expressed as clang matchers (with Transformer
  241. // extensions).
  242. //
  243. // * Edits: a set of Edits to the source code, described with ASTEdits.
  244. //
  245. // However, rules can also consist of (sub)rules, where the first that matches
  246. // is applied and the rest are ignored. So, the above components together form
  247. // a logical "case" and a rule is a sequence of cases.
  248. //
  249. // Rule cases have an additional, implicit, component: the parameters. These are
  250. // portions of the pattern which are left unspecified, yet bound in the pattern
  251. // so that we can reference them in the edits.
  252. //
  253. // The \c Transformer class can be used to apply the rewrite rule and obtain the
  254. // corresponding replacements.
  255. struct RewriteRuleBase {
  256. struct Case {
  257. ast_matchers::internal::DynTypedMatcher Matcher;
  258. EditGenerator Edits;
  259. };
  260. // We expect RewriteRules will most commonly include only one case.
  261. SmallVector<Case, 1> Cases;
  262. };
  263. /// A source-code transformation with accompanying metadata.
  264. ///
  265. /// When a case of the rule matches, the \c Transformer invokes the
  266. /// corresponding metadata generator and provides it alongside the edits.
  267. template <typename MetadataT> struct RewriteRuleWith : RewriteRuleBase {
  268. SmallVector<Generator<MetadataT>, 1> Metadata;
  269. };
  270. template <> struct RewriteRuleWith<void> : RewriteRuleBase {};
  271. using RewriteRule = RewriteRuleWith<void>;
  272. namespace detail {
  273. RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M,
  274. EditGenerator Edits);
  275. template <typename MetadataT>
  276. RewriteRuleWith<MetadataT> makeRule(ast_matchers::internal::DynTypedMatcher M,
  277. EditGenerator Edits,
  278. Generator<MetadataT> Metadata) {
  279. RewriteRuleWith<MetadataT> R;
  280. R.Cases = {{std::move(M), std::move(Edits)}};
  281. R.Metadata = {std::move(Metadata)};
  282. return R;
  283. }
  284. inline EditGenerator makeEditGenerator(EditGenerator Edits) { return Edits; }
  285. EditGenerator makeEditGenerator(llvm::SmallVector<ASTEdit, 1> Edits);
  286. EditGenerator makeEditGenerator(ASTEdit Edit);
  287. } // namespace detail
  288. /// Constructs a simple \c RewriteRule. \c Edits can be an \c EditGenerator,
  289. /// multiple \c ASTEdits, or a single \c ASTEdit.
  290. /// @{
  291. template <int &..., typename EditsT>
  292. RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M,
  293. EditsT &&Edits) {
  294. return detail::makeRule(
  295. std::move(M), detail::makeEditGenerator(std::forward<EditsT>(Edits)));
  296. }
  297. RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M,
  298. std::initializer_list<ASTEdit> Edits);
  299. /// @}
  300. /// Overloads of \c makeRule that also generate metadata when matching.
  301. /// @{
  302. template <typename MetadataT, int &..., typename EditsT>
  303. RewriteRuleWith<MetadataT> makeRule(ast_matchers::internal::DynTypedMatcher M,
  304. EditsT &&Edits,
  305. Generator<MetadataT> Metadata) {
  306. return detail::makeRule(
  307. std::move(M), detail::makeEditGenerator(std::forward<EditsT>(Edits)),
  308. std::move(Metadata));
  309. }
  310. template <typename MetadataT>
  311. RewriteRuleWith<MetadataT> makeRule(ast_matchers::internal::DynTypedMatcher M,
  312. std::initializer_list<ASTEdit> Edits,
  313. Generator<MetadataT> Metadata) {
  314. return detail::makeRule(std::move(M),
  315. detail::makeEditGenerator(std::move(Edits)),
  316. std::move(Metadata));
  317. }
  318. /// @}
  319. /// For every case in Rule, adds an include directive for the given header. The
  320. /// common use is assumed to be a rule with only one case. For example, to
  321. /// replace a function call and add headers corresponding to the new code, one
  322. /// could write:
  323. /// \code
  324. /// auto R = makeRule(callExpr(callee(functionDecl(hasName("foo")))),
  325. /// changeTo(cat("bar()")));
  326. /// addInclude(R, "path/to/bar_header.h");
  327. /// addInclude(R, "vector", IncludeFormat::Angled);
  328. /// \endcode
  329. void addInclude(RewriteRuleBase &Rule, llvm::StringRef Header,
  330. IncludeFormat Format = IncludeFormat::Quoted);
  331. /// Applies the first rule whose pattern matches; other rules are ignored. If
  332. /// the matchers are independent then order doesn't matter. In that case,
  333. /// `applyFirst` is simply joining the set of rules into one.
  334. //
  335. // `applyFirst` is like an `anyOf` matcher with an edit action attached to each
  336. // of its cases. Anywhere you'd use `anyOf(m1.bind("id1"), m2.bind("id2"))` and
  337. // then dispatch on those ids in your code for control flow, `applyFirst` lifts
  338. // that behavior to the rule level. So, you can write `applyFirst({makeRule(m1,
  339. // action1), makeRule(m2, action2), ...});`
  340. //
  341. // For example, consider a type `T` with a deterministic serialization function,
  342. // `serialize()`. For performance reasons, we would like to make it
  343. // non-deterministic. Therefore, we want to drop the expectation that
  344. // `a.serialize() = b.serialize() iff a = b` (although we'll maintain
  345. // `deserialize(a.serialize()) = a`).
  346. //
  347. // We have three cases to consider (for some equality function, `eq`):
  348. // ```
  349. // eq(a.serialize(), b.serialize()) --> eq(a,b)
  350. // eq(a, b.serialize()) --> eq(deserialize(a), b)
  351. // eq(a.serialize(), b) --> eq(a, deserialize(b))
  352. // ```
  353. //
  354. // `applyFirst` allows us to specify each independently:
  355. // ```
  356. // auto eq_fun = functionDecl(...);
  357. // auto method_call = cxxMemberCallExpr(...);
  358. //
  359. // auto two_calls = callExpr(callee(eq_fun), hasArgument(0, method_call),
  360. // hasArgument(1, method_call));
  361. // auto left_call =
  362. // callExpr(callee(eq_fun), callExpr(hasArgument(0, method_call)));
  363. // auto right_call =
  364. // callExpr(callee(eq_fun), callExpr(hasArgument(1, method_call)));
  365. //
  366. // RewriteRule R = applyFirst({makeRule(two_calls, two_calls_action),
  367. // makeRule(left_call, left_call_action),
  368. // makeRule(right_call, right_call_action)});
  369. // ```
  370. /// @{
  371. template <typename MetadataT>
  372. RewriteRuleWith<MetadataT>
  373. applyFirst(ArrayRef<RewriteRuleWith<MetadataT>> Rules) {
  374. RewriteRuleWith<MetadataT> R;
  375. for (auto &Rule : Rules) {
  376. assert(Rule.Cases.size() == Rule.Metadata.size() &&
  377. "mis-match in case and metadata array size");
  378. R.Cases.append(Rule.Cases.begin(), Rule.Cases.end());
  379. R.Metadata.append(Rule.Metadata.begin(), Rule.Metadata.end());
  380. }
  381. return R;
  382. }
  383. template <>
  384. RewriteRuleWith<void> applyFirst(ArrayRef<RewriteRuleWith<void>> Rules);
  385. template <typename MetadataT>
  386. RewriteRuleWith<MetadataT>
  387. applyFirst(const std::vector<RewriteRuleWith<MetadataT>> &Rules) {
  388. return applyFirst(llvm::ArrayRef(Rules));
  389. }
  390. template <typename MetadataT>
  391. RewriteRuleWith<MetadataT>
  392. applyFirst(std::initializer_list<RewriteRuleWith<MetadataT>> Rules) {
  393. return applyFirst(llvm::ArrayRef(Rules.begin(), Rules.end()));
  394. }
  395. /// @}
  396. /// Converts a \c RewriteRuleWith<T> to a \c RewriteRule by stripping off the
  397. /// metadata generators.
  398. template <int &..., typename MetadataT>
  399. std::enable_if_t<!std::is_same<MetadataT, void>::value, RewriteRule>
  400. stripMetadata(RewriteRuleWith<MetadataT> Rule) {
  401. RewriteRule R;
  402. R.Cases = std::move(Rule.Cases);
  403. return R;
  404. }
  405. /// Applies `Rule` to all descendants of the node bound to `NodeId`. `Rule` can
  406. /// refer to nodes bound by the calling rule. `Rule` is not applied to the node
  407. /// itself.
  408. ///
  409. /// For example,
  410. /// ```
  411. /// auto InlineX =
  412. /// makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
  413. /// makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))).bind("f"),
  414. /// flatten(
  415. /// changeTo(name("f"), cat("newName")),
  416. /// rewriteDescendants("body", InlineX)));
  417. /// ```
  418. /// Here, we find the function `f`, change its name to `newName` and change all
  419. /// appearances of `x` in its body to `3`.
  420. EditGenerator rewriteDescendants(std::string NodeId, RewriteRule Rule);
  421. /// The following three functions are a low-level part of the RewriteRule
  422. /// API. We expose them for use in implementing the fixtures that interpret
  423. /// RewriteRule, like Transformer and TransfomerTidy, or for more advanced
  424. /// users.
  425. //
  426. // FIXME: These functions are really public, if advanced, elements of the
  427. // RewriteRule API. Recast them as such. Or, just declare these functions
  428. // public and well-supported and move them out of `detail`.
  429. namespace detail {
  430. /// The following overload set is a version of `rewriteDescendants` that
  431. /// operates directly on the AST, rather than generating a Transformer
  432. /// combinator. It applies `Rule` to all descendants of `Node`, although not
  433. /// `Node` itself. `Rule` can refer to nodes bound in `Result`.
  434. ///
  435. /// For example, assuming that "body" is bound to a function body in MatchResult
  436. /// `Results`, this will produce edits to change all appearances of `x` in that
  437. /// body to `3`.
  438. /// ```
  439. /// auto InlineX =
  440. /// makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
  441. /// const auto *Node = Results.Nodes.getNodeAs<Stmt>("body");
  442. /// auto Edits = rewriteDescendants(*Node, InlineX, Results);
  443. /// ```
  444. /// @{
  445. llvm::Expected<SmallVector<Edit, 1>>
  446. rewriteDescendants(const Decl &Node, RewriteRule Rule,
  447. const ast_matchers::MatchFinder::MatchResult &Result);
  448. llvm::Expected<SmallVector<Edit, 1>>
  449. rewriteDescendants(const Stmt &Node, RewriteRule Rule,
  450. const ast_matchers::MatchFinder::MatchResult &Result);
  451. llvm::Expected<SmallVector<Edit, 1>>
  452. rewriteDescendants(const TypeLoc &Node, RewriteRule Rule,
  453. const ast_matchers::MatchFinder::MatchResult &Result);
  454. llvm::Expected<SmallVector<Edit, 1>>
  455. rewriteDescendants(const DynTypedNode &Node, RewriteRule Rule,
  456. const ast_matchers::MatchFinder::MatchResult &Result);
  457. /// @}
  458. /// Builds a single matcher for the rule, covering all of the rule's cases.
  459. /// Only supports Rules whose cases' matchers share the same base "kind"
  460. /// (`Stmt`, `Decl`, etc.) Deprecated: use `buildMatchers` instead, which
  461. /// supports mixing matchers of different kinds.
  462. ast_matchers::internal::DynTypedMatcher
  463. buildMatcher(const RewriteRuleBase &Rule);
  464. /// Builds a set of matchers that cover the rule.
  465. ///
  466. /// One matcher is built for each distinct node matcher base kind: Stmt, Decl,
  467. /// etc. Node-matchers for `QualType` and `Type` are not permitted, since such
  468. /// nodes carry no source location information and are therefore not relevant
  469. /// for rewriting. If any such matchers are included, will return an empty
  470. /// vector.
  471. std::vector<ast_matchers::internal::DynTypedMatcher>
  472. buildMatchers(const RewriteRuleBase &Rule);
  473. /// Gets the beginning location of the source matched by a rewrite rule. If the
  474. /// match occurs within a macro expansion, returns the beginning of the
  475. /// expansion point. `Result` must come from the matching of a rewrite rule.
  476. SourceLocation
  477. getRuleMatchLoc(const ast_matchers::MatchFinder::MatchResult &Result);
  478. /// Returns the index of the \c Case of \c Rule that was selected in the match
  479. /// result. Assumes a matcher built with \c buildMatcher.
  480. size_t findSelectedCase(const ast_matchers::MatchFinder::MatchResult &Result,
  481. const RewriteRuleBase &Rule);
  482. } // namespace detail
  483. } // namespace transformer
  484. } // namespace clang
  485. #endif // LLVM_CLANG_TOOLING_TRANSFORMER_REWRITERULE_H
  486. #ifdef __GNUC__
  487. #pragma GCC diagnostic pop
  488. #endif