1*e5dd7070Spatrick========================== 2*e5dd7070SpatrickClang's refactoring engine 3*e5dd7070Spatrick========================== 4*e5dd7070Spatrick 5*e5dd7070SpatrickThis document describes the design of Clang's refactoring engine and provides 6*e5dd7070Spatricka couple of examples that show how various primitives in the refactoring API 7*e5dd7070Spatrickcan be used to implement different refactoring actions. The :doc:`LibTooling` 8*e5dd7070Spatricklibrary provides several other APIs that are used when developing a 9*e5dd7070Spatrickrefactoring action. 10*e5dd7070Spatrick 11*e5dd7070SpatrickRefactoring engine can be used to implement local refactorings that are 12*e5dd7070Spatrickinitiated using a selection in an editor or an IDE. You can combine 13*e5dd7070Spatrick:doc:`AST matchers<LibASTMatchers>` and the refactoring engine to implement 14*e5dd7070Spatrickrefactorings that don't lend themselves well to source selection and/or have to 15*e5dd7070Spatrickquery ASTs for some particular nodes. 16*e5dd7070Spatrick 17*e5dd7070SpatrickWe assume basic knowledge about the Clang AST. See the :doc:`Introduction 18*e5dd7070Spatrickto the Clang AST <IntroductionToTheClangAST>` if you want to learn more 19*e5dd7070Spatrickabout how the AST is structured. 20*e5dd7070Spatrick 21*e5dd7070Spatrick.. FIXME: create new refactoring action tutorial and link to the tutorial 22*e5dd7070Spatrick 23*e5dd7070SpatrickIntroduction 24*e5dd7070Spatrick------------ 25*e5dd7070Spatrick 26*e5dd7070SpatrickClang's refactoring engine defines a set refactoring actions that implement 27*e5dd7070Spatricka number of different source transformations. The ``clang-refactor`` 28*e5dd7070Spatrickcommand-line tool can be used to perform these refactorings. Certain 29*e5dd7070Spatrickrefactorings are also available in other clients like text editors and IDEs. 30*e5dd7070Spatrick 31*e5dd7070SpatrickA refactoring action is a class that defines a list of related refactoring 32*e5dd7070Spatrickoperations (rules). These rules are grouped under a common umbrella - a single 33*e5dd7070Spatrick``clang-refactor`` command. In addition to rules, the refactoring action 34*e5dd7070Spatrickprovides the action's command name and description to ``clang-refactor``. 35*e5dd7070SpatrickEach action must implement the ``RefactoringAction`` interface. Here's an 36*e5dd7070Spatrickoutline of a ``local-rename`` action: 37*e5dd7070Spatrick 38*e5dd7070Spatrick.. code-block:: c++ 39*e5dd7070Spatrick 40*e5dd7070Spatrick class LocalRename final : public RefactoringAction { 41*e5dd7070Spatrick public: 42*e5dd7070Spatrick StringRef getCommand() const override { return "local-rename"; } 43*e5dd7070Spatrick 44*e5dd7070Spatrick StringRef getDescription() const override { 45*e5dd7070Spatrick return "Finds and renames symbols in code with no indexer support"; 46*e5dd7070Spatrick } 47*e5dd7070Spatrick 48*e5dd7070Spatrick RefactoringActionRules createActionRules() const override { 49*e5dd7070Spatrick ... 50*e5dd7070Spatrick } 51*e5dd7070Spatrick }; 52*e5dd7070Spatrick 53*e5dd7070SpatrickRefactoring Action Rules 54*e5dd7070Spatrick------------------------ 55*e5dd7070Spatrick 56*e5dd7070SpatrickAn individual refactoring action is responsible for creating the set of 57*e5dd7070Spatrickgrouped refactoring action rules that represent one refactoring operation. 58*e5dd7070SpatrickAlthough the rules in one action may have a number of different implementations, 59*e5dd7070Spatrickthey should strive to produce a similar result. It should be easy for users to 60*e5dd7070Spatrickidentify which refactoring action produced the result regardless of which 61*e5dd7070Spatrickrefactoring action rule was used. 62*e5dd7070Spatrick 63*e5dd7070SpatrickThe distinction between actions and rules enables the creation of actions 64*e5dd7070Spatrickthat define a set of different rules that produce similar results. For example, 65*e5dd7070Spatrickthe "add missing switch cases" refactoring operation typically adds missing 66*e5dd7070Spatrickcases to one switch at a time. However, it could be useful to have a 67*e5dd7070Spatrickrefactoring that works on all switches that operate on a particular enum, as 68*e5dd7070Spatrickone could then automatically update all of them after adding a new enum 69*e5dd7070Spatrickconstant. To achieve that, we can create two different rules that will use one 70*e5dd7070Spatrick``clang-refactor`` subcommand. The first rule will describe a local operation 71*e5dd7070Spatrickthat's initiated when the user selects a single switch. The second rule will 72*e5dd7070Spatrickdescribe a global operation that works across translation units and is initiated 73*e5dd7070Spatrickwhen the user provides the name of the enum to clang-refactor (or the user could 74*e5dd7070Spatrickselect the enum declaration instead). The clang-refactor tool will then analyze 75*e5dd7070Spatrickthe selection and other options passed to the refactoring action, and will pick 76*e5dd7070Spatrickthe most appropriate rule for the given selection and other options. 77*e5dd7070Spatrick 78*e5dd7070SpatrickRule Types 79*e5dd7070Spatrick^^^^^^^^^^ 80*e5dd7070Spatrick 81*e5dd7070SpatrickClang's refactoring engine supports several different refactoring rules: 82*e5dd7070Spatrick 83*e5dd7070Spatrick- ``SourceChangeRefactoringRule`` produces source replacements that are applied 84*e5dd7070Spatrick to the source files. Subclasses that choose to implement this rule have to 85*e5dd7070Spatrick implement the ``createSourceReplacements`` member function. This type of 86*e5dd7070Spatrick rule is typically used to implement local refactorings that transform the 87*e5dd7070Spatrick source in one translation unit only. 88*e5dd7070Spatrick 89*e5dd7070Spatrick- ``FindSymbolOccurrencesRefactoringRule`` produces a "partial" refactoring 90*e5dd7070Spatrick result: a set of occurrences that refer to a particular symbol. This type 91*e5dd7070Spatrick of rule is typically used to implement an interactive renaming action that 92*e5dd7070Spatrick allows users to specify which occurrences should be renamed during the 93*e5dd7070Spatrick refactoring. Subclasses that choose to implement this rule have to implement 94*e5dd7070Spatrick the ``findSymbolOccurrences`` member function. 95*e5dd7070Spatrick 96*e5dd7070SpatrickThe following set of quick checks might help if you are unsure about the type 97*e5dd7070Spatrickof rule you should use: 98*e5dd7070Spatrick 99*e5dd7070Spatrick#. If you would like to transform the source in one translation unit and if 100*e5dd7070Spatrick you don't need any cross-TU information, then the 101*e5dd7070Spatrick ``SourceChangeRefactoringRule`` should work for you. 102*e5dd7070Spatrick 103*e5dd7070Spatrick#. If you would like to implement a rename-like operation with potential 104*e5dd7070Spatrick interactive components, then ``FindSymbolOccurrencesRefactoringRule`` might 105*e5dd7070Spatrick work for you. 106*e5dd7070Spatrick 107*e5dd7070SpatrickHow to Create a Rule 108*e5dd7070Spatrick^^^^^^^^^^^^^^^^^^^^ 109*e5dd7070Spatrick 110*e5dd7070SpatrickOnce you determine which type of rule is suitable for your needs you can 111*e5dd7070Spatrickimplement the refactoring by subclassing the rule and implementing its 112*e5dd7070Spatrickinterface. The subclass should have a constructor that takes the inputs that 113*e5dd7070Spatrickare needed to perform the refactoring. For example, if you want to implement a 114*e5dd7070Spatrickrule that simply deletes a selection, you should create a subclass of 115*e5dd7070Spatrick``SourceChangeRefactoringRule`` with a constructor that accepts the selection 116*e5dd7070Spatrickrange: 117*e5dd7070Spatrick 118*e5dd7070Spatrick.. code-block:: c++ 119*e5dd7070Spatrick 120*e5dd7070Spatrick class DeleteSelectedRange final : public SourceChangeRefactoringRule { 121*e5dd7070Spatrick public: 122*e5dd7070Spatrick DeleteSelection(SourceRange Selection) : Selection(Selection) {} 123*e5dd7070Spatrick 124*e5dd7070Spatrick Expected<AtomicChanges> 125*e5dd7070Spatrick createSourceReplacements(RefactoringRuleContext &Context) override { 126*e5dd7070Spatrick AtomicChange Replacement(Context.getSources(), Selection.getBegin()); 127*e5dd7070Spatrick Replacement.replace(Context.getSource, 128*e5dd7070Spatrick CharSourceRange::getCharRange(Selection), ""); 129*e5dd7070Spatrick return { Replacement }; 130*e5dd7070Spatrick } 131*e5dd7070Spatrick private: 132*e5dd7070Spatrick SourceRange Selection; 133*e5dd7070Spatrick }; 134*e5dd7070Spatrick 135*e5dd7070SpatrickThe rule's subclass can then be added to the list of refactoring action's 136*e5dd7070Spatrickrules for a particular action using the ``createRefactoringActionRule`` 137*e5dd7070Spatrickfunction. For example, the class that's shown above can be added to the 138*e5dd7070Spatricklist of action rules using the following code: 139*e5dd7070Spatrick 140*e5dd7070Spatrick.. code-block:: c++ 141*e5dd7070Spatrick 142*e5dd7070Spatrick RefactoringActionRules Rules; 143*e5dd7070Spatrick Rules.push_back( 144*e5dd7070Spatrick createRefactoringActionRule<DeleteSelectedRange>( 145*e5dd7070Spatrick SourceRangeSelectionRequirement()) 146*e5dd7070Spatrick ); 147*e5dd7070Spatrick 148*e5dd7070SpatrickThe ``createRefactoringActionRule`` function takes in a list of refactoring 149*e5dd7070Spatrickaction rule requirement values. These values describe the initiation 150*e5dd7070Spatrickrequirements that have to be satisfied by the refactoring engine before the 151*e5dd7070Spatrickprovided action rule can be constructed and invoked. The next section 152*e5dd7070Spatrickdescribes how these requirements are evaluated and lists all the possible 153*e5dd7070Spatrickrequirements that can be used to construct a refactoring action rule. 154*e5dd7070Spatrick 155*e5dd7070SpatrickRefactoring Action Rule Requirements 156*e5dd7070Spatrick------------------------------------ 157*e5dd7070Spatrick 158*e5dd7070SpatrickA refactoring action rule requirement is a value whose type derives from the 159*e5dd7070Spatrick``RefactoringActionRuleRequirement`` class. The type must define an 160*e5dd7070Spatrick``evaluate`` member function that returns a value of type ``Expected<...>``. 161*e5dd7070SpatrickWhen a requirement value is used as an argument to 162*e5dd7070Spatrick``createRefactoringActionRule``, that value is evaluated during the initiation 163*e5dd7070Spatrickof the action rule. The evaluated result is then passed to the rule's 164*e5dd7070Spatrickconstructor unless the evaluation produced an error. For example, the 165*e5dd7070Spatrick``DeleteSelectedRange`` sample rule that's defined in the previous section 166*e5dd7070Spatrickwill be evaluated using the following steps: 167*e5dd7070Spatrick 168*e5dd7070Spatrick#. ``SourceRangeSelectionRequirement``'s ``evaluate`` member function will be 169*e5dd7070Spatrick called first. It will return an ``Expected<SourceRange>``. 170*e5dd7070Spatrick 171*e5dd7070Spatrick#. If the return value is an error the initiation will fail and the error 172*e5dd7070Spatrick will be reported to the client. Note that the client may not report the 173*e5dd7070Spatrick error to the user. 174*e5dd7070Spatrick 175*e5dd7070Spatrick#. Otherwise the source range return value will be used to construct the 176*e5dd7070Spatrick ``DeleteSelectedRange`` rule. The rule will then be invoked as the initiation 177*e5dd7070Spatrick succeeded (all requirements were evaluated successfully). 178*e5dd7070Spatrick 179*e5dd7070SpatrickThe same series of steps applies to any refactoring rule. Firstly, the engine 180*e5dd7070Spatrickwill evaluate all of the requirements. Then it will check if these requirements 181*e5dd7070Spatrickare satisfied (they should not produce an error). Then it will construct the 182*e5dd7070Spatrickrule and invoke it. 183*e5dd7070Spatrick 184*e5dd7070SpatrickThe separation of requirements, their evaluation and the invocation of the 185*e5dd7070Spatrickrefactoring action rule allows the refactoring clients to: 186*e5dd7070Spatrick 187*e5dd7070Spatrick- Disable refactoring action rules whose requirements are not supported. 188*e5dd7070Spatrick 189*e5dd7070Spatrick- Gather the set of options and define a command-line / visual interface 190*e5dd7070Spatrick that allows users to input these options without ever invoking the 191*e5dd7070Spatrick action. 192*e5dd7070Spatrick 193*e5dd7070SpatrickSelection Requirements 194*e5dd7070Spatrick^^^^^^^^^^^^^^^^^^^^^^ 195*e5dd7070Spatrick 196*e5dd7070SpatrickThe refactoring rule requirements that require some form of source selection 197*e5dd7070Spatrickare listed below: 198*e5dd7070Spatrick 199*e5dd7070Spatrick- ``SourceRangeSelectionRequirement`` evaluates to a source range when the 200*e5dd7070Spatrick action is invoked with some sort of selection. This requirement should be 201*e5dd7070Spatrick satisfied when a refactoring is initiated in an editor, even when the user 202*e5dd7070Spatrick has not selected anything (the range will contain the cursor's location in 203*e5dd7070Spatrick that case). 204*e5dd7070Spatrick 205*e5dd7070Spatrick.. FIXME: Future selection requirements 206*e5dd7070Spatrick 207*e5dd7070Spatrick.. FIXME: Maybe mention custom selection requirements? 208*e5dd7070Spatrick 209*e5dd7070SpatrickOther Requirements 210*e5dd7070Spatrick^^^^^^^^^^^^^^^^^^ 211*e5dd7070Spatrick 212*e5dd7070SpatrickThere are several other requirements types that can be used when creating 213*e5dd7070Spatricka refactoring rule: 214*e5dd7070Spatrick 215*e5dd7070Spatrick- The ``RefactoringOptionsRequirement`` requirement is an abstract class that 216*e5dd7070Spatrick should be subclassed by requirements working with options. The more 217*e5dd7070Spatrick concrete ``OptionRequirement`` requirement is a simple implementation of the 218*e5dd7070Spatrick aforementioned class that returns the value of the specified option when 219*e5dd7070Spatrick it's evaluated. The next section talks more about refactoring options and 220*e5dd7070Spatrick how they can be used when creating a rule. 221*e5dd7070Spatrick 222*e5dd7070SpatrickRefactoring Options 223*e5dd7070Spatrick------------------- 224*e5dd7070Spatrick 225*e5dd7070SpatrickRefactoring options are values that affect a refactoring operation and are 226*e5dd7070Spatrickspecified either using command-line options or another client-specific 227*e5dd7070Spatrickmechanism. Options should be created using a class that derives either from 228*e5dd7070Spatrickthe ``OptionalRequiredOption`` or ``RequiredRefactoringOption``. The following 229*e5dd7070Spatrickexample shows how one can created a required string option that corresponds to 230*e5dd7070Spatrickthe ``-new-name`` command-line option in clang-refactor: 231*e5dd7070Spatrick 232*e5dd7070Spatrick.. code-block:: c++ 233*e5dd7070Spatrick 234*e5dd7070Spatrick class NewNameOption : public RequiredRefactoringOption<std::string> { 235*e5dd7070Spatrick public: 236*e5dd7070Spatrick StringRef getName() const override { return "new-name"; } 237*e5dd7070Spatrick StringRef getDescription() const override { 238*e5dd7070Spatrick return "The new name to change the symbol to"; 239*e5dd7070Spatrick } 240*e5dd7070Spatrick }; 241*e5dd7070Spatrick 242*e5dd7070SpatrickThe option that's shown in the example above can then be used to create 243*e5dd7070Spatricka requirement for a refactoring rule using a requirement like 244*e5dd7070Spatrick``OptionRequirement``: 245*e5dd7070Spatrick 246*e5dd7070Spatrick.. code-block:: c++ 247*e5dd7070Spatrick 248*e5dd7070Spatrick createRefactoringActionRule<RenameOccurrences>( 249*e5dd7070Spatrick ..., 250*e5dd7070Spatrick OptionRequirement<NewNameOption>()) 251*e5dd7070Spatrick ); 252*e5dd7070Spatrick 253*e5dd7070Spatrick.. FIXME: Editor Bindings section 254