@@ -459,19 +459,20 @@ open class KotlinFileExtractor(
459459 }
460460
461461 private fun extractAnnotations (c : IrAnnotationContainer , parent : Label <out DbExprparent >) {
462- for ((idx, constructorCall: IrConstructorCall ) in c.annotations.withIndex()) {
463- extractAnnotation(constructorCall, parent, - 1 - idx)
462+ for ((idx, constructorCall: IrConstructorCall ) in c.annotations.sortedBy { v -> v.type.classFqName?.asString() }. withIndex()) {
463+ extractAnnotation(constructorCall, parent, idx)
464464 }
465465 }
466466
467467 private fun extractAnnotation (
468468 constructorCall : IrConstructorCall ,
469469 parent : Label <out DbExprparent >,
470- idx : Int
470+ idx : Int ,
471+ contextLabel : String? = null
471472 ): Label <out DbExpr > {
472473 val t = useType(constructorCall.type)
473-
474- val id = tw.getLabelFor<DbDeclannotation >(" @\" annotation_kotlin ;{$parent };{ ${t.javaResult.id} } \" " )
474+ val annotationContextLabel = contextLabel ? : " { ${t.javaResult.id} } "
475+ val id = tw.getLabelFor<DbDeclannotation >(" @\" annotation ;{$parent };$annotationContextLabel \" " )
475476 tw.writeExprs_declannotation(id, t.javaResult.id, parent, idx)
476477 tw.writeExprsKotlinType(id, t.kotlinResult.id)
477478
@@ -484,9 +485,10 @@ open class KotlinFileExtractor(
484485 .filterIsInstance<IrProperty >()
485486 .first { it.name == param.name }
486487 val v = constructorCall.getValueArgument(i) ? : param.defaultValue?.expression
487- val exprId = extractAnnotationValueExpression(v, id, i)
488+ val getterId = useFunction<DbMethod >(prop.getter!! )
489+ val exprId = extractAnnotationValueExpression(v, id, i, " {${getterId} }" )
488490 if (exprId != null ) {
489- tw.writeAnnotValue(id, useFunction(prop.getter !! ) , exprId)
491+ tw.writeAnnotValue(id, getterId , exprId)
490492 }
491493 }
492494 return id
@@ -495,41 +497,45 @@ open class KotlinFileExtractor(
495497 private fun extractAnnotationValueExpression (
496498 v : IrExpression ? ,
497499 parent : Label <out DbExprparent >,
498- idx : Int ): Label <out DbExpr >? {
500+ idx : Int ,
501+ contextLabel : String ): Label <out DbExpr >? {
502+
503+ fun exprId () = tw.getLabelFor<DbExpr >(" @\" annotationExpr;{$parent };$idx \" " )
499504
500505 return when (v) {
501506 is IrConst <* > -> {
502- extractConstant(v, parent, idx, null , null )
507+ extractConstant(v, parent, idx, null , null , overrideId = exprId() )
503508 }
504509 is IrGetEnumValue -> {
505- extractEnumValue(v, parent, idx, null , null )
510+ extractEnumValue(v, parent, idx, null , null , overrideId = exprId() )
506511 }
507512 is IrClassReference -> {
508- extractClassReference(v, parent, idx, null , null )
513+ val classRefId = exprId()
514+ val typeAccessId = tw.getLabelFor<DbUnannotatedtypeaccess >(" @\" annotationExpr;{$classRefId };0\" " )
515+ extractClassReference(v, parent, idx, null , null , overrideId = classRefId, typeAccessOverrideId = typeAccessId, useUnboundType = true )
509516 }
510517 is IrConstructorCall -> {
511- extractAnnotation(v, parent, idx)
518+ extractAnnotation(v, parent, idx, contextLabel )
512519 }
513520 is IrVararg -> {
514- val eId = tw.getFreshIdLabel<DbArrayinit >()
515- val type = useType(v.type)
516- tw.writeExprs_arrayinit(eId, type.javaResult.id, parent, idx)
517- tw.writeExprsKotlinType(eId, type.kotlinResult.id)
518- tw.writeHasLocation(eId, tw.getLocation(v))
519-
520- v.elements.forEachIndexed { index, irVarargElement -> run {
521- val argExpr = when (irVarargElement) {
522- is IrExpression -> irVarargElement
523- is IrSpreadElement -> irVarargElement.expression
524- else -> {
525- logger.errorElement(" Unrecognised IrVarargElement: " + irVarargElement.javaClass, irVarargElement)
526- null
521+ tw.getLabelFor<DbArrayinit >(" @\" annotationarray;{${parent} };$contextLabel \" " ).also { arrayId ->
522+ val type = useType(v.type)
523+ tw.writeExprs_arrayinit(arrayId, type.javaResult.id, parent, idx)
524+ tw.writeExprsKotlinType(arrayId, type.kotlinResult.id)
525+ tw.writeHasLocation(arrayId, tw.getLocation(v))
526+
527+ v.elements.forEachIndexed { index, irVarargElement -> run {
528+ val argExpr = when (irVarargElement) {
529+ is IrExpression -> irVarargElement
530+ is IrSpreadElement -> irVarargElement.expression
531+ else -> {
532+ logger.errorElement(" Unrecognised IrVarargElement: " + irVarargElement.javaClass, irVarargElement)
533+ null
534+ }
527535 }
528- }
529- extractAnnotationValueExpression(argExpr, eId, index)
530- } }
531-
532- eId
536+ extractAnnotationValueExpression(argExpr, arrayId, index, " child;$index " )
537+ } }
538+ }
533539 }
534540 // is IrErrorExpression
535541 // null
@@ -3525,17 +3531,17 @@ open class KotlinFileExtractor(
35253531 extractExprContext(it, locId, callable, enclosingStmt)
35263532 }
35273533
3528- private fun extractConstantInteger (v : Number , locId : Label <DbLocation >, parent : Label <out DbExprparent >, idx : Int , callable : Label <out DbCallable >? , enclosingStmt : Label <out DbStmt >? ) =
3529- tw.getFreshIdLabel <DbIntegerliteral >().also {
3534+ private fun extractConstantInteger (v : Number , locId : Label <DbLocation >, parent : Label <out DbExprparent >, idx : Int , callable : Label <out DbCallable >? , enclosingStmt : Label <out DbStmt >? , overrideId : Label < out DbExpr > ? = null ) =
3535+ exprIdOrFresh <DbIntegerliteral >(overrideId ).also {
35303536 val type = useType(pluginContext.irBuiltIns.intType)
35313537 tw.writeExprs_integerliteral(it, type.javaResult.id, parent, idx)
35323538 tw.writeExprsKotlinType(it, type.kotlinResult.id)
35333539 tw.writeNamestrings(v.toString(), v.toString(), it)
35343540 extractExprContext(it, locId, callable, enclosingStmt)
35353541 }
35363542
3537- private fun extractNull (t : IrType , locId : Label <DbLocation >, parent : Label <out DbExprparent >, idx : Int , callable : Label <out DbCallable >? , enclosingStmt : Label <out DbStmt >? ) =
3538- tw.getFreshIdLabel <DbNullliteral >().also {
3543+ private fun extractNull (t : IrType , locId : Label <DbLocation >, parent : Label <out DbExprparent >, idx : Int , callable : Label <out DbCallable >? , enclosingStmt : Label <out DbStmt >? , overrideId : Label < out DbExpr > ? = null ) =
3544+ exprIdOrFresh <DbNullliteral >(overrideId ).also {
35393545 val type = useType(t)
35403546 tw.writeExprs_nullliteral(it, type.javaResult.id, parent, idx)
35413547 tw.writeExprsKotlinType(it, type.kotlinResult.id)
@@ -3550,16 +3556,6 @@ open class KotlinFileExtractor(
35503556 extractExprContext(it, locId, callable, enclosingStmt)
35513557 }
35523558
3553- private fun escapeCharForQuotedLiteral (c : Char ) =
3554- when (c) {
3555- ' \r ' -> " \\ r"
3556- ' \n ' -> " \\ n"
3557- ' \t ' -> " \\ t"
3558- ' \\ ' -> " \\\\ "
3559- ' "' -> " \\\" "
3560- else -> c.toString()
3561- }
3562-
35633559 private fun extractExpression (e : IrExpression , callable : Label <out DbCallable >, parent : StmtExprParent ) {
35643560 with (" expression" , e) {
35653561 when (e) {
@@ -4182,31 +4178,44 @@ open class KotlinFileExtractor(
41824178 extractExpressionExpr(loop.condition, callable, id, 0 , id)
41834179 }
41844180
4181+ @Suppress(" UNCHECKED_CAST" )
4182+ private fun <T : DbExpr > exprIdOrFresh (id : Label <out DbExpr >? ) = id as ? Label <T > ? : tw.getFreshIdLabel()
4183+
4184+ private fun toUnbound (t : IrType ) =
4185+ when (t) {
4186+ is IrSimpleType -> t.classifier.typeWith()
4187+ else -> t
4188+ }
4189+
41854190 private fun extractClassReference (
41864191 e : IrClassReference ,
41874192 parent : Label <out DbExprparent >,
41884193 idx : Int ,
41894194 enclosingCallable : Label <out DbCallable >? ,
4190- enclosingStmt : Label <out DbStmt >?
4195+ enclosingStmt : Label <out DbStmt >? ,
4196+ overrideId : Label <out DbExpr >? = null,
4197+ typeAccessOverrideId : Label <out DbExpr >? = null,
4198+ useUnboundType : Boolean = false
41914199 ) =
4192- tw.getFreshIdLabel <DbTypeliteral >().also { id ->
4200+ exprIdOrFresh <DbTypeliteral >(overrideId ).also { id ->
41934201 val locId = tw.getLocation(e)
4194- val type = useType(e.type)
4202+ val type = useType(if (useUnboundType) toUnbound(e.type) else e.type)
41954203 tw.writeExprs_typeliteral(id, type.javaResult.id, parent, idx)
41964204 tw.writeExprsKotlinType(id, type.kotlinResult.id)
41974205 extractExprContext(id, locId, enclosingCallable, enclosingStmt)
41984206
4199- extractTypeAccessRecursive(e.classType, locId, id, 0 , enclosingCallable, enclosingStmt)
4207+ extractTypeAccessRecursive(e.classType, locId, id, 0 , enclosingCallable, enclosingStmt, overrideId = typeAccessOverrideId )
42004208 }
42014209
42024210 private fun extractEnumValue (
42034211 e : IrGetEnumValue ,
42044212 parent : Label <out DbExprparent >,
42054213 idx : Int ,
42064214 enclosingCallable : Label <out DbCallable >? ,
4207- enclosingStmt : Label <out DbStmt >?
4215+ enclosingStmt : Label <out DbStmt >? ,
4216+ overrideId : Label <out DbExpr >? = null
42084217 ) =
4209- tw.getFreshIdLabel <DbVaraccess >().also { id ->
4218+ exprIdOrFresh <DbVaraccess >(overrideId ).also { id ->
42104219 val type = useType(e.type)
42114220 val locId = tw.getLocation(e)
42124221 tw.writeExprs_varaccess(id, type.javaResult.id, parent, idx)
@@ -4223,6 +4232,16 @@ open class KotlinFileExtractor(
42234232 }
42244233 }
42254234
4235+ private fun escapeCharForQuotedLiteral (c : Char ) =
4236+ when (c) {
4237+ ' \r ' -> " \\ r"
4238+ ' \n ' -> " \\ n"
4239+ ' \t ' -> " \\ t"
4240+ ' \\ ' -> " \\\\ "
4241+ ' "' -> " \\\" "
4242+ else -> c.toString()
4243+ }
4244+
42264245 // Render a string literal as it might occur in Kotlin source. Note this is a reasonable guess; the real source
42274246 // could use other escape sequences to describe the same String. Importantly, this is the same guess the Java
42284247 // extractor makes regarding string literals occurring within annotations, which we need to coincide with to ensure
@@ -4235,15 +4254,17 @@ open class KotlinFileExtractor(
42354254 parent : Label <out DbExprparent >,
42364255 idx : Int ,
42374256 enclosingCallable : Label <out DbCallable >? ,
4238- enclosingStmt : Label <out DbStmt >?
4257+ enclosingStmt : Label <out DbStmt >? ,
4258+ overrideId : Label <out DbExpr >? = null
42394259 ): Label <out DbExpr >? {
4260+
42404261 val v = e.value
42414262 return when {
42424263 v is Number && (v is Int || v is Short || v is Byte ) -> {
4243- extractConstantInteger(v, tw.getLocation(e), parent, idx, enclosingCallable, enclosingStmt)
4264+ extractConstantInteger(v, tw.getLocation(e), parent, idx, enclosingCallable, enclosingStmt, overrideId = overrideId )
42444265 }
42454266 v is Long -> {
4246- tw.getFreshIdLabel <DbLongliteral >().also { id ->
4267+ exprIdOrFresh <DbLongliteral >(overrideId ).also { id ->
42474268 val type = useType(e.type)
42484269 val locId = tw.getLocation(e)
42494270 tw.writeExprs_longliteral(id, type.javaResult.id, parent, idx)
@@ -4253,7 +4274,7 @@ open class KotlinFileExtractor(
42534274 }
42544275 }
42554276 v is Float -> {
4256- tw.getFreshIdLabel <DbFloatingpointliteral >().also { id ->
4277+ exprIdOrFresh <DbFloatingpointliteral >(overrideId ).also { id ->
42574278 val type = useType(e.type)
42584279 val locId = tw.getLocation(e)
42594280 tw.writeExprs_floatingpointliteral(id, type.javaResult.id, parent, idx)
@@ -4263,7 +4284,7 @@ open class KotlinFileExtractor(
42634284 }
42644285 }
42654286 v is Double -> {
4266- tw.getFreshIdLabel <DbDoubleliteral >().also { id ->
4287+ exprIdOrFresh <DbDoubleliteral >(overrideId ).also { id ->
42674288 val type = useType(e.type)
42684289 val locId = tw.getLocation(e)
42694290 tw.writeExprs_doubleliteral(id, type.javaResult.id, parent, idx)
@@ -4273,7 +4294,7 @@ open class KotlinFileExtractor(
42734294 }
42744295 }
42754296 v is Boolean -> {
4276- tw.getFreshIdLabel <DbBooleanliteral >().also { id ->
4297+ exprIdOrFresh <DbBooleanliteral >(overrideId ).also { id ->
42774298 val type = useType(e.type)
42784299 val locId = tw.getLocation(e)
42794300 tw.writeExprs_booleanliteral(id, type.javaResult.id, parent, idx)
@@ -4283,7 +4304,7 @@ open class KotlinFileExtractor(
42834304 }
42844305 }
42854306 v is Char -> {
4286- tw.getFreshIdLabel <DbCharacterliteral >().also { id ->
4307+ exprIdOrFresh <DbCharacterliteral >(overrideId ).also { id ->
42874308 val type = useType(e.type)
42884309 val locId = tw.getLocation(e)
42894310 tw.writeExprs_characterliteral(id, type.javaResult.id, parent, idx)
@@ -4293,7 +4314,7 @@ open class KotlinFileExtractor(
42934314 }
42944315 }
42954316 v is String -> {
4296- tw.getFreshIdLabel <DbStringliteral >().also { id ->
4317+ exprIdOrFresh <DbStringliteral >(overrideId ).also { id ->
42974318 val type = useType(e.type)
42984319 val locId = tw.getLocation(e)
42994320 tw.writeExprs_stringliteral(id, type.javaResult.id, parent, idx)
@@ -4303,7 +4324,7 @@ open class KotlinFileExtractor(
43034324 }
43044325 }
43054326 v == null -> {
4306- extractNull(e.type, tw.getLocation(e), parent, idx, enclosingCallable, enclosingStmt)
4327+ extractNull(e.type, tw.getLocation(e), parent, idx, enclosingCallable, enclosingStmt, overrideId = overrideId )
43074328 }
43084329 else -> {
43094330 null .also {
@@ -5157,11 +5178,11 @@ open class KotlinFileExtractor(
51575178 /* *
51585179 * Extracts a single type access expression with no enclosing callable and statement.
51595180 */
5160- private fun extractTypeAccess (type : TypeResults , location : Label <out DbLocation >, parent : Label <out DbExprparent >, idx : Int ): Label <out DbExpr > {
5181+ private fun extractTypeAccess (type : TypeResults , location : Label <out DbLocation >, parent : Label <out DbExprparent >, idx : Int , overrideId : Label < out DbExpr > ? = null ): Label <out DbExpr > {
51615182 // TODO: elementForLocation allows us to give some sort of
51625183 // location, but a proper location for the type access will
51635184 // require upstream changes
5164- val id = tw.getFreshIdLabel <DbUnannotatedtypeaccess >()
5185+ val id = exprIdOrFresh <DbUnannotatedtypeaccess >(overrideId )
51655186 tw.writeExprs_unannotatedtypeaccess(id, type.javaResult.id, parent, idx)
51665187 tw.writeExprsKotlinType(id, type.kotlinResult.id)
51675188 tw.writeHasLocation(id, location)
@@ -5171,8 +5192,8 @@ open class KotlinFileExtractor(
51715192 /* *
51725193 * Extracts a single type access expression with enclosing callable and statement.
51735194 */
5174- private fun extractTypeAccess (type : TypeResults , location : Label <DbLocation >, parent : Label <out DbExprparent >, idx : Int , enclosingCallable : Label <out DbCallable >? , enclosingStmt : Label <out DbStmt >? ): Label <out DbExpr > {
5175- val id = extractTypeAccess(type, location, parent, idx)
5195+ private fun extractTypeAccess (type : TypeResults , location : Label <DbLocation >, parent : Label <out DbExprparent >, idx : Int , enclosingCallable : Label <out DbCallable >? , enclosingStmt : Label <out DbStmt >? , overrideId : Label < out DbExpr > ? = null ): Label <out DbExpr > {
5196+ val id = extractTypeAccess(type, location, parent, idx, overrideId = overrideId )
51765197 if (enclosingCallable != null ) {
51775198 tw.writeCallableEnclosingExpr(id, enclosingCallable)
51785199 }
@@ -5220,11 +5241,14 @@ open class KotlinFileExtractor(
52205241 /* *
52215242 * Extracts a type access expression and its child type access expressions in case of a generic type. Nested generics are also handled.
52225243 */
5223- private fun extractTypeAccessRecursive (t : IrType , location : Label <DbLocation >, parent : Label <out DbExprparent >, idx : Int , enclosingCallable : Label <out DbCallable >? , enclosingStmt : Label <out DbStmt >? , typeContext : TypeContext = TypeContext .OTHER ): Label <out DbExpr > {
5244+ private fun extractTypeAccessRecursive (t : IrType , location : Label <DbLocation >, parent : Label <out DbExprparent >, idx : Int , enclosingCallable : Label <out DbCallable >? , enclosingStmt : Label <out DbStmt >? , typeContext : TypeContext = TypeContext .OTHER , overrideId : Label < out DbExpr > ? = null ): Label <out DbExpr > {
52245245 // TODO: `useType` substitutes types to their java equivalent, and sometimes that also means changing the number of type arguments. The below logic doesn't take this into account.
52255246 // For example `KFunction2<Int,Double,String>` becomes `KFunction<String>` with three child type access expressions: `Int`, `Double`, `String`.
5226- val typeAccessId = extractTypeAccess(useType(t, typeContext), location, parent, idx, enclosingCallable, enclosingStmt)
5247+ val typeAccessId = extractTypeAccess(useType(t, typeContext), location, parent, idx, enclosingCallable, enclosingStmt, overrideId = overrideId )
52275248 if (t is IrSimpleType ) {
5249+ if (t.arguments.isNotEmpty() && overrideId != null ) {
5250+ logger.error(" Unexpected parameterized type with an overridden expression ID; children will be assigned fresh IDs" )
5251+ }
52285252 extractTypeArguments(t.arguments.filterIsInstance<IrType >(), location, typeAccessId, enclosingCallable, enclosingStmt)
52295253 }
52305254 return typeAccessId
0 commit comments