Light-annotations: fix for reading class-literal varargs (KT-29027, IDEA-204252)
This commit is contained in:
committed by
Nicolay Mitropolsky
parent
bcb220b919
commit
ebd6caaa71
@@ -157,9 +157,13 @@ class KtLightAnnotationForSourceEntry(
|
|||||||
val valueArguments = callEntry.value.arguments
|
val valueArguments = callEntry.value.arguments
|
||||||
val argument = valueArguments.firstOrNull()?.getArgumentExpression() ?: return null
|
val argument = valueArguments.firstOrNull()?.getArgumentExpression() ?: return null
|
||||||
|
|
||||||
if (!callEntry.key.type.let { KotlinBuiltIns.isArray(it) }) return null
|
if (!callEntry.key.type.let { KotlinBuiltIns.isArrayOrPrimitiveArray(it) }) return null
|
||||||
|
|
||||||
if (argument !is KtStringTemplateExpression && argument !is KtConstantExpression && getAnnotationName(argument) == null) {
|
if (argument !is KtStringTemplateExpression &&
|
||||||
|
argument !is KtConstantExpression &&
|
||||||
|
argument !is KtClassLiteralExpression &&
|
||||||
|
getAnnotationName(argument) == null
|
||||||
|
) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -159,9 +159,13 @@ class KtLightAnnotationForSourceEntry(
|
|||||||
val valueArguments = callEntry.value.arguments
|
val valueArguments = callEntry.value.arguments
|
||||||
val argument = valueArguments.firstOrNull()?.getArgumentExpression() ?: return null
|
val argument = valueArguments.firstOrNull()?.getArgumentExpression() ?: return null
|
||||||
|
|
||||||
if (!callEntry.key.type.let { KotlinBuiltIns.isArray(it) }) return null
|
if (!callEntry.key.type.let { KotlinBuiltIns.isArrayOrPrimitiveArray(it) }) return null
|
||||||
|
|
||||||
if (argument !is KtStringTemplateExpression && argument !is KtConstantExpression && getAnnotationName(argument) == null) {
|
if (argument !is KtStringTemplateExpression &&
|
||||||
|
argument !is KtConstantExpression &&
|
||||||
|
argument !is KtClassLiteralExpression &&
|
||||||
|
getAnnotationName(argument) == null
|
||||||
|
) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -474,6 +474,39 @@ class KtLightAnnotationTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun doVarargTest(type: String, parameters: List<String>) {
|
||||||
|
val paramsJoined = parameters.joinToString(", ")
|
||||||
|
|
||||||
|
myFixture.addClass(
|
||||||
|
"""
|
||||||
|
public @interface Annotation {
|
||||||
|
$type[] value() default {};
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.configureByText(
|
||||||
|
"AnnotatedClass.kt", """
|
||||||
|
@Annotation($paramsJoined)
|
||||||
|
open class AnnotatedClass
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
myFixture.testHighlighting("Annotation.java", "AnnotatedClass.kt")
|
||||||
|
|
||||||
|
val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1)
|
||||||
|
val annotationAttributeVal = annotations.first().findAttributeValue("value") as PsiArrayInitializerMemberValue
|
||||||
|
assertTextAndRange("($paramsJoined)", annotationAttributeVal)
|
||||||
|
UsefulTestCase.assertInstanceOf(annotationAttributeVal.parent, PsiNameValuePair::class.java)
|
||||||
|
for ((i, arg) in parameters.withIndex()) {
|
||||||
|
assertTextAndRange(arg, annotationAttributeVal.initializers[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun testVarargInt() = doVarargTest("int", listOf("1", "2", "3"))
|
||||||
|
|
||||||
|
fun testVarargClasses() = doVarargTest("""Class<?>""", listOf("Any::class", "String::class", "Int::class"))
|
||||||
|
|
||||||
fun testVarargWithSpread() {
|
fun testVarargWithSpread() {
|
||||||
myFixture.addClass("""
|
myFixture.addClass("""
|
||||||
public @interface Annotation {
|
public @interface Annotation {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import com.intellij.testFramework.LightProjectDescriptor
|
|||||||
import com.intellij.testFramework.UsefulTestCase
|
import com.intellij.testFramework.UsefulTestCase
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightAnnotationForSourceEntry
|
import org.jetbrains.kotlin.asJava.elements.KtLightAnnotationForSourceEntry
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KtLightPsiArrayInitializerMemberValue
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.idea.completion.test.assertInstanceOf
|
import org.jetbrains.kotlin.idea.completion.test.assertInstanceOf
|
||||||
import org.jetbrains.kotlin.idea.facet.configureFacet
|
import org.jetbrains.kotlin.idea.facet.configureFacet
|
||||||
@@ -241,6 +242,44 @@ class KtLightAnnotationTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testArrayOfClassLiterals() {
|
||||||
|
myFixture.addClass(
|
||||||
|
"""
|
||||||
|
public @interface ClazzAnnotation {
|
||||||
|
Class<?>[] cls();
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.configureByText(
|
||||||
|
"AnnotatedClass.kt", """
|
||||||
|
@ClazzAnnotation(cls = [String::class, Throwable::class, ShortArray::class, Array<Array<Int>>::class, Long::class, Unit::class])
|
||||||
|
class AnnotatedClass
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
myFixture.testHighlighting("AnnotatedClass.kt")
|
||||||
|
|
||||||
|
val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1)
|
||||||
|
val annotationAttributeVal = annotations.first().findAttributeValue("cls") as KtLightPsiArrayInitializerMemberValue
|
||||||
|
assertTextAndRange(
|
||||||
|
"[String::class, Throwable::class, ShortArray::class, Array<Array<Int>>::class, Long::class, Unit::class]",
|
||||||
|
annotationAttributeVal
|
||||||
|
)
|
||||||
|
val classLiterals = annotationAttributeVal.initializers.toList().map { it as PsiClassObjectAccessExpression }
|
||||||
|
val scope = GlobalSearchScope.everythingScope(project)
|
||||||
|
TestCase.assertEquals(
|
||||||
|
listOf(
|
||||||
|
PsiType.getJavaLangString(myFixture.psiManager, scope),
|
||||||
|
PsiType.getTypeByName("java.lang.Throwable", project, scope),
|
||||||
|
PsiType.SHORT.createArrayType(),
|
||||||
|
PsiType.getTypeByName("java.lang.Integer", project, scope).createArrayType().createArrayType(),
|
||||||
|
PsiType.LONG,
|
||||||
|
PsiType.getTypeByName("kotlin.Unit", project, scope)
|
||||||
|
),
|
||||||
|
classLiterals.map { it.operand.type }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun testAnnotationsInAnnotationsArrayDeclarations() {
|
fun testAnnotationsInAnnotationsArrayDeclarations() {
|
||||||
myFixture.addClass("""
|
myFixture.addClass("""
|
||||||
public @interface OuterAnnotation {
|
public @interface OuterAnnotation {
|
||||||
@@ -437,6 +476,39 @@ class KtLightAnnotationTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun doVarargTest(type: String, parameters: List<String>) {
|
||||||
|
val paramsJoined = parameters.joinToString(", ")
|
||||||
|
|
||||||
|
myFixture.addClass(
|
||||||
|
"""
|
||||||
|
public @interface Annotation {
|
||||||
|
$type[] value() default {};
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.configureByText(
|
||||||
|
"AnnotatedClass.kt", """
|
||||||
|
@Annotation($paramsJoined)
|
||||||
|
open class AnnotatedClass
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
myFixture.testHighlighting("Annotation.java", "AnnotatedClass.kt")
|
||||||
|
|
||||||
|
val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1)
|
||||||
|
val annotationAttributeVal = annotations.first().findAttributeValue("value") as PsiArrayInitializerMemberValue
|
||||||
|
assertTextAndRange("($paramsJoined)", annotationAttributeVal)
|
||||||
|
UsefulTestCase.assertInstanceOf(annotationAttributeVal.parent, PsiNameValuePair::class.java)
|
||||||
|
for ((i, arg) in parameters.withIndex()) {
|
||||||
|
assertTextAndRange(arg, annotationAttributeVal.initializers[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun testVarargInt() = doVarargTest("int", listOf("1", "2", "3"))
|
||||||
|
|
||||||
|
fun testVarargClasses() = doVarargTest("""Class<?>""", listOf("Any::class", "String::class", "Int::class"))
|
||||||
|
|
||||||
fun testVarargWithSpread() {
|
fun testVarargWithSpread() {
|
||||||
myFixture.addClass("""
|
myFixture.addClass("""
|
||||||
public @interface Annotation {
|
public @interface Annotation {
|
||||||
@@ -687,10 +759,12 @@ class KtLightAnnotationTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun PsiModifierListOwner.expectAnnotations(number: Int): Array<PsiAnnotation> =
|
private fun PsiModifierListOwner.expectAnnotations(number: Int): Array<PsiAnnotation> =
|
||||||
this.modifierList!!.annotations.apply {
|
this.modifierList!!.annotations.apply {
|
||||||
TestCase.assertEquals("expected one annotation, found ${this.joinToString(", ") { it.qualifiedName ?: "unknown" }}",
|
assertEquals(
|
||||||
number, size)
|
"expected $number annotation(s), found [${this.joinToString(", ") { it.qualifiedName ?: "unknown" }}]",
|
||||||
}
|
number, size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun configureKotlinVersion(version: String) {
|
private fun configureKotlinVersion(version: String) {
|
||||||
WriteAction.run<Throwable> {
|
WriteAction.run<Throwable> {
|
||||||
|
|||||||
Reference in New Issue
Block a user