Hadi Hariri's Blog

Removing old feed

Monday, 25 January 2010 12:50 by Hadi

Due to mostly uninteresting reasons, I’ve been running two different feeds to this blog:

http://feeds.feedburner.com/hadihariri/rSpO

and:

http://feeds2.feedburner.com/HadiHariri

This second one is the valid on. I’ll shortly be removing the first one (in about a week). There’s over 200 subscribers to it, so please, if you’re one of these, could you update your feed to the new one? Once again that would be this

 

Thanks.

Tags:   ,
Categories:  
Actions:   E-mail | del.icio.us | Permalink | Comments (1) | Comment RSSRSS comment feed

ASP.NET Support in ReSharper 5

Wednesday, 20 January 2010 17:58 by Hadi

Although I mentioned briefly in the past some of the new features ASP.NET MVC features ReSharper 5 supports, I thought it would be a good idea to sum up the main ones in a single post and go into a little bit more detail on them.

 

ASP.NET

ReSharper ‘s support for ASP.NET is not restricted only to MVC.In fact, most of the new features are for general ASP.NET, be it WebForms (also known as Traditional, Classic, For Historical Purposes Only?) or MVC.

 

Go to File Member

As part of the code navigation features of ReSharper, you have the possibility to locate a file member, be it a method, property, class, etc. very easily by using the the Go To File Member (Alt+\) option. You can search instantly and hit Enter to navigate to the specific one. [For the record, I’m using the Visual Studio Keyboard Scheme. If you’re using IntelliJ (why?) go to the web site and download the PDF mapping files.]

 

image

Notice how it it looks for anything that matches the characters introduced, so for instance typing “Exc” would give us all those with the word “Exception”

image

Well you now have this functionality in ASPX, ASCX, ASAX and Web.config files also as of ReSharper 5!

image 

 

The same goes for the File Structure tool Window (Ctrl+Alt+F).

image 

 

Go To Related Files

Many times, an ASPX has references to other files, such as Cascading Style Sheets, Javascript Files, Master Pages and User Controls. You can now navigate to these files efficiently by using the Go To Related Files (Ctrl+Alt+F7)

image

 

Master Pages

Version 5 also adds support for Master and Content Pages. To begin with, we have added support for navigation. Using Go To Declaration (Ctrl+Left Mouse) on the ContentPlaceHolderID will take you from the Content Form/Page to the corresponding ContentPlaceHolder of the Master Page

image

image

If you are in the Master Page, you can navigate to all its inheritors (Shift+Alt+F12)

image

You can also create content place holders from usage. When defining a ContentPlaceHolderID that does not exist, you have the option to create it in the Master Page (Alt+Enter)

image

Last but not least, in a page that uses a master page, you can generate content place holders by pressing Alt+Ins

image 

which in turn will bring up a dialog box for you to pick and choose what you want

image

 

User Controls

You can now navigate to user controls as well as automatically import the correct references.

image

 

File Generation

There are new code generation options for ASP.NET with version 5. By pressing Alt+Ins in the Solution Explorer, we are presented with a popup menu

image

where you can choose from a selection of items to generate. You can also access this menu from anywhere (not only in the Solution Explorer) by now pressing Ctrl+Alt+Ins. This is actually an awesome new addition to ReSharper 5 (Ctrl+Alt+Ins) and it removes even more friction when create new items!

image

We’re asked for a name (which is the base minimum required to create an item) and If the item selected requires more information, then we’ll be prompted accordingly. For example, when creating a WebForm with Master Page, it’s convenient to specify which Master Page we want to use. In this case, once the page has been created, we’ll be given a chance to provide this information

 

image

I have to say, that I love Ctrl+Alt+Ins in ReSharper 5.

 

Refactoring and Assistance

In terms of Refactoring and Coding Assistance there are a few new features. One of them is the auto-update of ending tags. If you have for instance a div tag, and want to change it to span, as you start typing span, the end tag is automatically updated to reflect the changes you’re making live.

image

If you have a series of elements that you want to surround within a tag, you can easily do this by selecting all the elements and choosing Surround with Template (Ctrl+E,U)

 

image

image

image

 

ASP.NET MVC

ReSharper 5 treats ASP.NET MVC as a first class citizen. As such, it now has knowledge of concepts such as Views, Controllers and Action.

 

Navigate to View

For those of you working with ASP.NET MVC, you might have noticed that Views are now underlined in Actions

image

When you click on the View with Ctrl+Left Mouse, you’ll be presented with a dropdown menu

image

Here you have two options. The first is to navigate to the source for the View method (navigation to external sources is another new feature of ReSharper 5). The second option is to go to the View. Although you can navigate to the View in Visual Studio by right-clicking and selecting Go To View, one advantage the underlining adds is that it serves as hint for non-existent views, as you can see in the action below, which doesn’t have a corresponding View file.

image

View discovery also works with named Views. If a named view exists, the string literal will be underlined

image

On the other hand, if it doesn’t exist, it will be highlighted as an error, once again providing you the benefit of discovering any missing views earlier on.

image

 

Action Links

Those of us who have worked with ASP.NET MVC applications, know the problems with using strings when defining ActionLinks. Not only do you run into issues when refactoring, but misspelling an action or controller causes unnecessary pain. Some of us, including myself, have often resorted to using the expression based Actions available in the MVC Futures library.

ReSharper 5 now provides Intellisense, preventing you from mistyping Actions and Controllers

image

Similar to named Views, if you define a non-existing Action, you will get it highlighted. The difference here is that by pressing Alt+Enter, ReSharper will create the Action for you (create based on usage)

image

image

 

And much like Views, you can now navigate to Actions and Controllers from an ActionLink by choosing Go To Declaration (Ctrl+Left Mouse) on the Action and Controller respectively.

image

 

User Controls

Navigation is also provided for User Controls

image

as well as Intellisense

image

 

Summary

I’ve outlined some of the main features that ReSharper 5 brings to the table in regard to ASP.NET. There are many smaller features that you can discover eventually as you play with it more. If you haven’t yet, make sure you download 5 from JetBrains. Don’t forget to follow ReSharper on Twitter if you want tips, tricks and latest info.

Categories:  
Actions:   E-mail | del.icio.us | Permalink | Comments (2) | Comment RSSRSS comment feed

Writing plug-ins for ReSharper: Part 1 of Undefined

Tuesday, 12 January 2010 14:24 by Hadi

ReSharper does a lot of things, but as they say, you can’t please all the people all of the time. However, one the great things about ReSharper is that it is quite extensible and there are already quite a number plug-ins available. Some of the better known ones are:

- StyleCop for ReSharper by Howard Van Rooijen

- TDD Productivity Plugin by Eric Hexter

- ReSharper Test Runner for MSpec by Alexander Groß 

and of course there is also the repository of plug-ins available from the JetBrains site, where many of these are located.

Now I’m no expert on writing plug-ins for ReSharper, and the authors of the previous ones leave the bar quite high, but seeing that I actually now have the time to play with them, I’ve decided to do so by sharing my experiences with you in a series of blog posts.

The ReSharper API is pretty extensive and can be overwhelming as I’ve been discovering, so I want to try and take it slowly. This might mean that at times, the code is not always complete and might be missing a few checks for example, but will come in due course.

Everything that I’ll cover applies to version 5.0 which is currently in Beta. There have been some changes from previous versions so if you’re working with 4.5 some of the code might not work.

 

The First Plug-in

I was initially intending to write a useless plug-in for the first demo that didn’t do much, but after talking to Orangy (aslo known as Ilya) who commented on a tweet Jeremy Skinner had posted a few days back:

image_thumb51

we decided to use it as the first sample.

I’m going to build up the sample over the next few series of posts, so the initial solution is not the ideal one or complete, but it will help introduce a few core concepts. Ideally this feature should be implemented as what’s known as a QuickFix but we’re first going to do it as a ContextAction.

 

ContextAction

So what exactly is a Context Action? It’s actions that can be applied based on the context (the name is quite descriptive). They shows up as items in a popup menu which is invoked using Alt+Enter (don’t use the mouse for this…it’s very unproductive).

image_thumb4

What we want to do in this first version of the plug-in is to write a new action that makes methods that are public and not declared virtual, virtual, something NHibernate users would appreciate greatly. As mentioned previously, in this first version we’re going to add a context action.

1. Creating a plug-in assembly

ReSharper plug-ins are assemblies that are located in Plugins folder (by default %programFiles%\JetBrains\ReSharper\v5.0\Bin\Plugins). Each plug-in is in it’s own folder and doesn’t require any further registration. Therefore the first step is to create a class library which will host our context action.

2. Creating the Context Action Skeleton

In order to create a context action, we need to implement the IContextAction interface. This interface has one method IsAvailable which indicates to us if that particular action is available given the context, and a property of type IBulbItem[] which contains a series of bulb items. Each IBulbItem in turn has a property Text which is the text that appears next to the item in the context dropdown, and an Execute action, which is what happens when the item is selected. So as we can see, a context action can consist of more than one bulb item. An added benefit to this decoupling is the re-usability of bulb items. By implementing IBulbItem, we can potentially use it in more than once place (obviously if it makes sense).

Many times however, we only want one bulb item per action, and to somehow simplify the process, we can inherit from the BulbItemImpl class. This class defines an abstract Text property that represents the text of the bulb item, and also has an ExecuteTransaction member which is where our code is executed. We’ll see the difference between this method and Execute shortly.

 

  1. public class MakeMethodVirtualContextActions: BulbItemImpl, IContextAction
  2. {
  3.     protected override Action<ITextControl> ExecuteTransaction(ISolution solution, IProgressIndicator progress)
  4.     {
  5.         throw new NotImplementedException();
  6.     }
  7.  
  8.     public override string Text
  9.     {
  10.         get { throw new NotImplementedException(); }
  11.     }
  12.  
  13.     public bool IsAvailable(IUserDataHolder cache)
  14.     {
  15.         throw new NotImplementedException();
  16.     }
  17. }

 

 

Before implementing any of the methods, there’s one thing we need to do. ReSharper requires that context action have a constructor with a parameter that implements a IContextActionDataProvider. This parameter is actually useful to use to provide information about the context as we’ll see shortly. Therefore, we need to add a constructor to the previous code (lines 6-9). Since our action is only for C#, we will use a ICSharpContextActionDataProvider. We then save this provider for later use (line 3). What we’re effectively doing here of course is nothing more than dependency injection. The plumbing (passing in the correct provider) is taken care of for us by ReSharper.

 

  1. public class MakeMethodVirtualContextAction : BulbItemImpl, IContextAction
  2. {
  3.     readonly ICSharpContextActionDataProvider _provider;
  4.  
  5.  
  6.     public MakeMethodVirtualContextAction(ICSharpContextActionDataProvider provider)
  7.     {
  8.         _provider = provider;
  9.     }

  10.     protected override Action<ITextControl> ExecuteTransaction(ISolution solution, IProgressIndicator progress)
  11.     {
  12.         throw new NotImplementedException();
  13.     }
  14.  
  15.     public override string Text
  16.     {
  17.         get { throw new NotImplementedException(); }
  18.     }
  19.  
  20.     public bool IsAvailable(IUserDataHolder cache)
  21.     {
  22.         throw new NotImplementedException();
  23.     }
  24. }

 

3. Defining Availability

The next step is to define when our action is available. In order to do so, we need to implement the IsAvailable method. In our case, we want to convert methods that are public and not virtual, to virtual. We therefore need to identify methods that are public and not virtual. We also need to filter out static methods. In order to get access to the current context we’re in, we can use the provider we injected in via the constructor. The provider has a GetSelectedElement method which corresponds to the element the caret is on. Since we’re interested in a method, we can invoke this function, requesting back a method declaration. If the caret is in the context of a method (i.e. header, body), it will return this information. If it’s not, it will return null.

If we have a valid method declaration, the next step is to find out if it is public. We do that by invoking GetAccessRights [In later series we’ll see that further checks are necessary here]. If it is public, we then need to check whether it is a static method, an override or already virtual. Based on that, we return true or false, indicating whether the action is available in the current context.

 

  1. public bool IsAvailable(IUserDataHolder cache)
  2. {
  3.     var item = _provider.GetSelectedElement<IMethodDeclaration>(false, true);
  4.  
  5.     if (item != null)
  6.     {
  7.         var accessRights = item.GetAccessRights();
  8.  
  9.         if (accessRights == AccessRights.PUBLIC && !item.IsStatic && !item.IsVirtual && !item.IsOverride)
  10.         {
  11.             return true;
  12.         }
  13.     }
  14.     return false;
  15. }

 

4. Performing the action

When the action is available and the user selects it, what we need to do is make the method virtual. This is done in the ExecuteTransaction method. Since we are going to modify the code, we need to make sure that the file is writable. Normally this would be done by invoking a call to a method named EnsureWritable. However, inside the method ExecuteTransaction, this is done for us, so we don’t have to worry about it. This is one of the differences between ExecuteTransaction and IBulbItem.Execute.

So how do we go about modifying code in ReSharper? Well remember that refactoring code is ReSharper’s daily bread. It’s what it does. As such, there’s a ton of infrastructure in place to allow us to do modify code easily. In fact, making a method virtual is as easy as calling a method, as shown below.

  1. protected override Action<ITextControl> ExecuteTransaction(ISolution solution, IProgressIndicator progress)
  2. {
  3.     var method = _provider.GetSelectedElement<IMethodDeclaration>(false, true);
  4.  
  5.     if (method != null)
  6.     {
  7.         method.SetVirtual(true);
  8.     }
  9.  
  10.     return null;
  11. }

 

5. Testing the plug-in

The only thing left to do is test that it works (writing unit tests for plug-ins is something we’ll cover in the future). One option is to copy the assembly to the plug-in folder for ReSharper and restart Visual Studio. However, in order to be able to debug it, what we can do is set the project properties to start an external program, which is non other than devenv.exe, and pass as parameter to it /ReSharper.Plugin <Path_to_Plugin_Assembly>, instructing ReSharper to load a specific plug-in.

How does ReSharper know which classes in the assembly are context actions? The easiest way is to decorate these with the ContextAction attribute

 

  1. [ContextAction(Group="C#", Name = "MakeMethodVirtual", Description = "Adds context action to make methods virtual")]
  2.     public class MakeMethodVirtualContextAction : BulbItemImpl, IContextAction
  3.     {
  4.   

 

This information is also what appears under ReSharper –> C# –> Context Actions

 

image_thumb1

Now all that’s left is to try it out. Write a new class, add a few methods and check to see it’s all working correctly.

 

image_thumb41

Public static method (not available)

 

image_thumb5

Private method (not available)

 

image_thumb7

Public method (option available)

 

 

 

 

 

 

 

What’s next?

In this first part we’ve seen the basics of writing plug-ins for ReSharper. In the next blog post, we’ll extend the example to also include properties and we’ll change it to be a QuickFix as opposed to a context action. This means that we’ll get some nice highlighting by ReSharper telling us something can be changed (similar to when you have something named incorrectly for instance), thus being more *in your face*.

There’s so much more to see than what’s here, and gradually we’ll drill more into each of the different areas, examining parameters, return values, etc. Until then, Happy ReSharping (did I just coin that? Too lame?)

Categories:  
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed