diff --git a/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/declarations/AbstractKotlinUVariable.kt b/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/declarations/AbstractKotlinUVariable.kt index 7e4b05e7ca5c..e48532fd3087 100644 --- a/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/declarations/AbstractKotlinUVariable.kt +++ b/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/declarations/AbstractKotlinUVariable.kt @@ -3,6 +3,8 @@ package org.jetbrains.uast.kotlin import com.intellij.psi.* import org.jetbrains.annotations.ApiStatus +import org.jetbrains.annotations.NotNull +import org.jetbrains.annotations.Nullable import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.psi.* @@ -70,11 +72,24 @@ abstract class AbstractKotlinUVariable( } private fun AbstractKotlinUVariable.buildAnnotations(): List { - val sourcePsi = sourcePsi ?: return javaPsi.annotations.map { WrappedUAnnotation(it, this) } val annotations = SmartList() - val hasInheritedGenericType = baseResolveProviderService.hasInheritedGenericType(sourcePsi) - if (!hasInheritedGenericType) { - annotations.add(KotlinNullabilityUAnnotation(baseResolveProviderService, sourcePsi, this)) + val sourcePsi = sourcePsi + if (sourcePsi != null) { + val hasInheritedGenericType = baseResolveProviderService.hasInheritedGenericType(sourcePsi) + if (!hasInheritedGenericType) { + annotations.add( + KotlinNullabilityUAnnotation(baseResolveProviderService, sourcePsi, this) + ) + } + } else { + javaPsi.annotations.filter { psiAnnotation -> + val fqName = psiAnnotation.qualifiedName + fqName == NotNull::class.qualifiedName || fqName == Nullable::class.qualifiedName + }.forEach { psiAnnotation -> + annotations.add( + WrappedUAnnotation(psiAnnotation, this) + ) + } } // NB: we can't use sourcePsi.annotationEntries directly due to annotation use-site targets. baseResolveProviderService.getPsiAnnotations(javaPsi).asSequence() diff --git a/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/UastResolveApiFixtureTestBase.kt b/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/UastResolveApiFixtureTestBase.kt index 6d49b64d4e0f..ed19fd03bf5c 100644 --- a/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/UastResolveApiFixtureTestBase.kt +++ b/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/common/kotlin/UastResolveApiFixtureTestBase.kt @@ -1474,6 +1474,52 @@ interface UastResolveApiFixtureTestBase { ) } + fun checkResolveAnnotationOnSetparam(myFixture: JavaCodeInsightTestFixture) { + myFixture.configureByText( + "main.kt", + """ + package test.pkg + + annotation class Anno(val attr: Int) + + class Test { + @get:Anno(attr = 42) + @setparam:Anno(attr = 21) + var prop = 0 + } + """.trimIndent() + ) + + val uFile = myFixture.file.toUElement()!! + var cnt = 0 + uFile.accept( + object : AbstractUastVisitor() { + override fun visitMethod(node: UMethod): Boolean { + val txt = node.sourcePsi?.text + when (node.name) { + "getProp" -> { + cnt++ + val anno = node.uAnnotations.single() + val resolved = anno.resolve() + TestCase.assertNotNull(txt, resolved) + TestCase.assertEquals("test.pkg.Anno", resolved!!.qualifiedName) + } + "setProp" -> { + cnt++ + val param = node.uastParameters.single() + val anno = param.uAnnotations.single() + val resolved = anno.resolve() + TestCase.assertNotNull(txt, resolved) + TestCase.assertEquals("test.pkg.Anno", resolved!!.qualifiedName) + } + } + return super.visitMethod(node) + } + } + ) + TestCase.assertEquals(2, cnt) + } + fun checkResolveDataClassSyntheticMember(myFixture: JavaCodeInsightTestFixture, isK2: Boolean) { myFixture.configureByText( "main.kt", diff --git a/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastResolveApiFixtureTest.kt b/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastResolveApiFixtureTest.kt index f508d91a8749..890d02ea9038 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastResolveApiFixtureTest.kt +++ b/plugins/kotlin/uast/uast-kotlin-fir/tests/test/org/jetbrains/fir/uast/test/FirUastResolveApiFixtureTest.kt @@ -218,6 +218,10 @@ class FirUastResolveApiFixtureTest : KotlinLightCodeInsightFixtureTestCase(), Ua checkOperatorMultiResolvable(myFixture) } + fun testResolveAnnotationOnSetparam() { + checkResolveAnnotationOnSetparam(myFixture) + } + fun testResolveDataClassSyntheticMember() { checkResolveDataClassSyntheticMember(myFixture, isK2 = true) } diff --git a/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastResolveApiFixtureTest.kt b/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastResolveApiFixtureTest.kt index e138fd8a7d44..b7d83d25e32c 100644 --- a/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastResolveApiFixtureTest.kt +++ b/plugins/kotlin/uast/uast-kotlin/tests/test/org/jetbrains/uast/test/kotlin/comparison/FE1UastResolveApiFixtureTest.kt @@ -178,6 +178,10 @@ class FE1UastResolveApiFixtureTest : KotlinLightCodeInsightFixtureTestCase(), Ua checkOperatorMultiResolvable(myFixture) } + fun testResolveAnnotationOnSetparam() { + checkResolveAnnotationOnSetparam(myFixture) + } + fun testResolveDataClassSyntheticMember() { checkResolveDataClassSyntheticMember(myFixture, isK2 = false) }