Is there a way to offset location where the completion list pops-up in custom language plugin?

The issue comes up for nested element completions inside other referenceable types, I can't think of any in a regular language but in Markdown there are quite a few. For example:

# Header with embedded emoji :warning: 

The whole header is a target for an anchor ref, the emoji shortcut between :: is completable but not referenceable. IntelliJ completion code looks for a referenceable element when doing completions. So even though I am completing at a given caret position with another element there, IJ insists on it being an outer element's completion. 

I was only able to make completions work for such inner elements by creating a custom wrapping decorator to:

1. add everything from start of header, up to and including the first colon as a prefix, used in matching the completion

2. add everything from the second colon to end of header text as a suffix to append to the completion text

Item 1. was needed because IntelliJ completion takes the header element as one being completed not the embedded emoji element. Without the prefix nothing would match and `No Suggestions` would pop up instead.

Item 2. was needed because tab completing an item would replace everything to the end of the header text element not the end of the emoji element

Now the completions work. but Intellij is thinking it is doing a header element completion, the completion list pop-up lines up with the start of the header instead the start of the emoji element within the header. That can be a ways off, depending on the header text.

Any quick pointers where to look on how to change the completion pop-up location or should I pack lunch and dive into the intellij-community code?

 

4 comments
Comment actions Permalink
Official comment

The completion infrastructure searches for all PsiReference's at the given offset (usually just one) and assumes their start offsets to be the points to align with and to calculate prefix from. One can change this behavior by changing the default suggested prefix, which is done by calling CompletionResultSet#withPrefixMatcher inside your completion contributor, and feeding your lookup elements into the returned CompletionResultSet.

To customize Tab behavior, you can call CompletionInitializationContext#setReplacementOffset inside CompletionContributor#duringCompletion.

Comment actions Permalink

A picture is worth a thousand words:

0
Comment actions Permalink

Thank you Peter, I will try it out but it sounds like exactly what I was looking for.

0
Comment actions Permalink

Just implemented the suggested changes and item 2. was addressed by calling CompletionInitializationContext#setReplacementOffset inside CompletionContributor#duringCompletion as suggested.

For 1. the suggested CompletionResultSet#withPrefixMatcher would do the same as the matcher I implemented which addresses the need for the prefix string.

Will the use of CompletionResultSet#withPrefixMatcher affect the location of the completion popup?

0

Please sign in to leave a comment.