ReSharper can be extended in several ways. It supports declarative extensions, in the form of settings files that include content like Live Templates, Structural Search and Replace patterns, or just alternative formatting and inspection defaults. It also supports a more traditional, binary based plugin, using a standard .net assembly.
Your plugin project needs to add a NuGet reference to the JetBrains.ReSharper.SDK package. When you use the SDK's project templates to create a project, this package is automatically added for you (even if you're not connected to the internet - the SDK includes a copy of the NuGet package). Of course, you can also add a NuGet reference manually using the NuGet reference manager inside Visual Studio.
The SDK package tracks the current version of ReSharper. In other words, the 8.2.1158 SDK package is used to target ReSharper 8.2. If you want to write plugins for a previous version of ReSharper, you can add a NuGet reference to a previous version of the SDK, e.g. ReSharper 8.1 will use the 8.1.555 SDK package. If you already have a plugin targeting 8.1, you can use NuGet to simply update your reference from 8.1.555 to 8.2.1158. During public EAP builds of new versions of ReSharper, a new NuGet package is periodically uploaded to nuget.org, but marked as pre-release. The stable version of the SDK package always reflects the latest production release of ReSharper.
Your plugin's test project should add a reference to the JetBrains.ReSharper.SDK.Tests package package. This package follows the same versioning scheme.
The assemblies included in the SDK packages are from a "checked build", providing more diagnostics while running your tests. Asserts are enabled and exceptions include more diagnostic information.
The packages are intended to work with NuGet's package restore, so you don't need to commit the packages folder into source control.
Metadata - assembly attributes
In order for ReSharper to load the plugin, the assembly must have appropriate metadata definitions. At the very least, plugin writers are asked to define the title of the plugin, its description and authorship. This information is then displayed in the Plugins tab of the Options dialog.
These attributes are added to the
AssemblyInfo.cs file by the SDK project templates:
No further metadata is necessary as the plug-in functionality is going to be picked up automatically by ReSharper via reflection. There are, however, several optional pieces of metadatathat can also be added. For example, if your plug-in uses images, you must also define an assembly-level
ImagesBaseAttribute. This attribute takes as a paramter the base path of the generated resource. For example, if you plug-in is called
Foo and you are keeping images as embedded resources in a folder called
Resources, then the parameter you have to pass is
Debugging a plug-in implies spinning up an additional instance of Visual Studio with the plug-in loaded. It’s important to note that you’ll be unable to debug a plug-in if another version of this plug-in has already been loaded. If you need to debug a plug-in while using that plug-in for development, simply disable the original plug-in in the Options dialog and restart the debugging session.
Debugging a plug-in is easy -- there are two flags that you can pass to
/ReSharper.Internal--- this flag turns on ReSharper’s internal menu, which provides many new menu items, used by the development team while building ReSharper. Several menu options are useful for plugin developers, especially the 'PSI Viewer' menu item, which displays a view of the abstract syntax tree of the current file. This flag is so useful, it's worth adding it to your default VS shortcut.
/ReSharper.Plugin <path to your plugin DLL>--- this tells ReSharper to load the specified DLL. You can specify the full path, but if you want to debug the plug-in in your output directory, you can just specify the filename.
If you are debugging your plug-in and its breakpoints are not being triggered, first check that the plug-in has actually been loaded by looking for the the list of loaded plugins in ReSharper’s Options dialog. If the plugin has been loaded, look for exceptions thrown via the
/ReSharper.Internal mode. These would typically appear in the bottom right corner of the window.
Please note that the #1 cause of plugins not debugging is lack of appropriate metadata - if previously you could mark up a context action with
ReSharper:ContextAction attribute without specifying any parameters, this will no longer work, and as a result, your component will not be loaded.
The #2 cause of plugins not debugging or acting strangely is that you’ve accidentally let a ReSharper assembly be copied into the same folder as your plug-in binaries. This can happen if you’ve accidentally set
CopyLocal = True on a R# assembly reference or if, for example, you’ve included the tests-related
.Targets file from the SDK.
- This issue concerns plugin developers who use a license file (licenses.licx) in their plugin project. Since the license compiler (
LC.EXE) takes as parameters the full path of each assembly reference, you may run into an exception if the sum total of all reference paths exceeds 32000 characters. Possible workarounds for this issue are:
- Install the ReSharper SDK into a path that is as short as possible; or
- Create your own
.Targetfiles, removing some of the entries that your plug-in does not require.
- Some users of the SDK under Visual Studio 2010 might have problems with debugging their plug-ins. This is typically manifested by the fact that the plug-in works and the breakpoints appear ‘healthy’ but do not fire. This issue appears due to a known Visual Studio bug that will not be fixed in VS2010. As a result, the recommended workaround for plug-in developers experiencing this problem is to start up the additional instance of VS without debugging, and then using Debug | Attach to Process… to attach the correct CLR debugger manually. In this case, breakpoints should trigger correctly.
- Using F5 to start a debug session can sometimes result in very slow debugging. It is not clear why this is - perhaps because JIT optimisations are disabled when an application is launched under a debugger. In this circumstance, you should start Visual Studio without debugging (Ctrl+F5), and attach to the process later. Performance is much improved.