How do I add extension codeInsight.declarativeInlayProvider

Answered

I am working on a plugin for intellij.  I query the lsp for diagnostics on a file and it gives me line numbers for problematic lines.  I want to provide an inlay hint at the end of each line with problematic code.  But I cannot get my InlayHintsProvider to be registered properly as an extension point.

My code is here

I have been able to run :runIde: gradle task in debug mode and the code never hits any debug point in MyDeclarativeInlayHintsProvider.
My assumption is that I'm doing something wrong in my plugn.xml that is not injecting my InlayHintsProvider properly but I have not been able to diagnose the problem
 

<idea-plugin require-restart="true">
…
    <extensions defaultExtensionNs="com.intellij">
        <codeInsight.declarativeInlayProvider
                language=""
                isEnabledByDefault="true"
                implementationClass="com.example.inlays.demo.lsp.MyDeclarativeInlayHintsProvider"
        />
    </extensions>
…
</idea-plugin>
0
7 comments

What are you trying to achieve with Inlay Hints? Are you not using LSP instead of PSI (which you must have for inlay hints) for your language? If you have PSI, you must specify language attribute in plugin.xml correctly (empty value is invalid).

0

I am using a lsp … in my example code I'm hardcoding the return from the lsp but the lsp return should have the line number I need for placement of the inlay hint. I don't think I have to use PSI do I?
 

package com.example.inlays.demo.lsp

import com.example.inlays.demo.model.Diagnostic
import com.intellij.codeInsight.hints.declarative.InlayHintsCollector
import com.intellij.codeInsight.hints.declarative.InlayHintsProvider
import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiFile
 
class MyDeclarativeInlayHintsProvider : InlayHintsProvider {
   /**
    * Creates collector for given file and editor if it may create inlays, or null otherwise.
    */
   override fun createCollector(file: PsiFile, editor: Editor): InlayHintsCollector {
       // hard coded return from lsp
       val diagnostics = listOf(Diagnostic("unique-identifier", "my diagnostic", "this code is bad", 5))
       return MyHintsCollector(diagnostics)
   }
}

 

package com.example.inlays.demo.lsp

import com.example.inlays.demo.model.Diagnostic
import com.intellij.codeInsight.hints.declarative.EndOfLinePosition
import com.intellij.codeInsight.hints.declarative.InlayPayload
import com.intellij.codeInsight.hints.declarative.InlayTreeSink
import com.intellij.codeInsight.hints.declarative.OwnBypassCollector
import com.intellij.codeInsight.hints.declarative.StringInlayActionPayload
import com.intellij.psi.PsiFile

class MyHintsCollector(private val diagnostics: List<Diagnostic>) : OwnBypassCollector {
   /**
    * Collects all inlays for a given file.
    */
   override fun collectHintsForFile(file: PsiFile, sink: InlayTreeSink) {
       diagnostics.forEach {
           sink.addPresentation(
               EndOfLinePosition(it.lineNumber),
               listOf( InlayPayload("my.hint", StringInlayActionPayload("you should fix this"))),
               null,
               true
           ) {
               text("you should really fix this")
           }
       }
   }
}

I have tried specifying “Java” as the language, but that does not seem to impact whether or not the inlay provider gets wired into the plugin

0

Actually … I just figured it out. My solution is language agnostic because the lsp handles all of the language specific stuff for me, so I needed to add a InlayHintFactory like so …

package com.example.inlays.demo.lsp

import com.intellij.codeInsight.hints.declarative.InlayHintsProviderFactory
import com.intellij.codeInsight.hints.declarative.InlayProviderInfo
import com.intellij.lang.Language

class MyInlayHintFactory : InlayHintsProviderFactory {
    private val provider = InlayProviderInfo(MyDeclarativeInlayHintsProvider(), "com.example.inlays.demo", setOf(), true, "demo")
    override fun getProviderInfo(language: Language, providerId: String): InlayProviderInfo = provider
    override fun getProvidersForLanguage(language: Language): List<InlayProviderInfo> = listOf(provider)
    override fun getSupportedLanguages(): Set<Language> = setOf()
}

and then update my plugin.xml like so


<extensions defaultExtensionNs="com.intellij">
    <codeInsight.declarativeInlayProviderFactory
            implementationClass="com.example.inlays.demo.lsp.MyInlayHintFactory"
    />
</extensions>
0

Followup question … although my hints show up now … I can right click them and disable them and then they're gone and I cannot reenable them without either wiring up a whole bunch of inlay settings that I don't want to build or do a clean rebuild of the plugin.  Is there anyway I can disable the DisableDeclarativeInlayAction?

0

That would be dangerous, and disabling it for specific inlays is not possible.

0

Fair enough … if I did want to declare it as an inlay setting that I could toggle back on if I wanted, what is the standard way of doing that with a declarative inlay?

0

Sorry, could you please rephrase your last question? It's not quite clear what you want to achieve to me.

0

Please sign in to leave a comment.