[draft] UAST: `KotlinNullabilityUAnnotation` now is created for every `AbstractKotlinUVariable`
diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt index 6035e25..66ab0ed 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt
@@ -25,8 +25,10 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.resolve.calls.callUtil.getType +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.TypeNullability import org.jetbrains.kotlin.types.typeUtil.nullability +import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.uast.* import org.jetbrains.uast.internal.acceptList import org.jetbrains.uast.java.JavaAbstractUExpression @@ -78,26 +80,14 @@ override val annotations by lz { - if (sourcePsi == null) - return@lz psi.annotations.map { WrappedUAnnotation(it, this) } + val sourcePsi = sourcePsi ?: return@lz psi.annotations.map { WrappedUAnnotation(it, this) } - val annotationEntries = (sourcePsi as? KtModifierListOwner)?.annotationEntries - val kotlinAnnotations = annotationEntries?. - filter { annotationEntry -> - annotationEntry.useSiteTarget?.getAnnotationUseSiteTarget().let { target -> - acceptsAnnotationTarget(target) - } - }?. - map { annotationEntry -> - KotlinUAnnotation(annotationEntry, this) - } ?: emptyList<UAnnotation>() + SmartList<UAnnotation>(KotlinNullabilityUAnnotation(sourcePsi, this)).also { annotations -> + (sourcePsi as? KtModifierListOwner)?.annotationEntries?. + filter { it.useSiteTarget?.getAnnotationUseSiteTarget().let { acceptsAnnotationTarget(it) } }?. + mapTo(annotations) { KotlinUAnnotation(it, this) } + } - val targetType = (sourcePsi as? KtCallableDeclaration)?.let { it.typeReference?.getType() } - ?: (sourcePsi as? KtProperty)?.initializer?.let { it.getType(it.analyze()) } - ?: (sourcePsi as? KtProperty)?.delegateExpression?.let { it.getType(it.analyze())?.arguments?.firstOrNull()?.type } - ?: sourcePsi?.getParentOfType<KtProperty>(false)?.let { it.typeReference?.getType() ?: it.initializer?.let { it.getType(it.analyze()) } } - val nullability = targetType?.nullability() - kotlinAnnotations + (nullability?.let { listOf(KotlinNullabilityUAnnotation(it, this)) } ?: emptyList()) } abstract protected fun acceptsAnnotationTarget(target: AnnotationUseSiteTarget?): Boolean @@ -214,7 +204,27 @@ } } -class KotlinNullabilityUAnnotation(val nullability: TypeNullability, override val uastParent: UElement) : UAnnotation, JvmDeclarationUElement { +class KotlinNullabilityUAnnotation(val annotatedElement: PsiElement, override val uastParent: UElement) : UAnnotation, JvmDeclarationUElement { + + + private fun getTargetType(annotatedElement: PsiElement): KotlinType? { + if (annotatedElement is KtCallableDeclaration) { + annotatedElement.typeReference?.getType()?.let { return it } + } + if (annotatedElement is KtProperty) { + annotatedElement.initializer?.let { it.getType(it.analyze()) }?.let { return it } + annotatedElement.delegateExpression?.let { it.getType(it.analyze())?.arguments?.firstOrNull()?.type }?.let { return it } + } + annotatedElement.getParentOfType<KtProperty>(false)?.let { + it.typeReference?.getType() ?: it.initializer?.let { it.getType(it.analyze()) } + }?.let { return it } + return null + } + + + val nullability by lz { getTargetType(annotatedElement)?.nullability() } + + override val attributeValues: List<UNamedExpression> get() = emptyList() override val psi: PsiElement? @@ -227,7 +237,8 @@ get() = when (nullability) { TypeNullability.NOT_NULL -> NotNull::class.qualifiedName TypeNullability.NULLABLE -> Nullable::class.qualifiedName - TypeNullability.FLEXIBLE -> TODO() + TypeNullability.FLEXIBLE -> "FlexibleNullability" + null -> null } override fun findAttributeValue(name: String?): UExpression? = null
diff --git a/plugins/uast-kotlin/testData/ParameterPropertyWithAnnotation.render.txt b/plugins/uast-kotlin/testData/ParameterPropertyWithAnnotation.render.txt index a65df8b..5f93a65 100644 --- a/plugins/uast-kotlin/testData/ParameterPropertyWithAnnotation.render.txt +++ b/plugins/uast-kotlin/testData/ParameterPropertyWithAnnotation.render.txt
@@ -17,14 +17,14 @@ @org.jetbrains.annotations.NotNull private var bar: int public final fun getBar() : int = UastEmptyExpression public final fun setBar(@org.jetbrains.annotations.NotNull p: int) : void = UastEmptyExpression - public fun Test1(@MyAnnotation @org.jetbrains.annotations.NotNull bar: int) = UastEmptyExpression + public fun Test1(@org.jetbrains.annotations.NotNull @MyAnnotation bar: int) = UastEmptyExpression } public final class Test2 { - @MyAnnotation5 @org.jetbrains.annotations.NotNull private var bar: int + @org.jetbrains.annotations.NotNull @MyAnnotation5 private var bar: int @MyAnnotation public final fun getBar() : int = UastEmptyExpression @MyAnnotation2 - public final fun setBar(@MyAnnotation3 @org.jetbrains.annotations.NotNull p: int) : void = UastEmptyExpression + public final fun setBar(@org.jetbrains.annotations.NotNull @MyAnnotation3 p: int) : void = UastEmptyExpression public fun Test2(@org.jetbrains.annotations.NotNull bar: int) = UastEmptyExpression }
diff --git a/plugins/uast-kotlin/testData/PropertyWithAnnotation.render.txt b/plugins/uast-kotlin/testData/PropertyWithAnnotation.render.txt index ef7ff4f..d299e0a 100644 --- a/plugins/uast-kotlin/testData/PropertyWithAnnotation.render.txt +++ b/plugins/uast-kotlin/testData/PropertyWithAnnotation.render.txt
@@ -1,5 +1,5 @@ public final class PropertyWithAnnotationKt { - @TestAnnotation @org.jetbrains.annotations.NotNull private static final var prop1: int = 0 + @org.jetbrains.annotations.NotNull @TestAnnotation private static final var prop1: int = 0 @org.jetbrains.annotations.NotNull private static var prop3: int = 0 public static final fun getProp1() : int = UastEmptyExpression @TestAnnotation