Click here to Skip to main content
15,893,161 members
Articles / Programming Languages / C#
Article

Getting Started with ReSharper OpenAPI

Rate me:
Please Sign up or sign in to vote.
3.25/5 (8 votes)
13 Jan 2007CPOL5 min read 39.9K   15   6
Very basic guide to beginning development of your ReSharper PlugIn

Introduction

ReSharper (R#) by JetBrains is an add-in for Visual Studio providing a whole host of productivity enhancements. Quite simply it is the must have utility when using Visual Studio. In the words of JetBrains:

"ReSharper is undoubtedly the most intelligent add-in to Visual Studio 2005. It comes equipped with a rich set of features that greatly increase the productivity of .NET developers. With ReSharper you get intelligent coding assistance, on-the-fly error highlighting and quick error correction, as well as unmatched support for code refactoring, unit testing, and a whole lot more. All of ReSharper's advanced features are available right from Visual Studio."

Background

R# provides an OpenAPI, which can be used to extend the functionality provided by R#. The OpenAPI is used to provide much of the base functionality provided by the product. However, there is virtually no documentation onto how to begin developing your own plug-in.

Using the Code

This article does not expand the functionality provided in the basic Getting Started guide provided by R# in the ReSharper\VS2005\PluginSamples directory when you install the product. The article's aim is to document the problems I experienced with getting started and discusses how to debug your plug-in within Visual Studio 2005.

So Let's Get Started

The "Getting Started" guide provided by R# tells you how to do two things, compile the plug-in and load your plug-in into Visual Studio. Compiling your plug-in is identical to any other project started build solution option in Visual Studio. There are two options on integrating your plug-in into Visual Studio from the command-line or installing in R# plug-in folder. I am only going to deal with it from the command-line, in this introduction article.

Compiling the Plug-in

The sample plug-ins provided by R# are located in the C:\Program Files\JetBrains\ ReSharper\VS2005\PluginSamples by default. Compiling the plug-in is as simple as opening the PluginSamples.sln in Visual Studio 2005.

Loading Your Plug-in

To load your plug-in, close your Visual Studio solution from when you built it in the previous step and go to a command prompt. You need to pass the /ReSharper.Plugin argument to Visual Studio and tell it where your plug-in DLL is located.

devenv.exe /ReSharper.Plugin 
    "C:\Program Files\JetBrains\ReSharper\VS2005\PluginSamples\AddMenuItem.dll"

If your plug-in consists of multiple assemblies, separate them by semicolons. Now Visual Studio will start with your plug-in integrated What gives where is it? Well first no solution is loaded in Visual Studio because we didn't pass one in when we specified the command line, go ahead and open one now (Make this the plug-in solution. We are going to look at some code from this now). Where should the plug-in be. Well let's look at the Actions.xml file in the AddMenuItem project.

XML
<insert group-id="ReSharper" anchor-id="Help" position="before">
    <separator/>
        <!-- 
          Tag "action" declares an action. 
          There should be an action handler class marked with 
          "ActionHandler" attribute with ID of this action. 
          Action ID should be unique so it's recommended to 
          prefix IDs of all your actions with your plugin prefix.
        -->
        <action id="AddMenuItem.ShowCurrentSolution" 
                text="Show Current Solution" 
                image="JetBrains.ReSharper.PluginSamples.AddMenuItem.testImage.gif"/>
        <action id="AddMenuItem.ShowCurrentLineNumber" 
                text="Show Current Line"/>
    </insert>

Not exactly obvious, but looking at the anchor-id="Help" position="before" it means within the help section of the ReSharper menu. Well let's look there ...

No R# PlugIn

Nope not there... After much searching I found starting with R# 2.5 a performance enhancement has been made to only reload the ReSharper menu when absolutely necessary, you can override this in the Registry. HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\ReSharper_OneTimeInitializationDoneForBuild.
You need to blank out the value and reload your plug-in.

PlugIn

R# should really realise when a new plug-in has been added and do this for you, but suppose I will let it off for this small problem considering all the coding time it saves me. Why's it added the items at the bottom? I would have thought position would have meant before the help item or before the help item section. Need to do some more work in Reflector, which is the only way I have found to get any information about the R# OpenAPI's.

Show Current Line Number Plug-In

Let's take a look at the first sample they have given us Right-Clicking in the code window or selecting ReSharper -> Show Current Line pops up the currently selected line in the code window. Closing all code windows disables the menu option from the main ReSharper menu and right-clicking no longer gives us the option. Clicking the option predictably display a message box showing the currently selected line number.

The Actions.xml file we checked out before briefly handles the plug-ins to be loaded:

XML
<action id="AddMenuItem.ShowCurrentLineNumber" text="Show Current Line"/>

The action id specifies the name of a class implementing your plug-in functionality. This must implement IActionHandler. This interface defines two methods.

C#
void Execute(IDataContext context, DelegateExecute nextExecute);
bool Update(IDataContext context, 
    ActionPresentation presentation, DelegateUpdate nextUpdate);    

Let's take a look at the Update method first ...

C#
public bool Update(IDataContext context, ActionPresentation presentation, 
DelegateUpdate nextUpdate)
{
    // fetch focused text editor control
    ITextControl textControl = context.GetData(DataConstants.TEXT_CONTROL);
            
    // enable this action if we are in text editor, disable otherwise
    return textControl != null;
}    

Update in this case is used to enable disable the option, this method like Execute accepts a IDataContext interface. The IDataContext interface allows us access to an important method GetData whose definition is as follows ...

C#
T GetData<T>(DataConstant<T>dataConstant) where T:class;    

Using the GetData method passing in the relevant DataConstant, we get access to various parts of the Visual Studio & ReSharper UI. In the example above, ITextControl textControl = context.GetData(DataConstants.TEXT_CONTROL); was used however there are other things we could have returned using the DataConstants:

C#
public static DataConstant<IContextMenuProvider> CONTEXT_MENU_ID;
public static DataConstant<IDeclaredElement> DECLARED_ELEMENT;
public static DataConstant<IDocument> DOCUMENT;
public static DataConstant<DocumentOffset> DOCUMENT_OFFSET;
public static DataConstant<IEditor> EDITOR;
public static DataConstant<IPopupWindowContext> POPUP_WINDOW_CONTEXT;
public static DataConstant<IProjectModelElement> PROJECT_MODEL_ELEMENT;
public static DataConstant<IProjectModelElement[]> PROJECT_MODEL_ELEMENTS;
public static DataConstant<PsiLanguageType> PSI_LANGUAGE_TYPE;
public static DataConstant<IReference> REFERENCE;
public static DataConstant<IReference[]> REFERENCES;
public static DataConstant<ISolution> SOLUTION;
public static DataConstant<object> SOLUTION_EXPLORER;
public static DataConstant<ITextControl> TEXT_CONTROL;
public static DataConstant<IDeclaredElement> TYPE_OR_TYPE_MEMBER;    

The Execute method called when you select the menu option is self explanatory. It grabs an instance of the ITextControl interface and determines the current line number using the ITextControl.Document object.

C#
public void Execute(IDataContext context, DelegateExecute nextExecute)
{
    ITextControl textControl = context.GetData(DataConstants.TEXT_CONTROL);

    // fetch caret line number
    int caretOffset = textControl.CaretModel.Offset;
    int line = textControl.Document.GetCoordsByOffset(caretOffset).Line;

    // note that we increment line number by one because 
    // "line number" in our API starts from zero
    string message = string.Format("Current line number is {0}", line + 1);
    MessageBox.Show(UIApplicationShell.Instance.MainWindow, message, 
            "AddMenuItem Sample Plugin");
}

Developing Your Own PlugIn

I recommend having Reflector open to look at the structure of the ReSharper OpenAPI's and that you set Visual Studio to load your plug-in when you hit run.

Getting Visual Studio to Load Your PlugIn

Within the Project Properties settings within your Visual Studio project, select the Debug tab and set start action to load an external program. Point this to your devenv.exe executable.

Set the command-line arguments with first the location and name of the *.sln file to open (make it a small sample project) followed by a space and the command-line used to load a ReSharper Plug-In.

Project Properties

Use Reflector to work out the ReSharper OpenAPI's start to try and interact with different DataConstant items.

Where Next ..

ReSharper provides loads of cool pop-up Windows such as Find Usages, Type Hierarchy. My aim is to develop some more for displaying useful information, may be for viewing Task List items for the whole solution, Internet Search Results, etc. and publish them here.

History

  • 13th January, 2007: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralResource hog Pin
craigg7516-Jan-07 4:34
craigg7516-Jan-07 4:34 
GeneralRe: Resource hog Pin
Robert Ensor17-Jan-07 13:07
Robert Ensor17-Jan-07 13:07 
GeneralRe: Resource hog Pin
Stuart Carnie3-Apr-07 7:51
Stuart Carnie3-Apr-07 7:51 
GeneralRe: Resource hog Pin
zucchini1-Dec-07 15:08
zucchini1-Dec-07 15:08 
GeneralRe: Resource hog Pin
Alexander Yezutov10-Jun-08 11:55
Alexander Yezutov10-Jun-08 11:55 
GeneralRe: Resource hog Pin
yetibrain17-Jun-13 2:15
yetibrain17-Jun-13 2:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.