21 August 2010

ReSharper’s Live Templates can do the repetitive work for you

I was inspired by Hadi Hariri's blog post about creating custom Live Templates to explore one of the features of ReSharper that I really regret not digging into before. Live Templates lets you create simple but intelligent code snippets that makes you more productive as a developer.

I’m not a fan of generating repetitive code, but I think generating repetitive structures is a great time saver that still keeps the code clean. One of the structures I write over and over all the time is new unit test methods, and I need a template that supports all relevant attributes for MSTest and Team Foundation Server integration. I also wanted to make it easier to write readable test method names by allowing me to use space instead of underscore to separate words.

Jimmy Bogard blogged about a similar solution that integrates with AutoHotKey to replace spaces with underscores while writing test method names. ReSharper macros are very powerful so I created a macro that ensures a given template variable is transformed to a valid C# identifier while typing (one limitation is that this macro doesn’t support Unicode escape characters):
using System.Text;
using JetBrains.ReSharper.Feature.Services.LiveTemplates.Macros;

namespace JoarOyen.Tools.ReSharper.Macros
{
    [Macro("JoarOyenLiveTemplateMacros.ValidIdentifier",
      ShortDescription = "Ensures that given variable is a valid C# identifier",
      LongDescription = 
        "Replaces invalid characters in a C# identifier with underscores")]
    public class ValidIdentifierMacro : QuickParameterlessMacro
    {
        public override string QuickEvaluate(string value)
        {
            return TransformToValidIdentifier(value);
        }

        private static string TransformToValidIdentifier(string value)
        {
            if (string.IsNullOrEmpty(value)) return value;

            var validIdentifier = new StringBuilder(value);

            PrefixWithUnderscoreIfNotStartingWithACharacter(validIdentifier);
            ReplaceInvalidCharactersWithUnderscore(validIdentifier);

            return validIdentifier.ToString();
        }

        private static void PrefixWithUnderscoreIfNotStartingWithACharacter(
            StringBuilder validIdentifier)
        {
            if (!char.IsLetter(validIdentifier[0]) && validIdentifier[0] != '_')
            {
                validIdentifier.Insert(0, '_');
            }
        }

        private static void ReplaceInvalidCharactersWithUnderscore(
            StringBuilder validIdentifier)
        {
            for (int i = 0; i < validIdentifier.Length; i++)
            {
                if (!char.IsLetterOrDigit(validIdentifier[i]))
                {
                    validIdentifier[i] = '_';
                }
            }
        }
    }
}

This is very simple, isn’t it? :)

ReSharper requires all macros to implement IMacro, and I’ve created an abstract class that implements a simplified version of macros. The only thing the concrete macro class needs to implement is the QuickEvaluate method that is called after a key is pressed. It’s responsibility is to transform the current value to the desired result that is then returned to ReSharper:
using System.Collections.Generic;
using JetBrains.ReSharper.Feature.Services.LiveTemplates.Hotspots;
using JetBrains.ReSharper.Feature.Services.LiveTemplates.Macros;

namespace JoarOyen.Tools.ReSharper.Macros
{
    public abstract class QuickParameterlessMacro : IMacro
    {
        public abstract string QuickEvaluate(string value);

        public ParameterInfo[] Parameters
        {
            get { return new ParameterInfo[] { }; }
        }

        public HotspotItems GetLookupItems(
            IHotspotContext context, IList<string> arguments)
        {
            return null;
        }

        public string GetPlaceholder()
        {
            return "a";
        }

        public string EvaluateQuickResult(
            IHotspotContext context, IList<string> arguments)
        {
            var currentHotspot = new CurrentHotspot(context.HotspotSession);
            return QuickEvaluate(currentHotspot.Value);
        }

        public bool HandleExpansion(
            IHotspotContext context, IList<string> arguments)
        {
            context.HotspotSession.HotspotUpdated += HotspotSessionHotspotUpdated;
            return false;
        }

        private static void HotspotSessionHotspotUpdated(
            object sender, System.EventArgs e)
        {
            var currentHotspot = new CurrentHotspot((HotspotSession)sender);
            currentHotspot.InvokeEvaluateQuickResult();
        }
    }
}

I discovered an issue (or maybe it’s by design?) with EvaluateQuickResult because it wasn’t called for each key press In the hotspot it was assigned to (key presses in other hotspots did trigger it though). As a workaround I attached an event handler to HotspotUpdated that invokes this method so that spaces can be replaced on the fly.

I’ve also created a class that has the responsibility of working with the current hotspot:
using JetBrains.ReSharper.Feature.Services.LiveTemplates.Hotspots;
using JetBrains.TextControl;
using JetBrains.TextControl.Coords;

namespace JoarOyen.Tools.ReSharper.Macros
{
    public class CurrentHotspot
    {
        private readonly HotspotSession _hotspotSession;
        private ITextControlPos _caretPosition;

        public CurrentHotspot(HotspotSession hotspotSession)
        {
            _hotspotSession = hotspotSession;
        }

        public void InvokeEvaluateQuickResult()
        {
            SaveCaretPosition();
            _hotspotSession.CurrentHotspot.QuickEvaluate();
            RestoreCaretPosition();
        }

        public string Value
        {
            get
            {
                return _hotspotSession.CurrentHotspot == null ?
                    null : _hotspotSession.CurrentHotspot.CurrentValue;
            }
        }

        private void SaveCaretPosition()
        {
            _caretPosition =
                _hotspotSession.Context.TextControl.Caret.Position.Value;
        }

        private void RestoreCaretPosition()
        {
            _hotspotSession.Context.TextControl.Caret.MoveTo(
                _caretPosition, CaretVisualPlacement.Generic);
        }
    }
}

A side issue of calling EvaluateQuickResult for each key press is that the caret is moved to the end of the current hotspot. This piece of code saves the current caret position before modifying the hotspot and restores it afterwards.

Using these classes, the macro for getting the current user name with domain is dead simple:
using System.Threading;
using JetBrains.ReSharper.Feature.Services.LiveTemplates.Macros;

namespace JoarOyen.Tools.ReSharper.Macros
{
    [Macro("JoarOyenLiveTemplateMacros.DomainAndUsername",
      ShortDescription = "Current username with domain",
      LongDescription = 
        "Current username with domain on the format <Domain>\\\\<Username>")]
    public class DomainAndUsernameMacro : QuickParameterlessMacro
    {
        public override string QuickEvaluate(string value)
        {
            return Thread.CurrentPrincipal.Identity.Name.Replace("\\", "\\\\");
        }
    }
}

To tie everything together, here is the Live Template that generates a new test method:
<TemplatesExport>
  <Template uid="0fb9eda3-89fa-4507-84c9-8d8b6847e66f" shortcut="tm"
    description="Creates an MS Test method" text="[TestMethod, TestCategory(&quot;$TestCategory$&quot;), Owner(&quot;$DomainAndUsername$&quot;)]&#xD;&#xA;public void $Test_method_name$()&#xD;&#xA;{&#xD;&#xA;    $END$&#xD;&#xA;}"
    reformat="True" shortenQualifiedReferences="True">
    <Context>
      <CSharpContext context="TypeMember" minimumLanguageVersion="2.0" />
    </Context>
    <Categories>
      <Category name="MSTest" />
    </Categories>
    <Variables>
      <Variable name="TestCategory"
        expression="list(&quot;,Unit,Integration&quot;)" initialRange="0" />
      <Variable name="DomainAndUsername"
        expression="JoarOyenLiveTemplateMacros.DomainAndUsername()"
        initialRange="-1" />
      <Variable name="Test_method_name"
        expression="JoarOyenLiveTemplateMacros.ValidIdentifier()" initialRange="0" />
    </Variables>
    <CustomProperties />
  </Template>
</TemplatesExport>
This template hardcodes my two preferred test categories, but that can be improved by implementing another macro.


Update: The complete code for the solution is pushed to GitHub http://github.com/joaroyen/ReSharperExtensions.

06 April 2010

Microsoft awarded me the MVP title for another year

MVP Logo I’ve been an MVP for one year, and it was with great pleasure and honor I received an email from Microsoft over the Easter holiday informing me that I have been awarded the the MVP title for 2010. Being a part of this program is very inspiring, and I’m looking forward to continue to contribute to the .NET community in Trondheim. By the way, I also hope to be a bit more active on this blog.

If I have to mention one event from the last year, it has to be the MVP Summit in Redmond in February. It was a very humbling experience meeting my fellow MVPs in the Connected System Division, and I’m honored to be a part of this group of very smart individuals that all share the same passion about technology and the .NET community as I do.

I would also like to thank Gaby Lieuw (my MVP Lead) and Ed Hickey (MVP Lead for Connected System Developers in Redmond) for their support, and I’m looking forward to seeing you both next year in Seattle.

22 July 2009

How to turn on code coverage when running unit tests in VSTS 2010

When running tests in Visual Studio Team System 2010, you can collect a lot of information about the code you’re testing and the environment the tests are running in. Previous versions were able to collect code coverage, but that’s was about it. VSTS 2010 provides a number of specific “collectors” that you can choose to enable for your tests. For instance, there is a collector for event log entries, system information and even a video recording of the test run (but this is not that interesting for unit tests :-)) The UI for enabling code coverage in VSTS 20210 has changed to accommodate these new features, and the code coverage settings is grouped together with the other collectors.

The easiest way to enable code coverage in VSTS 2010 is to open your existing Local.testsettings file (in VSTS 2008 these files had the extension testrunconfig), select the Execution Criteria category and enable Code Coverage in the list of Collectors:
image

Then you have to click the Advanced… button, which displays a dialog that is more or less equivalent to what you find when you select the Code Coverage category in the test run configuration in VSTS 2008. Here you select which assemblies you want to include in the code coverage:
image 

You might not always want to run your unit tests with code coverage, so I recommend clicking Save As... in the Configuration Settings dialog to create a new test settings file.

Another interesting feature of VSTS 2010 is that Visual Studio can now identify which test you should run when modifying your code. This feature is implemented by a collector named Test Impact Collector, and should reduce the number of test you run while coding to only include the ones covering the code you have modified. When you create a new unit test project in Visual Studio 2010, it adds an extra test settings file called TraceAndTestImpact.testingsettings for this purpose, but I haven’t used this feature enough to get a feeling of how effective this functionality yet. I hope to publish another post about this in the future though.

14 July 2009

How to update ReSharper 5 for Visual Studio 2010

Now that the Early Access Program for ReSharper for Visual Studio 2010 has begun, I’m starting to feel comfortable working in VS2010 again. This is a very early build of the new ReSharper and there are some exceptions popping up here and there, but the overall experience is quite good.

One thing you need to now when trying out new builds is that ReSharper uses the new extension mechanism in VS2010. This mechanism allows for much faster installations and improved management, but currently you have to manually uninstall an existing version of ReSharper before installing a new build. You can do this through the Extension Manager window from the Tools menu:
image

I assume you can skip this step when VS2010 and ReSharper is RTM, because you can use the Extension Manager to search for updates to your installed extensions. You can even configure Extension Manager to automatically detect if updates are available.

09 July 2009

You can create new project templates in VS with your own predefined settings

When I create a new class library or another project type, there are a couple of properties I want to modify right away. This task can be a bit tedious (note to self: DRY), but luckily Visual Studio has a nice feature that allows you to create your own templates. It’s very easy, just make your changes and then select Export template… from the File menu. Make sure Automatically import the template into Visual Studio is checked if you want to use the template right away. What this checkbox does is simply to copy the resulting template zip file to the Visual Studio <Version>\Templates\ProjectTemplates sub folder under your documents folder.

Your new template is now available together with the other out-of-the-box templates when you create a new project:
 image

For those who are interested, these are the class library properties I modify:

  • Application tab
    • If I don’t name the project with full namespace, I change these two properties
      • Assembly name prefix
      • Default namespace prefix
    • Assembly information…
      • Company
      • Copyright
  • Build tab
    • Treat Warning as errors = All
  • Signing
    • Sign the assembly
      I’m adding my own self generated strong name key file
  • Code Analysis
    • Enable Code Analysis on Build
    • For Visual Studio 2010: Rule Set = “Microsoft All Rules”
      I’m running all rules as default and suppress individual messages as needed, but I haven’t evaluated the other rule sets to see if one of those are more appropriate for my needs

I also make a couple of other change in addition to the strong name to satisfy the code analysis rules. The first is to add the CLSCompliant(true) attribute to the AssemblyInfo.cs file, and the second is to suppress code analysis warnings on my name because it thinks my name is misspelled in the namespace of the library.

And lastly, I always remove the Class1.cs file :)

01 April 2009

Microsoft recognizes long time community contributions

image Today,  I'm very happy to announce that Microsoft awarded me a Connected System Developer MVP (Most Valuable Professional) title for the work I've done in the local .NET community here in Trondheim. NNUG Trondheim was established in august 2002 with me as one of the founding board members, and since 2004 I've had the pleasure of being the chapter lead of a community full of smart and interesting people.

Although appearing in the same list of MVPs (the list is not updated as of today) as Christian Weyer, Michèle Leroux Bustamante, Juval Lowy, Lars Wilhelmsen  (country lead at NNUG) and many others makes me very humble, the Connected System Developer category suits me fine. I've been working with WCF for quite a while now, and my work on service oriented architecture is a perfect match for digging deeper into these technologies.

I also have some very interesting ideas for code name Oslo projects that I would like to explore, and my plan is to give a talk about creating DSL's, models and custom runtimes at one of our user group meetings after the summer break. My goal is to show why it might be preferable in some scenarios to allow users to modify and compose their own applications at a higher abstraction level than traditional source code.

Pål Fossmo, who is a friend and colleague of mine, also received his MVP title in the category Visual C# today. This proves that if you're enthusiastic and contribute to your local community, you will be recognized as a valuable professional. At least in the community, but also by Microsoft at a national and global level.

I don't think I would have gotten my title without the help of Rune Grothaug (Community Manager at Microsoft) and Morten Wennevik (C# MVP), so I would like to thank them both for nominating me to the MVP program. Also thanks to everyone twittering congratulations to @joaroyen.

PS: I'm pretty sure this is not an April Fool's joke, and now I just want to relax and enjoy some Alpine Legend on my Xbox 360 :)

27 March 2009

How I've implemented GTD with Outlook 2007

I've been trying to follow the Getting Things Done principles since I read David Allen's book with the same name, and I think I have much better control over incoming email and active tasks now. One important GTD principle is to organize incoming correspondence into what you can process right away, what you need more time to work on, what you probably will need in an ongoing project and what you can file for later reference.

After following this principle for a while, my inbox now contains just a handful of items that I have flagged for action, and I also have had the pleasure of achieving zero email bounce a couple of times. Yes, that is a completely empty inbox :) By flagging everything that needs attention, I’m also very confident that nothing will be forgotten or overlooked. The To-Do Bar in Outlook 2007 gives me a very nice overview of all upcoming tasks, and the default calendar view displays the items that are due each day:
image
This view has another great advantage because it also includes what I have completed each day. (This image is not grabbed from my primary work laptop, and I’ve been working on additional stuff during the week :) )

This can be done in Outlook by flagging emails and organize items in folders outside the main inbox manually, but it can be a tedious task in itself. I have therefore written a couple of macros in plain old VBA, that I can invoke from the keyboard. The macros are organized in a custom GTD Toolbar, that looks like this:
GTD toolbar in Outlook 2007 

As you can see from the image, every function is accessible from the keyboard by pressing the Alt key and a number. By using these macros , I can flag items with various actions, move them to my reference or project folders or delete them if I’m sure they aren’t need anymore. I can drill down into the action menu and flag items with actions and categories that indicates I’m waiting for somebody else before I can proceed or items that I intend to read later. If the reference and project folders contain subfolders, I can also drill down into them and file the items exactly where I want. I’ve also implemented an undo feature, but remember that it only tracks what the macros do (with the except of the standard follow up functions on the action menu) and what you do manually in Outlook will interfere with this function.

Installation

This is what you have to do to try out these macros yourself in Outlook 2007:

  • Download the code in this zip file and extract the six files to a local folder:
  • Enable unsigned macros
    • Open “Trust Center” from the “Tools” menu
    • Select “Macro Security”
    • Select “Warnings for all macros”
      This is a potential security concern, and you can sign the macros yourself if you want. Then you can choose to only trust macros signed by your own certificate.
  • Import macros into Outlook
    • Open “Visual Basic Editor” from the “Tools->Macro” menu
    • Click “File –> Import file…” and import each of the six files in the zip-file
  • Enable GTD when Outlook starts (This is optional, because you can also initialize GTD from the toolbar manually when you need it.)
    • Still in “Visual Basic Editor”, double click on “ThisOutlookSession” in the project explorer
    • Paste inn the following code or edit your existing Application_Startup method if you already have one:
      Option Explicit

      Private Sub Application_Startup()
          Set gtd = New CGTD
          gtd.InitializeGTD
      End Sub

    • Close “Visual Basic Editor”
  • Initialize GTD
    • Open the “Macros” window from the “Tools->Macros” menu
    • Select “Initialize” and click “Run”
    • The GTD toolbar is floating by default, but you can drag it everywhere you want

Customization and issues

You can customize the name of the root project and reference folders in the GTDConstants file, but if you have multiple Outlook data files the folder names have to be the same in each file. If GTD can’t find folders with the configured names the corresponding buttons will be disabled. You can also customize the categories that are used to tag items you like to read later or those you are waiting for, and the maximum number of items to keep in the undo stack (only meta information abut the items are stored in the stack). The undo stack is implemented as a ring, so when the stack is full, the new element will overwrite the bottom position and become the new top element.

If something goes wrong, you can usually press the Initialize button to recover from an error. You will loose the undo history, but everything else should work fine. There is one known exception though, and that is if you create a sub folder of your reference or project folders and they didn't previously have any subfolders. The reason for this is that the toolbar button has to be exchanged with an toolbar menu instead, and there is a bug in that code that I haven’t bothered tracking down. This is a rare problem, and it has a simple workaround:

  • Right click on the toolbar and select "Customize..."
  • Select the "Toolbars" tab
  • Select the "GTD" toolbar and click Delete
  • Follow the initialization steps above to recreate the whole toolbar from scratch

Conclusion

I’ve been using these macros for some time now without any problems, and I’m very confident in how I handle the emails I receive. This system also works for notes in OneNote, because you can assign an Outlook task to any text or page in OneNote. You can then track these tasks in the To-Do Bar like any other task or flagged email.

This isn’t a complete GTD solution though, because I still have flagged blog posts in FeedDemon and a list of web pages in the Firefox extension Read It Later. I’m not 100% sure it is smart to have everything in Outlook, but I want to check out News Gator Inbox and see if it can only synchronize the items I have flagged in FeedDemon.

Disclaimer: This code is released as-is without any warranty. If you have questions or comments you are welcome to post a comment on my blog.