DocumentationProvider for fake PsiElement
Answered
Hi. I want to use DocumentationProvider for all tokens in the text document. So I create some fake PsiElements for this tokens. But the quick documentation popup is displayed in the correct place only if I position the editor cursor on the token and press Ctrl + Q. When I hover over symbols with the mouse, the popup window is displayed either at the beginning of the document or in the middle after scrolling. How can I put the quick documentation popup on mouse hover in the right place?


Please sign in to leave a comment.
Hi,
Please provide more information:
class MyDocumentationProvider extends AbstractDocumentationProvider {
override def getCustomDocumentationElement(
editor: Editor,
file: PsiFile,
context: PsiElement,
targetOffset: Int
): PsiElement =
EditorEventManager.forEditor(editor) match {
case Some(eventManager) => eventManager.getElementAtOffset(targetOffset)
case None => null
}
override def generateDoc(
element: PsiElement,
originalElement: PsiElement
): String =
getQuickNavigateInfo(element, originalElement)
override def getQuickNavigateInfo(
element: PsiElement,
originalElement: PsiElement
): String =
element match {
case myPsiElement: MyPsiElement =>
EditorEventManager
.forUri(
FileUtils.VFSToURI(myPsiElement.getContainingFile.getVirtualFile)
)
.fold("")(eventManager =>
eventManager
.requestDoc(eventManager.editor, myPsiElement.getTextOffset)
)
case psiFile: PsiFile =>
val editor = FileUtils.editorFromPsiFile(psiFile)
EditorEventManager
.forEditor(editor)
.fold("")(
_.requestDoc(editor, editor.getCaretModel.getCurrentCaret.getOffset)
)
case _ => ""
}
}
case class MyPsiReference(var element: PsiElement) extends PsiReference {
def getElement: PsiElement = element
def getRangeInElement: TextRange = new TextRange(0, element.getTextLength)
def resolve: PsiElement = element
def getCanonicalText: String = element.getText
@throws[IncorrectOperationException]
def handleElementRename(newElementName: String): PsiElement = element
@throws[IncorrectOperationException]
def bindToElement(newElement: PsiElement): PsiElement = {
this.element = newElement
newElement
}
def isReferenceTo(newElement: PsiElement): Boolean =
this.element == newElement
override def getVariants: Array[AnyRef] = Array()
def isSoft: Boolean = false
}
Hi,
1. What is EditorEventManager.forEditor(editor)? What element is returned from MyDocumentationProvider.getCustomDocumentationElement() when you observe an issue?
2. Why do you implement your own fake element instead of using FakePsiElement? Is there any additional functionality that you implement? If not, I suggest switching to FakePsiElement to avoid implementing redundant code (it may help to spot the issue cause).
No, that's a workaround. One should never override services provided by the platform in 3rd party plugins.