@@ -1468,14 +1468,22 @@ open class KotlinFileExtractor(
1468
1468
val extractionMethod = if (isFunctionInvoke) {
1469
1469
// For `kotlin.FunctionX` and `kotlin.reflect.KFunctionX` interfaces, we're making sure that we
1470
1470
// extract the call to the `invoke` method that does exist, `kotlin.jvm.functions.FunctionX::invoke`.
1471
- val interfaceType = getFunctionalInterfaceTypeWithTypeArgs(drType.arguments).classOrNull!! .owner
1472
- val substituted = getJavaEquivalentClass(interfaceType) ? : interfaceType
1473
- findFunction(substituted, OperatorNameConventions .INVOKE .asString())!!
1471
+ val functionalInterface = getFunctionalInterfaceTypeWithTypeArgs(drType.arguments)
1472
+ if (functionalInterface == null ) {
1473
+ logger.warn(" Cannot find functional interface type for raw method access" )
1474
+ null
1475
+ } else {
1476
+ val interfaceType = functionalInterface.classOrNull!! .owner
1477
+ val substituted = getJavaEquivalentClass(interfaceType) ? : interfaceType
1478
+ findFunction(substituted, OperatorNameConventions .INVOKE .asString())!!
1479
+ }
1474
1480
} else {
1475
1481
callTarget
1476
1482
}
1477
1483
1478
- if (isBigArityFunctionInvoke) {
1484
+ if (extractionMethod == null ) {
1485
+ null
1486
+ } else if (isBigArityFunctionInvoke) {
1479
1487
// Big arity `invoke` methods have a special implementation on JVM, they are transformed to a call to
1480
1488
// `kotlin.jvm.functions.FunctionN<out R>::invoke(vararg args: Any?)`, so we only need to pass the type
1481
1489
// argument for the return type. Additionally, the arguments are extracted inside an array literal below.
@@ -1484,10 +1492,15 @@ open class KotlinFileExtractor(
1484
1492
useFunction<DbCallable >(extractionMethod, getDeclaringTypeArguments(callTarget, drType))
1485
1493
}
1486
1494
}
1487
- else
1495
+ else {
1488
1496
useFunction<DbCallable >(callTarget)
1497
+ }
1489
1498
1490
- tw.writeCallableBinding(id, methodId)
1499
+ if (methodId == null ) {
1500
+ logger.warn(" No method to bind call to for raw method access" )
1501
+ } else {
1502
+ tw.writeCallableBinding(id, methodId)
1503
+ }
1491
1504
1492
1505
if (callTarget.shouldExtractAsStatic) {
1493
1506
extractStaticTypeAccessQualifier(callTarget, id, locId, enclosingCallable, enclosingStmt)
@@ -3021,11 +3034,6 @@ open class KotlinFileExtractor(
3021
3034
var types = parameters.map { it.type }
3022
3035
types + = e.function.returnType
3023
3036
3024
- val fnInterfaceType = getFunctionalInterfaceType(types)
3025
- val id = extractGeneratedClass(
3026
- e.function, // We're adding this function as a member, and changing its name to `invoke` to implement `kotlin.FunctionX<,,,>.invoke(,,)`
3027
- listOf (pluginContext.irBuiltIns.anyType, fnInterfaceType))
3028
-
3029
3037
val isBigArity = types.size > BuiltInFunctionArity .BIG_ARITY
3030
3038
if (isBigArity) {
3031
3039
implementFunctionNInvoke(e.function, ids, locId, parameters)
@@ -3042,12 +3050,21 @@ open class KotlinFileExtractor(
3042
3050
tw.writeStatementEnclosingExpr(idLambdaExpr, exprParent.enclosingStmt)
3043
3051
tw.writeCallableBinding(idLambdaExpr, ids.constructor )
3044
3052
3045
- extractTypeAccessRecursive(fnInterfaceType, locId, idLambdaExpr, - 3 , callable, exprParent.enclosingStmt)
3046
-
3047
3053
// todo: fix hard coded block body of lambda
3048
3054
tw.writeLambdaKind(idLambdaExpr, 1 )
3049
3055
3050
- tw.writeIsAnonymClass(id, idLambdaExpr)
3056
+ val fnInterfaceType = getFunctionalInterfaceType(types)
3057
+ if (fnInterfaceType == null ) {
3058
+ logger.warnElement(" Cannot find functional interface type for function expression" , e)
3059
+ } else {
3060
+ val id = extractGeneratedClass(
3061
+ e.function, // We're adding this function as a member, and changing its name to `invoke` to implement `kotlin.FunctionX<,,,>.invoke(,,)`
3062
+ listOf (pluginContext.irBuiltIns.anyType, fnInterfaceType))
3063
+
3064
+ extractTypeAccessRecursive(fnInterfaceType, locId, idLambdaExpr, - 3 , callable, exprParent.enclosingStmt)
3065
+
3066
+ tw.writeIsAnonymClass(id, idLambdaExpr)
3067
+ }
3051
3068
}
3052
3069
is IrClassReference -> {
3053
3070
val exprParent = parent.expr(e, callable)
@@ -3737,7 +3754,6 @@ open class KotlinFileExtractor(
3737
3754
dispatchReceiverIdx = - 1
3738
3755
}
3739
3756
3740
- val targetCallableId = useFunction<DbCallable >(target.owner.realOverrideTarget, classTypeArguments)
3741
3757
val locId = tw.getLocation(functionReferenceExpr)
3742
3758
3743
3759
val javaResult = TypeResult (tw.getFreshIdLabel<DbClass >(), " " , " " )
@@ -3750,36 +3766,6 @@ open class KotlinFileExtractor(
3750
3766
constructorBlock = tw.getFreshIdLabel()
3751
3767
)
3752
3768
3753
- val helper = CallableReferenceHelper (functionReferenceExpr, locId, ids)
3754
-
3755
- val fnInterfaceType = getFunctionalInterfaceTypeWithTypeArgs(type.arguments)
3756
-
3757
- val currentDeclaration = declarationStack.peek()
3758
- // `FunctionReference` base class is required, because that's implementing `KFunction`.
3759
- val baseClass = pluginContext.referenceClass(FqName (" kotlin.jvm.internal.FunctionReference" ))?.owner?.typeWith()
3760
- ? : pluginContext.irBuiltIns.anyType
3761
-
3762
- val classId = extractGeneratedClass(ids, listOf (baseClass, fnInterfaceType), locId, currentDeclaration)
3763
-
3764
- helper.extractReceiverField()
3765
-
3766
- val isBigArity = type.arguments.size > BuiltInFunctionArity .BIG_ARITY
3767
- val funLabels = if (isBigArity) {
3768
- addFunctionNInvoke(ids.function, parameterTypes.last(), classId, locId)
3769
- } else {
3770
- addFunctionInvoke(ids.function, parameterTypes.dropLast(1 ), parameterTypes.last(), classId, locId)
3771
- }
3772
-
3773
- helper.extractCallToReflectionTarget(
3774
- funLabels,
3775
- target,
3776
- parameterTypes.last(),
3777
- expressionTypeArguments,
3778
- classTypeArguments,
3779
- dispatchReceiverIdx,
3780
- isBigArity,
3781
- parameterTypes.dropLast(1 ))
3782
-
3783
3769
// Add constructor (member ref) call:
3784
3770
val exprParent = parent.expr(functionReferenceExpr, callable)
3785
3771
val idMemberRef = tw.getFreshIdLabel<DbMemberref >()
@@ -3790,40 +3776,87 @@ open class KotlinFileExtractor(
3790
3776
tw.writeStatementEnclosingExpr(idMemberRef, exprParent.enclosingStmt)
3791
3777
tw.writeCallableBinding(idMemberRef, ids.constructor )
3792
3778
3793
- val typeAccessArguments = if (isBigArity) listOf (parameterTypes.last()) else parameterTypes
3794
- if (target is IrConstructorSymbol ) {
3795
- val returnType = typeAccessArguments.last()
3779
+ val targetCallableId = useFunction<DbCallable >(target.owner.realOverrideTarget, classTypeArguments)
3780
+ tw.writeMemberRefBinding(idMemberRef, targetCallableId)
3796
3781
3797
- val typeAccessId = extractTypeAccess(useType(fnInterfaceType, TypeContext .OTHER ), locId, idMemberRef, - 3 , callable, exprParent.enclosingStmt)
3798
- typeAccessArguments.dropLast(1 ).forEachIndexed { argIdx, arg ->
3799
- extractTypeAccessRecursive(arg, locId, typeAccessId, argIdx, callable, exprParent.enclosingStmt, TypeContext .GENERIC_ARGUMENT )
3800
- }
3782
+ val helper = CallableReferenceHelper (functionReferenceExpr, locId, ids)
3801
3783
3802
- extractConstructorTypeAccess(returnType, useType(returnType), target, locId, typeAccessId, typeAccessArguments.count() - 1 , callable, exprParent.enclosingStmt)
3784
+ val fnInterfaceType = getFunctionalInterfaceTypeWithTypeArgs(type.arguments)
3785
+ if (fnInterfaceType == null ) {
3786
+ logger.warnElement(" Cannot find functional interface type for function reference" , functionReferenceExpr)
3803
3787
} else {
3804
- extractTypeAccessRecursive(fnInterfaceType, locId, idMemberRef, - 3 , callable, exprParent.enclosingStmt)
3805
- }
3788
+ val currentDeclaration = declarationStack.peek()
3789
+ // `FunctionReference` base class is required, because that's implementing `KFunction`.
3790
+ val baseClass = pluginContext.referenceClass(FqName (" kotlin.jvm.internal.FunctionReference" ))?.owner?.typeWith()
3791
+ ? : pluginContext.irBuiltIns.anyType
3806
3792
3807
- tw.writeMemberRefBinding(idMemberRef, targetCallableId)
3793
+ val classId = extractGeneratedClass(ids, listOf (baseClass, fnInterfaceType), locId, currentDeclaration)
3794
+
3795
+ helper.extractReceiverField()
3796
+
3797
+ val isBigArity = type.arguments.size > BuiltInFunctionArity .BIG_ARITY
3798
+ val funLabels = if (isBigArity) {
3799
+ addFunctionNInvoke(ids.function, parameterTypes.last(), classId, locId)
3800
+ } else {
3801
+ addFunctionInvoke(ids.function, parameterTypes.dropLast(1 ), parameterTypes.last(), classId, locId)
3802
+ }
3803
+
3804
+ helper.extractCallToReflectionTarget(
3805
+ funLabels,
3806
+ target,
3807
+ parameterTypes.last(),
3808
+ expressionTypeArguments,
3809
+ classTypeArguments,
3810
+ dispatchReceiverIdx,
3811
+ isBigArity,
3812
+ parameterTypes.dropLast(1 ))
3813
+
3814
+ val typeAccessArguments = if (isBigArity) listOf (parameterTypes.last()) else parameterTypes
3815
+ if (target is IrConstructorSymbol ) {
3816
+ val returnType = typeAccessArguments.last()
3817
+
3818
+ val typeAccessId = extractTypeAccess(useType(fnInterfaceType, TypeContext .OTHER ), locId, idMemberRef, - 3 , callable, exprParent.enclosingStmt)
3819
+ typeAccessArguments.dropLast(1 ).forEachIndexed { argIdx, arg ->
3820
+ extractTypeAccessRecursive(arg, locId, typeAccessId, argIdx, callable, exprParent.enclosingStmt, TypeContext .GENERIC_ARGUMENT )
3821
+ }
3822
+
3823
+ extractConstructorTypeAccess(returnType, useType(returnType), target, locId, typeAccessId, typeAccessArguments.count() - 1 , callable, exprParent.enclosingStmt)
3824
+ } else {
3825
+ extractTypeAccessRecursive(fnInterfaceType, locId, idMemberRef, - 3 , callable, exprParent.enclosingStmt)
3826
+ }
3808
3827
3809
- helper.extractConstructorArguments(callable, idMemberRef, exprParent.enclosingStmt)
3828
+ helper.extractConstructorArguments(callable, idMemberRef, exprParent.enclosingStmt)
3810
3829
3811
- tw.writeIsAnonymClass(classId, idMemberRef)
3830
+ tw.writeIsAnonymClass(classId, idMemberRef)
3831
+ }
3812
3832
}
3813
3833
}
3814
3834
3815
- private fun getFunctionalInterfaceType (functionNTypeArguments : List <IrType >) =
3835
+ private fun getFunctionalInterfaceType (functionNTypeArguments : List <IrType >): IrSimpleType ? {
3816
3836
if (functionNTypeArguments.size > BuiltInFunctionArity .BIG_ARITY ) {
3817
- pluginContext.referenceClass(FqName (" kotlin.jvm.functions.FunctionN" ))!!
3818
- .typeWith(functionNTypeArguments.last())
3837
+ val funName = " kotlin.jvm.functions.FunctionN"
3838
+ val theFun = pluginContext.referenceClass(FqName (funName))
3839
+ if (theFun == null ) {
3840
+ logger.warn(" Cannot find $funName for getFunctionalInterfaceType" )
3841
+ return null
3842
+ } else {
3843
+ return theFun.typeWith(functionNTypeArguments.last())
3844
+ }
3819
3845
} else {
3820
- functionN(pluginContext)(functionNTypeArguments.size - 1 ).typeWith(functionNTypeArguments)
3846
+ return functionN(pluginContext)(functionNTypeArguments.size - 1 ).typeWith(functionNTypeArguments)
3821
3847
}
3848
+ }
3822
3849
3823
- private fun getFunctionalInterfaceTypeWithTypeArgs (functionNTypeArguments : List <IrTypeArgument >) =
3850
+ private fun getFunctionalInterfaceTypeWithTypeArgs (functionNTypeArguments : List <IrTypeArgument >): IrSimpleType ? =
3824
3851
if (functionNTypeArguments.size > BuiltInFunctionArity .BIG_ARITY ) {
3825
- pluginContext.referenceClass(FqName (" kotlin.jvm.functions.FunctionN" ))!!
3826
- .typeWithArguments(listOf (functionNTypeArguments.last()))
3852
+ val funName = " kotlin.jvm.functions.FunctionN"
3853
+ val theFun = pluginContext.referenceClass(FqName (funName))
3854
+ if (theFun == null ) {
3855
+ logger.warn(" Cannot find $funName for getFunctionalInterfaceTypeWithTypeArgs" )
3856
+ null
3857
+ } else {
3858
+ theFun.typeWithArguments(listOf (functionNTypeArguments.last()))
3859
+ }
3827
3860
} else {
3828
3861
functionN(pluginContext)(functionNTypeArguments.size - 1 ).symbol.typeWithArguments(functionNTypeArguments)
3829
3862
}
@@ -4321,6 +4354,10 @@ open class KotlinFileExtractor(
4321
4354
4322
4355
// Either Function1, ... Function22 or FunctionN type, but not Function23 or above.
4323
4356
val functionType = getFunctionalInterfaceTypeWithTypeArgs(st.arguments)
4357
+ if (functionType == null ) {
4358
+ logger.errorElement(" Cannot find functional interface." , e)
4359
+ return
4360
+ }
4324
4361
4325
4362
val invokeMethod = functionType.classOrNull?.owner?.declarations?.filterIsInstance<IrFunction >()?.find { it.name.asString() == OperatorNameConventions .INVOKE .asString()}
4326
4363
if (invokeMethod == null ) {
0 commit comments