Rory Becker - DevExpress CodeRush Blog

December 2013 - Posts

  • CodeRush Plugin – Cleanup File and Namespaces - How does it work?

    As promised in my last post, I’m going to explain just how the CleanupFileAndNamespaces plugin works.

    To recap, this plugin creates a new Command (CleanupFileAndNamespaces) which will cause CodeRush to fire the “Organize Namespace References” refactoring followed by the “CleanupFile” command.

    So how does it work?

    Overview

    This plugin consists of a single new command. When this command is triggered, it will perform a simple sequence of steps, which together will create the effect we are after.

    The high-level steps are:

    1. Store current location
    2. Execute CleanupFile command
    3. Move caret to first using \ Imports directive
    4. Execute Optimize Namespace References refactoring
    5. Restore Caret location.

    We’re going to look at 2 through 4 first and then revisit 1 and 5 together,

    Execute the CleanupFile command

    Executing an Command requires that we first know the name of the command we want to execute.


    CommandListIn this case I know that the command I want is called CleanupFile.
    However if I did not, the best place to check would be the Shortcuts options page.

    The Options screen can be found via DevExpress\CodeRush\Options.
    The Shortcuts page can be found at IDE\Shortcuts.

    On the right of this page is a dropdown labelled Command.
    This dropdown contains a list of all the Commands that CodeRush is aware of.

    Remember from previous blog posts that everything about CodeRush is dynamic, and so if you create a new action (the internal name for a command), you’ll find that CodeRush will list that action in this dropdown as well.

    We’d like to execute a command to cleanup the current file. Looking down through the list of commands, we soon come across several which are prefixed with the phrase Cleanup. They appear to work at a number of different levels (File, Folder, Project and Solution). We’ll pick CleanupFile for our plugin.


    Once we know which Command we’d like to execute, we need to get a reference to it in code. Internally commands are known as Actions. So in order to get a reference to the CleanupFile action, we would use code like….

    GetActionCleanupFile

    Having got a reference to the action, we can execute it like so….

    ActionExecuteCleanupFile

    Now that we know how to execute an action, let’s move on to the slightly more complex task of executing a refactoring.

    Position the Caret.

    Refactorings are very context sensitive and are typically not available all of the time. In this case the caret must be placed on a using (or imports) directive, before it will be available to use.

    In order to locate the first using\imports directive, we will use an ElementEnumerable object.

    This class is created with a scope (the Active File) and a LanguageElement Type (NamespaceReference – The internal name for a using or imports directive).

    ElementEnumerable

    Then we ask this class to enumerate and provide us with the first matching Element it can find.

    GetFirstNamespaceReference

    We use FirstOrDefault(), because it will return a null if no appropriate element is found. This is a sensible precaution, since there may not be any NamespaceReferences in the current file.

    Once we have a reference to the NamespaceReference, we can use it’s location as a destination to move to.

    Actually moving the caret into position is a simple matter of …

    MoveCaretToReference

    Once in position, we will be able to get a reference to the Refactoring in a very similar manner to that of obtaining a reference to an action

    Execute the Refactoring

    Again we need to know the name of the refactoring that we’d like to execute. In most cases the name of the refactoring, is the same as the display name of the refactoring, so you can just copy the text that you’re used to seeing when you execute a refactoring from within CodeRush.

    In this case the refactoring we want to execute  is “Organize Namespace References

    We can get our reference like this…

    GetRefactoringOptimizeNamespaceReferences

    Refactorings are executed via their Execute method. however we must first check if the refactoring is available. Only once we have confirmed availability, can we execute the refactoring.

    ExecuteRefactoring

    Saving and restoring the caret location.

    As you have seen, executing the ‘Optimize Namespace References’ refactoring, requires that we move the caret to a using\imports directive in order that it can function. Further, executing the CleanupFile action typically moves he caret to the end of the file which is processed. So no matter which way you look at it, the caret will not remain in its initial location.

    We should really do something about this, so let’s store the location of the caret at the start and return it to this location at the end of our action.

    We could capture the exact coordinates of the caret, but the we know the file is about to be altered. If anything above our caret’s initial position is removed, or added, then the stored position will be unlikely to make much sense afterwards.

    We could also bind the stored coordinates to the code, which would allow them to be adjusted up and down in these cases. however if methods are reordered this will still likely leave us in a strange location.

    So what to do? Should we give up and just leave the caret at the top or bottom of the file?

    Of course not.

    As luck would have it, the latest version of CodeRush provides us with a new subsystem for exactly this sort of situation.

    The new NavigationServices subsystem provides us with the means to capture our current location in terms of our place within the hierarchy of code elements.

    We get the current location and store it with…

    GetStartAddress

    Once we are done with our modifications, we can restore the relative position of the caret with…

    ResolveAddress

    Our New Action

    So now that we have all of the constituent parts of our plugin, we need a way to trigger their execution.

    There are several options available to us: Refactoring, CodeProvider, Command etc.

    Whilst one of the pieces used is a Refactoring, the combined effect is not.

    One characteristic of Refactorings and CodeProviders is that they present themselves contextually through the CodeRush SmartTag menu. This allows the Refactorings and CodeProviders to indicate when they are available.

    Our function would theoretically be available from any position in any C# or VB.net file. This means that it would show up all the time. This in turn would reduce the effectiveness of the SmartTagMenu. Therefore I decided not to implement the new functionality in either of these ways.

    Instead I chose to implement a new Action. If you recall, an Action is the internal name for a Command. These commands\actions are bindable to shortcut keys

    I created and registered the Action with the following code:

    CleanupFileAndNamespacesRegistrationGeneric2

    This is pretty much boilerplate stuff aside from the indicated customizations. The first of these is the Name of the new action. This is the value you will look for in the commands drop down on the shortcuts option page. The second of these is a reference to the method to execute when the action is triggered.

    Final steps

    The final steps are pretty simple.

    Implement the CleanupFileAndNamespaces_Execute function using all the code from the first half of this post.

    Then, lastly, be sure to call registerCleanupFileAndNamespace method from within your plugin’s InitializePlugIn method otherwise all of that lovely code, will never run at all. With that, we have all the elements we need and our action is complete.

    The full sourcecode for this plugin is available on github, as is the binary version

  • New CodeRush Plugin – Cleanup File and Namespaces

    This plugin wraps up 2 existing tasks (The ‘CleanupFile’ command and the ‘Optimize Namespace References’) in to a single new command ‘CleanupFileAndNamespaces’.

    In order to use this plugin:

    Step 0 – Requirements

    This plugin requires version 13.2 of CodeRush and a non-express version of Visual Studio version 2010 or higher.
    If you have a current CodeRush subscription, you can download the latest version through our download centre.
    If not, you can download a 30 day trial of all of our .Net products, including CodeRush.

    Step 1 – Download

    This plugin is hosted on GitHub and is available as either VSIX or as Sourcecode

    VISX_CleanupFileAndNamespaceCleanupFileAndNamespacesSourceCode

    Step 2- Install

    If you have downloaded the source, you will have to compile the plugin yourself, and then install from the VISX which the compile process creates.

    Once you have the VISX, (via download or compilation) simply double click it, and follow the prompts.

    CleanupFileAndNamespacesInstaller

    Step 3 - Configuration

    All that is necessary to configure this plugin, is to assign a key to the new ‘CleanupFileandNamespaces’ command.

    This is done via the Shortcuts options page.

    • To open the options screen either choose DevExpress\CodeRush\Options from the main menu, or use the Ctrl+Shift+Alt+O shortcut.
      To locate the shortcuts options page, locate the IDE\Shortcuts item in the tree on the left, or use the ShortcutsPageIcon icon in the upper right of the options screen.
    • CleanupFileAndNamespacesNewShortcut  Create a new shortcut by right clicking in an appropriate folder and choosing ‘New Keyboard Shortcut’ or ‘New Mouse Shortcut’.
    • CleanupFileAndNamespacesShortcutKeysThen choose a suitable key or mouse combination based on your preferences and previous choice. I usually pick Ctrl+T for testing purposes.

     

     

    CleanupFileAndNamespacesCommand Next choose the ‘CleanupFileAndNamespaces‘ command from the commands dropdown.

    Finally you should set the context of this command to make it only available when you are within a .vb or .cs file. CleanupFileAndNamespacesContext

    Finally click OK to accept your changes.

    Create a new shortcut and assign it to the the ‘CleanupFileAndNamespaces’ command.

    Step 4 – Usage

    • Place your caret in any .cs or .vb file. and invoke using the configured shortcut. CodeRush will run the ‘Optimize Namespace References’ refactoring and follow that by running any configured Code Clean operations.

    For example:

    The following is a fresh C# Library project, with a single unused variable declared.

    SimpleClassLibraryWithUnusedDeclaration

    Assuming that you have the default settings for Code Cleanup, and you trigger CleanupFileAndNamespaces from this start position, CodeRush will remove the unused using directive and the unused declaration:

    SimpleClassLibraryWithUnusedDeclarationAfterCleanup

    This simple plugin links together 2 often used features so that they can operate as one.

    In my next post I’ll explain how this plugin works in detail.

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