xref: /openbsd-src/gnu/llvm/clang/docs/ClangTransformerTutorial.rst (revision 12c855180aad702bbcca06e0398d774beeafb155)
1*12c85518Srobert==========================
2*12c85518SrobertClang Transformer Tutorial
3*12c85518Srobert==========================
4*12c85518Srobert
5*12c85518SrobertA tutorial on how to write a source-to-source translation tool using Clang Transformer.
6*12c85518Srobert
7*12c85518Srobert.. contents::
8*12c85518Srobert   :local:
9*12c85518Srobert
10*12c85518SrobertWhat is Clang Transformer?
11*12c85518Srobert--------------------------
12*12c85518Srobert
13*12c85518SrobertClang Transformer is a framework for writing C++ diagnostics and program
14*12c85518Sroberttransformations. It is built on the clang toolchain and the LibTooling library,
15*12c85518Srobertbut aims to hide much of the complexity of clang's native, low-level libraries.
16*12c85518Srobert
17*12c85518SrobertThe core abstraction of Transformer is the *rewrite rule*, which specifies how
18*12c85518Srobertto change a given program pattern into a new form. Here are some examples of
19*12c85518Sroberttasks you can achieve with Transformer:
20*12c85518Srobert
21*12c85518Srobert*   warn against using the name ``MkX`` for a declared function,
22*12c85518Srobert*   change ``MkX`` to ``MakeX``, where ``MkX`` is the name of a declared function,
23*12c85518Srobert*   change ``s.size()`` to ``Size(s)``, where ``s`` is a ``string``,
24*12c85518Srobert*   collapse ``e.child().m()`` to ``e.m()``, for any expression ``e`` and method named
25*12c85518Srobert    ``m``.
26*12c85518Srobert
27*12c85518SrobertAll of the examples have a common form: they identify a pattern that is the
28*12c85518Sroberttarget of the transformation, they specify an *edit* to the code identified by
29*12c85518Srobertthe pattern, and their pattern and edit refer to common variables, like ``s``,
30*12c85518Srobert``e``, and ``m``, that range over code fragments. Our first and second examples also
31*12c85518Srobertspecify constraints on the pattern that aren't apparent from the syntax alone,
32*12c85518Srobertlike "``s`` is a ``string``." Even the first example ("warn ...") shares this form,
33*12c85518Sroberteven though it doesn't change any of the code -- it's "edit" is simply a no-op.
34*12c85518Srobert
35*12c85518SrobertTransformer helps users succinctly specify rules of this sort and easily execute
36*12c85518Srobertthem locally over a collection of files, apply them to selected portions of
37*12c85518Sroberta codebase, or even bundle them as a clang-tidy check for ongoing application.
38*12c85518Srobert
39*12c85518SrobertWho is Clang Transformer for?
40*12c85518Srobert-----------------------------
41*12c85518Srobert
42*12c85518SrobertClang Transformer is for developers who want to write clang-tidy checks or write
43*12c85518Sroberttools to modify a large number of C++ files in (roughly) the same way. What
44*12c85518Srobertqualifies as "large" really depends on the nature of the change and your
45*12c85518Srobertpatience for repetitive editing. In our experience, automated solutions become
46*12c85518Srobertworthwhile somewhere between 100 and 500 files.
47*12c85518Srobert
48*12c85518SrobertGetting Started
49*12c85518Srobert---------------
50*12c85518Srobert
51*12c85518SrobertPatterns in Transformer are expressed with :doc:`clang's AST matchers <LibASTMatchers>`.
52*12c85518SrobertMatchers are a language of combinators for describing portions of a clang
53*12c85518SrobertAbstract Syntax Tree (AST). Since clang's AST includes complete type information
54*12c85518Srobert(within the limits of single `Translation Unit (TU)`_,
55*12c85518Srobertthese patterns can even encode rich constraints on the type properties of AST
56*12c85518Srobertnodes.
57*12c85518Srobert
58*12c85518Srobert.. _`Translation Unit (TU)`: https://en.wikipedia.org/wiki/Translation_unit_\(programming\)
59*12c85518Srobert
60*12c85518SrobertWe assume a familiarity with the clang AST and the corresponding AST matchers
61*12c85518Srobertfor the purpose of this tutorial. Users who are unfamiliar with either are
62*12c85518Srobertencouraged to start with the recommended references in `Related Reading`_.
63*12c85518Srobert
64*12c85518SrobertExample: style-checking names
65*12c85518Srobert^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66*12c85518Srobert
67*12c85518SrobertAssume you have a style-guide rule which forbids functions from being named
68*12c85518Srobert"MkX" and you want to write a check that catches any violations of this rule. We
69*12c85518Srobertcan express this a Transformer rewrite rule:
70*12c85518Srobert
71*12c85518Srobert.. code-block:: c++
72*12c85518Srobert
73*12c85518Srobert   makeRule(functionDecl(hasName("MkX").bind("fun"),
74*12c85518Srobert	    noopEdit(node("fun")),
75*12c85518Srobert	    cat("The name ``MkX`` is not allowed for functions; please rename"));
76*12c85518Srobert
77*12c85518Srobert``makeRule`` is our go-to function for generating rewrite rules. It takes three
78*12c85518Srobertarguments: the pattern, the edit, and (optionally) an explanatory note. In our
79*12c85518Srobertexample, the pattern (``functionDecl(...)``) identifies the declaration of the
80*12c85518Srobertfunction ``MkX``. Since we're just diagnosing the problem, but not suggesting a
81*12c85518Srobertfix, our edit is an no-op. But, it contains an *anchor* for the diagnostic
82*12c85518Srobertmessage: ``node("fun")`` says to associate the message with the source range of
83*12c85518Srobertthe AST node bound to "fun"; in this case, the ill-named function declaration.
84*12c85518SrobertFinally, we use ``cat`` to build a message that explains the change. Regarding the
85*12c85518Srobertname ``cat`` -- we'll discuss it in more detail below, but suffice it to say that
86*12c85518Srobertit can also take multiple arguments and concatenate their results.
87*12c85518Srobert
88*12c85518SrobertNote that the result of ``makeRule`` is a value of type
89*12c85518Srobert``clang::transformer::RewriteRule``, but most users don't need to care about the
90*12c85518Srobertdetails of this type.
91*12c85518Srobert
92*12c85518SrobertExample: renaming a function
93*12c85518Srobert^^^^^^^^^^^^^^^^^^^^^^^^^^^^
94*12c85518Srobert
95*12c85518SrobertNow, let's extend this example to a *transformation*; specifically, the second
96*12c85518Srobertexample above:
97*12c85518Srobert
98*12c85518Srobert.. code-block:: c++
99*12c85518Srobert
100*12c85518Srobert   makeRule(declRefExpr(to(functionDecl(hasName("MkX")))),
101*12c85518Srobert	    changeTo(cat("MakeX")),
102*12c85518Srobert	    cat("MkX has been renamed MakeX"));
103*12c85518Srobert
104*12c85518SrobertIn this example, the pattern (``declRefExpr(...)``) identifies any *reference* to
105*12c85518Srobertthe function ``MkX``, rather than the declaration itself, as in our previous
106*12c85518Srobertexample. Our edit (``changeTo(...)``) says to *change* the code matched by the
107*12c85518Srobertpattern *to* the text "MakeX". Finally, we use ``cat`` again to build a message
108*12c85518Srobertthat explains the change.
109*12c85518Srobert
110*12c85518SrobertHere are some example changes that this rule would make:
111*12c85518Srobert
112*12c85518Srobert+--------------------------+----------------------------+
113*12c85518Srobert| Original                 | Result                     |
114*12c85518Srobert+==========================+============================+
115*12c85518Srobert| ``X x = MkX(3);``        | ``X x = MakeX(3);``        |
116*12c85518Srobert+--------------------------+----------------------------+
117*12c85518Srobert| ``CallFactory(MkX, 3);`` | ``CallFactory(MakeX, 3);`` |
118*12c85518Srobert+--------------------------+----------------------------+
119*12c85518Srobert| ``auto f = MkX;``        | ``auto f = MakeX;``        |
120*12c85518Srobert+--------------------------+----------------------------+
121*12c85518Srobert
122*12c85518SrobertExample: method to function
123*12c85518Srobert^^^^^^^^^^^^^^^^^^^^^^^^^^^
124*12c85518Srobert
125*12c85518SrobertNext, let's write a rule to replace a method call with a (free) function call,
126*12c85518Srobertapplied to the original method call's target object. Specifically, "change
127*12c85518Srobert``s.size()`` to ``Size(s)``, where ``s`` is a ``string``." We start with a simpler
128*12c85518Srobertchange that ignores the type of ``s``. That is, it will modify *any* method call
129*12c85518Srobertwhere the method is named "size":
130*12c85518Srobert
131*12c85518Srobert.. code-block:: c++
132*12c85518Srobert
133*12c85518Srobert   llvm::StringRef s = "str";
134*12c85518Srobert   makeRule(
135*12c85518Srobert     cxxMemberCallExpr(
136*12c85518Srobert       on(expr().bind(s)),
137*12c85518Srobert       callee(cxxMethodDecl(hasName("size")))),
138*12c85518Srobert     changeTo(cat("Size(", node(s), ")")),
139*12c85518Srobert     cat("Method ``size`` is deprecated in favor of free function ``Size``"));
140*12c85518Srobert
141*12c85518SrobertWe express the pattern with the given AST matcher, which binds the method call's
142*12c85518Sroberttarget to ``s`` [#f1]_. For the edit, we again use ``changeTo``, but this
143*12c85518Sroberttime we construct the term from multiple parts, which we compose with ``cat``. The
144*12c85518Srobertsecond part of our term is ``node(s)``, which selects the source code
145*12c85518Srobertcorresponding to the AST node ``s`` that was bound when a match was found in the
146*12c85518SrobertAST for our rule's pattern. ``node(s)`` constructs a ``RangeSelector``, which, when
147*12c85518Srobertused in ``cat``, indicates that the selected source should be inserted in the
148*12c85518Srobertoutput at that point.
149*12c85518Srobert
150*12c85518SrobertNow, we probably don't want to rewrite *all* invocations of "size" methods, just
151*12c85518Srobertthose on ``std::string``\ s. We can achieve this change simply by refining our
152*12c85518Srobertmatcher. The rest of the rule remains unchanged:
153*12c85518Srobert
154*12c85518Srobert.. code-block:: c++
155*12c85518Srobert
156*12c85518Srobert   llvm::StringRef s = "str";
157*12c85518Srobert   makeRule(
158*12c85518Srobert     cxxMemberCallExpr(
159*12c85518Srobert       on(expr(hasType(namedDecl(hasName("std::string"))))
160*12c85518Srobert	 .bind(s)),
161*12c85518Srobert       callee(cxxMethodDecl(hasName("size")))),
162*12c85518Srobert     changeTo(cat("Size(", node(s), ")")),
163*12c85518Srobert     cat("Method ``size`` is deprecated in favor of free function ``Size``"));
164*12c85518Srobert
165*12c85518SrobertExample: rewriting method calls
166*12c85518Srobert^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
167*12c85518Srobert
168*12c85518SrobertIn this example, we delete an "intermediary" method call in a string of
169*12c85518Srobertinvocations. This scenario can arise, for example, if you want to collapse a
170*12c85518Srobertsubstructure into its parent.
171*12c85518Srobert
172*12c85518Srobert.. code-block:: c++
173*12c85518Srobert
174*12c85518Srobert   llvm::StringRef e = "expr", m = "member";
175*12c85518Srobert   auto child_call = cxxMemberCallExpr(on(expr().bind(e)),
176*12c85518Srobert				       callee(cxxMethodDecl(hasName("child"))));
177*12c85518Srobert   makeRule(cxxMemberCallExpr(on(child_call), callee(memberExpr().bind(m)),
178*12c85518Srobert	    changeTo(cat(e, ".", member(m), "()"))),
179*12c85518Srobert	    cat("``child`` accessor is being removed; call ",
180*12c85518Srobert		member(m), " directly on parent"));
181*12c85518Srobert
182*12c85518SrobertThis rule isn't quite what we want: it will rewrite ``my_object.child().foo()`` to
183*12c85518Srobert``my_object.foo()``, but it will also rewrite ``my_ptr->child().foo()`` to
184*12c85518Srobert``my_ptr.foo()``, which is not what we intend. We could fix this by restricting
185*12c85518Srobertthe pattern with ``not(isArrow())`` in the definition of ``child_call``. Yet, we
186*12c85518Srobert*want* to rewrite calls through pointers.
187*12c85518Srobert
188*12c85518SrobertTo capture this idiom, we provide the ``access`` combinator to intelligently
189*12c85518Srobertconstruct a field/method access. In our example, the member access is expressed
190*12c85518Srobertas:
191*12c85518Srobert
192*12c85518Srobert.. code-block:: c++
193*12c85518Srobert
194*12c85518Srobert   access(e, cat(member(m)))
195*12c85518Srobert
196*12c85518SrobertThe first argument specifies the object being accessed and the second, a
197*12c85518Srobertdescription of the field/method name. In this case, we specify that the method
198*12c85518Srobertname should be copied from the source -- specifically, the source range of ``m``'s
199*12c85518Srobertmember. To construct the method call, we would use this expression in ``cat``:
200*12c85518Srobert
201*12c85518Srobert.. code-block:: c++
202*12c85518Srobert
203*12c85518Srobert   cat(access(e, cat(member(m))), "()")
204*12c85518Srobert
205*12c85518SrobertReference: ranges, stencils, edits, rules
206*12c85518Srobert-----------------------------------------
207*12c85518Srobert
208*12c85518SrobertThe above examples demonstrate just the basics of rewrite rules. Every element
209*12c85518Srobertwe touched on has more available constructors: range selectors, stencils, edits
210*12c85518Srobertand rules. In this section, we'll briefly review each in turn, with references
211*12c85518Srobertto the source headers for up-to-date information. First, though, we clarify what
212*12c85518Srobertrewrite rules are actually rewriting.
213*12c85518Srobert
214*12c85518SrobertRewriting ASTs to... Text?
215*12c85518Srobert^^^^^^^^^^^^^^^^^^^^^^^^^^
216*12c85518Srobert
217*12c85518SrobertThe astute reader may have noticed that we've been somewhat vague in our
218*12c85518Srobertexplanation of what the rewrite rules are actually rewriting. We've referred to
219*12c85518Srobert"code", but code can be represented both as raw source text and as an abstract
220*12c85518Srobertsyntax tree. So, which one is it?
221*12c85518Srobert
222*12c85518SrobertIdeally, we'd be rewriting the input AST to a new AST, but clang's AST is not
223*12c85518Srobertterribly amenable to this kind of transformation. So, we compromise: we express
224*12c85518Srobertour patterns and the names that they bind in terms of the AST, but our changes
225*12c85518Srobertin terms of source code text. We've designed Transformer's language to bridge
226*12c85518Srobertthe gap between the two representations, in an attempt to minimize the user's
227*12c85518Srobertneed to reason about source code locations and other, low-level syntactic
228*12c85518Srobertdetails.
229*12c85518Srobert
230*12c85518SrobertRange Selectors
231*12c85518Srobert^^^^^^^^^^^^^^^
232*12c85518Srobert
233*12c85518SrobertTransformer provides a small API for describing source ranges: the
234*12c85518Srobert``RangeSelector`` combinators. These ranges are most commonly used to specify the
235*12c85518Srobertsource code affected by an edit and to extract source code in constructing new
236*12c85518Sroberttext.
237*12c85518Srobert
238*12c85518SrobertRoughly, there are two kinds of range combinators: ones that select a source
239*12c85518Srobertrange based on the AST, and others that combine existing ranges into new ranges.
240*12c85518SrobertFor example, ``node`` selects the range of source spanned by a particular AST
241*12c85518Srobertnode, as we've seen, while ``after`` selects the (empty) range located immediately
242*12c85518Srobertafter its argument range. So, ``after(node("id"))`` is the empty range immediately
243*12c85518Srobertfollowing the AST node bound to ``id``.
244*12c85518Srobert
245*12c85518SrobertFor the full collection of ``RangeSelector``\ s, see the header,
246*12c85518Srobert`clang/Tooling/Transformer/RangeSelector.h <https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Tooling/Transformer/RangeSelector.h>`_
247*12c85518Srobert
248*12c85518SrobertStencils
249*12c85518Srobert^^^^^^^^
250*12c85518Srobert
251*12c85518SrobertTransformer offers a large and growing collection of combinators for
252*12c85518Srobertconstructing output. Above, we demonstrated ``cat``, the core function for
253*12c85518Srobertconstructing stencils. It takes a series of arguments, of three possible kinds:
254*12c85518Srobert
255*12c85518Srobert#.  Raw text, to be copied directly to the output.
256*12c85518Srobert#.  Selector: specified with a ``RangeSelector``, indicates a range of source text
257*12c85518Srobert    to copy to the output.
258*12c85518Srobert#.  Builder: an operation that constructs a code snippet from its arguments. For
259*12c85518Srobert    example, the ``access`` function we saw above.
260*12c85518Srobert
261*12c85518SrobertData of these different types are all represented (generically) by a ``Stencil``.
262*12c85518Srobert``cat`` takes text and ``RangeSelector``\ s directly as arguments, rather than
263*12c85518Srobertrequiring that they be constructed with a builder; other builders are
264*12c85518Srobertconstructed explicitly.
265*12c85518Srobert
266*12c85518SrobertIn general, ``Stencil``\ s produce text from a match result. So, they are not
267*12c85518Srobertlimited to generating source code, but can also be used to generate diagnostic
268*12c85518Srobertmessages that reference (named) elements of the matched code, like we saw in the
269*12c85518Srobertexample of rewriting method calls.
270*12c85518Srobert
271*12c85518SrobertFurther details of the ``Stencil`` type are documented in the header file
272*12c85518Srobert`clang/Tooling/Transformer/Stencil.h <https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Tooling/Transformer/Stencil.h>`_.
273*12c85518Srobert
274*12c85518SrobertEdits
275*12c85518Srobert^^^^^
276*12c85518Srobert
277*12c85518SrobertTransformer supports additional forms of edits. First, in a ``changeTo``, we can
278*12c85518Srobertspecify the particular portion of code to be replaced, using the same
279*12c85518Srobert``RangeSelector`` we saw earlier. For example, we could change the function name
280*12c85518Srobertin a function declaration with:
281*12c85518Srobert
282*12c85518Srobert.. code-block:: c++
283*12c85518Srobert
284*12c85518Srobert   makeRule(functionDecl(hasName("bad")).bind(f),
285*12c85518Srobert	    changeTo(name(f), cat("good")),
286*12c85518Srobert	    cat("bad is now good"));
287*12c85518Srobert
288*12c85518SrobertWe also provide simpler editing primitives for insertion and deletion:
289*12c85518Srobert``insertBefore``, ``insertAfter`` and ``remove``. These can all be found in the header
290*12c85518Srobertfile
291*12c85518Srobert`clang/Tooling/Transformer/RewriteRule.h <https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Tooling/Transformer/RewriteRule.h>`_.
292*12c85518Srobert
293*12c85518SrobertWe are not limited one edit per match found. Some situations require making
294*12c85518Srobertmultiple edits for each match. For example, suppose we wanted to swap two
295*12c85518Srobertarguments of a function call.
296*12c85518Srobert
297*12c85518SrobertFor this, we provide an overload of ``makeRule`` that takes a list of edits,
298*12c85518Srobertrather than just a single one. Our example might look like:
299*12c85518Srobert
300*12c85518Srobert.. code-block:: c++
301*12c85518Srobert
302*12c85518Srobert   makeRule(callExpr(...),
303*12c85518Srobert	   {changeTo(node(arg0), cat(node(arg2))),
304*12c85518Srobert	    changeTo(node(arg2), cat(node(arg0)))},
305*12c85518Srobert	   cat("swap the first and third arguments of the call"));
306*12c85518Srobert
307*12c85518Srobert``EditGenerator``\ s (Advanced)
308*12c85518Srobert^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
309*12c85518Srobert
310*12c85518SrobertThe particular edits we've seen so far are all instances of the ``ASTEdit`` class,
311*12c85518Srobertor a list of such. But, not all edits can be expressed as ``ASTEdit``\ s. So, we
312*12c85518Srobertalso support a very general signature for edit generators:
313*12c85518Srobert
314*12c85518Srobert.. code-block:: c++
315*12c85518Srobert
316*12c85518Srobert   using EditGenerator = MatchConsumer<llvm::SmallVector<Edit, 1>>;
317*12c85518Srobert
318*12c85518SrobertThat is, an ``EditGenerator`` is function that maps a ``MatchResult`` to a set
319*12c85518Srobertof edits, or fails. This signature supports a very general form of computation
320*12c85518Srobertover match results. Transformer provides a number of functions for working with
321*12c85518Srobert``EditGenerator``\ s, most notably
322*12c85518Srobert`flatten <https://github.com/llvm/llvm-project/blob/1fabe6e51917bcd7a1242294069c682fe6dffa45/clang/include/clang/Tooling/Transformer/RewriteRule.h#L165-L167>`_
323*12c85518Srobert``EditGenerator``\ s, like list flattening. For the full list, see the header file
324*12c85518Srobert`clang/Tooling/Transformer/RewriteRule.h <https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Tooling/Transformer/RewriteRule.h>`_.
325*12c85518Srobert
326*12c85518SrobertRules
327*12c85518Srobert^^^^^
328*12c85518Srobert
329*12c85518SrobertWe can also compose multiple *rules*, rather than just edits within a rule,
330*12c85518Srobertusing ``applyFirst``: it composes a list of rules as an ordered choice, where
331*12c85518SrobertTransformer applies the first rule whose pattern matches, ignoring others in the
332*12c85518Srobertlist that follow. If the matchers are independent then order doesn't matter. In
333*12c85518Srobertthat case, ``applyFirst`` is simply joining the set of rules into one.
334*12c85518Srobert
335*12c85518SrobertThe benefit of ``applyFirst`` is that, for some problems, it allows the user to
336*12c85518Srobertmore concisely formulate later rules in the list, since their patterns need not
337*12c85518Srobertexplicitly exclude the earlier patterns of the list. For example, consider a set
338*12c85518Srobertof rules that rewrite compound statements, where one rule handles the case of an
339*12c85518Srobertempty compound statement and the other handles non-empty compound statements.
340*12c85518SrobertWith ``applyFirst``, these rules can be expressed compactly as:
341*12c85518Srobert
342*12c85518Srobert.. code-block:: c++
343*12c85518Srobert
344*12c85518Srobert   applyFirst({
345*12c85518Srobert     makeRule(compoundStmt(statementCountIs(0)).bind("empty"), ...),
346*12c85518Srobert     makeRule(compoundStmt().bind("non-empty"),...)
347*12c85518Srobert   })
348*12c85518Srobert
349*12c85518SrobertThe second rule does not need to explicitly specify that the compound statement
350*12c85518Srobertis non-empty -- it follows from the rules position in ``applyFirst``. For more
351*12c85518Srobertcomplicated examples, this can lead to substantially more readable code.
352*12c85518Srobert
353*12c85518SrobertSometimes, a modification to the code might require the inclusion of a
354*12c85518Srobertparticular header file. To this end, users can modify rules to specify include
355*12c85518Srobertdirectives with ``addInclude``.
356*12c85518Srobert
357*12c85518SrobertFor additional documentation on these functions, see the header file
358*12c85518Srobert`clang/Tooling/Transformer/RewriteRule.h <https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Tooling/Transformer/RewriteRule.h>`_.
359*12c85518Srobert
360*12c85518SrobertUsing a RewriteRule as a clang-tidy check
361*12c85518Srobert-----------------------------------------
362*12c85518Srobert
363*12c85518SrobertTransformer supports executing a rewrite rule as a
364*12c85518Srobert`clang-tidy <https://clang.llvm.org/extra/clang-tidy/>`_ check, with the class
365*12c85518Srobert``clang::tidy::utils::TransformerClangTidyCheck``. It is designed to require
366*12c85518Srobertminimal code in the definition. For example, given a rule
367*12c85518Srobert``MyCheckAsRewriteRule``, one can define a tidy check as follows:
368*12c85518Srobert
369*12c85518Srobert.. code-block:: c++
370*12c85518Srobert
371*12c85518Srobert   class MyCheck : public TransformerClangTidyCheck {
372*12c85518Srobert    public:
373*12c85518Srobert     MyCheck(StringRef Name, ClangTidyContext *Context)
374*12c85518Srobert	 : TransformerClangTidyCheck(MyCheckAsRewriteRule, Name, Context) {}
375*12c85518Srobert   };
376*12c85518Srobert
377*12c85518Srobert``TransformerClangTidyCheck`` implements the virtual ``registerMatchers`` and
378*12c85518Srobert``check`` methods based on your rule specification, so you don't need to implement
379*12c85518Srobertthem yourself. If the rule needs to be configured based on the language options
380*12c85518Srobertand/or the clang-tidy configuration, it can be expressed as a function taking
381*12c85518Srobertthese as parameters and (optionally) returning a ``RewriteRule``. This would be
382*12c85518Srobertuseful, for example, for our method-renaming rule, which is parameterized by the
383*12c85518Srobertoriginal name and the target. For details, see
384*12c85518Srobert`clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.h <https://github.com/llvm/llvm-project/blob/main/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.h>`_
385*12c85518Srobert
386*12c85518SrobertRelated Reading
387*12c85518Srobert---------------
388*12c85518Srobert
389*12c85518SrobertA good place to start understanding the clang AST and its matchers is with the
390*12c85518Srobertintroductions on clang's site:
391*12c85518Srobert
392*12c85518Srobert*   :doc:`Introduction to the Clang AST <IntroductionToTheClangAST>`
393*12c85518Srobert*   :doc:`Matching the Clang AST <LibASTMatchers>`
394*12c85518Srobert*   `AST Matcher Reference <https://clang.llvm.org/docs/LibASTMatchersReference.html>`_
395*12c85518Srobert
396*12c85518Srobert.. rubric:: Footnotes
397*12c85518Srobert
398*12c85518Srobert.. [#f1] Technically, it binds it to the string "str", to which our
399*12c85518Srobert    variable ``s`` is bound. But, the choice of that id string is
400*12c85518Srobert    irrelevant, so elide the difference.
401