@@ -1557,6 +1557,64 @@ open class KotlinFileExtractor(
15571557
15581558 }
15591559
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+
15601618
15611619 fun extractRawMethodAccess (
15621620 syntacticCallTarget : IrFunction ,
@@ -1588,86 +1646,30 @@ open class KotlinFileExtractor(
15881646 // type arguments at index -2, -3, ...
15891647 extractTypeArguments(typeArguments, locId, id, enclosingCallable, enclosingStmt, - 2 , true )
15901648
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)
16051650
1606- extractNewExprForLocalFunction(ids, id, locId, enclosingCallable, enclosingStmt)
1651+ if (methodId == null ) {
1652+ logger.warn(" No method to bind call to for raw method access" )
16071653 } 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+ }
16591656
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)
16671665 }
16681666
16691667 val idxOffset = if (extractExtensionReceiver != null ) 1 else 0
16701668
1669+ val isBigArityFunctionInvoke = drType is IrSimpleType &&
1670+ isFunctionInvoke(callTarget, drType) &&
1671+ drType.arguments.size > BuiltInFunctionArity .BIG_ARITY
1672+
16711673 val argParent = if (isBigArityFunctionInvoke) {
16721674 extractArrayCreationWithInitializer(id, nValueArguments + idxOffset, locId, enclosingCallable, enclosingStmt)
16731675 } else {
0 commit comments