Rider plugins
Rider is a cross-platform .NET IDE. While all language-related features discussed in this guide can be run by Rider in a ReSharper background process, the actual IDE frontend is based on the IntelliJ platform. The ReSharper backend is either running on the .NET Framework on Windows, and .NET Core or Mono on Mac or Linux. The frontend, however, is running on the JVM. In order to make those two processes talk with each other and let them share data, some kind of protocol is required. For instance, the frontend might need to tell the ReSharper process that we hit Tab after a value.
, and that auto-completion items should be calculated. In return, the background process needs to share all the possible items with the frontend, so that the user can choose from a list. This protocol is implemented using Kotlin.
As an author of a ReSharper extension, we might want to make it available for Rider as well. Depending on the types and extension points we are using, this sometimes doesn't require so much additional work, but only to create a Rider plugin project and to follow Rider's plugin packaging. This is usually true if we:
Don't use any XAML option pages or tool windows
Don't use any VisualStudio components
In all other cases, we would need to re-implement missing parts using the IntelliJ Platform SDK, which is structured similar to this guide. For inter-process communication, we can easily extend the protocol using a Kotlin DSL.
Plugin project (.NET)
The standard approach of migrating an existing ReSharper plugin to also work for Rider, is to copy the existing CSPROJ file and adapt the package reference from JetBrains.ReSharper.SDK
to JetBrains.Rider.SDK
.
We could name these two project files MyPlugin.RS.csproj
and MyPlugin.RD.csproj
, which is great for code sharing. Unfortunately, this won't play well when executing MSBuild on them, because both projects would share the same project.assets.json
file. A simple solution to fix this is to put a custom Directory.Build.props
file besides the two project files:
This will provide MSBuild with an individual OBJ and BIN folder both the ReSharper and Rider project.
Plugin packaging
Rider plugins are simple ZIP archives containing metadata about the plugin, ReSharper extensions (DLL) and/or IntelliJ extensions (JAR). The content is structured like this:
+ plugin-root-folder + META-INF - plugin.xml + lib - plugin.jar + dotnet - plugin.dll
Among other declarations, the plugin.xml
must provide common metadata about its id, name, version, and frontend dependencies:
For simple plugins that don't contain code that is specific to Rider, we might choose to manually pack the archive. However, this requires us to also manually update the idea-version
tag according to the About JetBrains Rider dialog. Also note that archives created using .NET capabilities (like System.IO.Compression
or PowerShell's Compress-Archive
) might not work.
For more complex plugins as well as for better testability, it is recommended to have a dedicated gradle build. This will also automatically take care of updating the idea-version
tag.
Plugin project (JVM)
The recommended solution for building Rider frontend plugins is to use the gradle-intellij-plugin. This usually involves two files settings.gradle
and build.gradle
.
Inside settings.gradle
we define the project name and other global data:
With build.gradle
we basically use and extend the intellij
task provided from the gradle plugin. Here is an example:
For more information about building IntelliJ plugins, please see the IntelliJ Platform SDK.
Protocol extension
Rider has an extensible protocol to allow communication between IntelliJ frontend and ReSharper backend. This requires our plugin to implement a data model that can be used on .NET and JVM side. For our convenience, the IntelliJ gradle plugin allows to generate these implementations from a Kotlin base definition. Here is an example:
To generate the Kotlin and C# model implementation from that, we need to extend our build.gradle
file. At the start we need to add a dependency for com.jetbrains.rd:rd-gen
:
Then we can define our own generateModel
task:
Development
Using the gradle-intellij-plugin, we can easily launch an experimental Rider installation with our plugin installed right away. We can either start the runIde
task from the Gradle tool window inside IntelliJ IDEA, or execute gradlew :runIde
from the command-line.