Refactorings are one of the most powerful features of ReSharper, but also the most complicated. A refactoring can be triggered from a variety of events (e.g., from a simple edit or deliberate invocation) and can result in all sorts of operations, some involving just local code, others involving the project (e.g., renaming a file) or changing multiple files in many projects.
At the most simple level, a refactoring consists of three things:
- The workflow
- The workflow provider
- The refactoring itself
Let's take a look at the way these components are defined.
The workflow, as its name suggests, is a class which orchestrates the workflow during which the user may - or may not - perform the refactoring. Most refactorings are driven, meaning that the user has to go through menus which present, e.g., conflicts that this refactoring would create.
In the simplest terms, a refactoring is a class which inherits from
DrivenRefactoringWorflow. This class has quite a few members, most of which perform fairly obvious function.
Execution of the workflow happens in the
PostExecute methods. All of these, as well as other methods such as
IsAvailable, return a
bool value indicating whether this step is a success. If any of these returns
false, the whole transaction is rolled back and no refactorings take place.
The workflow provider is a class which provides workflows for ReSharper to consume. It is a class that
- Implements the
- Is decorated with
The class has a single method -
CreateWorkflow() that returns an
IEnumerable of one or more workflows that you may wish to provide. Here is a typical example:
The constructor parameter passed into the workflow is an action ID, which is also useful if you want to expose the refactoring as an ordinary action.
One of the methods we forgot to mention in the workflow is the
CreateRefactoring() method. This method is used to put together the refactoring worflow and the refactoring driver - i.e., the element which drives the refactoring to completion.
Thus, the refactoring itself is typically a class (let's call it
C) inheriting from
DrivenRefactoring<Workflow, Refactoring>, where
Workflow corresponds to the refactoring workflow, and
Refactoring corresponds to a type of
The refactoring itself has the capability of dealing with cases where a particular refactoring is not supported on a R#-supported language. For example, a particular C# refactoring might not be supported in VB, so usages after the change will not be updated. The number of such refactorings in ReSharper itself is really small, but it is likely you might need this functionality if your refactoring is, e.g., C#-only.