diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Expressions.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Expressions.kt index df207704928..9b1a22d97f3 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Expressions.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Expressions.kt @@ -137,9 +137,9 @@ class LambdaExpression(val arguments: String?, val block: Block) : Expression() } } -class StarExpression(val methodCall: MethodCallExpression) : Expression() { +class StarExpression(val operand: Expression) : Expression() { override fun generateCode(builder: CodeBuilder) { - builder append "*" append methodCall + builder.append("*").appendOperand(this, operand) } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Util.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Util.kt index f42384e21f6..e1acdd80a23 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Util.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Util.kt @@ -37,7 +37,7 @@ fun CodeBuilder.appendOperand(expression: Expression, operand: Expression, paren private fun Expression.precedence(): Int? { return when(this) { - is QualifiedExpression, is MethodCallExpression, is ArrayAccessExpression, is PostfixOperator, is BangBangExpression -> 0 + is QualifiedExpression, is MethodCallExpression, is ArrayAccessExpression, is PostfixOperator, is BangBangExpression, is StarExpression -> 0 is PrefixOperator -> 1 diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt index bc1d61faa28..2101864a2cc 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt @@ -375,13 +375,18 @@ open class ExpressionVisitor(private val converter: Converter) : JavaElementVisi arguments = arguments.drop(1) } val resolved = expression.resolveMethod() - val expectedTypes = if (resolved != null) - resolved.getParameterList().getParameters().map { it.getType() } - else - listOf() + val parameters = resolved?.getParameterList()?.getParameters() + val expectedTypes = parameters?.map { it.getType() } ?: listOf() return if (arguments.size == expectedTypes.size()) - (0..expectedTypes.lastIndex).map { i -> converter.convertExpression(arguments[i], expectedTypes[i]) } + (0..arguments.lastIndex).map { i -> + val argument = arguments[i] + val converted = converter.convertExpression(argument, expectedTypes[i]) + if (parameters != null && i == arguments.lastIndex && parameters[i].isVarArgs() && argument.getType() is PsiArrayType) + StarExpression(converted).assignNoPrototype() + else + converted + } else arguments.map { converter.convertExpression(it) } } diff --git a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java index 6cf4b25102e..ede62bc7968 100644 --- a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java +++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java @@ -2035,6 +2035,16 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/methodCallExpression/simpleCall.java"); } + @TestMetadata("vararg1.java") + public void testVararg1() throws Exception { + doTest("j2k/tests/testData/ast/methodCallExpression/vararg1.java"); + } + + @TestMetadata("vararg2.java") + public void testVararg2() throws Exception { + doTest("j2k/tests/testData/ast/methodCallExpression/vararg2.java"); + } + } @TestMetadata("j2k/tests/testData/ast/misc") diff --git a/j2k/tests/testData/JavaApi.java b/j2k/tests/testData/JavaApi.java index 1da536be2ec..dfea9cb497f 100644 --- a/j2k/tests/testData/JavaApi.java +++ b/j2k/tests/testData/JavaApi.java @@ -49,10 +49,14 @@ public enum E { A, B, C } -class Base { +public class Base { public @Nullable String foo(@Nullable String s) { return s; } } -class Derived extends Base { +public class Derived extends Base { public String foo(String s) { return s; } } + +public class WithVarargConstructor { + public WithVarargConstructor(int p, Object... objects) { } +} diff --git a/j2k/tests/testData/ast/methodCallExpression/vararg1.java b/j2k/tests/testData/ast/methodCallExpression/vararg1.java new file mode 100644 index 00000000000..7a042b90a62 --- /dev/null +++ b/j2k/tests/testData/ast/methodCallExpression/vararg1.java @@ -0,0 +1,9 @@ +//file +import java.lang.reflect.Constructor; + +class X { + static void foo(Constructor constructor, Object[] args1, Object[] args2) throws Exception { + constructor.newInstance(args1); + constructor.newInstance(args1, args2); + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/methodCallExpression/vararg1.kt b/j2k/tests/testData/ast/methodCallExpression/vararg1.kt new file mode 100644 index 00000000000..9e4c30a7fd5 --- /dev/null +++ b/j2k/tests/testData/ast/methodCallExpression/vararg1.kt @@ -0,0 +1,11 @@ +import java.lang.reflect.Constructor + +class X { + class object { + throws(javaClass()) + fun foo(constructor: Constructor, args1: Array, args2: Array) { + constructor.newInstance(*args1) + constructor.newInstance(args1, args2) + } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/methodCallExpression/vararg2.java b/j2k/tests/testData/ast/methodCallExpression/vararg2.java new file mode 100644 index 00000000000..6dd22c8c208 --- /dev/null +++ b/j2k/tests/testData/ast/methodCallExpression/vararg2.java @@ -0,0 +1,12 @@ +//file +import javaApi.WithVarargConstructor; + +import java.lang.String; + +class X { + void foo() { + WithVarargConstructor o1 = new WithVarargConstructor(1, new Object[]{"a"}); + WithVarargConstructor o2 = new WithVarargConstructor(2, new Object[]{"a"}, new Object[]{"b"}); + WithVarargConstructor o3 = new WithVarargConstructor(2, "a"); + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/methodCallExpression/vararg2.kt b/j2k/tests/testData/ast/methodCallExpression/vararg2.kt new file mode 100644 index 00000000000..5ad7120342f --- /dev/null +++ b/j2k/tests/testData/ast/methodCallExpression/vararg2.kt @@ -0,0 +1,9 @@ +import javaApi.WithVarargConstructor + +class X { + fun foo() { + val o1 = WithVarargConstructor(1, *array("a")) + val o2 = WithVarargConstructor(2, array("a"), array("b")) + val o3 = WithVarargConstructor(2, "a") + } +} \ No newline at end of file