Is there any documentation that relates to how we can create and insert our own LocalQuickFix action for some HighlightInfo in a file above a certain Severity ?
And when we do insert a Quick Fix, we would like to change the light bulb icon to a different icon.
I’m a bit confused because there are so many different components that touch these things:
Unfortunately, Iconable only changes the icon within the popup menu.
I want to change the light bulb icon itself which appears floating next to the caret line. I want to slightly change its appearance so that users know when it contains the QuickFix that my plugin will provide.
Concisely, this little guy is what I want to change:
Creating a Quick Fix
Also, it remains unclear how I can register construct and register a QuickFix from a HighlightInfo. It seems like I have to go through InspectionManager#createProblemDescriptor which itself points at registering a LocalInspectionTool, but seems wrong since I want to do something based on other inspection tools, not create my own.
Intention Action
Highlighting range
For now, I created an IntentionAction, but it doesn’t fulfill my requirements because it doesn’t allow me to highlight the scope I will apply the fix on (since it extends beyond the PsiElement which relates to the HighlightInfo).
I believe this is what LocalQuickFixAndIntentionActionOnPsiElement is for given it has startElement and endElement properties.
Forcing no preview
One quirk I’m having with the IntentionAction for now is that it keeps trying to generate a preview, even though I don’t want it to.
I’ve tried this:
override fun startInWriteAction(): Boolean = false
Moreover, I get an Exception related to Directory Name URL being undefined. I’m not quite sure how I’m supposed to treat this, but it seems to relate to this part of the EP (it’s unclear what value I need to provide).
com.intellij.diagnostic.PluginException: Intention Description Dir URL is null
generatePreview(...) = IntentionPreviewInfo.EMPTY should have worked. startInWriteAction() should return true if the intention modifies things in-place, while <skipBeforeAfter> specifies that the intention does not have a before.ext.template and after.ext.template pair.
As for descriptionDirectoryName, that dictates the child directory of resources/intentionDescriptions in which description.html resides.
@insyncwithfoo thanks! This was very helpful. I think the documentation about descriptionDirectoryName could be improved (you mentioning the “child directory of” saved me some time).
I ended up setting a description and removing the IntentionPreviewInfo.EMPTY override. Now there is a simple HTML render, which is good enough
Problems left
However, I’m still stuck with:
Understanding how to properly setup a LocalQuickFix (to get a highlighting range on hover)
Understanding how to customize the floating icon.
Moreover, my IntentionAction is placed after a LocalQuickFix even though I’ve set:
override fun getPriority(): PriorityAction.Priority = PriorityAction.Priority.TOP
The goal is to resurface in the HintComponent (i.e. the floating LightBulb icon) my plugin’s action.
This action only appears when there is already a QuickFix resurfaced as a warning or error coming from linters and whatnot.
The action should always be placed first in the popup list of the HintComponent.
Ideally, hovering my plugin’s action in the popup should allow highlighting a TextRange in the Editor. Moreover, the floating light bulb icon should be changed if it contains my plugin’s action.
Current implementation
With the IntentionAction I’ve currently setup, I got to meet a few of the listed requirements, but I still have a few issues to achieve my goal.
My understanding is that using a LocalQuickFix instead of an IntentionAction will actually help me achieve most of my goals (except customizing the floating icon, which appears to be impossible?).
However, I don’t know how to work with Quick Fixes. It appears as though the only way to resurface them in the HintComponent is to register them via a LocalInspectionTool, so that’s the next thing I’ll look into.
Check the class hierarchy of LocalQuickfix and you’ll find IntentionWrapper.
If I’m not mistaken, com.intellij.codeInsight.intention.CustomizableIntentionAction#isOverrideIntentionBulb could be used to override the light bulb from an Intention.
Reading the code, com.intellij.codeInsight.intention.impl.IntentionHintComponent.LightBulbUtil#getIcon is the method which defines the light bulb icon (also check the caller).
IMHO this shouldn’t be done unless really necessary as it’s confusing and part of the core UX of the IDE.
@jansorg Ah, great find! I’m currently developing for idea/241, but I see that once we upgrade to idea/243, this method will actually be available (reference commit).