How-To's

Introducing ReSharper 5.0: Structural Search and Replace

Previous posts introducing ReSharper 5.0:

Structural Search and Replace is one of the most powerful yet less explored ReSharper 5.0 features. It allows you to find code that matches a structured template, parts of which may have certain restrictions. For example, you can set the type of the expression you are looking for, or specify the number of arguments. In addition to plainly finding parts of code that match the template, you can instantly replace them using an equally powerful replace template, or even configure ReSharper to inspect your solution for code that matches the search pattern and suggest replacing it using a quick-fix. Simply put, Structural Search and Replace provides you with an opportunity to easily extend built-in ReSharper code inspections with your custom ones.

Smart Search

Let’s look at a specific example. We’ll search for all expressions matching the pattern enumerable.Count() > 0, where enumerable is any expression of type IEnumerable.

If you were to solve this task with Find Usages, you would step through all the calls of the Count() method. This means you would have to go through tens or hundreds of calls, which is tiring and prone to error. Find Text might look slightly more promising, but once you think about it, problems come up too:

  1. The expression may be written with line returns or comments.
  2. The Count() method in your project may be implemented by objects of different types.

Find Text doesn’t cut it either.

Choose ReSharper | Find | Search With Pattern and enter the following pattern in the text box:

   $enumerable$.Count() > 0

The $enumerable$ string will be highlighted red. This is because dollar signs signify placeholders — a placeholder is replaced with any text matching the specified restrictions: the placeholder type and its parameters. In our case, $enumerable$ will match any expression of type IEnumerable. We must define this placeholder by clicking Add Placeholder, selecting Expression and entering “enumerable” in the Name field (the placeholder name without the dollar signs). For Expression Type enter “IEnumerable” (just start typing and ReSharper will suggest suitable options). Make sure to check Or derived type as well.

So, in just a few seconds, without even going near regular expressions we’ve created an effective search pattern. But here’s another feature that’s extra-useful! Note the Match similar constructs check box below the edit field. If you select it, ReSharper will search not only for exact matches but also for constructs that are semantically identical. For example, a > 0 and 0 < a are semantically identical. In our case, you should probably select this check box, because you’re likely to be looking for all the different conditional statements where Count() is compared with zero.

That’s all! Now click Find and see the results.

Smart Replace

A search feature this powerful would not be nearly as useful without a replace feature. You don’t want to just locate all the bad code — you want to replace it with good code! So, go ahead and click Replace in the Search With Pattern dialog. You will get a box to enter the replace pattern. The replace pattern can be any text that is valid for the language you’re using, plus placeholders if you need them. For example, enter the following:

$enumerable$.Any()

And click Replace!

Turn a Pattern into a Highlighting and a Quick-Fix

Now you have a search template and a replace pattern. It makes sense to create a highlighting and a quick-fix based on these patterns. To do so, click Save in the pattern editing dialog, and your pattern will be saved to the Pattern Catalog. This catalog is used to store commonly used patterns, and may turn into a powerful tool for creating your own code inspections.

If you open the catalog (ReSharper | Tools | Pattern Catalog), you can define a tooltip for your pattern, which will pop up in the corresponding quick-fix, as well as the type of highlighting you want to apply:

Once you set these options for your pattern, the highlighting works! Now all code that matches your pattern will be highlighted — on the fly. Also, the appropriate quick-fix will appear as soon as you position the caret on the highlighted expression. Ain’t it cool?!

Search Pattern Examples

This search pattern is designed to simplify expressions:

In this example we used placeholders for the types of the expression and the identifier. We didn’t impose any restrictions on them, but used them in the replace pattern. The only placeholder with restrictions is $seq$ — it’s an IEnumerable.

And here’s a pattern that implements highlighting and a quick-fix for Replace ‘if’ with ‘?:’:

Sharing Patterns

If you have created a useful search and replace pattern that detects and removes a code smell, share your knowledge with colleagues using import/export functionality in the the Pattern Catalog! As an option, leave comments with your patterns, and with your permission, we may include the most interesting patterns in the next version of ReSharper!

UPDATE! A sample Pattern Catalog is now available from the ReSharper web site. Learn details in this blog post.

Author: Alexander Zverev, senior ReSharper developer. Translated from original article (in Russian)

image description