From e4ca831f067e0f3df5179901581410f879cb94c2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Wed, 12 Sep 2018 11:47:07 +0300 Subject: [PATCH] Don't add overriding and refining interface methods to framework protocols As this appears to be inconvenient when adopting in Swift: #1884 --- .../objcexport/ObjCExportHeaderGenerator.kt | 112 +++++++++++++----- 1 file changed, 84 insertions(+), 28 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt index c8f7eb8b5f2..497af70c9cc 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt @@ -310,7 +310,7 @@ abstract class ObjCExportHeaderGenerator( if (!generatedClasses.add(descriptor)) return val name = translateClassName(descriptor) - val members: List> = buildMembers { translateClassOrInterfaceMembers(descriptor) } + val members: List> = buildMembers { translateInterfaceMembers(descriptor) } val superProtocols: List = descriptor.superProtocols val protocolStub = objCProtocol(name, descriptor, superProtocols, members) @@ -334,7 +334,7 @@ abstract class ObjCExportHeaderGenerator( val name = translateClassName(classDescriptor).objCName val members = buildMembers { - translateMembers(declarations) + translatePlainMembers(declarations) } stubs.add(ObjCInterface(name, categoryName = "Extensions", members = members)) } @@ -344,7 +344,7 @@ abstract class ObjCExportHeaderGenerator( // TODO: stop inheriting KotlinBase. val members = buildMembers { - translateMembers(declarations) + translatePlainMembers(declarations) } stubs.add(objCInterface( name, @@ -432,7 +432,7 @@ abstract class ObjCExportHeaderGenerator( } } - translateClassOrInterfaceMembers(descriptor) + translateClassMembers(descriptor) } val attributes = if (descriptor.isFinalOrEnum) listOf("objc_subclassing_restricted") else emptyList() @@ -448,14 +448,21 @@ abstract class ObjCExportHeaderGenerator( stubs.add(interfaceStub) } - private fun StubBuilder.translateClassOrInterfaceMembers(descriptor: ClassDescriptor) { - val members = descriptor.unsubstitutedMemberScope.getContributedDescriptors() - .asSequence() - .filterIsInstance() - .filter { mapper.shouldBeExposed(it) } - .toList() + private fun ClassDescriptor.getExposedMembers(): List = + this.unsubstitutedMemberScope.getContributedDescriptors() + .asSequence() + .filterIsInstance() + .filter { mapper.shouldBeExposed(it) } + .toList() - translateMembers(members) + private fun StubBuilder.translateClassMembers(descriptor: ClassDescriptor) { + require(!descriptor.isInterface) + translateClassMembers(descriptor.getExposedMembers()) + } + + private fun StubBuilder.translateInterfaceMembers(descriptor: ClassDescriptor) { + require(descriptor.isInterface) + translateBaseMembers(descriptor.getExposedMembers()) } private class RenderedStub>(val stub: T) { @@ -477,27 +484,68 @@ abstract class ObjCExportHeaderGenerator( } } - private fun StubBuilder.translateMembers(members: List) { + private fun List.toObjCMembers( + methodsBuffer: MutableList, + propertiesBuffer: MutableList + ) = this.forEach { + when (it) { + is FunctionDescriptor -> methodsBuffer += it + is PropertyDescriptor -> if (mapper.isObjCProperty(it)) { + propertiesBuffer += it + } else { + methodsBuffer.addIfNotNull(it.getter) + methodsBuffer.addIfNotNull(it.setter) + } + else -> error(it) + } + } + + private fun StubBuilder.translateClassMembers(members: List) { // TODO: add some marks about modality. val methods = mutableListOf() val properties = mutableListOf() - members.forEach { - when (it) { - is FunctionDescriptor -> methods += it - is PropertyDescriptor -> if (mapper.isObjCProperty(it)) { - properties += it - } else { - methods.addIfNotNull(it.getter) - methods.addIfNotNull(it.setter) - } - else -> error(it) + members.toObjCMembers(methods, properties) + + collectMethodsOrProperties(methods) { it -> buildAsDeclaredOrInheritedMethods(it.original) } + collectMethodsOrProperties(properties) { it -> buildAsDeclaredOrInheritedProperties(it.original) } + } + + private fun StubBuilder.translateBaseMembers(members: List) { + // TODO: add some marks about modality. + + val methods = mutableListOf() + val properties = mutableListOf() + + members.toObjCMembers(methods, properties) + + methods.retainAll { mapper.isBaseMethod(it) } + + properties.retainAll { + if (mapper.isBaseProperty(it)) { + true + } else { + methods.addIfNotNull(it.setter?.takeIf(mapper::isBaseMethod)) + false } } - collectMethodsOrProperties(methods) { it -> buildMethods(it.original) } - collectMethodsOrProperties(properties) { it -> buildProperties(it.original) } + translatePlainMembers(methods, properties) + } + + private fun StubBuilder.translatePlainMembers(members: List) { + val methods = mutableListOf() + val properties = mutableListOf() + + members.toObjCMembers(methods, properties) + + translatePlainMembers(methods, properties) + } + + private fun StubBuilder.translatePlainMembers(methods: List, properties: List) { + methods.forEach { +buildMethod(it, it) } + properties.forEach { +buildProperty(it, it) } } private fun > StubBuilder.collectMethodsOrProperties( @@ -521,20 +569,28 @@ abstract class ObjCExportHeaderGenerator( private val methodToSignatures = mutableMapOf>>() private val propertyToSignatures = mutableMapOf>>() - private fun buildMethods(method: FunctionDescriptor): Set> = methodToSignatures.getOrPut(method) { + private fun buildAsDeclaredOrInheritedMethods( + method: FunctionDescriptor + ): Set> = methodToSignatures.getOrPut(method) { + val isInterface = (method.containingDeclaration as ClassDescriptor).isInterface + mapper.getBaseMethods(method) .asSequence() .distinctBy { namer.getSelector(it) } - .map { base -> buildMethod(method, base) } + .map { base -> buildMethod((if (isInterface) base else method), base) } .map { method -> RenderedStub(method) } .toSet() } - private fun buildProperties(property: PropertyDescriptor): Set> = propertyToSignatures.getOrPut(property) { + private fun buildAsDeclaredOrInheritedProperties( + property: PropertyDescriptor + ): Set> = propertyToSignatures.getOrPut(property) { + val isInterface = (property.containingDeclaration as ClassDescriptor).isInterface + mapper.getBaseProperties(property) .asSequence() .distinctBy { namer.getPropertyName(it) } - .map { base -> buildProperty(property, base) } + .map { base -> buildProperty((if (isInterface) base else property), base) } .map { property -> RenderedStub(property) } .toSet() }