@@ -1557,6 +1557,64 @@ open class KotlinFileExtractor(
1557
1557
1558
1558
}
1559
1559
1560
+ private fun getFunctionInvokeMethod (typeArgs : List <IrTypeArgument >): IrFunction ? {
1561
+ // For `kotlin.FunctionX` and `kotlin.reflect.KFunctionX` interfaces, we're making sure that we
1562
+ // extract the call to the `invoke` method that does exist, `kotlin.jvm.functions.FunctionX::invoke`.
1563
+ val functionalInterface = getFunctionalInterfaceTypeWithTypeArgs(typeArgs)
1564
+ if (functionalInterface == null ) {
1565
+ logger.warn(" Cannot find functional interface type for raw method access" )
1566
+ return null
1567
+ }
1568
+ val functionalInterfaceClass = functionalInterface.classOrNull
1569
+ if (functionalInterfaceClass == null ) {
1570
+ logger.warn(" Cannot find functional interface class for raw method access" )
1571
+ return null
1572
+ }
1573
+ val interfaceType = functionalInterfaceClass.owner
1574
+ val substituted = getJavaEquivalentClass(interfaceType) ? : interfaceType
1575
+ val function = findFunction(substituted, OperatorNameConventions .INVOKE .asString())
1576
+ if (function == null ) {
1577
+ logger.warn(" Cannot find invoke function for raw method access" )
1578
+ return null
1579
+ }
1580
+ return function
1581
+ }
1582
+
1583
+ private fun isFunctionInvoke (callTarget : IrFunction , drType : IrSimpleType ) =
1584
+ (drType.isFunctionOrKFunction() || drType.isSuspendFunctionOrKFunction()) &&
1585
+ callTarget.name.asString() == OperatorNameConventions .INVOKE .asString()
1586
+
1587
+ private fun getCalleeMethodId (callTarget : IrFunction , drType : IrType ? , allowInstantiatedGenericMethod : Boolean ): Label <out DbCallable >? {
1588
+ if (callTarget.isLocalFunction())
1589
+ return getLocallyVisibleFunctionLabels(callTarget).function
1590
+
1591
+ if (allowInstantiatedGenericMethod && drType is IrSimpleType && ! isUnspecialised(drType, logger)) {
1592
+ val calleeIsInvoke = isFunctionInvoke(callTarget, drType)
1593
+
1594
+ val extractionMethod =
1595
+ if (calleeIsInvoke)
1596
+ getFunctionInvokeMethod(drType.arguments)
1597
+ else
1598
+ callTarget
1599
+
1600
+ return extractionMethod?.let {
1601
+ val typeArgs =
1602
+ if (calleeIsInvoke && drType.arguments.size > BuiltInFunctionArity .BIG_ARITY ) {
1603
+ // Big arity `invoke` methods have a special implementation on JVM, they are transformed to a call to
1604
+ // `kotlin.jvm.functions.FunctionN<out R>::invoke(vararg args: Any?)`, so we only need to pass the type
1605
+ // argument for the return type. Additionally, the arguments are extracted inside an array literal below.
1606
+ listOf (drType.arguments.last())
1607
+ } else {
1608
+ getDeclaringTypeArguments(callTarget, drType)
1609
+ }
1610
+ useFunction<DbCallable >(extractionMethod, typeArgs)
1611
+ }
1612
+ }
1613
+ else {
1614
+ return useFunction<DbCallable >(callTarget)
1615
+ }
1616
+ }
1617
+
1560
1618
1561
1619
fun extractRawMethodAccess (
1562
1620
syntacticCallTarget : IrFunction ,
@@ -1588,86 +1646,30 @@ open class KotlinFileExtractor(
1588
1646
// type arguments at index -2, -3, ...
1589
1647
extractTypeArguments(typeArguments, locId, id, enclosingCallable, enclosingStmt, - 2 , true )
1590
1648
1591
- val (isFunctionInvoke, isBigArityFunctionInvoke) =
1592
- if (drType is IrSimpleType &&
1593
- (drType.isFunctionOrKFunction() || drType.isSuspendFunctionOrKFunction()) &&
1594
- callTarget.name.asString() == OperatorNameConventions .INVOKE .asString()) {
1595
- Pair (true , drType.arguments.size > BuiltInFunctionArity .BIG_ARITY )
1596
- } else {
1597
- Pair (false , false )
1598
- }
1599
-
1600
- if (callTarget.isLocalFunction()) {
1601
- val ids = getLocallyVisibleFunctionLabels(callTarget)
1602
-
1603
- val methodId = ids.function
1604
- tw.writeCallableBinding(id, methodId)
1649
+ val methodId = getCalleeMethodId(callTarget, drType, extractClassTypeArguments)
1605
1650
1606
- extractNewExprForLocalFunction(ids, id, locId, enclosingCallable, enclosingStmt)
1651
+ if (methodId == null ) {
1652
+ logger.warn(" No method to bind call to for raw method access" )
1607
1653
} else {
1608
- val methodId =
1609
- if (extractClassTypeArguments && drType is IrSimpleType && ! isUnspecialised(drType, logger)) {
1610
-
1611
- val extractionMethod = if (isFunctionInvoke) {
1612
- // For `kotlin.FunctionX` and `kotlin.reflect.KFunctionX` interfaces, we're making sure that we
1613
- // extract the call to the `invoke` method that does exist, `kotlin.jvm.functions.FunctionX::invoke`.
1614
- val functionalInterface = getFunctionalInterfaceTypeWithTypeArgs(drType.arguments)
1615
- if (functionalInterface == null ) {
1616
- logger.warn(" Cannot find functional interface type for raw method access" )
1617
- null
1618
- } else {
1619
- val functionalInterfaceClass = functionalInterface.classOrNull
1620
- if (functionalInterfaceClass == null ) {
1621
- logger.warn(" Cannot find functional interface class for raw method access" )
1622
- null
1623
- } else {
1624
- val interfaceType = functionalInterfaceClass.owner
1625
- val substituted = getJavaEquivalentClass(interfaceType) ? : interfaceType
1626
- val function = findFunction(substituted, OperatorNameConventions .INVOKE .asString())
1627
- if (function == null ) {
1628
- logger.warn(" Cannot find invoke function for raw method access" )
1629
- null
1630
- } else {
1631
- function
1632
- }
1633
- }
1634
- }
1635
- } else {
1636
- callTarget
1637
- }
1638
-
1639
- if (extractionMethod == null ) {
1640
- null
1641
- } else if (isBigArityFunctionInvoke) {
1642
- // Big arity `invoke` methods have a special implementation on JVM, they are transformed to a call to
1643
- // `kotlin.jvm.functions.FunctionN<out R>::invoke(vararg args: Any?)`, so we only need to pass the type
1644
- // argument for the return type. Additionally, the arguments are extracted inside an array literal below.
1645
- useFunction<DbCallable >(extractionMethod, listOf (drType.arguments.last()))
1646
- } else {
1647
- useFunction<DbCallable >(extractionMethod, getDeclaringTypeArguments(callTarget, drType))
1648
- }
1649
- }
1650
- else {
1651
- useFunction<DbCallable >(callTarget)
1652
- }
1653
-
1654
- if (methodId == null ) {
1655
- logger.warn(" No method to bind call to for raw method access" )
1656
- } else {
1657
- tw.writeCallableBinding(id, methodId)
1658
- }
1654
+ tw.writeCallableBinding(id, methodId)
1655
+ }
1659
1656
1660
- if (callTarget.shouldExtractAsStatic) {
1661
- extractStaticTypeAccessQualifier(callTarget, id, locId, enclosingCallable, enclosingStmt)
1662
- } else if (superQualifierSymbol != null ) {
1663
- extractSuperAccess(superQualifierSymbol.typeWith(), enclosingCallable, id, - 1 , enclosingStmt, locId)
1664
- } else if (extractDispatchReceiver != null ) {
1665
- extractDispatchReceiver(id)
1666
- }
1657
+ if (callTarget.isLocalFunction()) {
1658
+ extractNewExprForLocalFunction(getLocallyVisibleFunctionLabels(callTarget), id, locId, enclosingCallable, enclosingStmt)
1659
+ } else if (callTarget.shouldExtractAsStatic) {
1660
+ extractStaticTypeAccessQualifier(callTarget, id, locId, enclosingCallable, enclosingStmt)
1661
+ } else if (superQualifierSymbol != null ) {
1662
+ extractSuperAccess(superQualifierSymbol.typeWith(), enclosingCallable, id, - 1 , enclosingStmt, locId)
1663
+ } else if (extractDispatchReceiver != null ) {
1664
+ extractDispatchReceiver(id)
1667
1665
}
1668
1666
1669
1667
val idxOffset = if (extractExtensionReceiver != null ) 1 else 0
1670
1668
1669
+ val isBigArityFunctionInvoke = drType is IrSimpleType &&
1670
+ isFunctionInvoke(callTarget, drType) &&
1671
+ drType.arguments.size > BuiltInFunctionArity .BIG_ARITY
1672
+
1671
1673
val argParent = if (isBigArityFunctionInvoke) {
1672
1674
extractArrayCreationWithInitializer(id, nValueArguments + idxOffset, locId, enclosingCallable, enclosingStmt)
1673
1675
} else {
0 commit comments