ReSharper 8 EAP: NuGet based Extension Manager

ReSharper has always had a powerful extensibility story – its Open API allows plugins to use the same APIs that the core product uses. But distribution – discovery, installing and uninstalling – has previously been left to the plugin author, meaning the user is left with an experience ranging from msi installers to zip and batch files. Recently, .NET has seen the success of the NuGet package manager, which makes it very easy to install, uninstall and update libraries in a project. We’d like to bring that ease of use and discovery to ReSharper, which is why we’re very happy to be taking the wraps off our NuGet based Extension Manager.

ReSharper Extension Manager window

The latest EAP build of ReSharper 8 adds support for extensions to be distributed as NuGet packages. You get to use a very familiar interface to browse and install extension packages from our new extensions gallery. Of course, you can easily uninstall and update, too, and ReSharper will check for updates for you, and notify you when a new build is available – perfect for keeping up to date with EAP changes.

ReSharper update notification balloon tooltip

Speaking of EAP changes – since ReSharper 8 is currently still under development, it is obviously changing and evolving with each EAP release. Which means our packages are marked as “prerelease”. Once 8.0 is released, these will of course become Stable. Until then, please make sure to select “Include Prerelease” when browsing with the Extension Manager, or in the Gallery.

Extensions, Not Plugins

A very important change, though, is that an extension is not just for plugins. An extension can also be used to distribute ReSharper’s settings files and External Annotations, meaning you can now write useful extensions without even having to write any code.

The benefit of distributing .dotSettings files is that these are the files used by ReSharper to store Live Templates, Structural Search and Replace patterns, and other settings. For example, the xUnit.net test runner extension includes a plugin to provide the test runner capabilities, but also includes a .dotSettings file, adding lots of Live Templates to help generate code to write asserts faster.

Live Templates imported by the xUnit.net extension

And the sample patterns catalog extension adds a sample set of Structural Search and Replace patterns. These patterns are a very powerful, declarative way of analysing code and applying the standard warning squiggly underline highlight. What’s more, they can also provide a declarative means for creating a quick-fix for this code – adding an action to the alt+enter quick-fix menu to replace the code. See here for an introduction to SSR, and check out these posts for more information.

Structural Search and Replace dialog with sample patterns imported

Of course, settings files aren’t limited to Live Templates and SSR patterns. While these were the primary motivation for adding support for .dotSettings files, it opens the door for more interesting extensions – defining code formatting standards, code cleanup profiles, extra To-do items, or even a different set of opinionated code inspection defaults (don’t like our default “var” recommendations? Change them!).

Extension packages take advantage of ReSharper’s settings layers. If the extension contains a .dotSettings file, it is added as a read-only layer. The settings in the file are merged with the other layers in your installation (This Computer, Solution and project files – see this post for more information on layers), and naturally appear in the Options dialog or Live Templates Explorer. This means you can edit the templates, patterns or other settings, and any changes are then saved in the This Computer layer.

If you don’t want these extra settings (for example, you want the test runner, but not the included Live Templates) you can easily remove them from the system by disabling the layer in the Manage Options dialog. The settings, templates or patterns are immediately removed.

ReSharper's Manage Options dialog showing xunitcontrib settings layer deselected

External Annotations are xml files that contain a map between ReSharper’s annotation attributes, and pre-compiled assemblies. ReSharper’s code analysis uses these annotations to make better decisions about the warnings to show. For example, without annotations, this test code warns about potential null usage, even though the preceding Assert will throw an exception if the value is null – in other words, the value is guaranteed to be not-null when accessed.

ReSharper warns of potential null reference exception, even though the line will never be hit due to preceding Not Null assert

The xUnit.net extension adds annotations for the xunit.dll assembly, which tells ReSharper that Assert.Null will throw if the passed parameter is null. Now, ReSharper knows that the second assert will never get hit, and marks it as unreachable.

ReSharper highlights unreachable code due to preceding assert

ReSharper ships with annotations for the BCL, and some annotations for third party assemblies, notably to enable INotifyPropertyChanged support. Extensions can now distribute annotations for other third party assemblies.

Dependencies

Since extensions are NuGet packages, they can have dependencies. Someone could write an extension that exports a Live Template for creating test methods. That template could use a macro from another extension to make sure the method name you type gets converted to a valid name – changing spaces to underscores, for example.

Bundled Extensions

Another exciting benefit we get from the extension manager is the ability to have bundled, or pre-installed, extensions. These are simply extensions that are installed for you as part of the normal installation process. Once installed, they behave just like normal extensions, and we can push updates to the Gallery at any time, allowing us to update these plugins on a separate schedule to ReSharper itself.

In the latest EAP build, we’re bundling our NuGet plugin which uses NuGet to add package references, rather than file references when importing types. We now get the best of both worlds – this really useful functionality is included by default for every ReSharper user, and we have the flexibility to update it at any time, decoupled from ReSharper’s release schedule.

Custom sources

Of course, since this is based on NuGet, we get to take advantage of the existing infrastructure and tooling available in the NuGet community. Our Gallery is based on the NuGet Gallery sources, and is the default, primary location for getting extensions (remember to select “Include Prerelease”!). But you can also use the Extension Manager page in the Options dialog to specify extra sources – local or remote file system or a custom NuGet feed, such as TeamCity or MyGet. This makes it easy to install private, company wide extensions that target your specific needs, or nightly builds of an extension you build, or perhaps create a curated feed of your favourites.

custom_sources

How to Build Your Own Extensions

Building extensions is very straightforward. While we’re based on NuGet, we have a very different purpose to NuGet – extensibility information as opposed to assembly references. So we don’t use the standard libs, tools or content folders. Instead, we have our own folder structure that makes more sense for the data we need to distribute in the package. But that’s really the only difference. We still use the .nuspec file for metadata, and we pack and push the .nupkg file to the ReSharper Gallery in the same way – sign up for an account, get an API key and push away! You can get more information on creating an extension package at the ReSharper 8 devguide site, and if you have more questions, please email us at resharper-plugins@jetbrains.com, or send a message to the new resharper-plugins Google Group.

Please note that the Extension Manager relies on NuGet’s core library to implement a lot of its functionality. Since this is a .NET 4 library, the Extension Manager is limited to Visual Studio 2010 and 2012. We’re looking at ways to improve this as we progress through the EAP.

We hope you enjoy the changes we’ve introduced around extensions. Please try it out and let us know your feedback. We’re still quite early on in the EAP cycle, so expect changes – but if there’s something you want to see changed or updated, let us know! You can report issues at our YouTrack instance.

And remember, you don’t need to write a plugin to release an extension – let’s see some Live Templates and SSR patterns!

This entry was posted in ReSharper Tips&Tricks and tagged , , , , . Bookmark the permalink.

7 Responses to ReSharper 8 EAP: NuGet based Extension Manager

  1. Khalid Abuhakmeh (@AquaBirdConsult) says:

    Man this is really awesome. It has always been a bit annoying to install ReSharper plugins so I usually try to avoid it unless I really really have to. Sharing ReSharper settings is really cool too, I can see that helping a lot of teams share code snippets (which is always a huge win).

    Keep up the great work.

  2. Eyal Shilony says:

    I really like where this is going, excellent! :)

  3. Martin says:

    Can we expect a new EAP build anytime soon?

    Build 8.0.4.1195 hast at least one bug (http://youtrack.jetbrains.com/issue/RSRP-361719) which makes working with it almost impossible.

  4. @Martin Sure, we’re aiming to release another build in a few days.

  5. porges says:

    The “unlist” feature doesn’t seem to be working correctly for the nuget feed.

    I created a package bundling up the annotations for Code Contracts only to find that this is now included by default in R# 8, so I tried to unlist the package, but it still shows up even when I’m logged out.

  6. Anon says:

    Is there anything plugin developers need to do to support a clean “Uninstall” ? Sometime R# states Visual Studio needs to be restarted to fully uninstall plugin.

  7. Matt Ellis says:

    Sadly, that’s unavoidable. If the plugin’s dll has been loaded into the Visual Studio AppDomain, .net won’t allow the dll to be unloaded, and so it can’t be uninstalled and deleted. Instead, the dll is marked for deletion at next restart, and we have to prompt the user that a restart is required.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">