Skip to content

Commit d5b414f

Browse files
committed
Kotlin: Fix some more not-null-exprs in the extractor
1 parent fb9a348 commit d5b414f

File tree

1 file changed

+102
-65
lines changed

1 file changed

+102
-65
lines changed

java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt

Lines changed: 102 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,14 +1468,22 @@ open class KotlinFileExtractor(
14681468
val extractionMethod = if (isFunctionInvoke) {
14691469
// For `kotlin.FunctionX` and `kotlin.reflect.KFunctionX` interfaces, we're making sure that we
14701470
// 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+
}
14741480
} else {
14751481
callTarget
14761482
}
14771483

1478-
if (isBigArityFunctionInvoke) {
1484+
if (extractionMethod == null) {
1485+
null
1486+
} else if (isBigArityFunctionInvoke) {
14791487
// Big arity `invoke` methods have a special implementation on JVM, they are transformed to a call to
14801488
// `kotlin.jvm.functions.FunctionN<out R>::invoke(vararg args: Any?)`, so we only need to pass the type
14811489
// argument for the return type. Additionally, the arguments are extracted inside an array literal below.
@@ -1484,10 +1492,15 @@ open class KotlinFileExtractor(
14841492
useFunction<DbCallable>(extractionMethod, getDeclaringTypeArguments(callTarget, drType))
14851493
}
14861494
}
1487-
else
1495+
else {
14881496
useFunction<DbCallable>(callTarget)
1497+
}
14891498

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+
}
14911504

14921505
if (callTarget.shouldExtractAsStatic) {
14931506
extractStaticTypeAccessQualifier(callTarget, id, locId, enclosingCallable, enclosingStmt)
@@ -3021,11 +3034,6 @@ open class KotlinFileExtractor(
30213034
var types = parameters.map { it.type }
30223035
types += e.function.returnType
30233036

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-
30293037
val isBigArity = types.size > BuiltInFunctionArity.BIG_ARITY
30303038
if (isBigArity) {
30313039
implementFunctionNInvoke(e.function, ids, locId, parameters)
@@ -3042,12 +3050,21 @@ open class KotlinFileExtractor(
30423050
tw.writeStatementEnclosingExpr(idLambdaExpr, exprParent.enclosingStmt)
30433051
tw.writeCallableBinding(idLambdaExpr, ids.constructor)
30443052

3045-
extractTypeAccessRecursive(fnInterfaceType, locId, idLambdaExpr, -3, callable, exprParent.enclosingStmt)
3046-
30473053
// todo: fix hard coded block body of lambda
30483054
tw.writeLambdaKind(idLambdaExpr, 1)
30493055

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+
}
30513068
}
30523069
is IrClassReference -> {
30533070
val exprParent = parent.expr(e, callable)
@@ -3737,7 +3754,6 @@ open class KotlinFileExtractor(
37373754
dispatchReceiverIdx = -1
37383755
}
37393756

3740-
val targetCallableId = useFunction<DbCallable>(target.owner.realOverrideTarget, classTypeArguments)
37413757
val locId = tw.getLocation(functionReferenceExpr)
37423758

37433759
val javaResult = TypeResult(tw.getFreshIdLabel<DbClass>(), "", "")
@@ -3750,36 +3766,6 @@ open class KotlinFileExtractor(
37503766
constructorBlock = tw.getFreshIdLabel()
37513767
)
37523768

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-
37833769
// Add constructor (member ref) call:
37843770
val exprParent = parent.expr(functionReferenceExpr, callable)
37853771
val idMemberRef = tw.getFreshIdLabel<DbMemberref>()
@@ -3790,40 +3776,87 @@ open class KotlinFileExtractor(
37903776
tw.writeStatementEnclosingExpr(idMemberRef, exprParent.enclosingStmt)
37913777
tw.writeCallableBinding(idMemberRef, ids.constructor)
37923778

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)
37963781

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)
38013783

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)
38033787
} 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
38063792

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+
}
38083827

3809-
helper.extractConstructorArguments(callable, idMemberRef, exprParent.enclosingStmt)
3828+
helper.extractConstructorArguments(callable, idMemberRef, exprParent.enclosingStmt)
38103829

3811-
tw.writeIsAnonymClass(classId, idMemberRef)
3830+
tw.writeIsAnonymClass(classId, idMemberRef)
3831+
}
38123832
}
38133833
}
38143834

3815-
private fun getFunctionalInterfaceType(functionNTypeArguments: List<IrType>) =
3835+
private fun getFunctionalInterfaceType(functionNTypeArguments: List<IrType>): IrSimpleType? {
38163836
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+
}
38193845
} else {
3820-
functionN(pluginContext)(functionNTypeArguments.size - 1).typeWith(functionNTypeArguments)
3846+
return functionN(pluginContext)(functionNTypeArguments.size - 1).typeWith(functionNTypeArguments)
38213847
}
3848+
}
38223849

3823-
private fun getFunctionalInterfaceTypeWithTypeArgs(functionNTypeArguments: List<IrTypeArgument>) =
3850+
private fun getFunctionalInterfaceTypeWithTypeArgs(functionNTypeArguments: List<IrTypeArgument>): IrSimpleType? =
38243851
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+
}
38273860
} else {
38283861
functionN(pluginContext)(functionNTypeArguments.size - 1).symbol.typeWithArguments(functionNTypeArguments)
38293862
}
@@ -4321,6 +4354,10 @@ open class KotlinFileExtractor(
43214354

43224355
// Either Function1, ... Function22 or FunctionN type, but not Function23 or above.
43234356
val functionType = getFunctionalInterfaceTypeWithTypeArgs(st.arguments)
4357+
if (functionType == null) {
4358+
logger.errorElement("Cannot find functional interface.", e)
4359+
return
4360+
}
43244361

43254362
val invokeMethod = functionType.classOrNull?.owner?.declarations?.filterIsInstance<IrFunction>()?.find { it.name.asString() == OperatorNameConventions.INVOKE.asString()}
43264363
if (invokeMethod == null) {

0 commit comments

Comments
 (0)