This conversation popped up on Twitter:
The customer wants a list of parameters inserted into a CodeRush Template. CodeRush Templates are like Visual Studio code snippets on steroids.
My first thought: “We might have this. Let me check.”
I opened the Template Editor options page, right-clicked the template expansion area, chose “Insert StringProvider”, and entered “param” in the Filter textbox:
Unfortunately, nothing. StringProviders are code-based helpers located in plug-ins that deliver strings of text. I close this dialog.
CodeRush also has TextCommands, which simply execute code (any code you write) from a plug-in. Sometimes that code execution can actually insert text in the middle of a template expansion. In cases like this, a TextCommand behaves similarly to a StringProvider. So I right-clicked the template expansion area again, but this time I chose “Insert TextCommand”, and once again entering “param” into the Filter textbox:
Unfortunately, not what we were hoping for.
So nothing we are currently shipping outputs a list of the current method’s parameters as a string. But I know we can do this pretty easily by writing our own plug-in.
My reply on Twitter goes out:
I return to my work, prepping for the pending release, and then it occurs to me – we can do this without a plug-in. One of the TextCommands we do ship with CodeRush is ForEach. It iterates over structural elements in your code, calling a specified template for each element found, and also optionally calling specified templates before, between, and after each element in the list.
With some clever template creation, we can get the customer exactly what they need.
CodeRush’s ForEach TextCommand
Next I bring up the CodeRush User Guide, and click the “Reference\Text Commands” node, then click the ForEach TextCommand so I can take a look at the syntax. The dynamically-generated help page (generated from the plug-in TextCommand itself) looks like this:
The ForEach TextCommand takes two required parameters (iterationBounds and the template to expand each time an element is found), and three optional parameters (firstTemplate, betweenTemplate, and lastTemplate – all names of templates to expand).
I want to create a simple comma-separated list of parameters. So I will only need to use betweenTemplate (to place a comma and a space between each parameter name found). Note that this template will only be called if there are two or more elements in the list.
Making it Work
Now things get fast and easy. Inside the template editor, I create a new template for testing, named “zzz”. This template’s expansion looks like this:
«ForEach(Parameter in Method,#AddParameter#,,#Comma#)»
Notes on this call:
- Parameter in Method is the iterationBounds. That means we’re going to iterate through every parameter in the active method (the method containing the caret).
- #AddParameter# is the name of a template I haven’t created yet. It’s going to simply insert the text of the parameter and nothing more.
- We pass nothing in for the firstTemplate argument.
- #Comma# is the name of a template I haven’t created yet. It’s going to simply insert a comma followed by a space.
- As a convention, I use the hash tag symbols around templates that I call from other locations (e.g., #Comma# and #AddParameter# – but these templates could have any name you want).
Next I create the #AddParameter# template. It looks like this:
This references the “Get” StringProvider, which is responsible for managing a list of variables and their values during template expansion. The ForEach TextCommand defines two variables for use in Templates – itemName (the name of the item being iterated), and itemType (that particular item’s type).
So this template is done – it’s just going to return back the name of the parameter.
Finally, I need to create the #Comma# template. This one is simple – just a comma followed by a space. I click OK to drop the CodeRush Options dialog.
I move the caret inside a method with some parameters and enter the name of my test template – “zzz”:
I press the Space bar (you might press Tab if that’s your template expansion key).
I see this:
The last step is to rename our “zzz” template into something more meaningful (e.g., #ParameterList#). You can rename templates by pressing F2 when the template is selected inside the Template Editor options page.
Now whenever we need a parameter list in a template, we can right-click that template expansion, choose “Insert Alias…” (a way of calling templates from templates), and select our new #ParameterList# template to insert a list of parameters.
Note that if we wanted to include the parameter type with each parameter, we could do that easily by modifying the #AddParameter# template to something like this:
Then our template expansion might give us something like this:
Learning More about TextCommands
Here’s a video webinar Rory Becker and I recorded a while back, that introduces TextCommands and also goes into several examples of what you can do with the ForEach TextCommand: