Line Markers are suddenly disappearing in kotlin file (UAST).

Answered

As I know, line markers should be placed only on special psi elements, for example, on class name identifier. Placing the marker on the wrong element may lead to its disappearing while file editing.

I place line marker on the `uClass.uastAnchor?.sourcePsi` element. Am I doing right? In Java files, it works perfectly. But in Kotlin it is not stable. I found an example in kotlin sources (https://github.com/JetBrains/kotlin/blob/ba6da7c40a6cc502508faf6e04fa105b96bc7777/idea/idea-android/src/org/jetbrains/kotlin/android/KotlinAndroidLineMarkerProvider.kt#L56), it is without UAST, however, it references the same element.

I tried kotlin versions 31 and 41. I suppose, there is a problem with the AST comparison in kotlin (leaf elements do not match correctly after changes).

0
5 comments

Please try

1) UElement uElement = org.jetbrains.uast.UastUtils#getUParentForIdentifier(psiElement)

2) if (uElement instance UClass)   PsiElement identifier = UElementKt.getSourcePsiElement(uClass.getUastAnchor())

 

0

Hi! Thank you for your reply, but it is exactly what I do :)

0

Please compare your code with this one from Devkit: https://github.com/JetBrains/intellij-community/blob/4999f5293e4307870020f1d0d672a3d35a52f22d/plugins/devkit/devkit-core/src/navigation/DevkitRelatedClassLineMarkerProviderBase.java#L19

It is important to get UClass from incoming identifier and not identifier from incoming UClass.

0

Thank you! I used `getUParentForIdentifier` and now it works.

 

By the way, as I understand, we can have several UClass instances at the same time for the same class? 

My now code look like:

override fun doCollectSlowLineMarkers(elements: MutableList<PsiElement>, result: MutableCollection<LineMarkerInfo<PsiElement>>) {
elements.asSequence()
.map { getUParentForIdentifier(it) }
.distinct()
.forEach { uElement ->
when (uElement) {
is UClass -> {
collectMarkersForClass(uElement, result)
}
}
}
}

Previously it was:

elements.asSequence()
.map(PsiElement::toUElement)
.distinct()
.forEach { uElement ->
when (uElement) {
is UClass -> {
collectMarkersForClass(uElement, result)
}
}
}

So, there are different UClass instances?

0

> By the way, as I understand, we can have several UClass instances at the same time for the same class? 

 

Do you mean caching? No UClasses are not cached so you'll create a new UClass instance each time you'll convert element to Uast.

Ans anyway I don't see any reason to use `distinct` here (at least in upper case), please report if you still need it for some reason

0

Please sign in to leave a comment.