[K/N] Extract ObjcOverridabilityCondition to separate file

^Kt-61511
This commit is contained in:
Pavel Kunyavskiy
2023-10-08 13:40:43 +02:00
committed by Space Team
parent 4c15509776
commit 202f30f910
2 changed files with 78 additions and 64 deletions
@@ -188,70 +188,6 @@ fun IrFunction.isObjCBridgeBased(): Boolean {
this.annotations.hasAnnotation(objCConstructorFqName)
}
/**
* Describes method overriding rules for Objective-C methods.
*
* This class is applied at [org.jetbrains.kotlin.resolve.OverridingUtil] as configured with
* `META-INF/services/org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition` resource.
*/
class ObjCOverridabilityCondition : ExternalOverridabilityCondition {
override fun getContract() = ExternalOverridabilityCondition.Contract.BOTH
override fun isOverridable(
superDescriptor: CallableDescriptor,
subDescriptor: CallableDescriptor,
subClassDescriptor: ClassDescriptor?
): ExternalOverridabilityCondition.Result {
if (superDescriptor.name == subDescriptor.name) { // Slow path:
if (superDescriptor is FunctionDescriptor && subDescriptor is FunctionDescriptor) {
superDescriptor.getExternalObjCMethodInfo()?.let { superInfo ->
val subInfo = subDescriptor.getExternalObjCMethodInfo()
if (subInfo != null) {
// Overriding Objective-C method by Objective-C method in interop stubs.
// Don't even check method signatures:
return if (superInfo.selector == subInfo.selector) {
ExternalOverridabilityCondition.Result.OVERRIDABLE
} else {
ExternalOverridabilityCondition.Result.INCOMPATIBLE
}
} else {
// Overriding Objective-C method by Kotlin method.
if (!parameterNamesMatch(superDescriptor, subDescriptor)) {
return ExternalOverridabilityCondition.Result.INCOMPATIBLE
}
}
}
} else if (superDescriptor.isExternalObjCClassProperty() && subDescriptor.isExternalObjCClassProperty()) {
return ExternalOverridabilityCondition.Result.OVERRIDABLE
}
}
return ExternalOverridabilityCondition.Result.UNKNOWN
}
private fun CallableDescriptor.isExternalObjCClassProperty() = this is PropertyDescriptor &&
(this.containingDeclaration as? ClassDescriptor)?.isExternalObjCClass() == true
private fun parameterNamesMatch(first: FunctionDescriptor, second: FunctionDescriptor): Boolean {
// The original Objective-C method selector is represented as
// function name and parameter names (except first).
if (first.valueParameters.size != second.valueParameters.size) {
return false
}
first.valueParameters.forEachIndexed { index, parameter ->
if (index > 0 && parameter.name != second.valueParameters[index].name) {
return false
}
}
return true
}
}
fun IrConstructor.objCConstructorIsDesignated(): Boolean =
this.getAnnotationArgumentValue<Boolean>(objCConstructorFqName, "designated")
?: error("Could not find 'designated' argument")
@@ -0,0 +1,78 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.objcinterop
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition
/**
* Describes method overriding rules for Objective-C methods.
*
* This class is applied at [org.jetbrains.kotlin.resolve.OverridingUtil] as configured with
* `META-INF/services/org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition` resource.
*
*
*/
class ObjCOverridabilityCondition : ExternalOverridabilityCondition {
override fun getContract() = ExternalOverridabilityCondition.Contract.BOTH
override fun isOverridable(
superDescriptor: CallableDescriptor,
subDescriptor: CallableDescriptor,
subClassDescriptor: ClassDescriptor?
): ExternalOverridabilityCondition.Result {
if (superDescriptor.name == subDescriptor.name) { // Slow path:
if (superDescriptor is FunctionDescriptor && subDescriptor is FunctionDescriptor) {
superDescriptor.getExternalObjCMethodInfo()?.let { superInfo ->
val subInfo = subDescriptor.getExternalObjCMethodInfo()
if (subInfo != null) {
// Overriding Objective-C method by Objective-C method in interop stubs.
// Don't even check method signatures:
return if (superInfo.selector == subInfo.selector) {
ExternalOverridabilityCondition.Result.OVERRIDABLE
} else {
ExternalOverridabilityCondition.Result.INCOMPATIBLE
}
} else {
// Overriding Objective-C method by Kotlin method.
if (!parameterNamesMatch(superDescriptor, subDescriptor)) {
return ExternalOverridabilityCondition.Result.INCOMPATIBLE
}
}
}
} else if (superDescriptor.isExternalObjCClassProperty() && subDescriptor.isExternalObjCClassProperty()) {
return ExternalOverridabilityCondition.Result.OVERRIDABLE
}
}
return ExternalOverridabilityCondition.Result.UNKNOWN
}
private fun CallableDescriptor.isExternalObjCClassProperty() = this is PropertyDescriptor &&
(this.containingDeclaration as? ClassDescriptor)?.isExternalObjCClass() == true
private fun parameterNamesMatch(first: FunctionDescriptor, second: FunctionDescriptor): Boolean {
// The original Objective-C method selector is represented as
// function name and parameter names (except first).
if (first.valueParameters.size != second.valueParameters.size) {
return false
}
first.valueParameters.forEachIndexed { index, parameter ->
if (index > 0 && parameter.name != second.valueParameters[index].name) {
return false
}
}
return true
}
}