Kotlin: useFunction might return null

This commit is contained in:
Ian Lynagh
2023-08-07 17:26:33 +01:00
parent 3e86c4c39e
commit 0eb6d1c76e
2 changed files with 109 additions and 43 deletions

View File

@@ -552,12 +552,16 @@ open class KotlinFileExtractor(
logger.warnElement("Expected annotation property to define a getter", prop)
} else {
val getterId = useFunction<DbMethod>(getter)
if (getterId == null) {
logger.errorElement("Couldn't get ID for getter", getter)
} else {
val exprId = extractAnnotationValueExpression(v, id, i, "{$getterId}", getter.returnType, extractEnumTypeAccesses)
if (exprId != null) {
tw.writeAnnotValue(id, getterId, exprId)
}
}
}
}
return id
}
@@ -979,6 +983,10 @@ open class KotlinFileExtractor(
private fun extractInstanceInitializerBlock(parent: StmtParent, enclosingConstructor: IrConstructor) {
with("object initializer block", enclosingConstructor) {
val constructorId = useFunction<DbConstructor>(enclosingConstructor)
if (constructorId == null) {
logger.errorElement("Cannot get ID for constructor", enclosingConstructor)
return
}
val enclosingClass = enclosingConstructor.parentClassOrNull
if (enclosingClass == null) {
logger.errorElement("Constructor's parent is not a class", enclosingConstructor)
@@ -1410,10 +1418,17 @@ open class KotlinFileExtractor(
val sourceDeclaration =
overriddenAttributes?.sourceDeclarationId ?:
if (typeSubstitution != null && overriddenAttributes?.id == null)
useFunction(f)
else
if (typeSubstitution != null && overriddenAttributes?.id == null) {
val sourceFunId = useFunction<DbCallable>(f)
if (sourceFunId == null) {
logger.errorElement("Cannot get source ID for function", f)
id // TODO: This is wrong; we ought to just fail in this case
} else {
sourceFunId
}
} else {
id
}
val extReceiver = f.extensionReceiverParameter
// The following parameter order is correct, because member $default methods (where the order would be [dispatchParam], [extensionParam], normalParams) are not extracted here
@@ -3274,7 +3289,14 @@ open class KotlinFileExtractor(
idx: Int,
callable: Label<out DbCallable>,
enclosingStmt: Label<out DbStmt>
): Label<DbNewexpr>? = extractNewExpr(useFunction<DbConstructor>(calledConstructor, constructorTypeArgs), constructedType, locId, parent, idx, callable, enclosingStmt)
): Label<DbNewexpr>? {
val funId = useFunction<DbConstructor>(calledConstructor, constructorTypeArgs)
if (funId == null) {
logger.error("Cannot get ID for newExpr function")
return null
}
return extractNewExpr(funId, constructedType, locId, parent, idx, callable, enclosingStmt)
}
private fun needsObinitFunction(c: IrClass) = c.primaryConstructor == null && c.constructors.count() > 1
@@ -3707,9 +3729,13 @@ open class KotlinFileExtractor(
val locId = tw.getLocation(e)
val methodId = useFunction<DbConstructor>(e.symbol.owner)
if (methodId == null) {
logger.errorElement("Cannot get ID for delegating constructor", e)
} else {
tw.writeCallableBinding(id.cast<DbCaller>(), methodId)
}
tw.writeHasLocation(id, locId)
tw.writeCallableBinding(id.cast<DbCaller>(), methodId)
extractCallValueArguments(id, e, id, callable, 0)
val dr = e.dispatchReceiver
if (dr != null) {
@@ -4645,7 +4671,11 @@ open class KotlinFileExtractor(
extractExprContext(callId, locId, labels.methodId, retId)
val callableId = useFunction<DbCallable>(target.owner.realOverrideTarget, classTypeArgsIncludingOuterClasses)
if (callableId == null) {
logger.error("Cannot get ID for reflection target")
} else {
tw.writeCallableBinding(callId.cast<DbCaller>(), callableId)
}
val useFirstArgAsDispatch: Boolean
if (dispatchReceiverInfo != null) {
@@ -4827,8 +4857,11 @@ open class KotlinFileExtractor(
val getterReturnType = parameterTypes.last()
if (getter != null) {
val getLabels = addFunctionManual(tw.getFreshIdLabel(), OperatorNameConventions.GET.asString(), getterParameterTypes, getterReturnType, classId, locId)
val getterCallableId = useFunction<DbCallable>(getter.owner.realOverrideTarget, classTypeArguments)
if (getterCallableId == null) {
logger.errorElement("Cannot get ID for getter", propertyReferenceExpr)
} else {
val getLabels = addFunctionManual(tw.getFreshIdLabel(), OperatorNameConventions.GET.asString(), getterParameterTypes, getterReturnType, classId, locId)
helper.extractCallToReflectionTarget(
getLabels,
@@ -4841,6 +4874,7 @@ open class KotlinFileExtractor(
tw.writePropertyRefGetBinding(idPropertyRef, getterCallableId)
helper.extractPropertyReferenceInvoke(getLabels.methodId, getterParameterTypes, getterReturnType)
}
} else {
// Property without a getter.
if (backingField == null) {
@@ -4861,9 +4895,11 @@ open class KotlinFileExtractor(
}
if (setter != null) {
val setLabels = addFunctionManual(tw.getFreshIdLabel(), OperatorNameConventions.SET.asString(), parameterTypes, pluginContext.irBuiltIns.unitType, classId, locId)
val setterCallableId = useFunction<DbCallable>(setter.owner.realOverrideTarget, classTypeArguments)
if (setterCallableId == null) {
logger.errorElement("Cannot get ID for setter", propertyReferenceExpr)
} else {
val setLabels = addFunctionManual(tw.getFreshIdLabel(), OperatorNameConventions.SET.asString(), parameterTypes, pluginContext.irBuiltIns.unitType, classId, locId)
helper.extractCallToReflectionTarget(
setLabels,
@@ -4874,6 +4910,7 @@ open class KotlinFileExtractor(
)
tw.writePropertyRefSetBinding(idPropertyRef, setterCallableId)
}
} else {
if (backingField != null && !backingField.owner.isFinal) {
val setLabels = addFunctionManual(tw.getFreshIdLabel(), OperatorNameConventions.SET.asString(), parameterTypes, pluginContext.irBuiltIns.unitType, classId, locId)
@@ -5008,7 +5045,11 @@ open class KotlinFileExtractor(
tw.writeCallableBinding(idMemberRef, ids.constructor)
val targetCallableId = useFunction<DbCallable>(target.owner.realOverrideTarget, classTypeArguments)
if (targetCallableId == null) {
logger.errorElement("Cannot get ID for function reference callable", functionReferenceExpr)
} else {
tw.writeMemberRefBinding(idMemberRef, targetCallableId)
}
val helper = CallableReferenceHelper(functionReferenceExpr, locId, ids)
@@ -5154,7 +5195,11 @@ open class KotlinFileExtractor(
tw.writeExprsKotlinType(callId, callType.kotlinResult.id)
extractExprContext(callId, locId, funLabels.methodId, retId)
val calledMethodId = useFunction<DbMethod>(lambda)
if (calledMethodId == null) {
logger.errorElement("Cannot get ID for called lambda", lambda)
} else {
tw.writeCallableBinding(callId, calledMethodId)
}
// this access
extractThisAccess(ids.type, funLabels.methodId, callId, -1, retId, locId)
@@ -5623,7 +5668,11 @@ open class KotlinFileExtractor(
tw.writeExprsKotlinType(callId, callType.kotlinResult.id)
extractExprContext(callId, locId, ids.function, returnId)
val calledMethodId = useFunction<DbMethod>(invokeMethod, functionType.arguments)
if (calledMethodId == null) {
logger.errorElement("Cannot get ID for called method", invokeMethod)
} else {
tw.writeCallableBinding(callId, calledMethodId)
}
// <fn> access
val lhsId = tw.getFreshIdLabel<DbVaraccess>()
@@ -5745,17 +5794,20 @@ open class KotlinFileExtractor(
val baseConstructor = baseClass.owner.declarations.findSubType<IrFunction> { it.symbol is IrConstructorSymbol && superConstructorSelector(it) }
if (baseConstructor == null) {
logger.warnElement("Cannot find base constructor", elementToReportOn)
} else {
val baseConstructorId = useFunction<DbConstructor>(baseConstructor)
if (baseConstructorId == null) {
logger.errorElement("Cannot find base constructor ID", elementToReportOn)
} else {
val superCallId = tw.getFreshIdLabel<DbSuperconstructorinvocationstmt>()
tw.writeStmts_superconstructorinvocationstmt(superCallId, constructorBlockId, 0, ids.constructor)
val baseConstructorId = useFunction<DbConstructor>(baseConstructor)
tw.writeHasLocation(superCallId, locId)
tw.writeCallableBinding(superCallId.cast<DbCaller>(), baseConstructorId)
extractSuperconstructorArgs(superCallId)
}
}
}
addModifiers(id, "final")
addVisibilityModifierToLocalOrAnonymousClass(id)

View File

@@ -1322,16 +1322,30 @@ open class KotlinUsesExtractor(
else -> false
}
fun <T: DbCallable> useFunction(f: IrFunction, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>? = null, noReplace: Boolean = false): Label<out T> {
return useFunction(f, null, classTypeArgsIncludingOuterClasses, noReplace)
}
fun <T: DbCallable> useFunction(f: IrFunction, parentId: Label<out DbElement>?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, noReplace: Boolean = false): Label<out T> {
fun <T: DbCallable> useFunction(f: IrFunction, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>? = null, noReplace: Boolean = false): Label<out T>? {
if (f.isLocalFunction()) {
val ids = getLocallyVisibleFunctionLabels(f)
return ids.function.cast<T>()
}
val javaFun = kotlinFunctionToJavaEquivalent(f, noReplace)
val parentId = useDeclarationParent(javaFun.parent, false, classTypeArgsIncludingOuterClasses, true)
if (parentId == null) {
logger.error("Couldn't find parent ID for function ${f.name.asString()}")
return null
}
return useFunction(f, javaFun, parentId, classTypeArgsIncludingOuterClasses)
}
fun <T: DbCallable> useFunction(f: IrFunction, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, noReplace: Boolean = false): Label<out T> {
if (f.isLocalFunction()) {
val ids = getLocallyVisibleFunctionLabels(f)
return ids.function.cast<T>()
}
val javaFun = kotlinFunctionToJavaEquivalent(f, noReplace)
return useFunction(f, javaFun, parentId, classTypeArgsIncludingOuterClasses)
}
private fun <T: DbCallable> useFunction(f: IrFunction, javaFun: IrFunction, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?): Label<out T> {
val label = getFunctionLabel(javaFun, parentId, classTypeArgsIncludingOuterClasses)
val id: Label<T> = tw.getLabelFor(label) {
extractPrivateSpecialisedDeclaration(f, classTypeArgsIncludingOuterClasses)