[psi] get type text based on provided stubs

This commit is contained in:
Anna Kozlova
2023-05-12 14:56:52 +02:00
committed by teamcity
parent 71844f81f4
commit faedea6aea
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementOrCallableRef
import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.psi.stubs.elements.KtTokenSets
@@ -57,4 +58,55 @@ class KtTypeReference : KtModifierListOwnerStub<KotlinPlaceHolderStub<KtTypeRefe
}
fun nameForReceiverLabel() = (typeElement as? KtUserType)?.referencedName
/**
* Returns presentable text for the underlying type based on stubs when provided.
* No decompilation happens if [KtTypeReference] represents compiled code.
*/
fun getTypeText(): String {
return stub?.let { getTypeText(typeElement) } ?: text
}
private fun getQualifiedName(userType: KtUserType): String? {
val qualifier = userType.qualifier ?: return userType.referencedName
return getQualifiedName(qualifier) + "." + userType.referencedName
}
private fun getTypeText(typeElement: KtTypeElement?): String? {
return when (typeElement) {
is KtUserType -> buildString {
append(getQualifiedName(typeElement))
val args = typeElement.typeArguments
if (args.isNotEmpty()) {
append(args.joinToString(", ", "<", ">") {
val projection = when (it.projectionKind) {
KtProjectionKind.IN -> "in "
KtProjectionKind.OUT -> "out "
KtProjectionKind.STAR -> "*"
KtProjectionKind.NONE -> ""
}
projection + (getTypeText(it.typeReference?.typeElement) ?: "")
})
}
}
is KtFunctionType -> buildString {
val contextReceivers = typeElement.contextReceiversTypeReferences
if (contextReceivers.isNotEmpty()) {
append(contextReceivers.joinToString(", ", "context(", ")") {getTypeText(it.typeElement) ?: ""})
}
typeElement.receiverTypeReference?.let { append(getTypeText(it.typeElement)) }
append(typeElement.parameters.joinToString(", ", "(", ")") { param ->
param.name + ": " + param.typeReference?.getTypeText()
})
typeElement.returnTypeReference?.let { returnType ->
append(" -> ")
append(getTypeText(returnType.typeElement))
}
}
is KtIntersectionType -> getTypeText(typeElement.getLeftTypeRef()?.typeElement) + " & " + getTypeText(typeElement.getRightTypeRef()?.typeElement)
is KtNullableType -> getTypeText(typeElement.innerType) + "?"
null -> null
else -> error("Unsupported type $typeElement")
}
}
}