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