Rory Becker - DevExpress CodeRush Blog

October 2010 - Posts

  • CodeRush Plugins – Your first ‘Action’ Plugin – “DX_HelloWorld”

    Yes that’s right we’re going to create a plugin. Don’t worry it’s very easy and I promise this won’t break studio.

    In the grand tradition of programming, we’re going to write a “Hello World” plugin. The idea is that the user/developer will press some key combination and the DXCore will respond by placing the “Hello world!” message on screen.

    To do this we’re going to use an Action component.

    What is an Action?

    An Action represents some managed code which can be bound to either a keyboard or mouse shortcut. The effect of this is to allow the user/developer to invoke the code on demand. Additionally, if the correct properties are set, your action can appear in one of the standard Visual Studio menus.

    For example: If you wanted a function to count the number of files on your C:\ whenever you pressed Ctrl+Shift+C, then you’d do this by creating an Action to perform the count, and then bind that Action to the specified key combination.

    The choice of task in this case is pretty arbitrary. You can connect any managed code to this action, and as you might appreciate, this doesn’t limit you very much. The choice to use an Action is more about the invocation UX. If your feature is designed to be triggered by a keyboard or mouse shortcut, then the Action is the way forward.

    So how do I use an Action?

    So on with our example…

    Ok so first up, you’ll need to create your plugin project. Call it “DX_HelloWorld”.

    Next up take a look at your toolbox (yes the same place you usually find buttons and lists) and find a tab called “DXCore". In here you should see several DXCore components allToolboxDXCore used for various plugin related activities. The one you’re looking for is unsurprisingly named “Action”.

    Drag an “Action” to the design surface and set it’s name property to “SayHello”.

    Next we need to give our Action a system-wide unique name. In this case we’ll use “MessageBox.SayHello” in order to distinguish ourselves from future actions (perhaps provided by other plugins) which might wish to provide other implementations of “SayHello”

    PropertiesActionSayHello 

    After this we need to handle the Execute event

     EventsActionSayHello

    And call the appropriate code…

    Either…
    CodeVBActionSayHello

    ..Or if you really must…
    CodeCSharpActionSayHello

    …and that’s it. No really … It is. That’s all the code you need to write.

    Ok let’s prove it. Press F5 and this copy of studio, will launch another one which, in turn, will load and initialize your plugin.

    Notice that absolutely nothing happens.

    Don’t worry, this is to be expected. First you will need to bind your action to a shortcut, and then you will need to invoke it using that shortcut.

    Funnily this can be one of the harder things to do. Visual Studio and CodeRush already ship many shortcuts between them, and so finding one that is available can prove sometimes prove a little frustrating. When testing, I tend to use (and reuse) Ctrl+Shift+Alt+T. It’s a bit complex, but I’ve not seen it conflict with anything else so it seems to do the job well enough.

    Once you’ve bound your key to your action (Yes, I’m going to link that reference a lot) you should be able to press whatever combination you allocated as much as you like and be greeted (along with the rest of the world) whenever you like.

    HelloWorld

    Note: If you prefer, you can use the properties of your action to specify a menu on which it will be placed. Use either the CommonMenu or ParentMenu properties (Note: These properties are mutually exclusive). The DXCore will then place a menu item beneath your indicated menu using the text specified in your action’s ‘ButtonText’ property.

    Well I think that’s about it for this lesson. Stay tuned as we’ll begin to dig deeper into other components, and start branching out into more complicated and indeed more useful plugins.

  • CodeRush Plugins – Plugin Components

    So you’ve created your base plugin project.

    Now you’ll need to decide on which components are necessary to implement the functionality you’re after.

    In order to do that, you’ll need at least a brief overview of some of the more common components and what they are used for.

    In a nutshell these components are: Action, StringProvider, TextCommand, RefactoringProvider, CodeProvider, IssueProvider and MetricProvider.

    iconActionAction
    The simplest of plugin component: Actions wrap managed code which can then be bound to either mouse or keyboard shortcuts by the end user/developer. Actions can also be rendered as menu options on any of the standard Studio menus.

    iconStringProviderStringProvider
    Used within Templates, Selection Embedding and similar features, StringProviders return strings to the features which they are placed within. The string in question can be sourced from anywhere: Settings, Envrionment, DateTime, the Clipboard or even a Web Service. Built-in examples include «?Username», «?FieldPrefix», «?DayOfWeek», «?Paste» and «?SolutionName».

    iconTextCommandTextCommand
    TextCommands, like StringProviders, are used in higher level features to provide blocks of functionality to those features. They may be considered ‘Void Proc’ versions of the StringProviders, in that they are unable to return any value to said calling function. Instead they provide functionality via the current TextDocument (Internal representation of the current text file) which they can both access and affect. Examples of shipping TextCommands include: «Caret», «BlockAnchor», «AddAssemblyReference» and «Marker».

    iconRefactoringProviderRefactoringProvider
    This component is used to add items to the Refactor menu within the CodeRush SmartTag. The RefactoringProvider provides events both for determining if your refactoring is suitable based on the current circumstances, and also for applying the refactoring itself when it is chosen. The RefactoringProvider should be used when providing a true refactoring to the end user. ie When the operation is required to not change the functionality of the code being acted upon.

    iconCodeProviderCodeProvider
    The CodeProvider compliments the RefactoringProvider and is use to add items to the Code menu within the CodeRush SmartTag. The CodeProvider should be used instead of a RefactoringProvider when the operation is required to change the functionality of the code being acted upon. Examples of CodeProviders include the ‘Declare X’ range of items of the Code menu, used to declare things like variables, enums and classes based on examples of their usage.

    iconIssueProviderIssueProvider
    Used to define your own Code Issues (inline hints, warnings and errors) which will then be presented within the environment. This component can be combined with either the CodeProvider or RefactoringProvider in order to provide a method of fixing the raised CodeIssue. Some good examples of using this component can be found in the CR_StyleNinja community plugin.

    iconCodeMetricProviderMetricProvider
    This component allows you to provide an algorithm, which produces a numeric value based on a code element (usually a member of a type). Said value is then shown inline in the editor or within the Metrics Toolwindow. Examples of existing metrics shipping with CodeRush include the ‘Line Count’, ‘Cyclomatic Complexity’ and ‘Maintenance Complexity’.

    This list is by no means definitive, but is intended only to represent the most commonly used components.

    It should be noted that your plugin can have many of these components on it’s design surface, and is not limited to just one or indeed even just one type. Your plugin might ultimately make use of 2 Actions, 3 RefactoringProviders and a MetricProvider. However, for the purposes of these first few examples, we’ll be concentrating on just one component at a time.

    In the coming posts I’ll be explaining these components in much greater detail. I’ll cover the specific use of each, and couple that with a complete example. Soon you’ll creating your own plugins to achieve all manner of clever things.

    The steps here are common to all plugins, and I’ll be referring back to them from each of my plugin examples.

    Next up we’ll create our first complete plugin – “DX_HelloWorld”

  • Starting a CodeRush Plugin Project

    This post is for primarily for reference. In it we are going to demonstrate the first steps for creating a DXCore plugin. These steps should remain the same for any plugin you choose to create, and therefore it makes sense to separate them into a common post which can be referenced in the future.

    There are 2 ways to create a DXCore plugin project

    Firstly you might create it via the standard “New Project” dialog.

    Choose File \ New \ Project … then … [Language] \ DXCore \ Standard Plug-in.

    NewProjectDialog-DXCorePlugin

    Alternatively chose DevExpress \ New Plugin

    NewDXCorePluginProject

    In either case you’ll arrive at this dialog:

    DXCoreProjectPluginSettings

    From here you’ll mostly be able to just leave the defaults. In case you’re interested the differences are:

    • System plugins are loaded a stage earlier in the initialization process than other plugins.
    • Load Manually causes the DXCore to ignore your plugin until such time as you explicitly ask for it to be loaded.
    • Alternatives to ‘On Demand’ are ‘On Idle’ and ‘At Start-up’.

    Once your choices are made here, VS will construct your initial DXCore Plugin project and show you it’s design surface.

    DXCoreDesignSurface

    From here, your next step will be to place some DXCore components on this design surface, fill out some properties and handle some events.

    We’ll stop here for now, and pick up next time with an introduction of some of the more common DXCore components.

  • CodeRush Plugins - What are they good for?… Absolutely everything!

    Ok so I might be overblowing things slightly, but stop and think for a moment…

    Mark Miller built a plugin that allowed him to interface a wireless guitar controller, with Visual studio. Using this plugin, CodeRush and his guitar instead of a keyboard, he was able to code faster than most people could with a keyboard and vanilla VS.

    Come on… That is Awesome!

    Oh yeah .. And don’t get me started about his next scheme.

    Anyway… all that out of the way… What *is* a plugin good for?

    Well that’s an interesting question. Well let’s put it this way….

    CodeRush == DXCore + Plugins

    Ok sure but what does that mean?

    It means that CodeRush is technically nothing more than a bunch of plugins built on top of the services of the DXCore. This in turn means that the DXCore provides everything you need to start building plugins as powerful as the features in CodeRush.

    So why is writing a plugin using the DXCore easier than writing it without.

    Ok, let’s have a look at the benefits of the DXCore:

    Managed Code
    The DXCore removes the need for programming against COM Interfaces for the vast majority of plugin code, without removing your access to that facility in case you should need it. Ask anyone (Oh ok … any semi-respectable programmer) … “All other things being equal, would you prefer to write against COM or against a managed library?”. If you find someone who votes for COM, you have found a <Insert polite term here>*.

    *Note: I did asked my followers on twitter, what a polite term for such a person would be. Answers included ‘a lunatic’, ‘grandpa’, ‘old’, ‘sadist’ and my personal favourite ‘There is no appropriate polite term for such a guy’.

    Get straight to the point.

    When you code add-ins with the DXCore, it can be a simple matter of dropping a component on a design surface setting a couple of properties (typically for sensible naming and such), and then handling one or more events. You don’t have to mess around with registering your plugin with anything. There’s no shimming to create tool-windows, and you don’t have to perform multiple casts on everything, just to get access to properties that you should have been able to see all along. The DXCore lets you just get on with creating your plugin. It worries about the glue so you don’t have to.

    Support all the way back to VS2005

    Just like it says on the tin. The DXCore can provide you with all sorts of contextual information and understands many different versions of each of the languages that are supported. This means that you can easily write a single version of a plugin, and have it support the last 3 versions of studio (VS2010, VS2008 and VS2005) without needing to recode or recompile. Your plugin can be installed in a single location on a machine which has all 3 of these IDE’s installed, and it will function quite happily in all of them. This does not mean that it has to function exactly the same in all 3. If you like you can ask the DXCore which version you’re operating under, and you can alter your plugin’s behaviour accordingly. So it’s not something you need to worry about, but if you want this sort of info, it’s available on tap for you to do with what you will.

    Deep Language Parsing

    The DXCore parses everything. I’m serious I really mean every part of your source. I remember trying to write CodeGen code before finding out about the DXCore. It was a black art at best, and worse there wasn’t much support for anything more detailed than a method declaration. The DXCore parses everything into an abstract syntax tree (AST) of objects which is completely language independent. Everything from the source files, through namespaces and types (Classes Structs and Interfaces) then on into fields, methods, properties, accessors … statements, branches, loops … expressions, primitives. Like I said… everything.

    Cross Language Plugins

    Given my previous point about how well parsed your code is, and that the result is an AST which is decoupled from your code, it should come as no surprise really, that this means a DXCore Plugin is able to perform it’s task needing little-to-no knowledge of the language within which it is operating. That’s right. you can write a single plugin which can work just as well with C#, VB.Net or even JavaScript. All these languages are parsed into the same objects within the AST, and can be analysed to produce information based upon this abstract nature. For example the ‘maintenance complexity’ metric feature of CodeRush works with all 3 languages, because what it’s analysing is loops, conditionals, declarations and the like. The feature itself has no real knowledge of any of these languages, because it doesn’t need to. The DXCore has been parsed out all of the language specifics and their nuances into an AST. All that’s left to do is analyse the AST and produce a result, which is exactly what the ‘Maintenance Complexity’ metric does.

    Likewise if you construct an AST of your own, adding classes, members, statements etc, it can be then emitted into any of these languages with a single function call. Allowing you to create Refactorings and CodeProviders that work across multiple languages without additional coding or even fully understanding the syntax of those languages.

    Rapid Plugin Prototyping

    Coding against the DXCore is quick. I’ve lost track of the number of times that I’ve said to myself "I wish that studio could do X” or “The lack of Y really annoys me” or “Wouldn’t it be great if…”

    Starting from a raw “Standard Plugin” project you literally drop a component on the design surface (if that’s the way you prefer), fill out a couple of properties and then handle one or more events to provide the specific functionality you’re after.

    You can have a workable prototype plugin in seconds, and a fully working version in minutes. If you add to this, the ability to change the code of your plugin on the fly whilst it’s still running inside Visual Studio (Edit and Continue**) and you’ve got a very flexible way to build plugins to do all sorts of crazy things.
    I’ll be showing you in subsequent posts, how individual types of plugins are created, and I’ll provide you example code for achieving all sorts of cool stuff.
    (**‘Edit and Continue’ really is teh awesome. Except if you’re coding in C# and like to use Lambdas, but hey nobody is perfect.)

    Summary

    What it boils down to is this: Visual Studio is not perfect. The guys on the IDE team at MS are great. No really they are… Look at what they have achieved. It really is awesome… but they simply cannot ship features as fast as we come up with requirements. The DXCore gives you the ability to take matters into your own hands.

    Imagine for a moment, all of your accumulated skill from all those years of programming that you’ve done. Wouldn’t it be nice if you could use some of that, to enhance your own day to day life, rather than always directly in service of your customers. I’m not suggesting the you should ignore your customers, but if your own programming life can be made smoother, then the benefits of this are passed on to your customers anyway through your increased productivity.

    The DXCore gives you back the power to do just this. So stick with me here, as I guide you through the process of building some plugins of your very own.

  • Binding keys in CodeRush

    If you happen to prefer different keys to the CodeRush defaults, or if you’ve downloaded a third party plugin which needs some keys configuring, then at some point you’re going to want to visit the shortcuts page of the options screen.

    Once you launch the options screen (DevExpress\Options or CTRL+SHIFT+ALT+O), you can locate the shortcuts page in the tree on the left at IDE\Shortcuts.

    At this point you should see something like the following:

    (Note:The page tree has been collapsed to allow extra space for the other features of this page.)
    OptionsIDEShortcuts

    The tree on the left shows a hierarchical view of all of the shortcut keys recognised by CodeRush at the current time.

    Above the tree are several icons allowing you to:

    • Create new Keyboard shortcut
    • Create new Mouse shortcut
    • Duplicate Shortcut
    • Create Folder
    • Rename
    • Delete
    • Hide Shortcut Folders – This will flatten the hierarchy and sort the items by shortcut. This is useful for tracking down any conflicts or quickly determining if a given keystroke is actually in use and in what context.
    • Search for Shortcut
    • Distinguish Left and Right Alt keys – Useful with some keyboard layouts / languages where these keys provide differing functions. FWIW I use a Qwerty keyboard with British English and I have never had to alter this setting.

    Here are some steps to guide you through the creation of CodeRush shortcuts.

    Create a Custom Folder
    Before creating any new shortcuts, create a new folder called “Custom”. Use this folder (or one beneath it) as the location in which any new shortcuts are created. This has the benefit of collecting all of your custom shortcuts in a single location which makes sharing or moving them to another machine much easier.

    Note: The on-disk representation of your shortcut settings can be found at: ‘%AppData%\CodeRush for VS.Net\1.1\Settings.xml\IDE\Shortcuts’                                             

    Choose your Shortcut 
    OptionsShortcutsKeysMost of the time you’ll want to invoke your functionality via a keyboard shortcut of some kind. However you’ll want to give some thought to which key combination to use.

    To specify a key combo, simply place your caret in the ‘Key 1’ box, and press the keys in the combination you’re after. If your shortcut is intended to be the first part of a chord (ie 2 key combos one after the other), you should enter the 2nd part of this chord in the ‘Key 2’ box. If either if these combos require any special keys ({Tab}, {Backspace}, {Delete}, {Esc} etc), these can be entered by using the right-click context menu of these boxes.

    As stated before, you can use the “Hide Shortcut Folders” to help determine if there might be a conflict with an existing piece of CodeRush feature. If this turns out to be the case, you might solve this by allocating differing contexts to each of the conflicting shortcuts. (See contexts – below)

    Command
    OptionsShortcutsCommandNext up you’ll have to choose the command that you want your shortcut to execute. Command refers to either a CodeRush Action or a Visual Studio command. CodeRush Actions are listed within the dropdown element of the command box. In the case of an Action, there might be some parameters you wish to pass to the Action. These may be passed via the Parameters box and should be comma separated if present.

    Note: It’s worth bearing in mind that CodeRush Shortcuts are processed before those of Visual Studio, and only passed on to studio, if not handled by CodeRush (unless otherwise expressly specified). If you find a case where you need to pass these on to Studio afterward, just check the tick box underneath the parameters box.

    Context
    OptionsShortcutsCoontextFinally you should setup the context in which you wish your Shortcut to operate. Context is one of the key parts of the DXCore. It allows you to indicate that certain operations are only valid under particular circumstances. This means that you can allocate the same shortcut to 2 or more completely different operations by supplying them with different contexts (prerequisites). If these contexts are mutually exclusive, then there can be no confusion about which action you meant to invoke.

    If you are assigning behaviour to a keystroke that is only appropriate when Studio is focused on the Code Editor, then you should indicate this in it’s context. Otherwise you might find that your functionality is also triggered from within a Find Dialog or similar. Most of the time this is not what you want.

     

     

     

     

    So in order to create your shortcut, you need only specify the key combination, command name and context. You may also edit these portions of any existing shortcuts. Once you are happy with your shortcuts, simply click the ‘Apply’ or ‘Ok’ buttons, and you should find that your shortcut is immediately available.

    Summary

    CodeRush Shortcuts, like their Template counterparts, are very powerful due to the Context provided by the DXCore on which they are both built. This enables the same key combination to be interpreted differently depending on the current situation. This post has demonstrated how to create or edit a shortcut, the key parts of a each and what they mean.

    You should now have everything you need to reassign any keys you like, as well as adding additional bindings for any third party plugins that you might download.

LIVE CHAT

Chat is one of the many ways you can contact members of the DevExpress Team.
We are available Monday-Friday between 7:30am and 4:30pm Pacific Time.

If you need additional product information, write to us at info@devexpress.com or call us at +1 (818) 844-3383

FOLLOW US

DevExpress engineers feature-complete Presentation Controls, IDE Productivity Tools, Business Application Frameworks, and Reporting Systems for Visual Studio, along with high-performance HTML JS Mobile Frameworks for developers targeting iOS, Android and Windows Phone. Whether using WPF, ASP.NET, WinForms, HTML5 or Windows 10, DevExpress tools help you build and deliver your best in the shortest time possible.

Copyright © 1998-2017 Developer Express Inc.
All trademarks or registered trademarks are property of their respective owners