Occasionally I realise that I’ve passed a couple of arguments to a method in the wrong order.

What follows is usually a complicated series of…

Move Left (Ctrl+Left)

Select Right (Shift+Ctrl+Right)

Cut Argument (Ctrl+X)

Move Right (Ctrl+Right)

Paste Argument (Ctrl+V)

The navigation operations usually need to be repeated several times in order to get into the correct position.

Additionally there’s that bit where you either…

Try to judge which comma to include in the cut/paste operation.

Or… Delete the comma, and enter it back again once the paste is complete.

Add this to the fact that I usually have something useful on the clipboard, which I’d prefer not to have to burn whilst correcting the order of these arguments.

The whole rigmarole is something to be avoided.

Enter CR_ReverseArgs

The new CR_ReverseArgs plugin allows you to just highlight the pair of arguments, and trigger Reverse Args from the CodeRush Smart Tag menu.

Then CodeRush will do the rest.

This CodeProvider should work with ints, strings, and all sorts of other objects. The 2 arguments need not be of the same type either. Feel free to switch whichever pairs you like.

Note: This plugin is NOT a Refactoring. It will affect the functionality of your code. If you wish to move both the Arguments and their corresponding Parameters, then you should use the Reorder Parameters refactoring

It would be great to have something that could recognise that an extension method was being called in the style of a normal method ie Method(Object, Params) and rewrite the call in the form of an extension method call. ie Object.Method(Params)

Ok well that seems simple enough:

Introducing the Use Extension Method Plugin

So given that we have an extension method like this:

… and some calling code looks like this :

The Use Extension Method plugin will add an option to your CodeRush SmartTag menu which will convert the method call in question to the following.

The circumstances that form the setting for an event, statement, or idea, and in terms of which it can be fully understood.

What does CodeRush use context for?

CodeRush uses context (in addition to user input) to decide which functionality to provide you with.

For example: The <Tab> key is used for indenting text, and also for invoking the Tab to Next Reference (TtNR) feature. When you hit the <Tab> key, CodeRush performs several context checks.

The context settings for TtNR are fairly complicated, but boils down to IsTheCaretWithinAnIdentifier. If CodeRush judges that this is the case, then it chooses the TtNR functionality, otherwise it chooses the indentation functionality.

CodeRush Templates and Shortcuts often overload each other in this way, and CodeRush uses the context to determine which overload to use.

How do I use a context?

You don’t use a context directly. Instead you choose a feature which is sensitive to context (a shortcut or template will do nicely) and configure it to only work within a given context (or set of contexts)

Features can be configured to work with a specific context where ever you see this UI.

Each node in the tree is a context. The contexts will either be true or false at a given moment.

When being tested, a ticked context will be tested at the moment of invocation and the feature\function will only be allowed if that context is found to be true. Alternatively if the context has a cross against it, then the function\feature will only be allowed to proceed if the context is explicitly found to be false.

What if I can’t find the context I need?

Well first of all I recommend contacting support@devexpress.com since it’s entirely possible that the context you’re after is there, but perhaps not named or located as you would expect. However, failing that, it is very easy to create a brand new context in a plugin.

How do I create a context?

Contexts are analogous to functions which return a boolean value. You check anything you like, (Source code, Project structure, color of the moon) and then set the context to true or false accordingly.

Creating a context is really really simple… just use the NewContext template. Note This template does not ship with CodeRush. See instructions later in this post for how to acquire the template.

Once you have the template installed, simply position your caret in the body of your plugin and type NewContext<space>

The Template will expand like so…

You will then need to fill out a few details.

A Component NameThis first name is used to identify the metric component itself within your code. You might be about to create several of these and they all need to be distinct from one another and their methods not confused.

A Display NameThe display name is a short identifier used whenever a group of contexts are listed together to distinguish them from each other.

A DescriptionExplains to the user ticking or crossing the context, what the context is looking for in order to be considered satisfied.

A Provider NameThis is the path at which the context will be listed. A backslash separated set of strings is required here. ie Editor\XML\InOpenTag

With these properties filled out, all you need to do is…

Implement the ContextSatisfied method Perform whatever calculations and discovery you like and then set ea.Satisfied = true; when your context is satisfied

The Add Data Contract plugin is a CodeProvider with the usual CheckAvailability and Apply methods. The basic plumbing of this plugin is created with the NewCodeProvider CodeRush template detailed in this blogpost.

Add Namespace

In the DXCore, a using directive (or an imports directive in VB.Net) is called a NamespaceReference

To add a NamespaceReference to the current file it is first necessary to determine if one already exists. For this we construct a new ElementEnumerable capable of searching the current file for NamespaceReference objects. This is then used to return an IEnumerable<NamespaceReference>

The list of namespace is queried to determine if the new namespace is already referenced. There is nothing to be gained by referencing the same namespace twice. If it is found, then we return from the apply method without having performed any modifications.

Location, Location, Location

Next we determine the best location to insert our NamespaceReference.

If there are no existing NamespaceReferences, then the InsertionPoint is set to the start of the current document.

Alternatively, if there are some pre-existing NamespaceReferences, then the start of the last of these is picked as a sensible default.

Code Generation and Insertion

Next we create our new NamespaceReference object (passing in the string representing the namespace in question) and have CodeRush generate the actual code that represents this object. The last step in generating our NamespaceReference is to queue the insertion of this code at the InsertionPoint determined in the previous step

A Generic AddAttribute Method

There are 2 attributes which this plugin adds to various parts of the target class.

The DataContract attribute is to be added to the class itself. Then we need to iterate through the properties on the class, and add the DataMember attribute to each of those.

In order to make this as easy as possible, I decided to create a utility method capable of quickly adding a named attribute to any given LanguageElement.

In the method above, an ElementBuilder is used to create the Attribute and then the AttributeSection. For those that don’t know the AttributeSection is the pair of square brackets that the attribute sits inside. (These are angle brackets in VB.Net).

As before, code is then generated and queue an insert into the ActiveTextDocument at the correct location.

Putting it all Together

All of this is drawn together in the body of the apply method.

First we add the System.Runtime.Serialization namespace. Next we decorate the class with the DataContract attribute. Then we iterate through all the properties of the class decorating each of these with the DataMember attribute. We call ApplyQueueEdits to apply each of the queued operations to the document in a single step.

Finally we reparse the document and call the FormatFile action to perform any additional reformatting that might be necessary.