Rory Becker - DevExpress CodeRush Blog
  • Extract Method and Inline literals – How does it work?

    If you recall in my previous post, I presented a new plugin "CR_ExtractMethodAndInlineLiterals

    In this post I’ll walk you through exactly how it works.

    Overview

    This plugin does it’s job by automating the execution of existing Refactorings, moving the caret around and executing more Refactorings.

    Broadly speaking there are 3 parts to this task.

  • Extract literals from selection.
  • Extract remaining code to new method.
  • Inline literals back into the call to the new method.
  • Extraction of the literals

    The first part of extracting the literals is to find them. For this we will use an instance of ElementEnumerable. The ElementEnumerable constructor requires a scope (in which to search) and a filter (to use for testing found items). We can’t pass the current selection as scope (Selection isn’t a LanguageElement). Instead we’ll pass the ActiveFileNode. For the Filter, we’ll pass a custom implementation of an IElementFilter. The bulk of our class (TypeInRangeFilter) is shown here:

    EMIL-TypeInRangeFilter

    IElementFilters are used to test IElements (or sequences of them) against specific criteria. The criteria will vary from implementation to implementation. In this case we have created an IElementFilter which passes elements if they are both of the required type, and their start is within the supplied range.

    We use this IElementFilter together with the ElementEnumerable in order to produce a list of PrimitiveExpressions (strings, numbers etc) )within the selected SourceRange.

    EMIL-GetPrimitivesMethod

    Having found these literals, we need to place our caret within their name, or better yet, select them entirely…

    EMIL-SelectRange

    Once selected, we need to call a refactoring.

    However calling a Refactoring from within another refactoring, is a little more complicated that just getting a reference and calling it:

    EMIL-ExecuteRefactoringMethod

    Using this helper method, we make the call to the ‘Introduce Local’ refactoring

    EMIL-CallIntroduceLocalRefactoring

    At this point it’s worth noting that the refactoring will have changed our code, and naturally enough the Active Document will have to be reparsed.

    For this, we need a call to…

    ReparseActiveDocument

    … which will cause CodeRush to update it’s internal representation of the code.

    Each call to Introduce Local will have caused the the introduction of a new Initialized variable. However each of these will have been placed immediately prior to it’s initial usage. This is less than ideal since since we’d like to exclude these initializations from the extraction. Not to worry, we can move these statements up above the original selection.

    Finding these InitializedVariables involves another custom implementation of IElementFilter (InitializedVarFilter).

    This time the internals look more like this:

    EMIL-InitializedVarFilter

    This IElementFilter looks for IElements whose type is InitializedVariable and also match a given name

    As before, we use our new IElementFilter like this

    EMIL-GetInitializedVarsMethod

    Iterating through our InitializedVars we can move each above the selection using:

    EMIL-MoveInitializedVar

    Extract Method

    Next we reselect our original selection. (Messing with code doesn’t always alter your selection, but it can be a good practice to ensure things are the way you want them anyway)

    EMIL-SelectSelectRange

    … and then Extract the Method using the helper function we created earlier.

    EMIL-CallExtractMethod

    Inline Variables

    Our final official step is to inline the Initialized Variables back into the method call.

    Once more we can iterate through our previously gathered list of InitializedVariables

    Select the range of each in turn

    EMIL-SelectInitializedVariable

    Then Execute the Inline Temp refactoring

    EMIL-CallInlineTempRefactoring

    Essentially that’s all there is to it.

    As usual the full code to this plugin can be found on github.com as well as the VSIX.

    Feel free to use these as a reference for your own plugins, or to extend them and contribute changes back again.

  • New CodeRush Plugin – Extract Method and Inline literals

    You know what it’s like. Every now and then you spot that you’re performing the same sequence of tasks over and over again, and you find yourself wishing that there was a way to automate what you’re doing.

    Well you’re not alone. Just recently I had one such situation.

    The pattern in question is a relatively simple one.

    It usually starts with a method which itself calls several other methods.

    ExtractAndInlineStart

    In the middle of that code, you realise there are a few lines which you’d like to be able to reuse a little easier.

    Naturally you reach for your trusty Extract Method refactoring. Highlight the code and extract away.

    However what you’re left with isn’t quite what you want.

    ExtractAndInlineSimple 

    What you really want is to have those literal values passed in as parameters.

    Your ultimate goal is more like:

    ExtractAndInlineImplemented

    There are 2 ways to go about this with CodeRush.

    Option 1 – Method First

    In this first case, you…

    - Extract your Target Code as shown in the first example. (Extract Method x 1)
    - Promote each literal to a parameter of the new method. (Promote Parameter x L)

    For a hypothetical method with 3 parameters, this will result in 4 operations. (3 x Promote Parameter + 1 x Extract Method)

    Option 2 – Params First (and Last)

    This second version is more complicated, but suits the way some people think a little better.

    - Extract each of the literal values in your Target Code (Introduce Local x L)
    - Move the resultant locals up above the portion of code you’re looking to extract. (Copy and Paste x L)
    - Extract your Target Code (Extract Method x 1)
    - Re-Inline the literals you created in the first step. (Inline Temp x L)

    For the same hypothetical method (with 3 params), this solution requires 10 operations. (3 x Introduce Local + 3 Copy\Paste + 1 Extract Method + 3 Inline Temp)

    Each option suits different people’s approach, but both are a few more steps more than I’d like to have to perform

    It’s lucky then that CodeRush is so Extensible Open-mouthed smile

    Enter a new plugin

    The new plugin provides an additional refactoring (Extract Method And Inline Temp) which sits in the usual smart Tag menu, and makes itself available alongside Extract Method.

    All that’s required is a single click, and CodeRush will whisk you passed all of those tedious (and potentially error ridden) manual steps.

    ExtractAndInlineRefactoring

    As usual, this project is Now available on github with full source code and VSIX Install.

    In a future post I’ll walk you through how this plugin works.

    For now, just look for the latest release, and away you go Smile

  • 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.

  • Custom Navigation within XML files

    The request

    A customer came to me and said:

    “So I’ve got some XML files which hold a sort of DSL which I use to configure my application. There are elements in this DSL which have id attributes, and other elements which have ref attributes. As you might expect, within my DSL, the ref attributes are references to the id attributes.

    Is there anything in CodeRush to help my navigate easily among these id and ref attributes where their values match?”

    My plugin-sense started tingling….

    I immediately thought of our awesome Tab to Next Reference feature, and figured we could probably extend it to work in this new scenario.

    Create the project

  • File… New Project
  • Choose Language (C# in this case)
  • DXCore\Standard Plug-in

    Choose a name for your project (I chose CR_XMLNav)

    The Coding

    First I used a template to add some boilerplate code. (Bold text shows custom changes)


    private void registerXMLRefSearch()
    {
        var XMLRefSearch = new DevExpress.CodeRush.Core.SearchProvider();
        ((System.ComponentModel.
    ISupportInitialize)(XMLRefSearch)).BeginInit();
        XMLRefSearch.Description =
    "XMLRefSearch";
        XMLRefSearch.ProviderName =
    "XMLRefSearch"; // Needs to be Unique
        XMLRefSearch.Register = true;
        XMLRefSearch.UseForNavigation =
    true;
        XMLRefSearch.CheckAvailability += XMLRefSearch_CheckAvailability;
        XMLRefSearch.SearchReferences += XMLRefSearch_SearchReferences;
        ((System.ComponentModel.
    ISupportInitialize)(XMLRefSearch)).EndInit();
    }

    private void XMLRefSearch_CheckAvailability(object sender, CheckSearchAvailabilityEventArgs ea)
    {
    }

    private
    void XMLRefSearch_SearchReferences(Object Sender, DevExpress.CodeRush.Core.SearchEventArgs ea)
    {
    }


    Then I fleshed out the CheckAvailability routine:


    private void XMLRefSearch_CheckAvailability(object sender, CheckSearchAvailabilityEventArgs ea)
    {
        // Get Active LanguageElement
        var Element = CodeRush.Documents.ActiveTextDocument.GetNodeAt(CodeRush.Caret.Line, CodeRush.Caret.Offset);

        if
    (Element == null)
            return;

        if
    (!(Element is XmlAttribute))
            return;

        // Allow search to start if Attribute
        ea.Available = new string[] { "id", "ref" }.Contains(((XmlAttribute)Element).Name);
    }


    Essentially this routine looks to see if the caret is on a LanguageElement of type XmlAttribute whose name matches either id or ref.

    If it finds that this is the case, our searchProvider is made available, and processing continues with the XMLRefSearch_SearchReferences routine.


    private void XMLRefSearch_SearchReferences(Object Sender, DevExpress.CodeRush.Core.SearchEventArgs ea)
    {
        // Store Value of initial XmlAttribute
        TextDocument activeDoc = CodeRush.Documents.ActiveTextDocument;
        string StartValue = ((XmlAttribute)activeDoc.GetNodeAt(CodeRush.Caret.Line, CodeRush.Caret.Offset)).Value;

       
    // Iterate LanguageElements in solution
        SolutionElement activeSolution = CodeRush.Source.ActiveSolution;
        foreach (ProjectElement project in activeSolution.AllProjects)
        {
            foreach (SourceFile sourceFile in project.AllFiles)
            {
                SourceFile activeFile = CodeRush.Source.ActiveSourceFile;
                ElementEnumerable Enumerator = new ElementEnumerable(sourceFile, new XMLAttributeFilter(StartValue), true);
                foreach (XmlAttribute CurrentAttribute in Enumerator
                {
                    ea.AddRange(
    new FileSourceRange(CurrentAttribute.FileNode, CurrentAttribute.ValueRange));
                }
            }
        }
    }

    This code iterates through your solution (projects files etc) looking for appropriate XmlAttributes. The key to this little piece of code is this line here:
    ElementEnumerable Enumerator = new ElementEnumerable(sourceFile, new XMLAttributeFilter(StartValue), true
    );


    This creates an object capable of enumerating through the code looking for things which match a very specific set of criteria.

    The specifics of what will match are handled by our last piece of code.


    public class XMLAttributeFilter : IElementFilter
    {
        private readonly string
    _startValue;
        public XMLAttributeFilter(string
    StartValue)
        {
            _startValue = StartValue;
        }
        public bool Apply(IElement
    element)
        {
            // Skip if null 
            if (element == null
    )
                return false
    ;

           
    // Skip if not XmlAttribute
            if (!(element is XmlAttribute
    ))
                return false
    ;
            XmlAttribute CurrentAttribute = (XmlAttribute
    )element;

           
    // Skip attribute if it doesn't have the correct name.
            if (CurrentAttribute.Name != "id" && CurrentAttribute.Name != "ref"
    )
                return false
    ;

           
    // Skip the attribute if it doesn't have the same value as start point.
            if
    (CurrentAttribute.Value != _startValue)
                return false


            return
    true
    ;
        }
        public bool SkipChildren(IElement
    element)
        {
            return false
    ;
        }
    }   

    Each LanguageElement is checked and passed over if it fails any single check.

    • In this way we pass a list of all valid items on to the Tab to Next Reference feature which then allows us to seamlessly tab through all the references.

    • CR_XMLNav

    • Summary
    • This sort of technique is, as you can see, very simple to apply. I’m sure you can think of many similar occasions when you’ve wished you could jump between related bits of configuration. Well now you have the ability to do just that.

    The full version of this plugin is hosted up on GitHub.com for those who are interested.

  • How to generate a Simple ToString() implementation with CodeRush templates

    A customer recently asked:

    Does CodeRush have a quick way to auto-implement ToString()?
    If it outputted each prop Name & value it would be great.

    Never one to shirk a challenge, I quickly set about finding the quickest way to allow a user to generate a ToString() method which
    would provide the requisite information.

    The approach I took this time, was that of Templates. Note: This task could certainly have been achieved with a plugin, but it’s
    quicker and arguably more efficient to use Templates in this case, so that’s the route I chose to take.

    For a generic primer on how to create CodeRush templates see my earlier post: CodeRush Templates - Creation Basics

    Structure

    The solution to this is to create 3 templates. An Iterating Template, An Item Template and a Delimiting Template

    • The Iterating Template: This is triggered by the user, and controls the iteration of the properties.
    • The Item Template: This represents the text that is emitted for each property encountered.
    • The Separation Template: This is used to determine text that sits between invocations of the item template.

    Specifics

    The Iterating Template

    As indicated this template is the one which is called directly by the user and as such should carry a sensible name. I’m not so great at naming so I chose to call mine ToStringPropertyMethod

    It will therefore be invoked whenever the user types ToStringPropertyMethod and hits the spacebar (or tab if you’re in Friction free mode)

    The body of this template is:

    -------------------------------------------------------------

    public override string ToString()
    {
    return «ForEach(Property,PropertyEach,,PropertySeparator)»;
    }

    -------------------------------------------------------------

    The basic structure of this will look familiar. The signature is that of the standard ToString() override, and the braces are those present in any method in order to denote the start and end of that method.


    What will be less familiar is the code within the chevrons (« and »)

    This code is a TextCommand which is interpreted by CodeRush, rather than emitted directly into your code.

    This TextCommand is called 'ForEach' and it takes up to 5 parameters. In this instance we only need 3 of these.

    • 'Property' specifies that we are interested in iterating through any properties of the current class.
    • 'PropertyEach' is the name of the template to expand for each property found.
    • 'PropertySeparator' is the name of the template to be expanded between any 2 calls to PropertyEach

    The other 2 params are unused in this case but control templates expanded at the start and end of the sequence.

    As you can see, this template depends on the existance of both PropertyEach and PropertySeperator.

    The expansion of the PropertySeperator Template is predictably a simple + sequence thus:

    -------------------------------------------------------------

     +

    -------------------------------------------------------------


    The content of the PropertyEach template is a little more complicated:

    -------------------------------------------------------------

    "«?Get(itemName)»: " + «?Get(itemName)».ToString()

    -------------------------------------------------------------

    This represets the building of some code which will itself emit a string representative of the property being iterated.

    The bit you may be less familiar with is «?Get(itemName)». It is a StringProvider which provides access to strings setup by previous uses of the «?Set» StringProvider.


    In this case, each time the «?ForEach» StringProvider  finds a new Property, it sets itemName to the name of that Property. This gives us a handy way to access that information and emit it into out code.

    If you put all of this together and Expand the ToStringPropertyMethod template from within the following class...

    -------------------------------------------------------------

        public class Example
        {
            public string PropertyName1 { get; set; }
            public string PropertyName2 { get; set; }
            public string PropertyName3 { get; set; }
        }
    -------------------------------------------------------------

    ...you get the following result...

    -------------------------------------------------------------

        public class Example
        {
            public string PropertyName1 { get; set; }
            public string PropertyName2 { get; set; }
            public override string ToString()
            {
                return "PropertyName1: " + PropertyName1.ToString() + "PropertyName2: " + PropertyName2.ToString();
            }

        }
    -------------------------------------------------------------


    Summary

    As you can see, this code will emit the name and value of each property of the class when called.

    Obviously the formatting could be improved, but I think you can see the potential demonstrated here.

    What about generating XML or JSON based strings.

    These, of course, are left as an exercise for the reader. :)





  • New CodeRush Plugin: CR_JumpToNamedMVCView

    So a customer came to me with plugin request:

    Customer: “I typically invoke my MVC razor views, by name, from within my controllers. Is there a plugin which can help me navigate to these views from the invocation?”

    Me: “Not right now, No. Let me see what I can do”. *Challenge Accepted"*

    And so I set off to create a new plugin to assist with this type of navigation.

    A few hours later, the result is CR_JumpToNamedMVCView. A simple plugin which adds a single item (Named MVC View) to our Navigation SmartMenu (Ctrl+Alt+N)

    Consider a very simple MVC CustomerController class.

    JumpToNamedMVCViewCustomerControllerFull

    The idea here is that you’re coding or reading through your controller and need to navigate to the view which you will be returning from a given action.

    With this new plugin, you can now…

    • Place your caret on the name of the view… (in this case “List”)
    • Press Ctrl+Alt+N

    JumpToNamedMVCViewCustomerControllerJumpToView

    • Select Named MVC View

    JumpToNamedMVCViewCustomerListView

    …and Voila! CodeRush delivers you to the view specified in the original call.

    See this plugin’s Community Wiki page for even more detail, including how to assign this action to F12 for a more ‘Goto Definition’ approach

    Hopefully this simple plugin will make your MVC coding, that little bit easier.

    So now let’s see what develops.

  • New CodeRush Plugin: CR_RefreshTemplate

    Background

    A customer came to me asking about Templates and what could be done with them.

    The desired use case seemed simple enough:

    • The user types a few characters, hits space and the template expands as usual.
    • The user fills out one piece of information, and that information is replicated to several other locations around the expanded text.
    • The user fills out a 2nd value and that is also replicated to several location.

    Normally I would assume the job would be done at this stage. However our customer was after something a little beyond the usual.

    They required that Fields used within the template should not be removed once the data had been entered. 

    I asked what the motivation for this was and was told : “I’d like them to remain, in case a user wanted to come back and alter them at some point in the future.”

    Whilst a little unconventional, this didn’t seem unreasonable. However Fields have some limitations…

    Field Limitations

    As it turns out, Fields are not very (read ‘at all’) persistent.

    They are removed when:

    • They are used (values set and enter pressed).
    • Another template is expanded.
    • The project\solution is closed\reopened.

    As you can see, this leaves a very narrow window in which to make modifications. As such Fields are not suited to the customer’s needs.

    Alternatives

    Note: This section details some alternative approaches to solving this problem that were considered. If you’re not interested in this, feel free to skip to “The Solution: Refresh Template” (below)

    So I sat down to consider what alternatives might be available.

    The brief: To allow someone to expand a template which would normally use fields and links, in such a way as they can come back (potentially much later) and edit the fields and, by proxy, the linked text.

    Ideas:

    • Rename: Suggest user could use our rename refactoring when they come back to change the linked value to something else.
    • Reconfigure Field Interaction: Alter CodeRush’s behaviour regarding fields through configuration.
    • Persistable Fields: Create new type of persistent field.
    • Recreate Fields on Demand: Recreate the fields when user returned to this area.
    • Refresh Template: Wipe and replay the template.

    Strategy: Rename

    If the fields and links created by a template are equivalent to the links generated by the act of triggering a Rename refactoring on some token generated by the template, then this prevents the need to leave fields intact after template expansion.

    However this is rarely the case. Fields and links within templates are often used to create related identifiers with the same prefix or suffix. They may also be used to create documentation (standard and non standard). Sometimes these links and fields may affect the types emitted by the template.

    In all these cases, the Rename refactoring is incapable of recreating the fields and links from the final static output of the template.

    Strategy: Reconfigure Field Interaction

    Imagine we take a configuration approach.

    We could create a new context (IsInPersistableField) which would determine if we were within a Field which should be considered persistable.

    Note: Without further plugin work the template would need to emit something which might mark all fields within it as Persistable.

    We would alter the shortcut for FieldAccept (Enter) and enable it only if the condition were not met.
    We would create a new shortcut for FieldNext (Enter) and enable it only if the condition were met.

    This allows us to redirect the use of Enter to navigate between Fields without killing them assuming that we were in the result of a particular type of template

    However this is just the tip of the iceberg. It does not make the field truly persistent. It merely prevents the premature removal of the field due to it receiving confirmed data. Additionally over time this would lead to a growing number of fields to manage.

    Strategy: Create Persistable Field

    Potentially we could create a plugin which introduces an additional type of Field. One which is persisted between sessions. This new field would need to reproduce all functionality of the existing field except the elimination of itself when enter was pressed. This would also need to be repeated with a persistable version of the Link TextCommand

    This is possible, but complex. Additionally it would create an even greater number of fields to manage over time, since none would appear to ever be removed.

    Strategy: Recreate Fields on Demand

    If there were some way we could infer the prior existence of a field and set of links, from the text its template had previously produced, we could recreate them on demand.

    Yeah this struck me as a bit far fetched as well :) It’s a bit like reassembling a egg and some wheat when given a cake.

    The Solution: Refresh Template

    Refresh (or replay) Template is the idea that you re-execute a template over the top of itself so that you can re-specify the values for any fields within.

    If we modify a template so that it emits its own name into the final text, we could then build a plugin that knows how to use that meta data as a way of clearing and re-executing that template at some later point.

    Consider the following template called DateNow which outputs the current Date and Time:

    DateNowBasic

    In order to allow this template to refresh, we need to augment it with a header and footer.

    DateNow

    Now we have all the information we need. If only we had a plugin that could make use of this information…

    Enter CR_RefreshTemplate:

    CR_RefreshTemplate provides a new CodeProvider Refresh Template, which is available when the caret is between an appropriate header and footer.

    CodeProviderRefreshTemplate

    Once triggered it will…

    • Read the name of the template from the header and footer.
    • Clear the Text between the header and footer inclusive.
    • Re-execute the original template by name.

    At this point you, the user, will need to re-enter data for any fields that were re-created by the template.

    Thus each time you invoke ‘Refresh Template’ on our example DateNow template(above), the output of the previous template expansion will be wiped and replaced with the latest date and time.

    ie The date\time is updated each time you refresh the template.

    So how long do you have to wait to get your hands on this little gem?

    I guess that depends how quickly you can click a link. CR_RefreshTemplate is fully functional and available now :)

    Limitations

    This approach is limited in that it proceeds from the assumption that your template expands into a single block of text. This means that text generated elsewhere in your project (or even file) will not be removed, and may therefore collide with later generated code.

    For example you would not be able to engineer this to work with the version of property templates which generates backing store variables elsewhere in the file.

    Added Bonuses

    It turns out that there are 1 or 2 interesting bonus features to this plugin.

    Bonus1: Code Upgrades

    Refresh Template can only execute the latest version of the specified template. Therefore if you have upgraded the template to be faster, more efficient, or just generally more awesome, the act of refreshing it will update the existing code to use the better version rather than the older less awesome version.

    You will still have to re-enter any old field values (assuming you don’t want to change them from their defaults), but this is a pretty small trade of for the optimization you could be receiving.

    One can even envisage a point in the future where you might issue an instruction to regenerate \ upgrade all Refreshable templates to their latest version throughout a file, project or solution.

    Bonus2: Sequenced Templates

    It turns out that the header and template don’t need to specify the template that generated the existing output.

    Say what?

    Yes that’s right. Instead you could indicate any other template which could be expanded given the same context.

    Why would I want to do that?

    Let’s imagine you’re in a presentation where you’re demonstrating a series of incremental changes to some code.

    Your existing options for this scenario are:

    • Rewrite\ adjust the code at each stage including the new incremental changes.
    • Load different projects, each one with a slightly improved version
    • Load different files, again with slightly differing versions of the code.
    • Skip about in source control history and have studio reload everything (hopefully) each time you do.

    With CR_RefreshTemplate, you can pre-create a chain of templates, each with a RefreshTemplate link to the next template in sequence.

    You could give a mini presentation, jumping from one code sample to another by repeatedly issuing the ‘Refresh Template’ command.

    Consider Step1<space>

    Step1

    …which could be refreshed to Step2

    Step2

    …which could be refreshed to Step3

    Step3

    …which, if you want, could be refreshed back to Step1 again.

    Summary

    So we’ve got a simple little plugin CR_RefreshTemplate which can:

    • Refresh code previously generated by an appropriate template.
    • Upgrade your code to the latest version of a template.
    • Proceed through a sequence of template driven steps in order to demonstrate the evolution of some code during a presentation.

    So what are you waiting for?
    Download now and let’s see what develops.

  • CodeRush: ‘Friction Free’ mode and Setting Schemes

    So in 12.1 we shipped a new feature. Well we shipped quite a few really, but I want to talk to you about one of the more subtle features, which might well change the way you use CodeRush.

    Setting schemes are conceptually quite simple, but have far reaching implications.

    Background

    Everyone has their own opinion on how any given feature should work. It can be very hard, some would say impossible, to keep everyone happy. So we try to make our product as configurable as possible. The idea being, that if our default configuration isn’t quite to your liking, you should be able to tweak it so that it is.

    The up side of this, is that there are lots of options you can tweak to make sure our product works exactly how you want it to. Of course the down side of this, is that there are lots of options you might have to tweak to get our product working just the way you want it to.

    Obviously we try to come up with sensible defaults so that as few people as possible will need to tweak the settings, and can use the product straight ‘out of the box’ so to speak :)

    However one man’s default can be another man’s disaster.

    Enter Setting Schemes

    A setting scheme is a named set of settings which has been customized for a specific purpose.

    CodeRush ships with 2 such schemes which you may switch between using the new drop down on the DXCore Visualize toolbar:

    The ‘Default’ scheme

    DXCoreVisualiseToolbar3

    The first scheme (‘Default’) is derived from the classic CodeRush settings as they have been up until 12.1. This set will also include any customizations you have made using previous versions of CodeRush. If such settings exist when CodeRush 12.1 installs, then it is these which will be selected by default.

    The ‘Friction Free’ scheme

    DXCoreVisualiseToolbar4

    The second scheme (‘Friction Free’) is a new set which is designed to remove as much friction as possible for a New User of CodeRush as they seek to go about their daily tasks. It does this by disabling or altering any CodeRush features which might otherwise clash with base Visual studio functionality.

    Alterations include:

  • Auto Complete for Brackets and Parenthesis is disabled.
  • Smart Enter is disabled.
  • Intelli Assist is disabled.
  • The Default Template Expansion shortcut is changed from Space to Tab.
  • Several Code Issues are disabled.
  • Most visual glyphs are turned off (Including SpellcheckMember IconsFlow break indicators and the Metrics icon)
  • Structural Highlighting, Region Painting and Current Line Highlighting are also disabled.

    If the CodeRush installer detects no previous settings, then it is this scheme which will be selected by default.

    Create your own schemes

    In addition to the inclusion of the ‘Default’ and new ‘Friction Free’ schemes, you are also able to create new schemes of your own. These schemes will be stored in parallel with the 2 that ship ‘out of the box’ and can be switched between at any time.

    To create or alter the high level components of a scheme, open the options screen and locate the ‘Settings schemes’ page: 

    SettingsLandingPage

    Once on this page you may create a new scheme, by copying it from an existing scheme.

    SettingsCreateScheme

    Select the preferred source scheme from the drop down, and then click ‘Add New Scheme’. 

    SettingNewScheme

    Choose a suitable name for your proposed scheme and click ok.

    Your scheme is created and added to the dropdown list. You can switch to it and immediately start customizing it to your liking.

    Tweaking

    You can also perform high level customization of your scheme from this page. Simply check or uncheck features as you see fit and save then with the Ok \ Apply buttons as usual.

    If you need to tweak the detail of a section, you can click it’s ellipsis button and you will be taken to an appropriate options page.

    SettingSchemeHighLevel

    Your newly created scheme will exist as an alternate named set, alongside the ‘Default’ and ‘Friction Free’ schemes. Customize this scheme as you see fit and then switch between any of them at will.

    Other Potential Schemes

    Schemes are a powerful feature which you might choose.

    You might create schemes for different purposes, moods or even people. :)

    So what other schemes could you create? Here are some ideas.

  • ‘Teach me’  - I need every prompt I can get. I’m a beginner and I’m happy to admit it.
  • ’Refactor Pro’ – Hide all but the refactoring functionality.
  • ‘The Generator’ - Templates and Code Gen Refactorings only please.
  • ‘The Minimalist’ - Hide all shortcut prompts and graphics. I know exactly what I’m doing already
  • ‘Clean Up Duty’ - Full on CodeIssues and Refactorings, but nothing else.
  • ‘Compiler Plus’ – Hide CodeIssues which pertain to style or readability and just show me things about my code which might be broken.
  • ‘Style Ninja’ – Inverse of ‘Compiler Plus’. Show me only style or readability Code Issues. I’ll fix stuff later.

    ProTip: Name one or more setting schemes after yourself, and copy them to your co-worker’s machines for when you have to pair with them.

    Feel free to suggest more. Tell us how you think this feature should evolve?

    The Future

    So what would you like to see us do in this space for the future?

    • Should we add some more schemes out of the box? Which ones?
    • Should we alter the ‘Friction Free’ scheme further?
    • Should we prevent any alteration of our ‘out of the box’ schemes and force you to copy them first. This would allow you a really quick method of restoring to any of our defaults.
    • Should we provide a “Copy page from Scheme…” button for slicing and dicing schemes?

    So take ‘Setting Schemes’ (including ‘Friction Free’) for a spin, tell us what you think and then let’s see what develops.

  • TO UPPER CASE or not to upper case.

    One of the more controversial points of VS2012 has been its UI.

    Originally put out without any colour and with ALL CAPS on every tool window, it caused a backlash of comments pleading for these decisions to be reversed. Microsoft listened and indeed removed the tool window ALL CAPS and returned some colour to the IDE. I’ve heard it suggested by some that there may even be more colour in the final release.

    However when the RC came out it became apparent that while one set of ALL CAPS had been removed, another seemed set to take its place. As those of us with the RC installed are very much aware, the main menu of VS2012 is currently ALL CAPS across the board.

    UPPERCASE

    There has been some wailing and gnashing of teeth over this and, as before, there have been parties on both sides of this argument.

    Enter DevExpress with a CodeRush plugin to help return the choice. *Insert gratuitous fanfare here*

    CR_UpperCaseMenuControl provides an additional options page which allows you to return your VS2012 RC menus to their former Mixed Case style (below)

    MixedCase

    For full details on the download, installation and configuration of this plugin please see its community plugin page

    Here’s a sneak peak at the plugin’s options page. As you can tell, it’s a really complex and involved bit of UI.

    CR_UpperCaseMenuControl

    Once again, this plugin can be downloaded from this page

    So let’s calm down our IDE of choice, and see what develops.

1 2 3 4
5
6 7 8 9 10
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