Uast: property resolve arrayOf in nested annotations (KT-29434)
This commit is contained in:
committed by
xiexed
parent
4ffeff5e6c
commit
a3ea7bcd3b
+7
-2
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
@@ -204,8 +205,12 @@ class KotlinUFunctionCallExpression(
|
||||
|
||||
private fun isAnnotationArgumentArrayInitializer(): Boolean {
|
||||
val resolvedCall = resolvedCall ?: return false
|
||||
// KtAnnotationEntry -> KtValueArgumentList -> KtValueArgument -> arrayOf call
|
||||
return psi.parents.elementAtOrNull(2) is KtAnnotationEntry && CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall)
|
||||
// KtAnnotationEntry (or KtCallExpression when annotation is nested) -> KtValueArgumentList -> KtValueArgument -> arrayOf call
|
||||
return when (val elementAt2 = psi.parents.elementAtOrNull(2)) {
|
||||
is KtAnnotationEntry -> true
|
||||
is KtCallExpression -> elementAt2.getParentOfType<KtAnnotationEntry>(true, KtDeclaration::class.java) != null
|
||||
else -> false
|
||||
} && CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall)
|
||||
}
|
||||
|
||||
override fun convertParent(): UElement? = super.convertParent().let { result ->
|
||||
|
||||
+7
-2
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
@@ -148,8 +149,12 @@ class KotlinUFunctionCallExpression(
|
||||
|
||||
private fun isAnnotationArgumentArrayInitializer(): Boolean {
|
||||
val resolvedCall = resolvedCall ?: return false
|
||||
// KtAnnotationEntry -> KtValueArgumentList -> KtValueArgument -> arrayOf call
|
||||
return psi.parents.elementAtOrNull(2) is KtAnnotationEntry && CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall)
|
||||
// KtAnnotationEntry (or KtCallExpression when annotation is nested) -> KtValueArgumentList -> KtValueArgument -> arrayOf call
|
||||
return when (val elementAt2 = psi.parents.elementAtOrNull(2)) {
|
||||
is KtAnnotationEntry -> true
|
||||
is KtCallExpression -> elementAt2.getParentOfType<KtAnnotationEntry>(true, KtDeclaration::class.java) != null
|
||||
else -> false
|
||||
} && CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall)
|
||||
}
|
||||
|
||||
override fun convertParent(): UElement? = super.convertParent().let { result ->
|
||||
|
||||
+7
-4
@@ -1,4 +1,4 @@
|
||||
annotation class Annotation
|
||||
annotation class Annotation(vararg val strings: String)
|
||||
|
||||
@Annotation
|
||||
class A
|
||||
@@ -8,10 +8,13 @@ annotation class AnnotationInner(val value: Annotation)
|
||||
@AnnotationArray(Annotation())
|
||||
class B1
|
||||
|
||||
@AnnotationArray(value = Annotation())
|
||||
@AnnotationArray(value = Annotation("sv1", "sv2"))
|
||||
class B2
|
||||
|
||||
annotation class AnnotationArray(vararg val value: Annotation)
|
||||
|
||||
@AnnotationArray(Annotation())
|
||||
class C
|
||||
@AnnotationArray(Annotation(strings = arrayOf("sar1", "sar2")))
|
||||
class C
|
||||
|
||||
@AnnotationArray(Annotation(strings = ["[sar]1", "[sar]2"]))
|
||||
class C2
|
||||
+21
-2
@@ -1,5 +1,6 @@
|
||||
UFile (package = )
|
||||
UClass (name = Annotation)
|
||||
UAnnotationMethod (name = strings)
|
||||
UClass (name = A)
|
||||
UAnnotation (fqName = Annotation)
|
||||
UAnnotationMethod (name = A)
|
||||
@@ -15,16 +16,34 @@ UFile (package = )
|
||||
UClass (name = B2)
|
||||
UAnnotation (fqName = AnnotationArray)
|
||||
UNamedExpression (name = value)
|
||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))
|
||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 2))
|
||||
UIdentifier (Identifier (Annotation))
|
||||
USimpleNameReferenceExpression (identifier = <init>)
|
||||
ULiteralExpression (value = "sv1")
|
||||
ULiteralExpression (value = "sv2")
|
||||
UAnnotationMethod (name = B2)
|
||||
UClass (name = AnnotationArray)
|
||||
UAnnotationMethod (name = value)
|
||||
UClass (name = C)
|
||||
UAnnotation (fqName = AnnotationArray)
|
||||
UNamedExpression (name = value)
|
||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))
|
||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
|
||||
UIdentifier (Identifier (Annotation))
|
||||
USimpleNameReferenceExpression (identifier = <init>)
|
||||
UCallExpression (kind = UastCallKind(name='array_initializer'), argCount = 2))
|
||||
UIdentifier (Identifier (arrayOf))
|
||||
USimpleNameReferenceExpression (identifier = arrayOf)
|
||||
ULiteralExpression (value = "sar1")
|
||||
ULiteralExpression (value = "sar2")
|
||||
UAnnotationMethod (name = C)
|
||||
UClass (name = C2)
|
||||
UAnnotation (fqName = AnnotationArray)
|
||||
UNamedExpression (name = value)
|
||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
|
||||
UIdentifier (Identifier (Annotation))
|
||||
USimpleNameReferenceExpression (identifier = <init>)
|
||||
UCallExpression (kind = UastCallKind(name='array_initializer'), argCount = 2))
|
||||
UIdentifier (Identifier ([))
|
||||
ULiteralExpression (value = "[sar]1")
|
||||
ULiteralExpression (value = "[sar]2")
|
||||
UAnnotationMethod (name = C2)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
public abstract annotation Annotation {
|
||||
public abstract fun strings() : java.lang.String[] = UastEmptyExpression
|
||||
}
|
||||
|
||||
public final class A {
|
||||
@@ -24,3 +25,7 @@ public abstract annotation AnnotationArray {
|
||||
public final class C {
|
||||
public fun C() = UastEmptyExpression
|
||||
}
|
||||
|
||||
public final class C2 {
|
||||
public fun C2() = UastEmptyExpression
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.jetbrains.uast.test.env.kotlin.findElementByTextFromPsi
|
||||
import org.jetbrains.uast.visitor.AbstractUastVisitor
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import kotlin.test.fail as kfail
|
||||
|
||||
|
||||
class KotlinUastApiTest : AbstractKotlinUastTest() {
|
||||
@@ -297,8 +298,8 @@ class KotlinUastApiTest : AbstractKotlinUastTest() {
|
||||
|
||||
@Test
|
||||
fun testNestedAnnotation() = doTest("AnnotationComplex") { _, file ->
|
||||
file.findElementByTextFromPsi<UElement>("@AnnotationArray(value = Annotation())")
|
||||
.findElementByTextFromPsi<UElement>("Annotation()")
|
||||
file.findElementByTextFromPsi<UElement>("@AnnotationArray(value = Annotation(\"sv1\", \"sv2\"))")
|
||||
.findElementByTextFromPsi<UElement>("Annotation(\"sv1\", \"sv2\")")
|
||||
.sourcePsiElement
|
||||
.let { referenceExpression ->
|
||||
val convertedUAnnotation = referenceExpression
|
||||
@@ -315,6 +316,44 @@ class KotlinUastApiTest : AbstractKotlinUastTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNestedAnnotationParameters() = doTest("AnnotationComplex") { _, file ->
|
||||
|
||||
fun UFile.annotationAndParam(refText: String, check: (PsiAnnotation, String?) -> Unit) {
|
||||
findElementByTextFromPsi<UElement>(refText)
|
||||
.let { expression ->
|
||||
val (annotation: PsiAnnotation, paramname: String?) =
|
||||
getContainingAnnotationEntry(expression) ?: kfail("annotation not found for '$refText' ($expression)")
|
||||
check(annotation, paramname)
|
||||
}
|
||||
}
|
||||
|
||||
file.annotationAndParam("sv1") { annotation, paramname ->
|
||||
assertEquals("Annotation", annotation.qualifiedName)
|
||||
assertEquals(null, paramname)
|
||||
}
|
||||
file.annotationAndParam("sv2") { annotation, paramname ->
|
||||
assertEquals("Annotation", annotation.qualifiedName)
|
||||
assertEquals(null, paramname)
|
||||
}
|
||||
file.annotationAndParam("sar1") { annotation, paramname ->
|
||||
assertEquals("Annotation", annotation.qualifiedName)
|
||||
assertEquals("strings", paramname)
|
||||
}
|
||||
file.annotationAndParam("sar2") { annotation, paramname ->
|
||||
assertEquals("Annotation", annotation.qualifiedName)
|
||||
assertEquals("strings", paramname)
|
||||
}
|
||||
file.annotationAndParam("[sar]1") { annotation, paramname ->
|
||||
assertEquals("Annotation", annotation.qualifiedName)
|
||||
assertEquals("strings", paramname)
|
||||
}
|
||||
file.annotationAndParam("[sar]2") { annotation, paramname ->
|
||||
assertEquals("Annotation", annotation.qualifiedName)
|
||||
assertEquals("strings", paramname)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testParametersDisorder() = doTest("ParametersDisorder") { _, file ->
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.jetbrains.uast.test.env.kotlin.findElementByTextFromPsi
|
||||
import org.jetbrains.uast.visitor.AbstractUastVisitor
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import kotlin.test.fail as kfail
|
||||
|
||||
|
||||
class KotlinUastApiTest : AbstractKotlinUastTest() {
|
||||
@@ -297,8 +298,8 @@ class KotlinUastApiTest : AbstractKotlinUastTest() {
|
||||
|
||||
@Test
|
||||
fun testNestedAnnotation() = doTest("AnnotationComplex") { _, file ->
|
||||
file.findElementByTextFromPsi<UElement>("@AnnotationArray(value = Annotation())")
|
||||
.findElementByTextFromPsi<UElement>("Annotation()")
|
||||
file.findElementByTextFromPsi<UElement>("@AnnotationArray(value = Annotation(\"sv1\", \"sv2\"))")
|
||||
.findElementByTextFromPsi<UElement>("Annotation(\"sv1\", \"sv2\")")
|
||||
.sourcePsiElement
|
||||
.let { referenceExpression ->
|
||||
val convertedUAnnotation = referenceExpression
|
||||
@@ -315,6 +316,44 @@ class KotlinUastApiTest : AbstractKotlinUastTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNestedAnnotationParameters() = doTest("AnnotationComplex") { _, file ->
|
||||
|
||||
fun UFile.annotationAndParam(refText: String, check: (PsiAnnotation, String?) -> Unit) {
|
||||
findElementByTextFromPsi<UElement>(refText)
|
||||
.let { expression ->
|
||||
val (annotation: PsiAnnotation, paramname: String?) =
|
||||
getContainingAnnotationEntry(expression) ?: kfail("annotation not found for '$refText' ($expression)")
|
||||
check(annotation, paramname)
|
||||
}
|
||||
}
|
||||
|
||||
file.annotationAndParam("sv1") { annotation, paramname ->
|
||||
assertEquals("Annotation", annotation.qualifiedName)
|
||||
assertEquals(null, paramname)
|
||||
}
|
||||
file.annotationAndParam("sv2") { annotation, paramname ->
|
||||
assertEquals("Annotation", annotation.qualifiedName)
|
||||
assertEquals(null, paramname)
|
||||
}
|
||||
file.annotationAndParam("sar1") { annotation, paramname ->
|
||||
assertEquals("Annotation", annotation.qualifiedName)
|
||||
assertEquals("strings", paramname)
|
||||
}
|
||||
file.annotationAndParam("sar2") { annotation, paramname ->
|
||||
assertEquals("Annotation", annotation.qualifiedName)
|
||||
assertEquals("strings", paramname)
|
||||
}
|
||||
file.annotationAndParam("[sar]1") { annotation, paramname ->
|
||||
assertEquals("Annotation", annotation.qualifiedName)
|
||||
assertEquals("strings", paramname)
|
||||
}
|
||||
file.annotationAndParam("[sar]2") { annotation, paramname ->
|
||||
assertEquals("Annotation", annotation.qualifiedName)
|
||||
assertEquals("strings", paramname)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testParametersDisorder() = doTest("ParametersDisorder") { _, file ->
|
||||
|
||||
Reference in New Issue
Block a user