xref: /llvm-project/clang/docs/RefactoringEngine.rst (revision eac034b992d38eaadd33a9540e0fda6ae059fcd5)
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