xref: /openbsd-src/gnu/llvm/clang/docs/RefactoringEngine.rst (revision e5dd70708596ae51455a0ffa086a00c5b29f8583)
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