Question about extending PsiDocumentationTargetProvider
SHORT VERSION: Is there a way I can extend PsiDocumentationTargetProvider to add an additional page of docs on top of the KDoc page that is already shown?
------------------------------------------------------------------------------------------------------------------------
I am working on a framework that wraps, among other things, web CSS properties. I am also writing an IDEA plugin for working with this framework.
What I would like to do is extend the existing Kotlin “quick documentation” popup with an additional page that shows the CSS documentation from the MDN.
For example, the quick docs for Modifier.backgroundColor would show the KDoc I wrote for that function on page 1 / 2, and the MDN docs for the background-color property on page 2 / 2.
However, the way that PsiDocumentationTargetProvider works (it seems) is it finds the first docs provider that matches and stops there. Which means I can show either MDN docs or KDocs but not both.
The way I “fixed” this was by basically instantiating an instance of KotlinPsiDocumentationTargetProvider myself and then calling kotlinDocProvider.documentationTargets(element, originalElement) to get the KDocs, and to result that I add my own additional documentation as an additional entry. In plugin.xml I also declared that my documentation provider should be triggered before the kotlin documentation provider. And that worked!
However, it did trigger a verification violation:
Invocation of override-only method
PsiDocumentationTargetProvider.documentationTargets(PsiElement, PsiElement)
Override-only method PsiDocumentationTargetProvider.documentationTargets(PsiElement, PsiElement) is invoked in CssModifierDocumentationTargetProvider.documentationTargets(PsiElement, PsiElement) : List. This method is marked with @ApiStatus.OverrideOnly annotation, which indicates that the method must be only overridden but not invoked by client code. See documentation of the @ApiStatus.OverrideOnly for more info.but the verifyPlugin task still passed at the time. This was with intellij-platform version 2.10.5.
I just upgraded to 2.18.1 and it seems like the violation has been upgraded into an error.
Is there another way I'm supposed to be doing this? Is this going to get my plugin rejected in the future, meaning I need to back the feature out?
------------------------------------------------------------------------------------------------------------------------
The following is all relevant code:
Plugin.xml
<platform.backend.documentation.psiTargetProvider
order="before KotlinDocumentationTargetProvider"
implementation="com.varabyte.kobweb.intellij.docs.CssModifierDocumentationTargetProvider"/>CssModifierDocumentationTargetProvider.kt
private val MODIFIER_ID = ClassId.fromString("com/varabyte/kobweb/compose/ui/Modifier")
class CssModifierDocumentationTarget(val cssPropertyName: String, val element: PsiElement) : DocumentationTarget {
override fun computePresentation(): TargetPresentation =
TargetPresentation.builder(cssPropertyName)
.icon(com.intellij.icons.AllIcons.FileTypes.Css)
.presentation()
override fun computeDocumentation(): DocumentationResult? {
val mdnDoc = getCssMdnDocumentation(cssPropertyName, MdnCssSymbolKind.Property)
?: return null
val html = mdnDoc.getDocumentation(withDefinition = true)
return DocumentationResult.documentation(html).externalUrl(mdnDoc.url)
}
override fun createPointer(): Pointer<out DocumentationTarget> {
val elementPointer = element.createSmartPointer()
return Pointer {
elementPointer.element?.let {
CssModifierDocumentationTarget(cssPropertyName, it)
}
}
}
}
/**
* Provides documentation for CSS modifier functions tied to CSS properties.
*
* For example, `Modifier.backgroundColor(...)` will show the MDN documentation for the `background-color` CSS property
* on the second page.
*/
class CssModifierDocumentationTargetProvider : PsiDocumentationTargetProvider {
val kotlinDocProvider = KotlinPsiDocumentationTargetProvider()
override fun documentationTargets(
element: PsiElement,
originalElement: PsiElement?,
): List<DocumentationTarget> {
return kotlinDocProvider.documentationTargets(element, originalElement) +
listOfNotNull(documentationTarget(element))
}
private fun documentationTarget(element: PsiElement): DocumentationTarget? {
val function = element.asKtNamedFunction() ?: return null
analyze(function) {
if (function.receiverTypeReference?.type?.isClassType(MODIFIER_ID) != true) {
return null
}
if (!function.returnType.isClassType(MODIFIER_ID)) {
return null
}
}
val propertyName = function.name?.camelCaseToKebabCase() ?: return null
return CssModifierDocumentationTarget(propertyName, element)
}
}
Please sign in to leave a comment.
I realize now this was the wrong community to post in, sorry about that! Moderator, feel free to reject / delete this post.