Kotlin: Put overloads together

Makes it easier when reading the code.

The substituteTypeArguments functions aren't actually overloads, but I
think the same applies.
This commit is contained in:
Ian Lynagh
2022-06-09 17:43:11 +01:00
parent 4a025053cc
commit 6055aaf048
4 changed files with 62 additions and 64 deletions

View File

@@ -19,6 +19,9 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
val externalDeclsDone = HashSet<IrDeclaration>()
val externalDeclWorkList = ArrayList<Pair<IrDeclaration, String>>()
val propertySignature = ";property"
val fieldSignature = ";field"
fun extractLater(d: IrDeclaration, signature: String): Boolean {
if (d !is IrClass && !isExternalFileClassMember(d)) {
logger.errorElement("External declaration is neither a class, nor a top-level declaration", d)
@@ -28,13 +31,8 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
if (ret) externalDeclWorkList.add(Pair(d, signature))
return ret
}
val propertySignature = ";property"
val fieldSignature = ";field"
fun extractLater(p: IrProperty) = extractLater(p, propertySignature)
fun extractLater(f: IrField) = extractLater(f, fieldSignature)
fun extractLater(c: IrClass) = extractLater(c, "")
fun extractExternalClasses() {

View File

@@ -975,35 +975,6 @@ open class KotlinUsesExtractor(
return getFunctionLabel(f, null, classTypeArgsIncludingOuterClasses)
}
fun getAdjustedReturnType(f: IrFunction) : IrType {
// The return type of `java.util.concurrent.ConcurrentHashMap<K,V>.keySet/0` is defined as `Set<K>` in the stubs inside the Android SDK.
// This does not match the Java SDK return type: `ConcurrentHashMap.KeySetView<K,V>`, so it's adjusted here.
// This is a deliberate change in the Android SDK: https://github.com/AndroidSDKSources/android-sdk-sources-for-api-level-31/blob/2c56b25f619575bea12f9c5520ed2259620084ac/java/util/concurrent/ConcurrentHashMap.java#L1244-L1249
// The annotation on the source is not visible in the android.jar, so we can't make the change based on that.
// TODO: there are other instances of `dalvik.annotation.codegen.CovariantReturnType` in the Android SDK, we should handle those too if they cause DB inconsistencies
val parentClass = f.parentClassOrNull
if (parentClass == null ||
parentClass.fqNameWhenAvailable?.asString() != "java.util.concurrent.ConcurrentHashMap" ||
getFunctionShortName(f).nameInDB != "keySet" ||
f.valueParameters.isNotEmpty() ||
f.returnType.classFqName?.asString() != "kotlin.collections.MutableSet") {
return f.returnType
}
val otherKeySet = parentClass.declarations.filterIsInstance<IrFunction>().find { it.name.asString() == "keySet" && it.valueParameters.size == 1 }
?: return f.returnType
return otherKeySet.returnType.codeQlWithHasQuestionMark(false)
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun getJavaMethod(f: IrFunction) = (f.descriptor.source as? JavaSourceElement)?.javaElement as? JavaMethod
fun hasWildcardSuppressionAnnotation(d: IrDeclaration) =
d.hasAnnotation(jvmWildcardSuppressionAnnotaton) ||
// Note not using `parentsWithSelf` as that only works if `d` is an IrDeclarationParent
d.parents.any { (it as? IrAnnotationContainer)?.hasAnnotation(jvmWildcardSuppressionAnnotaton) == true }
/*
* There are some pairs of classes (e.g. `kotlin.Throwable` and
* `java.lang.Throwable`) which are really just 2 different names
@@ -1110,6 +1081,35 @@ open class KotlinUsesExtractor(
return "@\"$prefix;{$parentId}.$name($paramTypeIds){$returnTypeId}${typeArgSuffix}\""
}
fun getAdjustedReturnType(f: IrFunction) : IrType {
// The return type of `java.util.concurrent.ConcurrentHashMap<K,V>.keySet/0` is defined as `Set<K>` in the stubs inside the Android SDK.
// This does not match the Java SDK return type: `ConcurrentHashMap.KeySetView<K,V>`, so it's adjusted here.
// This is a deliberate change in the Android SDK: https://github.com/AndroidSDKSources/android-sdk-sources-for-api-level-31/blob/2c56b25f619575bea12f9c5520ed2259620084ac/java/util/concurrent/ConcurrentHashMap.java#L1244-L1249
// The annotation on the source is not visible in the android.jar, so we can't make the change based on that.
// TODO: there are other instances of `dalvik.annotation.codegen.CovariantReturnType` in the Android SDK, we should handle those too if they cause DB inconsistencies
val parentClass = f.parentClassOrNull
if (parentClass == null ||
parentClass.fqNameWhenAvailable?.asString() != "java.util.concurrent.ConcurrentHashMap" ||
getFunctionShortName(f).nameInDB != "keySet" ||
f.valueParameters.isNotEmpty() ||
f.returnType.classFqName?.asString() != "kotlin.collections.MutableSet") {
return f.returnType
}
val otherKeySet = parentClass.declarations.filterIsInstance<IrFunction>().find { it.name.asString() == "keySet" && it.valueParameters.size == 1 }
?: return f.returnType
return otherKeySet.returnType.codeQlWithHasQuestionMark(false)
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun getJavaMethod(f: IrFunction) = (f.descriptor.source as? JavaSourceElement)?.javaElement as? JavaMethod
fun hasWildcardSuppressionAnnotation(d: IrDeclaration) =
d.hasAnnotation(jvmWildcardSuppressionAnnotaton) ||
// Note not using `parentsWithSelf` as that only works if `d` is an IrDeclarationParent
d.parents.any { (it as? IrAnnotationContainer)?.hasAnnotation(jvmWildcardSuppressionAnnotaton) == true }
protected fun IrFunction.isLocalFunction(): Boolean {
return this.visibility == DescriptorVisibilities.LOCAL
}

View File

@@ -276,12 +276,6 @@ open class FileTrapWriter (
fun getLocation(e: IrElement): Label<DbLocation> {
return getLocation(e.startOffset, e.endOffset)
}
/**
* Gets a label for the location representing the whole of this file.
*/
fun getWholeFileLocation(): Label<DbLocation> {
return getWholeFileLocation(fileId)
}
/**
* Gets a label for the location corresponding to `startOffset` and
* `endOffset` within this file.
@@ -303,6 +297,12 @@ open class FileTrapWriter (
// to be 0.
return "file://$filePath"
}
/**
* Gets a label for the location representing the whole of this file.
*/
fun getWholeFileLocation(): Label<DbLocation> {
return getWholeFileLocation(fileId)
}
}
/**

View File

@@ -37,6 +37,30 @@ fun IrType.substituteTypeArguments(params: List<IrTypeParameter>, arguments: Lis
else -> this
}
fun IrSimpleType.substituteTypeArguments(substitutionMap: Map<IrTypeParameterSymbol, IrTypeArgument>): IrSimpleType {
if (substitutionMap.isEmpty()) return this
val newArguments = arguments.map {
if (it is IrTypeProjection) {
val itType = it.type
if (itType is IrSimpleType) {
subProjectedType(substitutionMap, itType, it.variance)
} else {
it
}
} else {
it
}
}
return IrSimpleTypeImpl(
classifier,
hasQuestionMark,
newArguments,
annotations
)
}
/**
* Returns true if substituting `innerVariance T` into the context `outerVariance []` discards all knowledge about
* what T could be.
@@ -76,30 +100,6 @@ private fun subProjectedType(substitutionMap: Map<IrTypeParameterSymbol, IrTypeA
}
} ?: makeTypeProjection(t.substituteTypeArguments(substitutionMap), outerVariance)
fun IrSimpleType.substituteTypeArguments(substitutionMap: Map<IrTypeParameterSymbol, IrTypeArgument>): IrSimpleType {
if (substitutionMap.isEmpty()) return this
val newArguments = arguments.map {
if (it is IrTypeProjection) {
val itType = it.type
if (itType is IrSimpleType) {
subProjectedType(substitutionMap, itType, it.variance)
} else {
it
}
} else {
it
}
}
return IrSimpleTypeImpl(
classifier,
hasQuestionMark,
newArguments,
annotations
)
}
fun IrTypeArgument.upperBound(context: IrPluginContext) =
when(this) {
is IrStarProjection -> context.irBuiltIns.anyNType