KT-13043: fix translation of super call from secondary constructor when base constructor has default arguments

This commit is contained in:
Alexey Andreev
2016-07-08 20:06:08 +03:00
parent b00b0caa9b
commit c767b3d0ac
7 changed files with 70 additions and 7 deletions
@@ -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();
}
}
@@ -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()
}
}
@@ -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.<JsExpression>emptyList(),
JsExpression fixedInvocation = AstUtilsKt.toInvocationWith(expression, Collections.<JsExpression>emptyList(), 0,
JsLiteral.THIS);
initializerStatements.add(0, fixedInvocation.makeStmt());
}
@@ -56,22 +56,21 @@ fun JsNode.any(predicate: (JsNode) -> Boolean): Boolean {
return visitor.matched
}
fun JsExpression.toInvocationWith(leadingExtraArgs: List<JsExpression>, thisExpr: JsExpression): JsExpression {
fun JsExpression.toInvocationWith(leadingExtraArgs: List<JsExpression>, parameterCount: Int, thisExpr: JsExpression): JsExpression {
val qualifier: JsExpression
val arguments: MutableList<JsExpression>
fun padArguments(arguments: List<JsExpression>) = 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)
}
@@ -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"
}
@@ -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"
}
@@ -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"
}