Don't replace own callables, and use a more exact replacement-finding test

This commit is contained in:
Chris Smowton
2022-04-20 11:46:26 +01:00
parent ce87a89009
commit 71d2e7be3e
2 changed files with 34 additions and 19 deletions

View File

@@ -682,7 +682,9 @@ open class KotlinFileExtractor(
?: if (f.isLocalFunction()) ?: if (f.isLocalFunction())
getLocallyVisibleFunctionLabels(f).function getLocallyVisibleFunctionLabels(f).function
else else
useFunction<DbCallable>(f, parentId, classTypeArgsIncludingOuterClasses) // If this is a class that would ordinarily be replaced by a Java equivalent (e.g. kotlin.Map -> java.util.Map),
// don't replace here, really extract the Kotlin version:
useFunction<DbCallable>(f, parentId, classTypeArgsIncludingOuterClasses, noReplace = true)
val sourceDeclaration = val sourceDeclaration =
if (typeSubstitution != null) if (typeSubstitution != null)

View File

@@ -899,34 +899,47 @@ open class KotlinUsesExtractor(
return id return id
} }
fun kotlinFunctionToJavaEquivalent(f: IrFunction) = fun kotlinFunctionToJavaEquivalent(f: IrFunction, noReplace: Boolean) =
f.parent.let { if (noReplace)
when (it) { f
is IrClass -> else
getJavaEquivalentClass(it)?.let { javaClass -> f.parentClassOrNull?.let { parentClass ->
if (javaClass != it) getJavaEquivalentClass(parentClass)?.let { javaClass ->
javaClass.declarations.find { decl -> if (javaClass != parentClass)
decl is IrFunction && decl.name == f.name && decl.valueParameters.size == f.valueParameters.size // Look for an exact type match...
} as IrFunction javaClass.declarations.find { decl ->
else decl is IrFunction &&
decl.name == f.name &&
decl.valueParameters.size == f.valueParameters.size &&
decl.valueParameters.zip(f.valueParameters).all { p -> p.first.type == p.second.type }
} ?:
// Or if there is none, look for the only viable overload
javaClass.declarations.singleOrNull { decl ->
decl is IrFunction &&
decl.name == f.name &&
decl.valueParameters.size == f.valueParameters.size
} ?:
run {
logger.warn("Couldn't find a Java equivalent function to ${f.name}")
null null
} }
else -> null else
} ?: f null
} }
} as IrFunction? ?: f
fun <T: DbCallable> useFunction(f: IrFunction, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>? = null): Label<out T> { fun <T: DbCallable> useFunction(f: IrFunction, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>? = null, noReplace: Boolean = false): Label<out T> {
if (f.isLocalFunction()) { if (f.isLocalFunction()) {
val ids = getLocallyVisibleFunctionLabels(f) val ids = getLocallyVisibleFunctionLabels(f)
return ids.function.cast<T>() return ids.function.cast<T>()
} else { } else {
val realFunction = kotlinFunctionToJavaEquivalent(f) val realFunction = kotlinFunctionToJavaEquivalent(f, noReplace)
return useFunctionCommon<T>(realFunction, getFunctionLabel(realFunction, classTypeArgsIncludingOuterClasses)) return useFunctionCommon<T>(realFunction, getFunctionLabel(realFunction, classTypeArgsIncludingOuterClasses))
} }
} }
fun <T: DbCallable> useFunction(f: IrFunction, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?) = fun <T: DbCallable> useFunction(f: IrFunction, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, noReplace: Boolean = false) =
kotlinFunctionToJavaEquivalent(f).let { kotlinFunctionToJavaEquivalent(f, noReplace).let {
useFunctionCommon<T>(it, getFunctionLabel(it, parentId, classTypeArgsIncludingOuterClasses)) useFunctionCommon<T>(it, getFunctionLabel(it, parentId, classTypeArgsIncludingOuterClasses))
} }