KT-13043: fix translation of super call from secondary constructor when base constructor has default arguments
This commit is contained in:
@@ -71,4 +71,16 @@ public class DefaultArgumentsTest extends SingleFileTranslationTest {
|
|||||||
public void testDefaultArgumentsInFunctionWithExpressionAsBody() throws Exception {
|
public void testDefaultArgumentsInFunctionWithExpressionAsBody() throws Exception {
|
||||||
checkFooBoxIsOk();
|
checkFooBoxIsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testPrimarySuperConstructor() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSecondarySuperConstructor() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testEnumSuperConstructor() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -205,7 +205,9 @@ class ClassTranslator private constructor(
|
|||||||
|
|
||||||
if (resolvedCall != null && !KotlinBuiltIns.isAny(delegationClassDescriptor!!)) {
|
if (resolvedCall != null && !KotlinBuiltIns.isAny(delegationClassDescriptor!!)) {
|
||||||
superCallGenerators += {
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -168,7 +168,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
if (classDeclaration instanceof KtEnumEntry) {
|
if (classDeclaration instanceof KtEnumEntry) {
|
||||||
JsExpression expression = CallTranslator.translate(context(), superCall, null);
|
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);
|
JsLiteral.THIS);
|
||||||
initializerStatements.add(0, fixedInvocation.makeStmt());
|
initializerStatements.add(0, fixedInvocation.makeStmt());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,22 +56,21 @@ fun JsNode.any(predicate: (JsNode) -> Boolean): Boolean {
|
|||||||
return visitor.matched
|
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 qualifier: JsExpression
|
||||||
val arguments: MutableList<JsExpression>
|
fun padArguments(arguments: List<JsExpression>) = arguments + (1..(parameterCount - arguments.size))
|
||||||
|
.map { Namer.getUndefinedExpression() }
|
||||||
|
|
||||||
when (this) {
|
when (this) {
|
||||||
is JsNew -> {
|
is JsNew -> {
|
||||||
qualifier = Namer.getFunctionCallRef(constructorExpression)
|
qualifier = Namer.getFunctionCallRef(constructorExpression)
|
||||||
arguments = getArguments()
|
|
||||||
// `new A(a, b, c)` -> `A.call($this, a, b, c)`
|
// `new A(a, b, c)` -> `A.call($this, a, b, c)`
|
||||||
return JsInvocation(qualifier, listOf(thisExpr) + leadingExtraArgs + arguments)
|
return JsInvocation(qualifier, listOf(thisExpr) + leadingExtraArgs + arguments)
|
||||||
}
|
}
|
||||||
is JsInvocation -> {
|
is JsInvocation -> {
|
||||||
qualifier = getQualifier()
|
qualifier = getQualifier()
|
||||||
arguments = getArguments()
|
|
||||||
// `A(a, b, c)` -> `A(a, b, c, $this)`
|
// `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)
|
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"
|
||||||
|
}
|
||||||
+18
@@ -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"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user