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