Monday, April 1, 2013

Removing excess lambda expressions with a Roslyn Visual Studio plugin

I've created a Roslyn application that will let us write LINQ statements and make sure that we don't copy and paste them in the same class

The plugin, called 'Refactor Lambdas' does the following :

  • Looks for duplicated lambda expressions
  • Once detected, breaks them out into a separate function
  • Names the function something based on what the function is doing
  • Has some capacity to do fuzzy matching (if 2 lambdas are both the same logically but use variables  from the outer scope with different names and the same type, it can still refactor those 2 lambda expressions)

Showing may be easier than explaining in this situation.  Here's how the plugin would react to a scaffolded controller from the MVC scaffolding project (A gallery of images is below if you don't have Flash)

Here's a link to the repository on BitBucket

I would enjoy having this as apart of ReSharper so I think it's actually a worthwhile plugin.  Also you could get really crazy and search the entire codebase, with a fuzzy search, and condense all duplicated lambdas.  It would have to be torn apart but I think this is a good end-goal to have with this project.

Some Todos in case anyone is interested.  This would be a good project for someone to get their feet with in open source :

  • Unit tests are good but need a little work.  I could not find an easy way to unit test without specifying cursor position in each test; yuck.  Still has >90% test coverage and does all testing in memory.  Could use some negative tests.
  • Fuzzy matching could be improved when deciding if 2 lambdas are equivalent. 
  • Make it work on files with multiple classes (not really super important--right now it just takes the first class and does the search there)
  • Speed considerations?  Any way to detect this code issue more efficiently?  
I'll release this as a Visual Studio plugin on the gallery once Roslyn is finished and pushed out to Visual Studio 2012 and is enabled by default.  Comments?


  1. Wouldn't this work on VS 2010 ?

  2. Not without a big rewrite. You could rewrite it as a plugin that simply uses Roslyn to parse the code and not Roslyn language services like I have here.

    It won't even work in 2012 unless you have the Roslyn command-line argument set (and Roslyn downloaded). And even then it won't work in modules that use things like 'dynamic'.