diff --git a/j2k/src/org/jetbrains/kotlin/j2k/ast/Expressions.kt b/j2k/src/org/jetbrains/kotlin/j2k/ast/Expressions.kt index e7e702c39fa..04750b0d0ba 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/ast/Expressions.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/ast/Expressions.kt @@ -33,6 +33,8 @@ class ArrayAccessExpression(val expression: Expression, val index: Expression, v open class AssignmentExpression(val left: Expression, val right: Expression, val op: Operator) : Expression() { + fun isMultiAssignment() = right is AssignmentExpression + fun appendAssignment(builder: CodeBuilder, left: Expression, right: Expression) { builder.appendOperand(this, left).append(" ").append(op).append(" ").appendOperand(this, right) } diff --git a/j2k/src/org/jetbrains/kotlin/j2k/ast/Statements.kt b/j2k/src/org/jetbrains/kotlin/j2k/ast/Statements.kt index 086ca5933c1..b7a7be1a5e3 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/ast/Statements.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/ast/Statements.kt @@ -65,9 +65,9 @@ class IfStatement( private val brAfterElse = if (singleLine || elseStatement is IfStatement) " " else "\n" override fun generateCode(builder: CodeBuilder) { - builder append "if (" append condition append ")" append br append thenStatement + builder append "if (" append condition append ")" append br append thenStatement.wrapToBlockIfRequired() if (!elseStatement.isEmpty) { - builder append br append "else" append brAfterElse append elseStatement + builder append br append "else" append brAfterElse append elseStatement.wrapToBlockIfRequired() } } } @@ -78,7 +78,7 @@ class WhileStatement(val condition: Expression, val body: Element, singleLine: B private val br = if (singleLine) " " else "\n" override fun generateCode(builder: CodeBuilder) { - builder append "while (" append condition append ")" append br append body + builder append "while (" append condition append ")" append br append body.wrapToBlockIfRequired() } } @@ -86,7 +86,7 @@ class DoWhileStatement(val condition: Expression, val body: Element, singleLine: private val br = if (singleLine) " " else "\n" override fun generateCode(builder: CodeBuilder) { - builder append "do" append br append body append br append "while (" append condition append ")" + builder append "do" append br append body.wrapToBlockIfRequired() append br append "while (" append condition append ")" } } @@ -105,7 +105,7 @@ class ForeachStatement( if (explicitVariableType != null) { builder append ":" append explicitVariableType } - builder append " in " append collection append ")" append br append body + builder append " in " append collection append ")" append br append body.wrapToBlockIfRequired() } } diff --git a/j2k/src/org/jetbrains/kotlin/j2k/ast/Util.kt b/j2k/src/org/jetbrains/kotlin/j2k/ast/Util.kt index 935d456bd6a..33d46ebcc8f 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/ast/Util.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/ast/Util.kt @@ -32,6 +32,12 @@ fun CodeBuilder.appendOperand(expression: Expression, operand: Expression, paren return this } +fun Element.wrapToBlockIfRequired(): Element = when (this) { + is AssignmentExpression -> if (isMultiAssignment()) Block.of(this).assignNoPrototype() else this + else -> this +} + + private fun Expression.precedence(): Int? { return when (this) { is QualifiedExpression, is MethodCallExpression, is ArrayAccessExpression, is PostfixExpression, is BangBangExpression, is StarExpression -> 0 diff --git a/j2k/testData/fileOrElement/doWhileStatement/whileWithAssignmentAsExpression.java b/j2k/testData/fileOrElement/doWhileStatement/whileWithAssignmentAsExpression.java new file mode 100644 index 00000000000..b15036e95fa --- /dev/null +++ b/j2k/testData/fileOrElement/doWhileStatement/whileWithAssignmentAsExpression.java @@ -0,0 +1,7 @@ +public class SomeClass { + int a; + int b; + void doSomeWhile(int i) { + do a = b = i; while (i < 0) + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/doWhileStatement/whileWithAssignmentAsExpression.kt b/j2k/testData/fileOrElement/doWhileStatement/whileWithAssignmentAsExpression.kt new file mode 100644 index 00000000000..7f473cac004 --- /dev/null +++ b/j2k/testData/fileOrElement/doWhileStatement/whileWithAssignmentAsExpression.kt @@ -0,0 +1,10 @@ +class SomeClass { + internal var a: Int = 0 + internal var b: Int = 0 + internal fun doSomeWhile(i: Int) { + do { + b = i + a = b + } while (i < 0) + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/for/assignmentAsExpressionInBody.java b/j2k/testData/fileOrElement/for/assignmentAsExpressionInBody.java new file mode 100644 index 00000000000..90b11e5cc75 --- /dev/null +++ b/j2k/testData/fileOrElement/for/assignmentAsExpressionInBody.java @@ -0,0 +1,7 @@ +public class SomeClass { + void doSomeFor() { + int a,b; + for (int i = 0; i < 10; i++) + a = b = i; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/for/assignmentAsExpressionInBody.kt b/j2k/testData/fileOrElement/for/assignmentAsExpressionInBody.kt new file mode 100644 index 00000000000..0788c612138 --- /dev/null +++ b/j2k/testData/fileOrElement/for/assignmentAsExpressionInBody.kt @@ -0,0 +1,10 @@ +class SomeClass { + internal fun doSomeFor() { + var a: Int + var b: Int + for (i in 0..9) { + b = i + a = b + } + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/ifStatement/assignmentAsExpressionInIf.java b/j2k/testData/fileOrElement/ifStatement/assignmentAsExpressionInIf.java new file mode 100644 index 00000000000..752b7570b93 --- /dev/null +++ b/j2k/testData/fileOrElement/ifStatement/assignmentAsExpressionInIf.java @@ -0,0 +1,9 @@ +public class SomeClass { + void doSomeIf(int i) { + int a,b,c + if (i < 0) + a = b = i; + else + b = c = i; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/ifStatement/assignmentAsExpressionInIf.kt b/j2k/testData/fileOrElement/ifStatement/assignmentAsExpressionInIf.kt new file mode 100644 index 00000000000..924632ea0e5 --- /dev/null +++ b/j2k/testData/fileOrElement/ifStatement/assignmentAsExpressionInIf.kt @@ -0,0 +1,14 @@ +class SomeClass { + internal fun doSomeIf(i: Int) { + val a: Int + val b: Int + val c: Int + if (i < 0) { + b = i + a = b + } else { + c = i + b = c + } + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/whileStatement/whileWithAssignmentAsExpression.java b/j2k/testData/fileOrElement/whileStatement/whileWithAssignmentAsExpression.java new file mode 100644 index 00000000000..b53f65b8c6d --- /dev/null +++ b/j2k/testData/fileOrElement/whileStatement/whileWithAssignmentAsExpression.java @@ -0,0 +1,8 @@ +public class SomeClass { + int a; + int b; + void doSomeWhile(int i) { + while (i < 0) + a = b = i; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/whileStatement/whileWithAssignmentAsExpression.kt b/j2k/testData/fileOrElement/whileStatement/whileWithAssignmentAsExpression.kt new file mode 100644 index 00000000000..c9e314e38ab --- /dev/null +++ b/j2k/testData/fileOrElement/whileStatement/whileWithAssignmentAsExpression.kt @@ -0,0 +1,10 @@ +class SomeClass { + internal var a: Int = 0 + internal var b: Int = 0 + internal fun doSomeWhile(i: Int) { + while (i < 0) { + b = i + a = b + } + } +} \ No newline at end of file diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java index 72aee4ed1f9..b3bb20c2a24 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java @@ -1733,6 +1733,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/testData/fileOrElement/doWhileStatement"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true); } + @TestMetadata("whileWithAssignmentAsExpression.java") + public void testWhileWithAssignmentAsExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/doWhileStatement/whileWithAssignmentAsExpression.java"); + doTest(fileName); + } + @TestMetadata("whileWithBlock.java") public void testWhileWithBlock() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/doWhileStatement/whileWithBlock.java"); @@ -2108,6 +2114,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("assignmentAsExpressionInBody.java") + public void testAssignmentAsExpressionInBody() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/assignmentAsExpressionInBody.java"); + doTest(fileName); + } + @TestMetadata("commonCaseForTest.java") public void testCommonCaseForTest() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/commonCaseForTest.java"); @@ -2699,6 +2711,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/testData/fileOrElement/ifStatement"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true); } + @TestMetadata("assignmentAsExpressionInIf.java") + public void testAssignmentAsExpressionInIf() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/ifStatement/assignmentAsExpressionInIf.java"); + doTest(fileName); + } + @TestMetadata("elseIf.java") public void testElseIf() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/ifStatement/elseIf.java"); @@ -5018,6 +5036,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/testData/fileOrElement/whileStatement"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true); } + @TestMetadata("whileWithAssignmentAsExpression.java") + public void testWhileWithAssignmentAsExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/whileStatement/whileWithAssignmentAsExpression.java"); + doTest(fileName); + } + @TestMetadata("whileWithBlock.java") public void testWhileWithBlock() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/whileStatement/whileWithBlock.java"); diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java index 294c464e4e3..6c8f6cb517f 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java @@ -1733,6 +1733,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/testData/fileOrElement/doWhileStatement"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true); } + @TestMetadata("whileWithAssignmentAsExpression.java") + public void testWhileWithAssignmentAsExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/doWhileStatement/whileWithAssignmentAsExpression.java"); + doTest(fileName); + } + @TestMetadata("whileWithBlock.java") public void testWhileWithBlock() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/doWhileStatement/whileWithBlock.java"); @@ -2108,6 +2114,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("assignmentAsExpressionInBody.java") + public void testAssignmentAsExpressionInBody() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/assignmentAsExpressionInBody.java"); + doTest(fileName); + } + @TestMetadata("commonCaseForTest.java") public void testCommonCaseForTest() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/commonCaseForTest.java"); @@ -2699,6 +2711,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/testData/fileOrElement/ifStatement"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true); } + @TestMetadata("assignmentAsExpressionInIf.java") + public void testAssignmentAsExpressionInIf() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/ifStatement/assignmentAsExpressionInIf.java"); + doTest(fileName); + } + @TestMetadata("elseIf.java") public void testElseIf() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/ifStatement/elseIf.java"); @@ -5018,6 +5036,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/testData/fileOrElement/whileStatement"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true); } + @TestMetadata("whileWithAssignmentAsExpression.java") + public void testWhileWithAssignmentAsExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/whileStatement/whileWithAssignmentAsExpression.java"); + doTest(fileName); + } + @TestMetadata("whileWithBlock.java") public void testWhileWithBlock() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/whileStatement/whileWithBlock.java");