Background
When developing a plugin for Rider, one might want to implement a custom action implemented purely in C#. When binding a custom action class in plugin.xml, attempting to bind a C# class name results in error java.lang.ClassNotFoundException
e.g., having a TestAction.cs class declared in the backend part of the plugin, the following snippet is wrong:
<actions>
<action id="ReSharperPlugin.TestPlugin.TestAction" class="ReSharperPlugin.TestPlugin.TestAction"/>
</actions>
Question
How to properly bind an action implemented in C# to <action> in plugin.xml?
Answer
Considering you start from https://github.com/ForNeVeR/rider-plugin-template template:
-
First, create a Kotlin/Java class in the frontend part of the plugin, e.g. FrontendSampleAction.kt, deriving from
com.jetbrains.rider.actions.base.RiderAnAction. In braces specify the exact 'backend id' of the action. This is the ID that must be used in C# later:package com.jetbrains.rider.plugins.ridertestplugin.actions import com.jetbrains.rider.actions.base.RiderAnAction /** * Frontend delegating action (proxy) for Rider. * * Registered on the IntelliJ (Kotlin) side and shown in menus/keymap, this action does not implement logic itself. * When invoked, it forwards Update/Execute to the Rider/ReSharper backend action with ID "MyBackendActionID". * * Also commonly called: *frontend stub action*, *delegating action*, or *bridge action*. */ class FrontendSampleAction: RiderAnAction("MyBackendActionID") { } -
Then bind this class to the action in plugin.xml, e.g.:
<actions> <action id="MyFrontendAction" class="com.jetbrains.rider.plugins.ridertestplugin.actions.FrontendSampleAction" text="Name visible to user on action invocation. Coming from plugin.xml" description="Action description appears on hover."> <add-to-group group-id="ToolsMenu" anchor="first"/> </action> </actions>- This text and description will be visible to the end-user:
- This text and description will be visible to the end-user:
-
Switch to the backend part of the plugin (C# project);
-
Create a .resx file in a project (Right-Click -> Add -> Resource (.resx) and define sample string data. It can be used for localization purposes, but it is out of scope. Still, you need to declare it now. Consider the name is "PluginResources.resx"
Sample .resx
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="MyBackendAction_Text" xml:space="preserve">
<value/>
</data>
</root>
- Declare your C# action class:
-
Ensure to specify ActionId (same as used as argument for RiderAnAction in .kt):
-
Sample action that writes to the backend log:
using System; using JetBrains.Application.UI.ActionsRevised.Menu; using JetBrains.Util; using JetBrains.Util.Logging; using JetBrains.Application.DataContext; using JetBrains.Application.UI.Actions; namespace Rider.Plugins.RiderTestPlugin.Actions; [Action( ResourceType: typeof(Resources1), TextResourceName:nameof(Resources1.MyBackendAction_Text), ActionId="MyBackendActionID")] public class MyBackendAction : IExecutableAction { private static ILogger _logger = Logger.GetLogger<MyBackendAction>(); public bool Update(IDataContext context, ActionPresentation presentation, DelegateUpdate nextUpdate) => true; public void Execute(IDataContext context, DelegateExecute nextExecute) { _logger.Info("MyBackendAction executed"); } }
-
That is it. Now you can launch :runIde from IDEA, and the action "Name visible to user on action invocation. Coming from plugin.xml" that executes MyBackendAction.Execute will be available in UI.
Comments
0 comments
Please sign in to leave a comment.