Handle generic annotations

This commit is contained in:
Chris Smowton
2022-11-09 19:07:27 +00:00
parent 14a47f628c
commit 06133e74a5
3 changed files with 34 additions and 12 deletions

View File

@@ -470,7 +470,8 @@ open class KotlinFileExtractor(
idx: Int, idx: Int,
contextLabel: String? = null contextLabel: String? = null
): Label<out DbExpr> { ): Label<out DbExpr> {
val t = useType(constructorCall.type) // Erase the type here because the JVM lowering erases the annotation type, and so the Java extractor will see it in erased form.
val t = useType(erase(constructorCall.type))
val annotationContextLabel = contextLabel ?: "{${t.javaResult.id}}" val annotationContextLabel = contextLabel ?: "{${t.javaResult.id}}"
val id = tw.getLabelFor<DbDeclannotation>("@\"annotation;{$parent};$annotationContextLabel\"") val id = tw.getLabelFor<DbDeclannotation>("@\"annotation;{$parent};$annotationContextLabel\"")
tw.writeExprs_declannotation(id, t.javaResult.id, parent, idx) tw.writeExprs_declannotation(id, t.javaResult.id, parent, idx)
@@ -485,8 +486,9 @@ open class KotlinFileExtractor(
.filterIsInstance<IrProperty>() .filterIsInstance<IrProperty>()
.first { it.name == param.name } .first { it.name == param.name }
val v = constructorCall.getValueArgument(i) ?: param.defaultValue?.expression val v = constructorCall.getValueArgument(i) ?: param.defaultValue?.expression
val getterId = useFunction<DbMethod>(prop.getter!!) val getter = prop.getter!!
val exprId = extractAnnotationValueExpression(v, id, i, "{${getterId}}") val getterId = useFunction<DbMethod>(getter)
val exprId = extractAnnotationValueExpression(v, id, i, "{${getterId}}", getter.returnType)
if (exprId != null) { if (exprId != null) {
tw.writeAnnotValue(id, getterId, exprId) tw.writeAnnotValue(id, getterId, exprId)
} }
@@ -498,7 +500,8 @@ open class KotlinFileExtractor(
v: IrExpression?, v: IrExpression?,
parent: Label<out DbExprparent>, parent: Label<out DbExprparent>,
idx: Int, idx: Int,
contextLabel: String): Label<out DbExpr>? { contextLabel: String,
contextType: IrType?): Label<out DbExpr>? {
fun exprId() = tw.getLabelFor<DbExpr>("@\"annotationExpr;{$parent};$idx\"") fun exprId() = tw.getLabelFor<DbExpr>("@\"annotationExpr;{$parent};$idx\"")
@@ -519,7 +522,10 @@ open class KotlinFileExtractor(
} }
is IrVararg -> { is IrVararg -> {
tw.getLabelFor<DbArrayinit>("@\"annotationarray;{${parent}};$contextLabel\"").also { arrayId -> tw.getLabelFor<DbArrayinit>("@\"annotationarray;{${parent}};$contextLabel\"").also { arrayId ->
val type = useType(kClassToJavaClass(v.type)) // Use the context type (i.e., the type the annotation expects, not the actual type of the array)
// because the Java extractor fills in array types using the same technique. These should only
// differ for generic annotations.
val type = useType(kClassToJavaClass(contextType!!))
tw.writeExprs_arrayinit(arrayId, type.javaResult.id, parent, idx) tw.writeExprs_arrayinit(arrayId, type.javaResult.id, parent, idx)
tw.writeExprsKotlinType(arrayId, type.kotlinResult.id) tw.writeExprsKotlinType(arrayId, type.kotlinResult.id)
tw.writeHasLocation(arrayId, tw.getLocation(v)) tw.writeHasLocation(arrayId, tw.getLocation(v))
@@ -533,7 +539,7 @@ open class KotlinFileExtractor(
null null
} }
} }
extractAnnotationValueExpression(argExpr, arrayId, index, "child;$index") extractAnnotationValueExpression(argExpr, arrayId, index, "child;$index", null)
} } } }
} }
} }

View File

@@ -31,9 +31,14 @@ test.kt:
# 5| 5: [Method] t # 5| 5: [Method] t
# 7| 3: [Interface] Ann3 # 7| 3: [Interface] Ann3
# 7| 1: [Method] a # 7| 1: [Method] a
# 9| 4: [Class] Annotated # 9| 4: [GenericType,Interface,ParameterizedType] GenericAnnotation
#-----| -2: (Generic Parameters)
# 9| 0: [TypeVariable] T
# 9| 1: [Method] x
# 9| 2: [Method] y
# 11| 6: [Class] Annotated
#-----| -3: (Annotations) #-----| -3: (Annotations)
# 9| 2: [Annotation] Ann1 # 11| 2: [Annotation] Ann1
# 0| 1: [IntegerLiteral] 1 # 0| 1: [IntegerLiteral] 1
# 0| 1: [Annotation] Ann2 # 0| 1: [Annotation] Ann2
# 0| 1: [StringLiteral] "Hello" # 0| 1: [StringLiteral] "Hello"
@@ -53,7 +58,15 @@ test.kt:
# 0| 0: [TypeAccess] String # 0| 0: [TypeAccess] String
# 0| 1: [TypeLiteral] int.class # 0| 1: [TypeLiteral] int.class
# 0| 0: [TypeAccess] int # 0| 0: [TypeAccess] int
# 10| 1: [Constructor] Annotated # 12| 3: [Annotation] GenericAnnotation<>
# 9| 5: [BlockStmt] { ... } # 13| 1: [Constructor] Annotated
# 9| 0: [SuperConstructorInvocationStmt] super(...) # 11| 5: [BlockStmt] { ... }
# 10| 1: [BlockStmt] { ... } # 11| 0: [SuperConstructorInvocationStmt] super(...)
# 13| 1: [BlockStmt] { ... }
# 0| [TypeLiteral] String.class
# 0| 0: [TypeAccess] String
# 0| [ArrayInit] {...}
# 0| 1: [TypeLiteral] String.class
# 0| 0: [TypeAccess] String
# 0| 1: [TypeLiteral] String.class
# 0| 0: [TypeAccess] String

View File

@@ -6,5 +6,8 @@ annotation class Ann2(val z: String, val w: KClass<*>, val v: IntArray, val u: A
annotation class Ann3(val a: Int) { } annotation class Ann3(val a: Int) { }
annotation class GenericAnnotation<T : Any>(val x: KClass<T>, val y: Array<KClass<T>>) { }
@Ann1(1, Ann2("Hello", String::class, intArrayOf(1, 2, 3), arrayOf(Ann3(1), Ann3(2)), arrayOf(String::class, Int::class))) @Ann1(1, Ann2("Hello", String::class, intArrayOf(1, 2, 3), arrayOf(Ann3(1), Ann3(2)), arrayOf(String::class, Int::class)))
@GenericAnnotation<String>(String::class, arrayOf(String::class, String::class))
class Annotated { } class Annotated { }