From 07601b2ec484d5fd4089a182ac40ab222f2f9fe2 Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Wed, 22 Nov 2017 11:49:18 +0300 Subject: [PATCH] KtLightAnnotationForSourceEntry: varargs handling improved (KT-21335, EA-107118) --- .../asJava/elements/lightAnnotations.kt | 11 ++- .../kotlin/asJava/KtLightAnnotationTest.kt | 92 ++++++++++++++++++- 2 files changed, 97 insertions(+), 6 deletions(-) diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt index f10d044c1f1..96704e8d146 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt @@ -139,8 +139,14 @@ class KtLightAnnotationForSourceEntry( is VarargValueArgument -> memberValue.unwrapArray(resolvedArgument.arguments) - ?: resolvedArgument.arguments.first().asElement().parent.parent.let { - it.asKtCall() ?: it + ?: resolvedArgument.arguments.first().asElement().let { + (it as? KtValueArgument) + ?.takeIf { + it.getSpreadElement() != null || + it.getArgumentName() != null || + it.getArgumentExpression() is KtCollectionLiteralExpression + } + ?.getArgumentExpression() ?: it.parent } else -> error("resolvedArgument: ${resolvedArgument.javaClass} cant be processed") @@ -189,6 +195,7 @@ class KtLightAnnotationForSourceEntry( wrapAnnotationValue(memberValue, this, { originalExpression.let { ktOrigin -> when (ktOrigin) { + is KtValueArgumentList -> ktOrigin.arguments.getOrNull(i)?.getArgumentExpression() is KtCallElement -> ktOrigin.valueArguments.getOrNull(i)?.getArgumentExpression() is KtCollectionLiteralExpression -> ktOrigin.getInnerExpressions().getOrNull(i) else -> null diff --git a/idea/tests/org/jetbrains/kotlin/asJava/KtLightAnnotationTest.kt b/idea/tests/org/jetbrains/kotlin/asJava/KtLightAnnotationTest.kt index 8835b08849d..9e298696e09 100644 --- a/idea/tests/org/jetbrains/kotlin/asJava/KtLightAnnotationTest.kt +++ b/idea/tests/org/jetbrains/kotlin/asJava/KtLightAnnotationTest.kt @@ -267,7 +267,7 @@ class KtLightAnnotationTest : KotlinLightCodeInsightFixtureTestCase() { val annotations = myFixture.findClass("MyAnnotated").expectAnnotations(1) annotations[0].let { annotation -> val annotationAttributeVal = annotation.findAttributeValue("value") as PsiElement - assertTextAndRange("@Outer(Inner())", annotationAttributeVal) + assertTextAndRange("(Inner())", annotationAttributeVal) annotationAttributeVal as PsiArrayInitializerMemberValue annotationAttributeVal.initializers[0].let { innerAnnotationAttributeVal -> assertTextAndRange("Inner()", innerAnnotationAttributeVal) @@ -276,6 +276,90 @@ class KtLightAnnotationTest : KotlinLightCodeInsightFixtureTestCase() { } + fun testVarargWithSpread() { + myFixture.addClass(""" + public @interface Annotation { + String[] value(); + } + """.trimIndent()) + + myFixture.configureByText("AnnotatedClass.kt", """ + @Annotation(value = *arrayOf("a", "b", "c")) + 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("arrayOf(\"a\", \"b\", \"c\")", annotationAttributeVal) + for ((i, arg) in listOf("\"a\"", "\"b\"", "\"c\"").withIndex()) { + assertTextAndRange(arg, annotationAttributeVal.initializers[i]) + } + } + + fun testVarargWithSpreadComplex() { + myFixture.addClass(""" + public @interface Annotation { + String[] value(); + } + """.trimIndent()) + + myFixture.configureByText("AnnotatedClass.kt", """ + @Annotation(value = arrayOf(*arrayOf("a", "b"), "c", *arrayOf("d", "e"))) + 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("arrayOf(*arrayOf(\"a\", \"b\"), \"c\", *arrayOf(\"d\", \"e\"))", annotationAttributeVal) + for ((i, arg) in listOf("arrayOf(\"a\", \"b\")", "\"c\"", "arrayOf(\"d\", \"e\")").withIndex()) { + assertTextAndRange(arg, annotationAttributeVal.initializers[i]) + } + } + + fun testVarargWithArrayLiteral() { + myFixture.addClass(""" + public @interface Annotation { + String[] value(); + } + """.trimIndent()) + + myFixture.configureByText("AnnotatedClass.kt", """ + @Annotation(value = ["a", "b", "c"]) + 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("[\"a\", \"b\", \"c\"]", annotationAttributeVal) + for ((i, arg) in listOf("\"a\"", "\"b\"", "\"c\"").withIndex()) { + assertTextAndRange(arg, annotationAttributeVal.initializers[i]) + } + } + + fun testVarargWithArrayLiteralAndSpread() { + myFixture.addClass(""" + public @interface Annotation { + String[] value(); + } + """.trimIndent()) + + myFixture.configureByText("AnnotatedClass.kt", """ + @Annotation(*["a", "b", "c"]) + 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("[\"a\", \"b\", \"c\"]", annotationAttributeVal) + for ((i, arg) in listOf("\"a\"", "\"b\"", "\"c\"").withIndex()) { + assertTextAndRange(arg, annotationAttributeVal.initializers[i]) + } + } + fun testRepeatableAnnotationsArray() { myFixture.configureByText("RAnno.java", """ @@ -306,7 +390,7 @@ class KtLightAnnotationTest : KotlinLightCodeInsightFixtureTestCase() { } annotations[1].let { annotation -> val annotationAttributeVal = annotation.findAttributeValue("value") as PsiElement - assertTextAndRange("@RAnno(\"1\")", annotationAttributeVal) + assertTextAndRange("(\"1\")", annotationAttributeVal) annotationAttributeVal as PsiArrayInitializerMemberValue annotationAttributeVal.initializers[0].let { innerAnnotationAttributeVal -> assertTextAndRange("\"1\"", innerAnnotationAttributeVal) @@ -314,7 +398,7 @@ class KtLightAnnotationTest : KotlinLightCodeInsightFixtureTestCase() { } annotations[2].let { annotation -> val annotationAttributeVal = annotation.findAttributeValue("value") as PsiElement - assertTextAndRange("@RAnno(\"1\", \"2\")", annotationAttributeVal) + assertTextAndRange("(\"1\", \"2\")", annotationAttributeVal) annotationAttributeVal as PsiArrayInitializerMemberValue annotationAttributeVal.initializers[0].let { innerAnnotationAttributeVal -> assertTextAndRange("\"1\"", innerAnnotationAttributeVal) @@ -382,7 +466,7 @@ class KtLightAnnotationTest : KotlinLightCodeInsightFixtureTestCase() { } private fun assertTextAndRange(expected: String, psiElement: PsiElement) { - TestCase.assertEquals(expected, psiElement.text) + TestCase.assertEquals("mismatch for $psiElement of ${psiElement.javaClass}", expected, psiElement.text) TestCase.assertEquals(expected, psiElement.textRange.substring(psiElement.containingFile.text)) }