180275fefSAlex Lorenz========================== 280275fefSAlex LorenzClang's refactoring engine 380275fefSAlex Lorenz========================== 480275fefSAlex Lorenz 580275fefSAlex LorenzThis document describes the design of Clang's refactoring engine and provides 680275fefSAlex Lorenza couple of examples that show how various primitives in the refactoring API 780275fefSAlex Lorenzcan be used to implement different refactoring actions. The :doc:`LibTooling` 880275fefSAlex Lorenzlibrary provides several other APIs that are used when developing a 980275fefSAlex Lorenzrefactoring action. 1080275fefSAlex Lorenz 1180275fefSAlex LorenzRefactoring engine can be used to implement local refactorings that are 1280275fefSAlex Lorenzinitiated using a selection in an editor or an IDE. You can combine 1380275fefSAlex Lorenz:doc:`AST matchers<LibASTMatchers>` and the refactoring engine to implement 1480275fefSAlex Lorenzrefactorings that don't lend themselves well to source selection and/or have to 1580275fefSAlex Lorenzquery ASTs for some particular nodes. 1680275fefSAlex Lorenz 1780275fefSAlex LorenzWe assume basic knowledge about the Clang AST. See the :doc:`Introduction 1880275fefSAlex Lorenzto the Clang AST <IntroductionToTheClangAST>` if you want to learn more 1980275fefSAlex Lorenzabout how the AST is structured. 2080275fefSAlex Lorenz 2180275fefSAlex Lorenz.. FIXME: create new refactoring action tutorial and link to the tutorial 2280275fefSAlex Lorenz 2380275fefSAlex LorenzIntroduction 2480275fefSAlex Lorenz------------ 2580275fefSAlex Lorenz 2680275fefSAlex LorenzClang's refactoring engine defines a set refactoring actions that implement 2780275fefSAlex Lorenza number of different source transformations. The ``clang-refactor`` 2880275fefSAlex Lorenzcommand-line tool can be used to perform these refactorings. Certain 2980275fefSAlex Lorenzrefactorings are also available in other clients like text editors and IDEs. 3080275fefSAlex Lorenz 3180275fefSAlex LorenzA refactoring action is a class that defines a list of related refactoring 3280275fefSAlex Lorenzoperations (rules). These rules are grouped under a common umbrella - a single 3380275fefSAlex Lorenz``clang-refactor`` command. In addition to rules, the refactoring action 3480275fefSAlex Lorenzprovides the action's command name and description to ``clang-refactor``. 3580275fefSAlex LorenzEach action must implement the ``RefactoringAction`` interface. Here's an 3680275fefSAlex Lorenzoutline of a ``local-rename`` action: 3780275fefSAlex Lorenz 3880275fefSAlex Lorenz.. code-block:: c++ 3980275fefSAlex Lorenz 4080275fefSAlex Lorenz class LocalRename final : public RefactoringAction { 4180275fefSAlex Lorenz public: 4280275fefSAlex Lorenz StringRef getCommand() const override { return "local-rename"; } 4380275fefSAlex Lorenz 4480275fefSAlex Lorenz StringRef getDescription() const override { 4580275fefSAlex Lorenz return "Finds and renames symbols in code with no indexer support"; 4680275fefSAlex Lorenz } 4780275fefSAlex Lorenz 4880275fefSAlex Lorenz RefactoringActionRules createActionRules() const override { 4980275fefSAlex Lorenz ... 5080275fefSAlex Lorenz } 5180275fefSAlex Lorenz }; 5280275fefSAlex Lorenz 5380275fefSAlex LorenzRefactoring Action Rules 5480275fefSAlex Lorenz------------------------ 5580275fefSAlex Lorenz 5680275fefSAlex LorenzAn individual refactoring action is responsible for creating the set of 5780275fefSAlex Lorenzgrouped refactoring action rules that represent one refactoring operation. 5880275fefSAlex LorenzAlthough the rules in one action may have a number of different implementations, 5980275fefSAlex Lorenzthey should strive to produce a similar result. It should be easy for users to 6080275fefSAlex Lorenzidentify which refactoring action produced the result regardless of which 6180275fefSAlex Lorenzrefactoring action rule was used. 6280275fefSAlex Lorenz 6380275fefSAlex LorenzThe distinction between actions and rules enables the creation of actions 6480275fefSAlex Lorenzthat define a set of different rules that produce similar results. For example, 6580275fefSAlex Lorenzthe "add missing switch cases" refactoring operation typically adds missing 6680275fefSAlex Lorenzcases to one switch at a time. However, it could be useful to have a 6780275fefSAlex Lorenzrefactoring that works on all switches that operate on a particular enum, as 6880275fefSAlex Lorenzone could then automatically update all of them after adding a new enum 6980275fefSAlex Lorenzconstant. To achieve that, we can create two different rules that will use one 7080275fefSAlex Lorenz``clang-refactor`` subcommand. The first rule will describe a local operation 7180275fefSAlex Lorenzthat's initiated when the user selects a single switch. The second rule will 7280275fefSAlex Lorenzdescribe a global operation that works across translation units and is initiated 7380275fefSAlex Lorenzwhen the user provides the name of the enum to clang-refactor (or the user could 7480275fefSAlex Lorenzselect the enum declaration instead). The clang-refactor tool will then analyze 7580275fefSAlex Lorenzthe selection and other options passed to the refactoring action, and will pick 7680275fefSAlex Lorenzthe most appropriate rule for the given selection and other options. 7780275fefSAlex Lorenz 7880275fefSAlex LorenzRule Types 7980275fefSAlex Lorenz^^^^^^^^^^ 8080275fefSAlex Lorenz 8180275fefSAlex LorenzClang's refactoring engine supports several different refactoring rules: 8280275fefSAlex Lorenz 8380275fefSAlex Lorenz- ``SourceChangeRefactoringRule`` produces source replacements that are applied 8480275fefSAlex Lorenz to the source files. Subclasses that choose to implement this rule have to 8580275fefSAlex Lorenz implement the ``createSourceReplacements`` member function. This type of 8680275fefSAlex Lorenz rule is typically used to implement local refactorings that transform the 8780275fefSAlex Lorenz source in one translation unit only. 8880275fefSAlex Lorenz 8980275fefSAlex Lorenz- ``FindSymbolOccurrencesRefactoringRule`` produces a "partial" refactoring 9080275fefSAlex Lorenz result: a set of occurrences that refer to a particular symbol. This type 9180275fefSAlex Lorenz of rule is typically used to implement an interactive renaming action that 9280275fefSAlex Lorenz allows users to specify which occurrences should be renamed during the 9380275fefSAlex Lorenz refactoring. Subclasses that choose to implement this rule have to implement 9480275fefSAlex Lorenz the ``findSymbolOccurrences`` member function. 9580275fefSAlex Lorenz 9680275fefSAlex LorenzThe following set of quick checks might help if you are unsure about the type 9780275fefSAlex Lorenzof rule you should use: 9880275fefSAlex Lorenz 9980275fefSAlex Lorenz#. If you would like to transform the source in one translation unit and if 10080275fefSAlex Lorenz you don't need any cross-TU information, then the 10180275fefSAlex Lorenz ``SourceChangeRefactoringRule`` should work for you. 10280275fefSAlex Lorenz 10380275fefSAlex Lorenz#. If you would like to implement a rename-like operation with potential 10480275fefSAlex Lorenz interactive components, then ``FindSymbolOccurrencesRefactoringRule`` might 10580275fefSAlex Lorenz work for you. 10680275fefSAlex Lorenz 10780275fefSAlex LorenzHow to Create a Rule 10880275fefSAlex Lorenz^^^^^^^^^^^^^^^^^^^^ 10980275fefSAlex Lorenz 11080275fefSAlex LorenzOnce you determine which type of rule is suitable for your needs you can 11180275fefSAlex Lorenzimplement the refactoring by subclassing the rule and implementing its 11280275fefSAlex Lorenzinterface. The subclass should have a constructor that takes the inputs that 11380275fefSAlex Lorenzare needed to perform the refactoring. For example, if you want to implement a 11480275fefSAlex Lorenzrule that simply deletes a selection, you should create a subclass of 11580275fefSAlex Lorenz``SourceChangeRefactoringRule`` with a constructor that accepts the selection 11680275fefSAlex Lorenzrange: 11780275fefSAlex Lorenz 11880275fefSAlex Lorenz.. code-block:: c++ 11980275fefSAlex Lorenz 12080275fefSAlex Lorenz class DeleteSelectedRange final : public SourceChangeRefactoringRule { 12180275fefSAlex Lorenz public: 12280275fefSAlex Lorenz DeleteSelection(SourceRange Selection) : Selection(Selection) {} 12380275fefSAlex Lorenz 12480275fefSAlex Lorenz Expected<AtomicChanges> 12580275fefSAlex Lorenz createSourceReplacements(RefactoringRuleContext &Context) override { 12680275fefSAlex Lorenz AtomicChange Replacement(Context.getSources(), Selection.getBegin()); 12780275fefSAlex Lorenz Replacement.replace(Context.getSource, 12880275fefSAlex Lorenz CharSourceRange::getCharRange(Selection), ""); 12980275fefSAlex Lorenz return { Replacement }; 13080275fefSAlex Lorenz } 13180275fefSAlex Lorenz private: 13280275fefSAlex Lorenz SourceRange Selection; 13380275fefSAlex Lorenz }; 13480275fefSAlex Lorenz 13580275fefSAlex LorenzThe rule's subclass can then be added to the list of refactoring action's 13680275fefSAlex Lorenzrules for a particular action using the ``createRefactoringActionRule`` 13780275fefSAlex Lorenzfunction. For example, the class that's shown above can be added to the 13880275fefSAlex Lorenzlist of action rules using the following code: 13980275fefSAlex Lorenz 14080275fefSAlex Lorenz.. code-block:: c++ 14180275fefSAlex Lorenz 14280275fefSAlex Lorenz RefactoringActionRules Rules; 14380275fefSAlex Lorenz Rules.push_back( 14480275fefSAlex Lorenz createRefactoringActionRule<DeleteSelectedRange>( 14580275fefSAlex Lorenz SourceRangeSelectionRequirement()) 146*eac034b9SHaojian Wu ); 14780275fefSAlex Lorenz 14880275fefSAlex LorenzThe ``createRefactoringActionRule`` function takes in a list of refactoring 14980275fefSAlex Lorenzaction rule requirement values. These values describe the initiation 15080275fefSAlex Lorenzrequirements that have to be satisfied by the refactoring engine before the 15180275fefSAlex Lorenzprovided action rule can be constructed and invoked. The next section 15280275fefSAlex Lorenzdescribes how these requirements are evaluated and lists all the possible 15380275fefSAlex Lorenzrequirements that can be used to construct a refactoring action rule. 15480275fefSAlex Lorenz 15580275fefSAlex LorenzRefactoring Action Rule Requirements 15680275fefSAlex Lorenz------------------------------------ 15780275fefSAlex Lorenz 15880275fefSAlex LorenzA refactoring action rule requirement is a value whose type derives from the 15980275fefSAlex Lorenz``RefactoringActionRuleRequirement`` class. The type must define an 16080275fefSAlex Lorenz``evaluate`` member function that returns a value of type ``Expected<...>``. 16180275fefSAlex LorenzWhen a requirement value is used as an argument to 16280275fefSAlex Lorenz``createRefactoringActionRule``, that value is evaluated during the initiation 16380275fefSAlex Lorenzof the action rule. The evaluated result is then passed to the rule's 16480275fefSAlex Lorenzconstructor unless the evaluation produced an error. For example, the 16580275fefSAlex Lorenz``DeleteSelectedRange`` sample rule that's defined in the previous section 16680275fefSAlex Lorenzwill be evaluated using the following steps: 16780275fefSAlex Lorenz 16880275fefSAlex Lorenz#. ``SourceRangeSelectionRequirement``'s ``evaluate`` member function will be 16980275fefSAlex Lorenz called first. It will return an ``Expected<SourceRange>``. 17080275fefSAlex Lorenz 17180275fefSAlex Lorenz#. If the return value is an error the initiation will fail and the error 17280275fefSAlex Lorenz will be reported to the client. Note that the client may not report the 17380275fefSAlex Lorenz error to the user. 17480275fefSAlex Lorenz 17580275fefSAlex Lorenz#. Otherwise the source range return value will be used to construct the 17680275fefSAlex Lorenz ``DeleteSelectedRange`` rule. The rule will then be invoked as the initiation 17780275fefSAlex Lorenz succeeded (all requirements were evaluated successfully). 17880275fefSAlex Lorenz 17980275fefSAlex LorenzThe same series of steps applies to any refactoring rule. Firstly, the engine 18080275fefSAlex Lorenzwill evaluate all of the requirements. Then it will check if these requirements 18180275fefSAlex Lorenzare satisfied (they should not produce an error). Then it will construct the 18280275fefSAlex Lorenzrule and invoke it. 18380275fefSAlex Lorenz 18480275fefSAlex LorenzThe separation of requirements, their evaluation and the invocation of the 18580275fefSAlex Lorenzrefactoring action rule allows the refactoring clients to: 18680275fefSAlex Lorenz 18780275fefSAlex Lorenz- Disable refactoring action rules whose requirements are not supported. 18880275fefSAlex Lorenz 18980275fefSAlex Lorenz- Gather the set of options and define a command-line / visual interface 19080275fefSAlex Lorenz that allows users to input these options without ever invoking the 19180275fefSAlex Lorenz action. 19280275fefSAlex Lorenz 19380275fefSAlex LorenzSelection Requirements 19480275fefSAlex Lorenz^^^^^^^^^^^^^^^^^^^^^^ 19580275fefSAlex Lorenz 19680275fefSAlex LorenzThe refactoring rule requirements that require some form of source selection 19780275fefSAlex Lorenzare listed below: 19880275fefSAlex Lorenz 19980275fefSAlex Lorenz- ``SourceRangeSelectionRequirement`` evaluates to a source range when the 20080275fefSAlex Lorenz action is invoked with some sort of selection. This requirement should be 20180275fefSAlex Lorenz satisfied when a refactoring is initiated in an editor, even when the user 20280275fefSAlex Lorenz has not selected anything (the range will contain the cursor's location in 20380275fefSAlex Lorenz that case). 20480275fefSAlex Lorenz 20580275fefSAlex Lorenz.. FIXME: Future selection requirements 20680275fefSAlex Lorenz 20780275fefSAlex Lorenz.. FIXME: Maybe mention custom selection requirements? 20880275fefSAlex Lorenz 20980275fefSAlex LorenzOther Requirements 21080275fefSAlex Lorenz^^^^^^^^^^^^^^^^^^ 21180275fefSAlex Lorenz 21280275fefSAlex LorenzThere are several other requirements types that can be used when creating 21380275fefSAlex Lorenza refactoring rule: 21480275fefSAlex Lorenz 21580275fefSAlex Lorenz- The ``RefactoringOptionsRequirement`` requirement is an abstract class that 21680275fefSAlex Lorenz should be subclassed by requirements working with options. The more 21780275fefSAlex Lorenz concrete ``OptionRequirement`` requirement is a simple implementation of the 21880275fefSAlex Lorenz aforementioned class that returns the value of the specified option when 21980275fefSAlex Lorenz it's evaluated. The next section talks more about refactoring options and 22080275fefSAlex Lorenz how they can be used when creating a rule. 22180275fefSAlex Lorenz 22280275fefSAlex LorenzRefactoring Options 22380275fefSAlex Lorenz------------------- 22480275fefSAlex Lorenz 22580275fefSAlex LorenzRefactoring options are values that affect a refactoring operation and are 22680275fefSAlex Lorenzspecified either using command-line options or another client-specific 22780275fefSAlex Lorenzmechanism. Options should be created using a class that derives either from 22880275fefSAlex Lorenzthe ``OptionalRequiredOption`` or ``RequiredRefactoringOption``. The following 22980275fefSAlex Lorenzexample shows how one can created a required string option that corresponds to 23080275fefSAlex Lorenzthe ``-new-name`` command-line option in clang-refactor: 23180275fefSAlex Lorenz 23280275fefSAlex Lorenz.. code-block:: c++ 23380275fefSAlex Lorenz 23480275fefSAlex Lorenz class NewNameOption : public RequiredRefactoringOption<std::string> { 23580275fefSAlex Lorenz public: 23680275fefSAlex Lorenz StringRef getName() const override { return "new-name"; } 23780275fefSAlex Lorenz StringRef getDescription() const override { 23880275fefSAlex Lorenz return "The new name to change the symbol to"; 23980275fefSAlex Lorenz } 24080275fefSAlex Lorenz }; 24180275fefSAlex Lorenz 24280275fefSAlex LorenzThe option that's shown in the example above can then be used to create 24380275fefSAlex Lorenza requirement for a refactoring rule using a requirement like 24480275fefSAlex Lorenz``OptionRequirement``: 24580275fefSAlex Lorenz 24680275fefSAlex Lorenz.. code-block:: c++ 24780275fefSAlex Lorenz 24880275fefSAlex Lorenz createRefactoringActionRule<RenameOccurrences>( 24980275fefSAlex Lorenz ..., 25080275fefSAlex Lorenz OptionRequirement<NewNameOption>()) 25180275fefSAlex Lorenz ); 25280275fefSAlex Lorenz 25380275fefSAlex Lorenz.. FIXME: Editor Bindings section 254