JS: fix generation of bridge methods for non-abstract methods inherited from interfaces
This commit is contained in:
+48
-24
@@ -503,25 +503,28 @@ class ClassTranslator private constructor(
|
|||||||
.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
|
.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
|
||||||
.mapNotNull { it as? CallableMemberDescriptor }
|
.mapNotNull { it as? CallableMemberDescriptor }
|
||||||
for (member in members) {
|
for (member in members) {
|
||||||
if (member.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) continue
|
if (member.kind.isReal) continue
|
||||||
if (member.modality == Modality.ABSTRACT || member.overriddenDescriptors.size != 1) continue
|
if (member.modality == Modality.ABSTRACT || member.overriddenDescriptors.size != 1) continue
|
||||||
|
|
||||||
val overriddenFunction = generateSequence(member) { it.overriddenDescriptors.firstOrNull() }
|
val overriddenMember = generateSequence(member) { it.overriddenDescriptors.firstOrNull() }
|
||||||
.drop(1)
|
.drop(1)
|
||||||
.dropWhile { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
|
.dropWhile { !it.kind.isReal && DescriptorUtils.isInterface(it.containingDeclaration) }
|
||||||
DescriptorUtils.isInterface(it.containingDeclaration) }
|
.firstOrNull() ?: continue
|
||||||
.firstOrNull() ?: continue
|
|
||||||
|
|
||||||
if (overriddenFunction.modality == Modality.ABSTRACT) continue
|
if (overriddenMember.modality == Modality.ABSTRACT) continue
|
||||||
|
|
||||||
val interfaceDescriptor = overriddenFunction.containingDeclaration as ClassDescriptor
|
val interfaceDescriptor = overriddenMember.containingDeclaration as ClassDescriptor
|
||||||
if (interfaceDescriptor.kind != ClassKind.INTERFACE) continue
|
if (interfaceDescriptor.kind != ClassKind.INTERFACE) continue
|
||||||
|
|
||||||
val directContainer = member.overriddenDescriptors.first().containingDeclaration as ClassDescriptor
|
val directContainer = member.overriddenDescriptors.first().containingDeclaration as ClassDescriptor
|
||||||
|
|
||||||
when (member) {
|
when (overriddenMember) {
|
||||||
is FunctionDescriptor -> addDefaultMethodFromInterface(member, directContainer, descriptor, context)
|
is FunctionDescriptor -> {
|
||||||
is PropertyDescriptor -> addDefaultPropertyFromInterface(member, directContainer, descriptor, context)
|
addDefaultMethodFromInterface(overriddenMember, directContainer, descriptor,context)
|
||||||
|
}
|
||||||
|
is PropertyDescriptor -> {
|
||||||
|
addDefaultPropertyFromInterface(overriddenMember, directContainer, descriptor, context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -532,12 +535,13 @@ class ClassTranslator private constructor(
|
|||||||
descriptor: ClassDescriptor,
|
descriptor: ClassDescriptor,
|
||||||
context: StaticContext
|
context: StaticContext
|
||||||
) {
|
) {
|
||||||
val classPrototype = JsAstUtils.prototypeOf(pureFqn(context.getInnerNameForDescriptor(descriptor), null))
|
for (name in generateAllNames(function, context)) {
|
||||||
val interfacePrototype = JsAstUtils.prototypeOf(pureFqn(context.getInnerNameForDescriptor(interfaceDescriptor), null))
|
val classPrototype = JsAstUtils.prototypeOf(pureFqn(context.getInnerNameForDescriptor(descriptor), null))
|
||||||
val functionName = context.getNameForDescriptor(function)
|
val interfacePrototype = JsAstUtils.prototypeOf(pureFqn(context.getInnerNameForDescriptor(interfaceDescriptor), null))
|
||||||
val classFunction = JsNameRef(functionName, classPrototype)
|
val classFunction = JsNameRef(name, classPrototype)
|
||||||
val interfaceFunction = JsNameRef(functionName, interfacePrototype)
|
val interfaceFunction = JsNameRef(name, interfacePrototype)
|
||||||
context.declarationStatements += JsAstUtils.assignment(classFunction, interfaceFunction).makeStmt()
|
context.declarationStatements += JsAstUtils.assignment(classFunction, interfaceFunction).makeStmt()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addDefaultPropertyFromInterface(
|
private fun addDefaultPropertyFromInterface(
|
||||||
@@ -546,15 +550,35 @@ class ClassTranslator private constructor(
|
|||||||
descriptor: ClassDescriptor,
|
descriptor: ClassDescriptor,
|
||||||
context: StaticContext
|
context: StaticContext
|
||||||
) {
|
) {
|
||||||
val classPrototype = JsAstUtils.prototypeOf(pureFqn(context.getInnerNameForDescriptor(descriptor), null))
|
for (name in generateAllNames(property, context)) {
|
||||||
val interfacePrototype = JsAstUtils.prototypeOf(pureFqn(context.getInnerNameForDescriptor(interfaceDescriptor), null))
|
val classPrototype = JsAstUtils.prototypeOf(pureFqn(context.getInnerNameForDescriptor(descriptor), null))
|
||||||
val functionName = context.getNameForDescriptor(property)
|
val interfacePrototype = JsAstUtils.prototypeOf(pureFqn(context.getInnerNameForDescriptor(interfaceDescriptor), null))
|
||||||
val nameLiteral = context.program.getStringLiteral(functionName.ident)
|
val nameLiteral = context.program.getStringLiteral(name.ident)
|
||||||
|
|
||||||
val getPropertyDescriptor = JsInvocation(JsNameRef("getOwnPropertyDescriptor", "Object"), interfacePrototype, nameLiteral)
|
val getPropertyDescriptor = JsInvocation(JsNameRef("getOwnPropertyDescriptor", "Object"), interfacePrototype, nameLiteral)
|
||||||
val defineProperty = JsAstUtils.defineProperty(classPrototype, functionName.ident, getPropertyDescriptor, context.program)
|
val defineProperty = JsAstUtils.defineProperty(classPrototype, name.ident, getPropertyDescriptor, context.program)
|
||||||
|
|
||||||
context.declarationStatements += defineProperty.makeStmt()
|
context.declarationStatements += defineProperty.makeStmt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateAllNames(member: CallableMemberDescriptor, context: StaticContext): Sequence<JsName> {
|
||||||
|
return (generateBridges(member) + member)
|
||||||
|
.map { context.getNameForDescriptor(it) }
|
||||||
|
.distinctBy { it.ident }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateBridges(member: CallableMemberDescriptor): Sequence<CallableMemberDescriptor> = when (member) {
|
||||||
|
is FunctionDescriptor -> {
|
||||||
|
generateBridgesForFunctionDescriptor(member, identity()) { false }
|
||||||
|
.map { it.from }
|
||||||
|
.asSequence()
|
||||||
|
}
|
||||||
|
is PropertyDescriptor -> generateBridgesForFunctionDescriptor(member.getter!!, identity()) { false }
|
||||||
|
.map { it.from }
|
||||||
|
.map { (it as PropertyAccessorDescriptor).correspondingProperty }
|
||||||
|
.asSequence()
|
||||||
|
else -> error("Expected either be function or property: $member")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user