Light Classes: Correctly handle annotations for property parameters
When getting annotations for KtLightParameter which is property parameter we should return annotations for parameter instead of property #KT-19671 Fixed
This commit is contained in:
+28
-10
@@ -30,7 +30,9 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
|||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.isPropertyParameter
|
||||||
import org.jetbrains.kotlin.resolve.AnnotationChecker
|
import org.jetbrains.kotlin.resolve.AnnotationChecker
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
|
|
||||||
abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(protected val owner: T)
|
abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(protected val owner: T)
|
||||||
@@ -115,8 +117,19 @@ private fun lightAnnotationsForEntries(lightModifierList: KtLightModifierList<*>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAnnotationDescriptors(declaration: KtDeclaration?, annotatedLightElement: KtLightElement<*, *>): List<AnnotationDescriptor> {
|
private fun getAnnotationDescriptors(declaration: KtDeclaration, annotatedLightElement: KtLightElement<*, *>): List<AnnotationDescriptor> {
|
||||||
val descriptor = declaration?.let { LightClassGenerationSupport.getInstance(it.project).resolveToDescriptor(it) }
|
val context = LightClassGenerationSupport.getInstance(declaration.project).analyze(declaration)
|
||||||
|
|
||||||
|
val descriptor = if (declaration is KtParameter && declaration.isPropertyParameter()) {
|
||||||
|
if (annotatedLightElement is KtLightParameter && annotatedLightElement.method.isConstructor)
|
||||||
|
context[BindingContext.VALUE_PARAMETER, declaration]
|
||||||
|
else
|
||||||
|
context[BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, declaration]
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration]
|
||||||
|
}
|
||||||
|
|
||||||
val annotatedDescriptor = when {
|
val annotatedDescriptor = when {
|
||||||
descriptor is ClassDescriptor && annotatedLightElement is KtLightMethod && annotatedLightElement.isConstructor -> descriptor.unsubstitutedPrimaryConstructor
|
descriptor is ClassDescriptor && annotatedLightElement is KtLightMethod && annotatedLightElement.isConstructor -> descriptor.unsubstitutedPrimaryConstructor
|
||||||
descriptor !is PropertyDescriptor || annotatedLightElement !is KtLightMethod -> descriptor
|
descriptor !is PropertyDescriptor || annotatedLightElement !is KtLightMethod -> descriptor
|
||||||
@@ -125,9 +138,9 @@ private fun getAnnotationDescriptors(declaration: KtDeclaration?, annotatedLight
|
|||||||
else -> descriptor
|
else -> descriptor
|
||||||
} ?: return emptyList()
|
} ?: return emptyList()
|
||||||
|
|
||||||
return annotatedDescriptor.annotations.getAllAnnotations().
|
return annotatedDescriptor.annotations.getAllAnnotations()
|
||||||
filter { it.matches(annotatedLightElement) }.
|
.filter { it.matches(annotatedLightElement) }
|
||||||
map { it.annotation }
|
.map { it.annotation }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasAnnotationsInSource(declaration: KtDeclaration): Boolean {
|
private fun hasAnnotationsInSource(declaration: KtDeclaration): Boolean {
|
||||||
@@ -143,12 +156,17 @@ private fun hasAnnotationsInSource(declaration: KtDeclaration): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun AnnotationWithTarget.matches(annotated: KtLightElement<*, *>): Boolean {
|
private fun AnnotationWithTarget.matches(annotated: KtLightElement<*, *>): Boolean {
|
||||||
if (annotated !is KtLightFieldImpl.KtLightFieldForDeclaration) return true
|
if (annotated is KtLightFieldImpl.KtLightFieldForDeclaration) {
|
||||||
|
if (target == AnnotationUseSiteTarget.FIELD) return true
|
||||||
|
|
||||||
if (target == AnnotationUseSiteTarget.FIELD) return true
|
if (target != null) return false
|
||||||
|
|
||||||
if (target != null) return false
|
val declarationSiteTargets = AnnotationChecker.applicableTargetSet(annotation)
|
||||||
|
return KotlinTarget.FIELD in declarationSiteTargets && KotlinTarget.PROPERTY !in declarationSiteTargets
|
||||||
|
}
|
||||||
|
else if (annotated is KtLightParameter && annotated.method.isSetter) {
|
||||||
|
return target == AnnotationUseSiteTarget.SETTER_PARAMETER
|
||||||
|
}
|
||||||
|
|
||||||
val declarationSiteTargets = AnnotationChecker.applicableTargetSet(annotation)
|
return true
|
||||||
return KotlinTarget.FIELD in declarationSiteTargets && KotlinTarget.PROPERTY !in declarationSiteTargets
|
|
||||||
}
|
}
|
||||||
+2
-1
@@ -148,7 +148,8 @@ public class KtLightParameter extends LightParameter implements KtLightDeclarati
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText() {
|
public String getText() {
|
||||||
return "";
|
KtParameter origin = getKotlinOrigin();
|
||||||
|
return origin != null ? origin.getText() : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
annotation class MyAnnotation
|
||||||
|
|
||||||
|
class Test1(@MyAnnotation var bar: Int)
|
||||||
|
|
||||||
|
class Test2(@get:MyAnnotation @set:MyAnnotation @setparam:MyAnnotation @property:MyAnnotation @field:MyAnnotation var bar: Int)
|
||||||
@@ -7,6 +7,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
|||||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
||||||
import org.jetbrains.uast.*
|
import org.jetbrains.uast.*
|
||||||
import org.jetbrains.uast.test.env.findElementByText
|
import org.jetbrains.uast.test.env.findElementByText
|
||||||
|
import org.jetbrains.uast.visitor.UastVisitor
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
@@ -67,4 +68,34 @@ class KotlinUastApiTest : AbstractKotlinUastTest() {
|
|||||||
assertTrue(bar.containingFile.text!!, bar.psi.modifierList.hasModifierProperty(PsiModifier.DEFAULT))
|
assertTrue(bar.containingFile.text!!, bar.psi.modifierList.hasModifierProperty(PsiModifier.DEFAULT))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test fun testParameterPropertyWithAnnotation() {
|
||||||
|
doTest("ParameterPropertyWithAnnotation") { _, file ->
|
||||||
|
val test1 = file.classes.find { it.name == "Test1" }!!
|
||||||
|
|
||||||
|
val constructor1 = test1.methods.find { it.name == "Test1" }!!
|
||||||
|
assertTrue(constructor1.uastParameters.first().annotations.any { it.qualifiedName == "MyAnnotation" })
|
||||||
|
|
||||||
|
val getter1 = test1.methods.find { it.name == "getBar" }!!
|
||||||
|
assertFalse(getter1.annotations.any { it.qualifiedName == "MyAnnotation" })
|
||||||
|
|
||||||
|
val setter1 = test1.methods.find { it.name == "setBar" }!!
|
||||||
|
assertFalse(setter1.annotations.any { it.qualifiedName == "MyAnnotation" })
|
||||||
|
assertFalse(setter1.uastParameters.first().annotations.any { it.qualifiedName == "MyAnnotation" })
|
||||||
|
|
||||||
|
|
||||||
|
val test2 = file.classes.find { it.name == "Test2" }!!
|
||||||
|
val constructor2 = test2.methods.find { it.name == "Test2" }!!
|
||||||
|
assertFalse(constructor2.uastParameters.first().annotations.any { it.qualifiedName == "MyAnnotation" })
|
||||||
|
|
||||||
|
val getter2 = test2.methods.find { it.name == "getBar" }!!
|
||||||
|
getter2.annotations.single { it.qualifiedName == "MyAnnotation" }
|
||||||
|
|
||||||
|
val setter2 = test2.methods.find { it.name == "setBar" }!!
|
||||||
|
setter2.annotations.single { it.qualifiedName == "MyAnnotation" }
|
||||||
|
setter2.uastParameters.first().annotations.single { it.qualifiedName == "MyAnnotation" }
|
||||||
|
|
||||||
|
test2.fields.find { it.name == "bar" }!!.annotations.single { it.qualifiedName == "MyAnnotation" }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user