Stories about Software


Creating a DxCore plugin

Coding standards are one of those things that generally involve some degree of compromise, as there is often a goal during collaboration to give the code a uniform look and feel. I don’t necessarily agree with this goal in all cases, but I do understand it. Having code formatted in wildly different styles in the same solution or assembly steepens the learning curve for newcomers to the project and will have some negative effects on maintenance activities.

So, what to do when the group’s agreed-upon coding standards don’t match your own preferences? Most would simply adapt. I’m not really like most, though. I’m an inveterate tinkerer and heavy customizer. In all of my IDEs, I use a black background and arrange the colors just so. This mentality extends to everything from my windows folder views to my coding idioms. Everything that I do, I make a point to do because of conscious deliberation and not simply because I’m used to doing it. There is a method to my madness. So my solution to being asked to adopt a common set of standards was to write an IDE plugin that would convert my idioms to the group’s and vice-versa.

Because I’ve really been enjoying the DxCore set of tools lately, I decided to go this route. Here are the steps that I’ve taken in order to get a plugin up and running. At the time of writing, this plugin is fairly simple. I like to use camel casing in my code, and I distinguish between class fields, method parameters, and local variables by using the following idioms, respectively: _classField, methodParameter, myLocalVariable (properties and methods are ClassProperty and ClassMethod()). My rationale is that this allows me at a glance to tell what each thing is that I’m referring to. The standard of one of the groups in which I’m developing is _ClassField and localVariable (sans my). I don’t prefer this because I can’t distinguish between method parameters and my local variables at a glance, meaning I don’t know whether I own the reference or my caller does. So, the plugin converts all class variables and method variables back and forth between these idioms, and that’s it.

For usability purposes, I created a CodeRush action to which I could bind a shortcut key sequence, and I adorned it with some niceties such as putting it in a menu and showing a BIGHINT when the actions are executed. Since the documentation for the DxCore API is somewhat scattered and not always complete, a fair bit of reverse engineering went into this, so I make no claims that what I’m doing is the preferred way to do things. But it does work. I may refine this and revisit this as I get more familiar with it, but here is what I’ve done so far (using CodeRush/DXCore 10.2.5 and Visual Studio 2010):

Getting started

Getting started with a new DXCore plugin is pretty straightforward. Open a new Visual Studio project, go to the DevExpress menu, and select “New Plugin.”

Create a new DXCore plugin

From there, give your plugin a descriptive name that suits your purposes and take care of all of the particulars of naming the classes the way you want. Then you’re ready to go. This link describes some steps in detail, including selecting manual rather than automatic loading of the plugin that you’re creating (you probably don’t want Visual Studio scooping this up until it’s tested and stable): Create a plugin. This blog was actually what I referred to for the how-to of creating this.

Lights, Camera, Action

This will create an empty plugin project ready to use. In order to have it do anything useful, you must open the Toolbox from the designer and drag and drop an Action (from the DXCore portion) onto your designer.

Create a new action

Once the action is on your designer page, double click on it.  You will be booted into the code behind, ala classic Visual Studio development. Here, an event handler will be created for the action’s execution. This is going to be the plugin’s entry point. We’ll bind the action to a shortcut key sequence in the IDE, and this is the method to which you’ll add code to manipulate the IDE.

Newly created event handler

For now, if you want to verify that something is happening, I would suggest dropping a “Big Hint” onto your designer, naming it something (I got creative and left it as “bigFeedback1”), and adding the following to your execute event handler:

Now that you have an actual action and something that it does, you’re ready to try it out. Follow the instructions on Dror Helper’s blog for running the plugin. Basically, you’re going to do a normal run which will, in turn, launch a new instance of Visual Studio. Assuming that you’ve bound a shortcut sequence to your new action, once you load your plugin and execute that sequence, you will see that big CodeRush feedback:

Big Hint

(Clearly, my code does not say “Hello World” at the time of running, but you get the idea.)

One thing to look out for is an exception message when you run. I don’t know if it’s something about my setup specifically, but I see the following:

Loader Lock message

For me, ignoring this and hitting continue makes everything go fine. YMMV.

The code to make it go

I wrote a good bit of code and some unit tests to make this work. The full, zipped solution (as of this writing) can be downloaded here for anyone interested. I certainly won’t go into everything, especially the logic of modifying the variable names. But I will go over a few concepts with which I struggled a bit and had to learn by trial and error.

The DXCore engine has a very deep inheritance hierarchy, and it’s important to find the right level of object in the hierarchy to get the operations that you want. This API is not yet thoroughly documented, so it can be a bit confusing. The first thing that you’re going to be interested in for my plugin is the ActiveClass. This corresponds to the class that’s currently active in the IDE. ActiveClass is obtained by querying static class CodeRush — specifically, CodeRush.Source.ActiveClass.

ActiveClass exposes IEnumerables of TypeDeclaration called “AllFields”, “AllMethods”, “AllProperties”, etc. that correspond to language elements of interest in the class. However, you don’t want TypeDeclarations — you want LanguageElements.  So you’ll want to cast these guys as LanguageElement. Doing so exposes a “NameRange” property, which is what you pass to ActiveClass.Document.SetText(namerange, newname) to change the name of the variable. You’re also going to be interested in LanguageElement’s “FindAllReferences()” method, which returns an IEnumerable of IElements.  You’ll need this in order to pass to CodeRush.Source.GetLanguageElement(IElement) so that additional LanguageElements correspond to additional instances of your element besides its declaration.

And, finally, if you want to check certain properties of a language element (is it private, protected, etc., what its parent element is, etc.), you will need to cast it to AccessSpecifiedElement.

This is not incredibly intuitive, so I’m hoping that this helps people — at least by pointing in the right direction of which types and classes to look at in the meta-data or to play with.

Adding your action to menus

This part is relatively straightforward once you know what to do, but it took me a while to figure that out. I was looking to create something like this where I could right-click inside the class and apply my conversions:

Context Menu

So, as it turns out, if you right-click on your action in the designer and display the properties, you can set this all through the properties. I’ve circled the ones that I needed to set in order to achieve the desired effect in the previous screenshot. If you want to create another layer of sub-menuing, I have no idea how this would be achieved. But, I don’t want to do that right now, so that’s that.

Adding to the context menu

If you want to add it to one of the existing menus in Visual Studio like the edit menu or the DevExpress menu, you can do that too.

Switching out of Development Mode

When you’re finished with developing and ready for your plugin to be loaded automatically when Visual Studio and DXCore startup, navigate to the project’s AssemblyInfo.cs and edit the properties of the assembly DXCoreAssembly. Change “PluginLoadType.Demand” to “PluginLoadType.Startup”, and now your plugin will be available for loading at startup. You will still need to configure it in the DevExpress plugin manager.

An interesting thing to note is that DXCore’s plugin creator automatically sets the build output to go in the DevExpress plugins directory (DevExpress\IDE Tools\Community\PlugIns). So if you want to redistribute this guy, you can just grab the DLL from there and email it to your friends, or whatever.

Follow Up

This is very much a work in progress, and I expect to polish this tool more as I use it. I may revisit this post and edit a bit if it needs it or create follow-up posts if there is interest. One thing that comes to mind off the top is that I plan to disable the conversions menu item if the user does not click inside a class. Other nice features might be to play with and set some default settings on the context picker for users to have some guidance when creating keyboard shortcuts.

If anyone has questions, comments, or suggestions for improvement, all are welcome.

Edit: I just now uploaded a slightly modified version of the plugin about a day after this post. I discovered that I local variables were not being modified properly in methods if they were nested in any kind of scoping delimiter, like an “if” statement or a try/catch block. The reason for this was that I was previously checking to see if the AccessSpecifiedElement had a parent of type Method, not realizing that these other scopers were considered logical parents. I modified that code to instead call GetMethod() and check to see if it was null. There’s doubtless some better heuristic for distinguishing locals, but this one seems to work.

Edit2: I have created a new post detailing additional progress on this matter.


Adding CodeRush Templates

Today I’m going to briefly describe one of the cool and slightly more advanced features of CodeRush in a little more detail. But first, a bit of background. One of the many things I found enjoyable about CodeRush is the templated shortcuts, ala VS code snippets but better. I found myself typing “tne-space” a lot for generating:

throw new Exception("");

with my caret placed in the quotes within the exception. However, I would dutifully go back and modify “Exception” so that I wasn’t throwing a generic exception and arousing the ire of best-practices-adherents everywhere. That rained on my parade a bit, as I found the time savings not to be optimized.

I decided that I’d create specific templates for the exceptions that I commonly used, and I am going to document that process here in case anyone may find it helpful. This is a very simple template addition and probably a good foray into creating your own CodeRush templates.

The first thing to do is fire up Visual Studio and launch the CodeRush options, which, in the spirit of CodeRush, can be short-cutted by using Ctrl-Alt-Shift-O. From here, you can select “Editor” from the main menu and then select “Templates.” This will bring up the templates sub-screen:
CodeRush templates

From here, you can either search for “tne” or navigate to “Program Blocks -> Flow -> tne”:

Create duplicate

Now, you will be prompted for a name. Call it “tnioe” for “throw new InvalidOperationException(“”);” (You can call it whatever you prefer to type in.) Next, in the “Expansion” frame, change “Exception” to “InvalidOperationException” and click “Apply.”

New Template

Now, when you exit the options window and type “tnioe-space” in the editor, you will see your new template.

As a bonus, I’m going to describe something that I encountered and was driving me nuts before I figured out how to fix it. CodeRush’s options screen remembers where you last were in its navigation tree for the next time you launch it. However, it is possible somehow to lose the actual view of the main tree and get stuck in whatever sub-options page you were in without being able to get back.

To fix this, go to DevExpress->about and click on the “Settings” button. This will open a folder on your drive containing settings XML files. Close the options window in Visual Studio and then open OptionsDialog.xml. Set the Option with name attribute “SplitOpen” to “True” and you’ll have your normal, sane options back.


The Pleasure of Using CodeRush

For some months now, I’ve been using CodeRush/DevExpress express (read: free) version, and I’ve just recently upgraded to the paid version. After playing with it for only a few short weeks, I’ve come to find it indispensable, so I thought I’d log a post highlighting some of my favorite features. These are relevant to C# 3.5 and up in Visual Studio 2010.

  • The “Issues List” is one of the first features that you might notice if you don’t turn it off because it puts various squigglies under things that it flags as issues. This includes dead code, overly-complicated methods, expressions that could be converted to lambdas, etc. This facet of the utility has immediate payoff in that it may make you aware of some coding practices that you hadn’t previously thought were issues. For example, I had squigglies every time I had something along the lines of:

    Foo myFoo = new Foo();
    CodeRush informed me that I could (should) use var instead of the declarative Foo. This took some getting used to for me, since the “var” looks suspiciously like weak typing and reminds me of Visual Basic 6.0 (which I do not count amount my favorite languages) and its “dim.” However, I see the logic in it. Declaring a Foo twice is needlessly verbose and redundant, so CodeRush has been helping me conform to what are, evidently, now best practices.

  • Ctrl-3 to encapsulate selected text in a region. This is simple but cool. I’ve got a bunch of functions or properties that I want to put into a region and I can just hit Ctrl-3, type the region name, and it’s done. (We can discuss the merits or lack thereof regarding regioning somewhere else, but for the time being I’ll simply state that it’s the convention in which I’m using CodeRush).
  • “mv”-space. This guy creates a new private void method and highlights the method name. So, you type mv-space, type the name of the method, hit enter, type your parameters, hit enter, and you’re off. Also, if you don’t like the method as private, you can hit alt-up/alt-down and cycle the visibility of the method.
  • “tne”-space. (In general, {expr}-space is the CodeRush paradigm for executing ‘templates,’ which are similar but more sophisticated than code snippets in Visual Studio.) This creates the code:

    throw new Exception("");
    and it places your cursor inside the quotes. I think that the default is to have it predicated by String.Format, but it’s seemed to learn that I’m more likely to throw exceptions with no variables than I am to include them in a formatted string.

  • NumberPad +/- highlights growing/shrinking amounts of text, respectively. So, if your mouse is on a string inside a method call that’s inside a method inside a region, continuously hitting + will highlight the string, then the method parameters, then the method call, then the whole method that you’re in, then the whole region, then the class. Minus will take you back down again. Very handy.
  • Tab to next reference. If you place the cursor over an identifier and start hitting tab, you can cycle through instances of the identifier in the code. Hitting escape will take you back to where you started. This is a huge improvement over Ctrl-K, R (find all references) in Visual Studio, which displays in a different window.
  • Smart Cut. One of the things I very much enjoy is being able to put my cursor at the beginning of a line, hit Ctrl-C, and then paste the line. There are a lot of other features of Smart Copy as well, but that one really sticks out for me as handy. Generally speaking, I try to avoid the mouse as much as possible, and this is a help.
  • Camel Case Navigation. Much like Ctrl-Arrow moves in chunks and Ctrl-Shift-Arrow highlights words in chunks, using the same while also holding down Alt navigates that way through CamelCaseWords.