Merge pull request #10646 from tamasvajk/kotlin-java-kotlin-function-mapping

Kotlin: Simplify `kotlinFunctionToJavaEquivalent`
This commit is contained in:
Ian Lynagh
2022-10-04 13:46:22 +01:00
committed by GitHub
17 changed files with 361 additions and 139 deletions

View File

@@ -1267,13 +1267,6 @@ open class KotlinUsesExtractor(
return tw.lm.locallyVisibleFunctionLabelMapping[f]?.function
}
// These are classes with Java equivalents, but whose methods don't all exist on those Java equivalents--
// for example, the numeric classes define arithmetic functions (Int.plus, Long.or and so on) that lower to
// primitive arithmetic on the JVM, but which we extract as calls to reflect the source syntax more closely.
private val expectedMissingEquivalents = setOf(
"kotlin.Boolean", "kotlin.Byte", "kotlin.Char", "kotlin.Double", "kotlin.Float", "kotlin.Int", "kotlin.Long", "kotlin.Number", "kotlin.Short"
)
private fun kotlinFunctionToJavaEquivalent(f: IrFunction, noReplace: Boolean): IrFunction =
if (noReplace)
f
@@ -1281,17 +1274,18 @@ open class KotlinUsesExtractor(
f.parentClassOrNull?.let { parentClass ->
getJavaEquivalentClass(parentClass)?.let { javaClass ->
if (javaClass != parentClass) {
val jvmName = getJvmName(f) ?: f.name.asString()
var jvmName = getFunctionShortName(f).nameInDB
if (f.name.asString() == "get" && parentClass.fqNameWhenAvailable?.asString() == "kotlin.String") {
// `kotlin.String.get` has an equivalent `java.lang.String.get`, which in turn will be stored in the DB as `java.lang.String.charAt`.
// Maybe all operators should be handled the same way, but so far I only found this case that needed to be special cased. This is the
// only operator in `JvmNames.specialFunctions`
jvmName = "get"
}
// Look for an exact type match...
javaClass.declarations.findSubType<IrFunction> { decl ->
decl.name.asString() == jvmName &&
decl.valueParameters.size == f.valueParameters.size &&
decl.valueParameters.zip(f.valueParameters).all { p -> erase(p.first.type) == erase(p.second.type) }
} ?:
// Or if there is none, look for the only viable overload
javaClass.declarations.singleOrNullSubType<IrFunction> { decl ->
decl.name.asString() == jvmName &&
decl.valueParameters.size == f.valueParameters.size
decl.valueParameters.zip(f.valueParameters).all { p -> erase(p.first.type).classifierOrNull == erase(p.second.type).classifierOrNull }
} ?:
// Or check property accessors:
(f.propertyIfAccessor as? IrProperty)?.let { kotlinProp ->
@@ -1305,9 +1299,7 @@ open class KotlinUsesExtractor(
else null
} ?: run {
val parentFqName = parentClass.fqNameWhenAvailable?.asString()
if (!expectedMissingEquivalents.contains(parentFqName)) {
logger.warn("Couldn't find a Java equivalent function to $parentFqName.${f.name} in ${javaClass.fqNameWhenAvailable}")
}
logger.warn("Couldn't find a Java equivalent function to $parentFqName.${f.name.asString()} in ${javaClass.fqNameWhenAvailable?.asString()}")
null
}
}