I am posting this as a warning for naive people like myself.
I had an idea to create a simple plugin to help my own development.
The idea:
a) Right click a method => add custom context menu action
b) Use some logic => find parent method of this selected method
c) Clicking the said context menu action => find usages of desired ‘parent’ method
Total time spent: 2 weeks.
Total documentation consumed: 20-30+ pages
Total plugins&samples download/tested: 15+
Total time finding & guessing resources via Perplexity, Grok 3, Claude 3.7, ChatGPT 4 = MANY, many hours
Plugin Slack chat: not working any more.
Try guessing API => test => fail x 100s of times
Final code working per goal, after 2 weeks:
a) Right click shows a new action on the context menu: 0%
Spent 1 week trying to get right-click context menu to have an extra option. I’m sure you are thinking “It can’t be that hard, I’ve seen the extra options in other plugins.” I warned you. I don’t think I suffered any major lack of effort or intelligence.
b) Find specific method’s parent method.: 70%
Partial success. Couldn’t do the whole thing since documentation is non-existent. Or very well hidden. A lot of guessing. Even more failing.
c) Showing Find Usages window result for my particular method: 0%
Again, no documentations. So many different versions. Unclear which documentation is relevant and for what. (ReSharper, IntelliJ…)
There is a major problem finding ANY relevant and current documentation, references.
When you hear the words “Rider plugin development is not easy”, BELIEVE IT.
From my own experience, LLMs are terribly bad at plugin development. I guess they (LLMs providers) did not steal enough data on the Internet. They are better for developing JS stuff, things like that.
So, my advice would be:
don’t spend too much time with LLMs. They can help you, but if they fail, do not insist
read the official documentation, and use the Search box
checkout and explore the IntelliJ Community sources (they’re on GitHub). You will learn a LOT of things. Really. Enable the Internal mode to find actions IDs etc., then if you want to implement a feature, look for something similar in the IJ sources
there are many 3rd-party open-source plugins on GitHub, GitLab, and Gitee
probably the most important: ask some help here The Slack server was very useful, and we recently migrated to Discourse. I’m developing IJ plugins since 7 years, and the community (volunteers and JetBrains staff) are a great help
be patient
I’m not saying it’s easy. The learning curve can be discouraging, but this is absolutely not specific to plugin development. This is not as easy as plugin development for Chrome or Firefox, or for VSCode, but the IJ Platform is much powerful (really).
Access the underlying libraries with either dot peek or the built in funcitonality in rider/resharper to decompile libraries. Much of the rider/resharper functionality can be found in this decompiled code. It has helped me a lot.
If you for instance have a context action up and running. Try setting a breakpoint and play around in there to test what different methods do.
But hopefully this forum can also be a help. Do you have a github repo with the current progress?
I unfortunately don’t know how to find usages of a method. But I think that what you want to do can be achived through a ContextAction.
But roughly the skeleton should be something like this
[ContextAction(
Name = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
Description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
GroupType = typeof(CSharpContextActions))]
public class FindUsagesOfParentAction : ContextActionBase
{
private readonly ICSharpContextActionDataProvider _provider;
public FindUsagesOfParentAction(ICSharpContextActionDataProvider provider)
{
_provider = provider;
}
// This is called when the user clicks the action
protected override Action<ITextControl>? ExecutePsiTransaction(ISolution solution, IProgressIndicator progress)
{
if (_provider.GetSelectedTreeNode<IMethodDeclaration>() is not { } methodDeclaration)
{
// Do something with this
// If you don't modify the class you are in just return null
return null;
}
return null;
}
public override string Text => "Find parent usages";
public override bool IsAvailable(IUserDataHolder cache)
{
// This might catch the outer method.
if (_provider.GetSelectedTreeNode<IMethodDeclaration>() is not { } methodDeclaration)
return false;
return true;
}
}
This should at least present you with a context action when on a method.