Showing available intentions for a highlight in a popup at a custom position
I have a `HighlightInfo`, and would like to display an Alt+Enter style popup, with the available intentions / quick fixes for that `HighlightInfo`, near the cursor when a user clicks somewhere.
For collecting the list of intentions, it looks like I could use `ShowIntentionsPass`, but `#getAvailableFixes` processes all highlights at an offset, not just the `HighlightInfo` I have. The most useful API for this would be `SIP#addAvailableFixesForGroups` which lets me pass a `HighlightInfo`, but this method is private. I cannot replicate this method, because a bunch of the things it uses, such as `HighlightInfo#isFromInjection` or `#getGroup`, are package-private.
The second problem is with positioning the popup. I can call `IntentionHintComponent.showIntentionHint` with the collected intentions, but no option to set the position. The method returns a `IntentionHintComponent` which has no way to access `#myPopup`, and all the `#showPopup` methods are also private. I cannot create a custom popup, because once again, `IntentionHintComponent#IntentionPopup` is package-private with a private constructor.
Could `ShowIntentionsPass#getAvailableFixes` and `IntentionHintComponent#showPopup` overloads, and possibly the package-private getter methods in `HighlightInfo`, be made public for plugins to use?
Please sign in to leave a comment.
Could you please explain what highlighting you're trying to achieve in your plugin and what API you're using to manually construct HighlightInfo?
I'm not manually constructing `HighlightInfo`. I'm showing highlight descriptions as inlays, and need to get intentions for a specific `HighlightInfo` so I can show a popup for it when you click the inlay. https://plugins.jetbrains.com/plugin/19678-inspection-lens/
Any updates on this?
Sorry for delay due to vacation, I pinged the responsible developer on this.
Yes, you can use com.intellij.codeInsight.daemon.impl.HighlightInfo#findRegisteredQuickFix for finding and filtering quick fixes inside HighlightInfo. As for the position, no, the intentions popup is always shown at the caret position, there's no way currently to customize it.
The thing about `ShowIntentionsPass` is that it seems to have a lot of additional logic for handling injected code, and I cannot even replicate that in my own code because many of the `HighlightInfo` methods are package-private.
My goal is to show the intention popup when you click an inlay hint, which references an existing inspection in the code, and display only the relevant quick fixes for that single inspection:
With all the required methods being private or package-private and inability to set the location of the popup, I cannot easily do that. This screenshot is a proof-of-concept using reflection to call the private methods.
instead of hacking inlay hint implementation, could you have an inspection which highlights the ranges your want to show hints for? For example, in the screenshot above, highlight the “KeyEvent” identifier to show the needed quick fixes
A user interface where someone clicks and that opens a context menu somewhere else doesn't make sense to me. It would also show quick fixes for any other inspections at that position, not just the one the user clicked.
>A user interface where someone clicks and that opens a context menu somewhere else doesn't make sense to me. It would also show quick fixes for any other inspections at that position, not just the one the user clicked.
My thoughts exactly. If the API for customizing the popup position was available it would lead to “opening a context menu somewhere else”.
So you want the user to click the inlay and show them the popup with available fixes? Doesn't the standard
Inlay#getRenderer()#getContextMenuGroup
fit well enough for this?
I don't follow. My code is creating a popup in response to a click event, so the popup should appear near where the user clicked, not wherever the highlight is in the code.
please use Inlay#getRenderer()#getContextMenuGroup
This is not a context menu, it's a left-click action, so according to the documentation getContextMenuGroup is not going work. The popup is also intended to have all the features of IntentionHintComponent#IntentionPopup, which I don't know how could be integrated into a context menu generated from an ActionGroup.
>This is not a context menu
no, it's not. Inlay UI does differ from the Alt-Enter quick fix UI, it's true. But when you choose inaly hints for your UI, it should be consistent with inlay hints UI.
Alternatively, there's a possibility to have an inspection which produces a number of quick fixes at this very specific offset in the file, and shows popup when Alt-Enter is pressed.
How is my idea inconsistent with inlay hint UI? The Code Vision inlays already behave like hyperlinks and display custom popups at the clicked location after a left click. I cannot find any difference between your existing inlay hint UI and how I want my plugin to work.
EditorCustomElementRenderer#getContextMenuGroup doesn't even have a single override in the entire intellij-community project (maybe with the exception of the Android stuff, I don't have that loaded), and EditorCustomElementRenderer#getContextMenuGroupId appears to only have one functioning implementation, and the rest are dummy ids.
I followed how Code Vision inlays work to make my UI consistent.
>How is my idea inconsistent with inlay hint UI?
Sorry, I might have misunderstood, I thought you was not happy that inlay hint “is not a context menu, it's a left-click action”, and wanted popup triggered with alt-enter, not with left click on the inlay hint. If you are ok with inlay-hint-clickable popup, then EditorCustomElementRenderer#getContextMenuGroup will probably work for you.
I want a popup triggered by left click, the problem is that there is no way to tell the popup to appear at the clicked location. Without a way to customize its location, the popup appears at the location of the highlighted code, far away from the mouse.
The screenshot from earlier is how it's supposed to look, but that screenshot was made using reflection to customize the popup location.
did the EditorCustomElementRenderer#getContextMenuGroup popup show in the correct position?
I don't know, I'm trying to use IntentionHintComponent.showIntentionHint which already has all the features related to quick fixes and previews, at first glance it doesn't seem possible to integrate that with getContextMenuGroup.