Change displayed name of PsiElement

Hi,

I have a PsiReferenceContributor, which successfully triggers my ReferenceProvider, which provides the references seen in the following picture.

These references are generated using the following class (Kotlin):

class BasicReference(origin: PsiElement, private val target: PsiElement) : PsiReferenceBase<PsiElement>(origin) {
override fun getVariants(): Array<Any?> {
return arrayOfNulls(0)
}

override fun resolve(): PsiElement {
return target
}
}

...where target is a PhpFile. I want to change the displayed names (in the picture), to show the files without the extensions .phtml, and to shorten the displayed path to one word (standard/special - because there is no other difference between these paths). How can I do that?

0
3 comments

This is not the intended way of using references. Usually references are created as fast as possible, based on the surrounding PSI, and the resolution (which can be very expensive) happens inside `resolve` method. If you need several targets, you don't create several references. Instead, you create one PsiPolyVariantReference and return several targets from it.

There's no easy way currently to change the presentation (similar question is asked at https://intellij-support.jetbrains.com/hc/en-us/community/posts/115000731870-GotoDeclarationHandler-with-multiple-targets-How-to-change-the-rendering-of-found-targets- , and we'll probably add such possibility in future). You could resolve to a (Renameable)FakePsiElement where you could control rendering (via ItemPresentation), but then you'd have to ensure that following the reference navigates you to the correct file (by implementing getNavigationElement), and that rename works (by correctly handling PsiReference#isReferenceTo and possibly handleElementRename).

1

Your reference returns one target, but the screenshot shows several of them. Why is that?

0

Because the picture shows instances of that class, which are instantiated using the following method:

private fun generateReferences(psiElement: PsiElement): List<PsiReference> {
val references = mutableListOf<PsiReference>()
val project = psiElement.project
val parameterData = psiElement.text.substring(1, psiElement.textLength - 1)
val paths = listOf("standard/views/$parameterData", "special/views/$parameterData")

for (path in paths) {
project.baseDir.findFileByRelativePath(path + ".phtml")?.parent?.children // parent folder with phtml files
?.filter { !it.isDirectory && it.extension == "phtml" && it.path.contains(path) } // filter the data
?.map { PsiManager.getInstance(project).findFile(it) } // returns PsiFile
?.mapNotNullTo(references) {
// adds BasicReferences of PsiFiles to references list
it?.let { BasicReference(psiElement, it) }
}
}
return references.toList()
}

Basically, I need to scan a folder, find all phtml files, and make a reference out of them. The function above achieves that, but I want to change the name of the created reference to something else. How can I achieve that?

0

Please sign in to leave a comment.