From c767b3d0acaccff977849b8987d06749e48e7aef Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 8 Jul 2016 20:06:08 +0300 Subject: [PATCH] KT-13043: fix translation of super call from secondary constructor when base constructor has default arguments --- .../test/semantics/DefaultArgumentsTest.java | 12 ++++++++++++ .../translate/declaration/ClassTranslator.kt | 4 +++- .../ClassInitializerTranslator.java | 2 +- .../kotlin/js/translate/utils/astUtils.kt | 9 ++++----- .../cases/enumSuperConstructor.kt | 16 ++++++++++++++++ .../cases/primarySuperConstructor.kt | 16 ++++++++++++++++ .../cases/secondarySuperConstructor.kt | 18 ++++++++++++++++++ 7 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 js/js.translator/testData/defaultArguments/cases/enumSuperConstructor.kt create mode 100644 js/js.translator/testData/defaultArguments/cases/primarySuperConstructor.kt create mode 100644 js/js.translator/testData/defaultArguments/cases/secondarySuperConstructor.kt diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/DefaultArgumentsTest.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/DefaultArgumentsTest.java index 9c09ec6ab77..a723cb2a551 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/DefaultArgumentsTest.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/DefaultArgumentsTest.java @@ -71,4 +71,16 @@ public class DefaultArgumentsTest extends SingleFileTranslationTest { public void testDefaultArgumentsInFunctionWithExpressionAsBody() throws Exception { checkFooBoxIsOk(); } + + public void testPrimarySuperConstructor() throws Exception { + checkFooBoxIsOk(); + } + + public void testSecondarySuperConstructor() throws Exception { + checkFooBoxIsOk(); + } + + public void testEnumSuperConstructor() throws Exception { + checkFooBoxIsOk(); + } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt index 95d4f8f9314..c286e95ec16 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt @@ -205,7 +205,9 @@ class ClassTranslator private constructor( if (resolvedCall != null && !KotlinBuiltIns.isAny(delegationClassDescriptor!!)) { superCallGenerators += { - it += CallTranslator.translate(context, resolvedCall).toInvocationWith(leadingArgs, thisNameRef).makeStmt() + val delegationConstructor = resolvedCall.resultingDescriptor + it += CallTranslator.translate(context, resolvedCall) + .toInvocationWith(leadingArgs, delegationConstructor.valueParameters.size, thisNameRef).makeStmt() } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/initializer/ClassInitializerTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/initializer/ClassInitializerTranslator.java index 494e635c672..b27ad5e9c15 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/initializer/ClassInitializerTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/initializer/ClassInitializerTranslator.java @@ -168,7 +168,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator { if (classDeclaration instanceof KtEnumEntry) { JsExpression expression = CallTranslator.translate(context(), superCall, null); - JsExpression fixedInvocation = AstUtilsKt.toInvocationWith(expression, Collections.emptyList(), + JsExpression fixedInvocation = AstUtilsKt.toInvocationWith(expression, Collections.emptyList(), 0, JsLiteral.THIS); initializerStatements.add(0, fixedInvocation.makeStmt()); } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/astUtils.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/astUtils.kt index 4e1db7ee50c..c96d44170b4 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/astUtils.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/astUtils.kt @@ -56,22 +56,21 @@ fun JsNode.any(predicate: (JsNode) -> Boolean): Boolean { return visitor.matched } -fun JsExpression.toInvocationWith(leadingExtraArgs: List, thisExpr: JsExpression): JsExpression { +fun JsExpression.toInvocationWith(leadingExtraArgs: List, parameterCount: Int, thisExpr: JsExpression): JsExpression { val qualifier: JsExpression - val arguments: MutableList + fun padArguments(arguments: List) = arguments + (1..(parameterCount - arguments.size)) + .map { Namer.getUndefinedExpression() } when (this) { is JsNew -> { qualifier = Namer.getFunctionCallRef(constructorExpression) - arguments = getArguments() // `new A(a, b, c)` -> `A.call($this, a, b, c)` return JsInvocation(qualifier, listOf(thisExpr) + leadingExtraArgs + arguments) } is JsInvocation -> { qualifier = getQualifier() - arguments = getArguments() // `A(a, b, c)` -> `A(a, b, c, $this)` - return JsInvocation(qualifier, leadingExtraArgs + arguments + thisExpr) + return JsInvocation(qualifier, leadingExtraArgs + padArguments(arguments) + thisExpr) } else -> throw IllegalStateException("Unexpected node type: " + javaClass) } diff --git a/js/js.translator/testData/defaultArguments/cases/enumSuperConstructor.kt b/js/js.translator/testData/defaultArguments/cases/enumSuperConstructor.kt new file mode 100644 index 00000000000..41bc6908b75 --- /dev/null +++ b/js/js.translator/testData/defaultArguments/cases/enumSuperConstructor.kt @@ -0,0 +1,16 @@ +package foo + +enum class A { + B(2); + + val c: Int + + constructor (a: Int, b: Int = 3) { + c = a + b + } +} + +fun box(): String { + assertEquals(5, A.B.c) + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/defaultArguments/cases/primarySuperConstructor.kt b/js/js.translator/testData/defaultArguments/cases/primarySuperConstructor.kt new file mode 100644 index 00000000000..fc4fdcb6d1a --- /dev/null +++ b/js/js.translator/testData/defaultArguments/cases/primarySuperConstructor.kt @@ -0,0 +1,16 @@ +package foo + +open class Base(a: Int, b: Int = 3) { + val c: Int + + init { + c = a + b + } +} + +class Derived(a: Int) : Base(a) + +fun box(): String { + assertEquals(5, Derived(2).c) + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/defaultArguments/cases/secondarySuperConstructor.kt b/js/js.translator/testData/defaultArguments/cases/secondarySuperConstructor.kt new file mode 100644 index 00000000000..de22ae97f37 --- /dev/null +++ b/js/js.translator/testData/defaultArguments/cases/secondarySuperConstructor.kt @@ -0,0 +1,18 @@ +package foo + +open class Base { + val c: Int + + constructor(a: Int, b: Int = 3) { + c = a + b + } +} + +class Derived : Base { + constructor(a: Int) : super(a) +} + +fun box(): String { + assertEquals(5, Derived(2).c) + return "OK" +} \ No newline at end of file