Highlighting Custom Patterns with ReSharper
A new feature that has shipped with ReSharper 5 is the Structural Search and Replace. It is a way for us to locate certain patterns in our code, and optionally replace them. However, it is more than just a Find and Replace. It allows us to somehow extend ReSharper’s inspection settings by offering us means to identify patterns and highlight them.
As many of you know, ReSharper offers a series of Suggestions, Hints, Warnings and Errors when it detects certain code patterns. For instance, when explicitly declaring a variable, ReSharper suggests you use var (and with good reason)
These are configurable, in that you can tell ReSharper whether you want them to be displayed as hints, suggestions, warnings or errors, which is done via ReSharper | Options | Inspection Severity
Setting it to Show as error for instance will display a red (or whatever color you have configured) underlining and the right-hand side border will display the a Red box indicating an error in the file.
If we now combine this with Solution Wide-Analysis, ReSharper will also indicate an error in the solution.
Have you ever encountered the following?
This is a perfect candidate for using String.Format. How about this?
Did you know StringBuilder has an AppendFormat? You might know that, I might, but maybe other developers don’t. It would be good to provide developers with a hint or suggestion that they could use AppendFormat. Up to version 5 of ReSharper, the inspections were limited to what ReSharper provided out of the box and the only thing we could do to extend this functionality was create/use a plug-in We can now use Structural Search and Replace to accomplish this. Let’s see how it works.
1. Open up a Solution (I’m using BlogEngine.NET but feel free to create your own with some sb.Append calls).
2. Select ReSharper | Tools | Pattern Catalog.
By default, the Pattern Catalog is empty.
3. Click on the Add Pattern
4. In this first sample, all we want to do is highlight code, so click on the Find button at the top to switch the dialog to Find mode only.
The Search Pattern is what we’ll use to define what we are looking for. The Description is a text which helps us identify the pattern easily in the Catalog. The box on the right is for place holders which we’ll see in a moment.
5. Enter the following pattern in the Search Pattern editor
What this does is indicate the pattern we are looking for. The values surrounded with $’s (same notation as that used in Live Templates) represent placeholders. A placeholder can be an expression, statement, type, etc. If it is red, it means it has not yet been defined (next step).
6. Click on the Add Placeholder button on the right box and select Expression, and enter the following values:
We are indicating that the placeholder sb (first one used) is an expression of type System.Text.StringBuilder
7. Click on the Add Placeholder button to define the second placeholder, args. Select Argument and enter the following values:
We can optionally indicate whether we want to limit the number of minimum or maximum arguments.
If both placeholders have been defined correctly, the Search pattern box should now look like this:
(we’ve entered a description at the bottom)
8. We need to define the type of severity we want. In this case we want it to be marked as a Suggestion. We do that using the Pattern severity dropdown and then click Save
Our Pattern Catalog should now be updated to reflect this new pattern
9. At this stage we can either close the Patterns dialog or Search for a pattern. Let’s see what happens if we click Search now button.
A Find Results window is displayed highlighting everywhere where ReSharper can find a pattern match. But what about the Pattern severity? Where does that come into play? Let’s double-click on one of the entries:
See the highlighting of the sb.Append call? Set the Pattern Severity to Error and that will display in Red.
Turn on Solution-Wide Analysis and that will list as an error!
So as we can see, the Structural Search (we haven’t replaced yet), allows us to monitor for certain code patterns in our projects. Potentially we could use it to detect certain code smells.
Fixing things up
Now that we have certain patterns located, and even highlighted, how do we go about fixing things? As we saw in the previous screenshots, we have a little icon pop up when placing the cursor on the line:
This context action however doesn’t offer us anything in order to fix the situation, i.e. there is no QuickFix. The reason is obvious: ReSharper doesn’t know what a fix is. Let’s show it!
1. Open up the Patterns Catalog and Edit the previously created Pattern
2. Click on the Replace button to open up the Replace editor at the bottom
3. Enter the following text in the Replace pattern section
4. Provide a description (this is what the hint of the QuickFix will dispaly)
5. Click on the Save button
Locate the previous sb.Append call and place the cursor on top of the line. We can now see a QuickFix icon appear (A red bulb in this case since it’s an Error)
Alt+Enter and we’re done!
What we’ve just done is a manual local fix, that is, locate the offending entry and hit Alt+Enter to apply a QuickFix. We can do this at a global scope by using the Pattern Catalog tool window.
1. Undo the prefix fix (so as to have several instances)
2. Open up the Patterns Catalog
3. Select the recently created Pattern and click on Search now. This time, instead of the Find Results dialog, we get a Replace dialog which displays all matching patterns and a Replace button
4. We can select the entries we want replacing (by default all checked). Click Replace
We’re done! ReSharper will now replace all occurrences. So we’ve applied a QuickFix globally.
What we’ve seen here is just a simple example of how to improve on a call to a class. We can of course do more complex searches, allowing us to identify code smells, etc. The pattern we created in this tutorial is actually included in a Patterns catalog you can download from the documentation section of our web site (or click here for direct link). All you need to do is unzip it and import the XML from the Patterns Catalog window (Import button). Currently, Pattern Catalogs are PER solution.
There’s much more planned for Structural Search and Replace in vNext and we are always happy to receive feedback, so please try it out, and let us know what you think.