Advanced CodeRush Plug-ins: Converting an Object Initializer into a Constructor

Today Rory Becker and I presented an Advanced CodeRush Plug-ins session, showing how to create CodeProviders and RefactoringProviders. These providers show up on the CodeRush/Refactor menu, like this:

RefactoringMenu

The session included several moments where we tasted sweet success, and at least one tough coding segment where we were pushing through some challenging code.

The new feature converts code like this:

  Box box = new Box() { Height = 33, Width = 44, Depth = 22 };

into this:

  Box box = new Box(33, 44, 22);

and creates a constructor if needed.

At the end of the two-hour session, we were left with a refactoring that worked, but a CodeProvider that needed more effort. The CodeProvider was challenging because it needed to modify code in two places (it is adding a constructor and replacing the object initializer with a call to new constructor), potentially in two files.

Here’s an overview of the points we learned in the session:

1. The Expressions Lab can reveal many of the hidden details behind the source code you want to analyze or generate.

2. The ObjectCreationExpression class represents a call to a constructor.

3. ObjectCreationExpression elements have three interesting properties:

  • Arguments – the parameters to the constructor call, if any
  • ObjectType – a reference to the type being constructed
  • ObjectInitializer – an ObjectInitializerExpression (if the constructor call includes an initializer).
4. ObjectInitializerExpression has one interesting property:
  • Initializers – a collection of MemberInitializerExpressions
5. MemberInitializerExpression has two interesting properties:
  • Name – the property name being assigned.
  • Value – the value assigned to the property in the initializer expression.
6. MemberInitializerExpression also has an interesting method, Resolve, which allows us to determine the type of the initializer argument.

7. We can use the FileChange object to queue up changes to multiple files.

At the end of the webinar, we encountered an issue where the CodeProvider wouldn’t generate any code. The problem was due to this line of code which set the source file Path property of a FileChange instance to the folder holding the text document (but not the actual file name):

  newConstructor.Path = CodeRush.Documents.ActiveTextDocument.Path;

it should have been this:

  newConstructor.Path = CodeRush.Documents.ActiveTextDocument.FileNode.Name;

Correcting the two places where we set FileChange’s Path property enabled the plug-in to generate code correctly. We’ll record a part 2 to this webinar where we’ll see this fix and wrap up all remaining issues:

  1. Fix the FileChange code generation.
  2. Add code that transfers parameters to the properties.
  3. Declare parameters in the developer’s preferred style.
  4. Test, and handle any new issues found.
2 comment(s)

Allready learned a lot. However i think there is a lot of stuff you need to know about the api before you can make great plugins. Maybe it is a good idea to, as long as not everything is in the eventargs, to make a small api reference for common things you will need to do a lot when making refactorings/codeproviders. (Like when to use ParserServices or that you need to use Resolve to get to the type of an initializer member argument). Also integration of dxcorecommunityplugins (like VS extension manager) in refactor/coderush would be awesome.

22 June, 2011

Tom, your feedback about the less discoverable aspects about the DXCore has been heard and we're already talking about how to improve this in 11.2. Thanks for your support.

23 June, 2011

Please login or register to post comments.