@@ -441,17 +441,20 @@ open class KotlinFileExtractor(
441441
442442 private fun extractValueParameter (vp : IrValueParameter , parent : Label <out DbCallable >, idx : Int , typeSubstitution : TypeSubstitution ? , parentSourceDeclaration : Label <out DbCallable >): TypeResults {
443443 with (" value parameter" , vp) {
444- return extractValueParameter(useValueParameter(vp, parent), vp.type, vp.name.asString(), tw.getLocation(vp), parent, idx, typeSubstitution, useValueParameter(vp, parentSourceDeclaration))
444+ return extractValueParameter(useValueParameter(vp, parent), vp.type, vp.name.asString(), tw.getLocation(vp), parent, idx, typeSubstitution, useValueParameter(vp, parentSourceDeclaration), vp.isVararg )
445445 }
446446 }
447447
448- private fun extractValueParameter (id : Label <out DbParam >, t : IrType , name : String , locId : Label <DbLocation >, parent : Label <out DbCallable >, idx : Int , typeSubstitution : TypeSubstitution ? , paramSourceDeclaration : Label <out DbParam >): TypeResults {
448+ private fun extractValueParameter (id : Label <out DbParam >, t : IrType , name : String , locId : Label <DbLocation >, parent : Label <out DbCallable >, idx : Int , typeSubstitution : TypeSubstitution ? , paramSourceDeclaration : Label <out DbParam >, isVararg : Boolean ): TypeResults {
449449 val substitutedType = typeSubstitution?.let { it(t, TypeContext .OTHER , pluginContext) } ? : t
450450 val type = useType(substitutedType)
451451 tw.writeParams(id, type.javaResult.id, idx, parent, paramSourceDeclaration)
452452 tw.writeParamsKotlinType(id, type.kotlinResult.id)
453453 tw.writeHasLocation(id, locId)
454454 tw.writeParamName(id, name)
455+ if (isVararg) {
456+ tw.writeIsVarargsParam(id)
457+ }
455458 return type
456459 }
457460
@@ -1079,9 +1082,15 @@ open class KotlinFileExtractor(
10791082 idxOffset = 0
10801083 }
10811084
1082- valueArguments.forEachIndexed { i, arg ->
1085+ var i = 0
1086+ valueArguments.forEach { arg ->
10831087 if (arg != null ) {
1084- extractExpressionExpr(arg, enclosingCallable, id, i + idxOffset, enclosingStmt)
1088+ if (arg is IrVararg ) {
1089+ arg.elements.forEachIndexed { varargNo, vararg -> extractVarargElement(vararg, enclosingCallable, id, i + idxOffset + varargNo, enclosingStmt) }
1090+ i + = arg.elements.size
1091+ } else {
1092+ extractExpressionExpr(arg, enclosingCallable, id, (i++ ) + idxOffset, enclosingStmt)
1093+ }
10851094 }
10861095 }
10871096 }
@@ -1121,6 +1130,22 @@ open class KotlinFileExtractor(
11211130 result
11221131 }
11231132
1133+ val javaLangObject by lazy {
1134+ val result = pluginContext.referenceClass(FqName (" java.lang.Object" ))?.owner
1135+ result?.let { extractExternalClassLater(it) }
1136+ result
1137+ }
1138+
1139+ val objectCloneMethod by lazy {
1140+ val result = javaLangObject?.declarations?.find {
1141+ it is IrFunction && it.name.asString() == " clone"
1142+ } as IrFunction ?
1143+ if (result == null ) {
1144+ logger.error(" Couldn't find declaration java.lang.Object.clone(...)" )
1145+ }
1146+ result
1147+ }
1148+
11241149 fun extractCall (c : IrCall , callable : Label <out DbCallable >, parent : Label <out DbExprparent >, idx : Int , enclosingStmt : Label <out DbStmt >) {
11251150 with (" call" , c) {
11261151 fun isFunction (pkgName : String , className : String , fName : String , hasQuestionMark : Boolean? = false): Boolean {
@@ -1458,37 +1483,63 @@ open class KotlinFileExtractor(
14581483 || isBuiltinCallKotlin(c, " shortArrayOf" )
14591484 || isBuiltinCallKotlin(c, " byteArrayOf" )
14601485 || isBuiltinCallKotlin(c, " booleanArrayOf" ) -> {
1461- val id = tw.getFreshIdLabel<DbArraycreationexpr >()
1462- val type = useType(c.type)
1463- tw.writeExprs_arraycreationexpr(id, type.javaResult.id, parent, idx)
1464- tw.writeExprsKotlinType(id, type.kotlinResult.id)
1465- val locId = tw.getLocation(c)
1466- tw.writeHasLocation(id, locId)
1467- tw.writeCallableEnclosingExpr(id, callable)
1468-
1469- if (isBuiltinCallKotlin(c, " arrayOf" )) {
1470- if (c.typeArgumentsCount == 1 ) {
1471- extractTypeArguments(c, id, callable, enclosingStmt,- 1 )
1472- } else {
1473- logger.errorElement(" Expected to find one type argument in arrayOf call" , c )
1486+
1487+ val arg = if (c.valueArgumentsCount == 1 ) c.getValueArgument(0 ) else {
1488+ logger.errorElement(" Expected to find only one (vararg) argument in ${c.symbol.owner.name.asString()} call" , c)
1489+ null
1490+ }?.let {
1491+ if (it is IrVararg ) it else {
1492+ logger.errorElement(" Expected to find vararg argument in ${c.symbol.owner.name.asString()} call" , c)
1493+ null
14741494 }
1475- } else {
1476- val elementType = c.type.getArrayElementType(pluginContext.irBuiltIns)
1477- extractTypeAccess(elementType, callable, id, - 1 , c, enclosingStmt)
14781495 }
1479-
1480- if (c.valueArgumentsCount == 1 ) {
1481- val vararg = c.getValueArgument(0 )
1482- if (vararg is IrVararg ) {
1496+
1497+ // If this is [someType]ArrayOf(*x), x, otherwise null
1498+ val clonedArray = arg?.let {
1499+ if (arg.elements.size == 1 ) {
1500+ val onlyElement = arg.elements[0 ]
1501+ if (onlyElement is IrSpreadElement )
1502+ onlyElement.expression
1503+ else null
1504+ } else null
1505+ }
1506+
1507+ if (clonedArray != null ) {
1508+ // This is an array clone: extract is as a call to java.lang.Object.clone
1509+ objectCloneMethod?.let {
1510+ extractRawMethodAccess(it, c, callable, parent, idx, enclosingStmt, listOf (), clonedArray, null )
1511+ }
1512+ } else {
1513+ // This is array creation: extract it as a call to new ArrayType[] { ... }
1514+ val id = tw.getFreshIdLabel<DbArraycreationexpr >()
1515+ val type = useType(c.type)
1516+ tw.writeExprs_arraycreationexpr(id, type.javaResult.id, parent, idx)
1517+ tw.writeExprsKotlinType(id, type.kotlinResult.id)
1518+ val locId = tw.getLocation(c)
1519+ tw.writeHasLocation(id, locId)
1520+ tw.writeCallableEnclosingExpr(id, callable)
1521+
1522+ if (isBuiltinCallKotlin(c, " arrayOf" )) {
1523+ if (c.typeArgumentsCount == 1 ) {
1524+ extractTypeArguments(c, id, callable, enclosingStmt,- 1 )
1525+ } else {
1526+ logger.errorElement(" Expected to find one type argument in arrayOf call" , c )
1527+ }
1528+ } else {
1529+ val elementType = c.type.getArrayElementType(pluginContext.irBuiltIns)
1530+ extractTypeAccess(elementType, callable, id, - 1 , c, enclosingStmt)
1531+ }
1532+
1533+ arg?.let {
14831534 val initId = tw.getFreshIdLabel<DbArrayinit >()
14841535 tw.writeExprs_arrayinit(initId, type.javaResult.id, id, - 2 )
14851536 tw.writeExprsKotlinType(initId, type.kotlinResult.id)
14861537 tw.writeHasLocation(initId, locId)
14871538 tw.writeCallableEnclosingExpr(initId, callable)
14881539 tw.writeStatementEnclosingExpr(initId, enclosingStmt)
1489- vararg .elements.forEachIndexed { i, arg -> extractVarargElement(arg, callable, initId, i, enclosingStmt) }
1490-
1491- val dim = vararg .elements.size
1540+ it .elements.forEachIndexed { i, arg -> extractVarargElement(arg, callable, initId, i, enclosingStmt) }
1541+
1542+ val dim = it .elements.size
14921543 val dimId = tw.getFreshIdLabel<DbIntegerliteral >()
14931544 val dimType = useType(pluginContext.irBuiltIns.intType)
14941545 tw.writeExprs_integerliteral(dimId, dimType.javaResult.id, id, 0 )
@@ -1497,11 +1548,7 @@ open class KotlinFileExtractor(
14971548 tw.writeCallableEnclosingExpr(dimId, callable)
14981549 tw.writeStatementEnclosingExpr(dimId, enclosingStmt)
14991550 tw.writeNamestrings(dim.toString(), dim.toString(), dimId)
1500- } else {
1501- logger.errorElement(" Expected to find vararg argument in ${c.symbol.owner.name.asString()} call" , c)
15021551 }
1503- } else {
1504- logger.errorElement(" Expected to find only one (vararg) argument in ${c.symbol.owner.name.asString()} call" , c)
15051552 }
15061553 }
15071554 isBuiltinCall(c, " <unsafe-coerce>" , " kotlin.jvm.internal" ) -> {
@@ -2123,16 +2170,7 @@ open class KotlinFileExtractor(
21232170 extractTypeOperatorCall(e, callable, exprParent.parent, exprParent.idx, exprParent.enclosingStmt)
21242171 }
21252172 is IrVararg -> {
2126- val exprParent = parent.expr(e, callable)
2127- val id = tw.getFreshIdLabel<DbVarargexpr >()
2128- val locId = tw.getLocation(e)
2129- val type = useType(e.type)
2130- tw.writeExprs_varargexpr(id, type.javaResult.id, exprParent.parent, exprParent.idx)
2131- tw.writeExprsKotlinType(id, type.kotlinResult.id)
2132- tw.writeHasLocation(id, locId)
2133- tw.writeCallableEnclosingExpr(id, callable)
2134- tw.writeStatementEnclosingExpr(id, exprParent.enclosingStmt)
2135- e.elements.forEachIndexed { i, arg -> extractVarargElement(arg, callable, id, i, exprParent.enclosingStmt) }
2173+ logger.errorElement(" Unexpected IrVararg" , e)
21362174 }
21372175 is IrGetObjectValue -> {
21382176 // For `object MyObject { ... }`, the .class has an
@@ -2349,7 +2387,7 @@ open class KotlinFileExtractor(
23492387 stmtIdx : Int
23502388 ) {
23512389 val paramId = tw.getFreshIdLabel<DbParam >()
2352- val paramType = extractValueParameter(paramId, type, paramName, locId, ids.constructor , paramIdx, null , paramId)
2390+ val paramType = extractValueParameter(paramId, type, paramName, locId, ids.constructor , paramIdx, null , paramId, false )
23532391
23542392 val assignmentStmtId = tw.getFreshIdLabel<DbExprstmt >()
23552393 tw.writeStmts_exprstmt(assignmentStmtId, ids.constructorBlock, stmtIdx, ids.constructor )
@@ -2548,7 +2586,7 @@ open class KotlinFileExtractor(
25482586
25492587 val parameters = parameterTypes.mapIndexed { idx, p ->
25502588 val paramId = tw.getFreshIdLabel<DbParam >()
2551- val paramType = extractValueParameter(paramId, p, " a$idx " , locId, methodId, idx, null , paramId)
2589+ val paramType = extractValueParameter(paramId, p, " a$idx " , locId, methodId, idx, null , paramId, false )
25522590
25532591 Pair (paramId, paramType)
25542592 }
@@ -2695,18 +2733,17 @@ open class KotlinFileExtractor(
26952733
26962734 fun extractVarargElement (e : IrVarargElement , callable : Label <out DbCallable >, parent : Label <out DbExprparent >, idx : Int , enclosingStmt : Label <out DbStmt >) {
26972735 with (" vararg element" , e) {
2698- when (e) {
2699- is IrExpression -> {
2700- extractExpressionExpr(e, callable, parent, idx, enclosingStmt)
2701- }
2702- is IrSpreadElement -> {
2703- // TODO:
2704- logger.errorElement(" Unhandled IrSpreadElement" , e)
2705- }
2736+ val argExpr = when (e) {
2737+ is IrExpression -> e
2738+ is IrSpreadElement -> e.expression
27062739 else -> {
27072740 logger.errorElement(" Unrecognised IrVarargElement: " + e.javaClass, e)
2741+ null
27082742 }
27092743 }
2744+ argExpr?.let {
2745+ extractExpressionExpr(it, callable, parent, idx, enclosingStmt)
2746+ }
27102747 }
27112748 }
27122749
0 commit comments