KtLightAnnotationForSourceEntry: varargs handling improved (KT-21335, EA-107118)

This commit is contained in:
Nicolay Mitropolsky
2017-11-22 11:49:18 +03:00
committed by xiexed
parent 23344783a5
commit 07601b2ec4
2 changed files with 97 additions and 6 deletions
@@ -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
@@ -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))
}