JS: fix copying fun with default args from interface to abstract class

See KT-20451
This commit is contained in:
Alexey Andreev
2017-09-26 16:20:07 +03:00
parent 676e5d2a88
commit 43c6f8b9b1
6 changed files with 47 additions and 3 deletions
@@ -0,0 +1,17 @@
interface I {
fun foo(x: Int = 23): String
}
abstract class Base : I
class C : Base(), I {
override fun foo(x: Int) = "C:$x"
}
fun box(): String {
val x: I = C()
val r = x.foo() + ";" + x.foo(42)
if (r != "C:23;C:42") return "fail: $r"
return "OK"
}
@@ -6479,6 +6479,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("inheritedFromInterfaceViaAbstractSuperclass.kt")
public void testInheritedFromInterfaceViaAbstractSuperclass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/inheritedFromInterfaceViaAbstractSuperclass.kt");
doTest(fileName);
}
@TestMetadata("kt6382.kt")
public void testKt6382() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/kt6382.kt");
@@ -6479,6 +6479,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("inheritedFromInterfaceViaAbstractSuperclass.kt")
public void testInheritedFromInterfaceViaAbstractSuperclass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/inheritedFromInterfaceViaAbstractSuperclass.kt");
doTest(fileName);
}
@TestMetadata("kt6382.kt")
public void testKt6382() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/kt6382.kt");
@@ -6479,6 +6479,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/defaultArguments"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("inheritedFromInterfaceViaAbstractSuperclass.kt")
public void testInheritedFromInterfaceViaAbstractSuperclass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/inheritedFromInterfaceViaAbstractSuperclass.kt");
doTest(fileName);
}
@TestMetadata("kt6382.kt")
public void testKt6382() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/kt6382.kt");
@@ -7151,6 +7151,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("inheritedFromInterfaceViaAbstractSuperclass.kt")
public void testInheritedFromInterfaceViaAbstractSuperclass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/inheritedFromInterfaceViaAbstractSuperclass.kt");
doTest(fileName);
}
@TestMetadata("kt6382.kt")
public void testKt6382() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/kt6382.kt");
@@ -54,7 +54,7 @@ class ClassModelGenerator(val context: TranslationContext) {
// Traverse fake non-abstract member. Current class does not provide their implementation,
// it can be inherited from interface.
for (member in members.filter { !it.kind.isReal && it.modality != Modality.ABSTRACT }) {
for (member in members.filter { !it.kind.isReal }) {
if (member is FunctionDescriptor) {
tryCopyWhenImplementingInterfaceWithDefaultArgs(member, model)
}
@@ -63,7 +63,7 @@ class ClassModelGenerator(val context: TranslationContext) {
// Copy *implementation* functions (i.e. those ones which end with `$default` suffix)
// of Kotlin functions with optional parameters.
if (member is FunctionDescriptor && !hasImplementationInPrototype(member)) {
if (member is FunctionDescriptor && !hasImplementationInPrototype(member) && member.modality != Modality.ABSTRACT) {
copyMemberWithOptionalArgs(descriptor, member, model, Namer.DEFAULT_PARAMETER_IMPLEMENTOR_SUFFIX)
}
}
@@ -155,7 +155,10 @@ class ClassModelGenerator(val context: TranslationContext) {
// When none found, we have nothing to copy, ignore.
// When multiple found, our current class should provide implementation, ignore.
val memberToCopy = member.findNonRepeatingOverriddenDescriptors({ overriddenDescriptors }, { original })
.singleOrNull { it.modality != Modality.ABSTRACT } ?: return null
.singleOrNull {
it.modality != Modality.ABSTRACT ||
(it is FunctionDescriptor && it.hasOwnParametersWithDefaultValue())
} ?: return null
// If found member is not from interface, we don't need to copy it, it's already in prototype
if ((memberToCopy.containingDeclaration as ClassDescriptor).kind != ClassKind.INTERFACE) return null