Java to Kotlin converter: do not produce incorrect "code blocks" which are actually parsed as lambda's in Kotlin
#KT-4670 Fixed
This commit is contained in:
@@ -51,7 +51,8 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
|
||||
}
|
||||
|
||||
override fun visitBlockStatement(statement: PsiBlockStatement) {
|
||||
result = converter.convertBlock(statement.getCodeBlock())
|
||||
val block = converter.convertBlock(statement.getCodeBlock())
|
||||
result = MethodCallExpression.build(null, "run", listOf(), listOf(), false, LambdaExpression(null, block))
|
||||
}
|
||||
|
||||
override fun visitBreakStatement(statement: PsiBreakStatement) {
|
||||
@@ -82,7 +83,7 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
|
||||
converter.convertExpression(condition, condition.getType())
|
||||
else
|
||||
converter.convertExpression(condition)
|
||||
result = DoWhileStatement(expression, converter.convertStatement(statement.getBody()), statement.isInSingleLine())
|
||||
result = DoWhileStatement(expression, convertStatementOrBlock(statement.getBody()), statement.isInSingleLine())
|
||||
}
|
||||
|
||||
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
|
||||
@@ -111,7 +112,7 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
|
||||
&& condition != null
|
||||
&& update != null
|
||||
&& update.getChildren().size == 1
|
||||
&& isPlusPlusExpression(update.getChildren().single())
|
||||
&& update.getChildren().single().isPlusPlusExpression()
|
||||
&& (operationTokenType == JavaTokenType.LT || operationTokenType == JavaTokenType.LE)
|
||||
&& loopVar != null
|
||||
&& loopVar.getNameIdentifier() != null
|
||||
@@ -121,19 +122,48 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
|
||||
result = ForeachWithRangeStatement(loopVar.declarationIdentifier(),
|
||||
converter.convertExpression(loopVar.getInitializer()),
|
||||
endExpression,
|
||||
converter.convertStatement(body),
|
||||
convertStatementOrBlock(body),
|
||||
statement.isInSingleLine())
|
||||
}
|
||||
else {
|
||||
var forStatements = ArrayList<Statement>()
|
||||
forStatements.add(converter.convertStatement(initialization))
|
||||
val bodyAndUpdate = listOf(converter.convertStatement(body),
|
||||
Block(listOf(converter.convertStatement(update)), LBrace(), RBrace()))
|
||||
forStatements.add(WhileStatement(
|
||||
if (condition == null) LiteralExpression("true") else converter.convertExpression(condition),
|
||||
Block(bodyAndUpdate, LBrace(), RBrace()),
|
||||
statement.isInSingleLine()))
|
||||
result = Block(forStatements, LBrace(), RBrace())
|
||||
val initializationConverted = converter.convertStatement(initialization)
|
||||
val updateConverted = converter.convertStatement(update)
|
||||
|
||||
val whileBody = if (updateConverted.isEmpty) {
|
||||
converter.convertStatement(body)
|
||||
}
|
||||
else if (body is PsiBlockStatement) {
|
||||
val nameConflict = initialization is PsiDeclarationStatement && initialization.getDeclaredElements().any { loopVar ->
|
||||
loopVar is PsiNamedElement && body.getCodeBlock().getStatements().any { statement ->
|
||||
statement is PsiDeclarationStatement && statement.getDeclaredElements().any {
|
||||
it is PsiNamedElement && it.getName() == loopVar.getName()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nameConflict) {
|
||||
Block(listOf(converter.convertStatement(body), updateConverted), LBrace(), RBrace(), true)
|
||||
}
|
||||
else {
|
||||
val block = converter.convertBlock(body.getCodeBlock(), true)
|
||||
Block(block.statements + listOf(updateConverted), block.lBrace, block.rBrace, true).assignPrototypesFrom(block)
|
||||
}
|
||||
}
|
||||
else {
|
||||
Block(listOf(converter.convertStatement(body), updateConverted), LBrace(), RBrace(), true)
|
||||
}
|
||||
val whileStatement = WhileStatement(
|
||||
if (condition != null) converter.convertExpression(condition) else LiteralExpression("true"),
|
||||
whileBody,
|
||||
statement.isInSingleLine())
|
||||
|
||||
if (initializationConverted.isEmpty) {
|
||||
result = whileStatement
|
||||
}
|
||||
else {
|
||||
val block = Block(listOf(initializationConverted, whileStatement), LBrace(), RBrace())
|
||||
result = MethodCallExpression.build(null, "run", listOf(), listOf(), false, LambdaExpression(null, block))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +177,7 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
|
||||
}
|
||||
result = ForeachStatement(converter.convertParameter(statement.getIterationParameter()),
|
||||
iterator,
|
||||
converter.convertStatement(statement.getBody()),
|
||||
convertStatementOrBlock(statement.getBody()),
|
||||
statement.isInSingleLine())
|
||||
}
|
||||
|
||||
@@ -155,8 +185,8 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
|
||||
val condition = statement.getCondition()
|
||||
val expression = converter.convertExpression(condition, PsiType.BOOLEAN)
|
||||
result = IfStatement(expression,
|
||||
converter.convertStatement(statement.getThenBranch()),
|
||||
converter.convertStatement(statement.getElseBranch()),
|
||||
convertStatementOrBlock(statement.getThenBranch()),
|
||||
convertStatementOrBlock(statement.getElseBranch()),
|
||||
statement.isInSingleLine())
|
||||
}
|
||||
|
||||
@@ -307,7 +337,7 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
|
||||
converter.convertExpression(condition, condition!!.getType())
|
||||
else
|
||||
converter.convertExpression(condition)
|
||||
result = WhileStatement(expression, converter.convertStatement(statement.getBody()), statement.isInSingleLine())
|
||||
result = WhileStatement(expression, convertStatementOrBlock(statement.getBody()), statement.isInSingleLine())
|
||||
}
|
||||
|
||||
override fun visitReturnStatement(statement: PsiReturnStatement) {
|
||||
@@ -324,9 +354,9 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
|
||||
result = Statement.Empty
|
||||
}
|
||||
|
||||
private fun isPlusPlusExpression(psiElement: PsiElement): Boolean {
|
||||
return (psiElement is PsiPostfixExpression && psiElement.getOperationTokenType() == JavaTokenType.PLUSPLUS) ||
|
||||
(psiElement is PsiPrefixExpression && psiElement.getOperationTokenType() == JavaTokenType.PLUSPLUS)
|
||||
private fun PsiElement.isPlusPlusExpression(): Boolean {
|
||||
return (this is PsiPostfixExpression && this.getOperationTokenType() == JavaTokenType.PLUSPLUS) ||
|
||||
(this is PsiPrefixExpression && this.getOperationTokenType() == JavaTokenType.PLUSPLUS)
|
||||
}
|
||||
|
||||
private fun containsBreak(slice: List<PsiElement?>) = slice.any { it is PsiBreakStatement }
|
||||
@@ -371,4 +401,11 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
|
||||
|
||||
return cases
|
||||
}
|
||||
|
||||
private fun convertStatementOrBlock(statement: PsiStatement?): Statement {
|
||||
return if (statement is PsiBlockStatement)
|
||||
converter.convertBlock(statement.getCodeBlock())
|
||||
else
|
||||
converter.convertStatement(statement)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterTest;
|
||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("j2k/tests/testData/ast")
|
||||
@InnerTestClasses({JavaToKotlinConverterTestGenerated.Annotations.class, JavaToKotlinConverterTestGenerated.AnonymousBlock.class, JavaToKotlinConverterTestGenerated.ArrayAccessExpression.class, JavaToKotlinConverterTestGenerated.ArrayInitializerExpression.class, JavaToKotlinConverterTestGenerated.ArrayType.class, JavaToKotlinConverterTestGenerated.AssertStatement.class, JavaToKotlinConverterTestGenerated.AssignmentExpression.class, JavaToKotlinConverterTestGenerated.BinaryExpression.class, JavaToKotlinConverterTestGenerated.BoxedType.class, JavaToKotlinConverterTestGenerated.BreakStatement.class, JavaToKotlinConverterTestGenerated.CallChainExpression.class, JavaToKotlinConverterTestGenerated.Class.class, JavaToKotlinConverterTestGenerated.ClassExpression.class, JavaToKotlinConverterTestGenerated.Comments.class, JavaToKotlinConverterTestGenerated.ConditionalExpression.class, JavaToKotlinConverterTestGenerated.Constructors.class, JavaToKotlinConverterTestGenerated.ContinueStatement.class, JavaToKotlinConverterTestGenerated.DeclarationStatement.class, JavaToKotlinConverterTestGenerated.DoWhileStatement.class, JavaToKotlinConverterTestGenerated.Enum.class, JavaToKotlinConverterTestGenerated.Equals.class, JavaToKotlinConverterTestGenerated.Field.class, JavaToKotlinConverterTestGenerated.For.class, JavaToKotlinConverterTestGenerated.ForeachStatement.class, JavaToKotlinConverterTestGenerated.Formatting.class, JavaToKotlinConverterTestGenerated.Function.class, JavaToKotlinConverterTestGenerated.Identifier.class, JavaToKotlinConverterTestGenerated.IfStatement.class, JavaToKotlinConverterTestGenerated.ImportStatement.class, JavaToKotlinConverterTestGenerated.InProjectionType.class, JavaToKotlinConverterTestGenerated.Inheritance.class, JavaToKotlinConverterTestGenerated.IsOperator.class, JavaToKotlinConverterTestGenerated.Issues.class, JavaToKotlinConverterTestGenerated.KotlinApiAccess.class, JavaToKotlinConverterTestGenerated.LabelStatement.class, JavaToKotlinConverterTestGenerated.List.class, JavaToKotlinConverterTestGenerated.LiteralExpression.class, JavaToKotlinConverterTestGenerated.LocalVariable.class, JavaToKotlinConverterTestGenerated.MethodCallExpression.class, JavaToKotlinConverterTestGenerated.Misc.class, JavaToKotlinConverterTestGenerated.NewClassExpression.class, JavaToKotlinConverterTestGenerated.Nullability.class, JavaToKotlinConverterTestGenerated.ObjectLiteral.class, JavaToKotlinConverterTestGenerated.OutProjectionType.class, JavaToKotlinConverterTestGenerated.PackageStatement.class, JavaToKotlinConverterTestGenerated.ParenthesizedExpression.class, JavaToKotlinConverterTestGenerated.PolyadicExpression.class, JavaToKotlinConverterTestGenerated.PostfixOperator.class, JavaToKotlinConverterTestGenerated.PrefixOperator.class, JavaToKotlinConverterTestGenerated.RawGenerics.class, JavaToKotlinConverterTestGenerated.ReturnStatement.class, JavaToKotlinConverterTestGenerated.Settings.class, JavaToKotlinConverterTestGenerated.StarProjectionType.class, JavaToKotlinConverterTestGenerated.StaticMembers.class, JavaToKotlinConverterTestGenerated.SuperExpression.class, JavaToKotlinConverterTestGenerated.Switch.class, JavaToKotlinConverterTestGenerated.SynchronizedStatement.class, JavaToKotlinConverterTestGenerated.ThisExpression.class, JavaToKotlinConverterTestGenerated.ThrowStatement.class, JavaToKotlinConverterTestGenerated.ToKotlinClasses.class, JavaToKotlinConverterTestGenerated.Trait.class, JavaToKotlinConverterTestGenerated.TryStatement.class, JavaToKotlinConverterTestGenerated.TryWithResource.class, JavaToKotlinConverterTestGenerated.TypeCastExpression.class, JavaToKotlinConverterTestGenerated.TypeParameters.class, JavaToKotlinConverterTestGenerated.VarArg.class, JavaToKotlinConverterTestGenerated.WhileStatement.class})
|
||||
@InnerTestClasses({JavaToKotlinConverterTestGenerated.Annotations.class, JavaToKotlinConverterTestGenerated.AnonymousBlock.class, JavaToKotlinConverterTestGenerated.ArrayAccessExpression.class, JavaToKotlinConverterTestGenerated.ArrayInitializerExpression.class, JavaToKotlinConverterTestGenerated.ArrayType.class, JavaToKotlinConverterTestGenerated.AssertStatement.class, JavaToKotlinConverterTestGenerated.AssignmentExpression.class, JavaToKotlinConverterTestGenerated.BinaryExpression.class, JavaToKotlinConverterTestGenerated.Blocks.class, JavaToKotlinConverterTestGenerated.BoxedType.class, JavaToKotlinConverterTestGenerated.BreakStatement.class, JavaToKotlinConverterTestGenerated.CallChainExpression.class, JavaToKotlinConverterTestGenerated.Class.class, JavaToKotlinConverterTestGenerated.ClassExpression.class, JavaToKotlinConverterTestGenerated.Comments.class, JavaToKotlinConverterTestGenerated.ConditionalExpression.class, JavaToKotlinConverterTestGenerated.Constructors.class, JavaToKotlinConverterTestGenerated.ContinueStatement.class, JavaToKotlinConverterTestGenerated.DeclarationStatement.class, JavaToKotlinConverterTestGenerated.DoWhileStatement.class, JavaToKotlinConverterTestGenerated.Enum.class, JavaToKotlinConverterTestGenerated.Equals.class, JavaToKotlinConverterTestGenerated.Field.class, JavaToKotlinConverterTestGenerated.For.class, JavaToKotlinConverterTestGenerated.ForeachStatement.class, JavaToKotlinConverterTestGenerated.Formatting.class, JavaToKotlinConverterTestGenerated.Function.class, JavaToKotlinConverterTestGenerated.Identifier.class, JavaToKotlinConverterTestGenerated.IfStatement.class, JavaToKotlinConverterTestGenerated.ImportStatement.class, JavaToKotlinConverterTestGenerated.InProjectionType.class, JavaToKotlinConverterTestGenerated.Inheritance.class, JavaToKotlinConverterTestGenerated.IsOperator.class, JavaToKotlinConverterTestGenerated.Issues.class, JavaToKotlinConverterTestGenerated.KotlinApiAccess.class, JavaToKotlinConverterTestGenerated.LabelStatement.class, JavaToKotlinConverterTestGenerated.List.class, JavaToKotlinConverterTestGenerated.LiteralExpression.class, JavaToKotlinConverterTestGenerated.LocalVariable.class, JavaToKotlinConverterTestGenerated.MethodCallExpression.class, JavaToKotlinConverterTestGenerated.Misc.class, JavaToKotlinConverterTestGenerated.NewClassExpression.class, JavaToKotlinConverterTestGenerated.Nullability.class, JavaToKotlinConverterTestGenerated.ObjectLiteral.class, JavaToKotlinConverterTestGenerated.OutProjectionType.class, JavaToKotlinConverterTestGenerated.PackageStatement.class, JavaToKotlinConverterTestGenerated.ParenthesizedExpression.class, JavaToKotlinConverterTestGenerated.PolyadicExpression.class, JavaToKotlinConverterTestGenerated.PostfixOperator.class, JavaToKotlinConverterTestGenerated.PrefixOperator.class, JavaToKotlinConverterTestGenerated.RawGenerics.class, JavaToKotlinConverterTestGenerated.ReturnStatement.class, JavaToKotlinConverterTestGenerated.Settings.class, JavaToKotlinConverterTestGenerated.StarProjectionType.class, JavaToKotlinConverterTestGenerated.StaticMembers.class, JavaToKotlinConverterTestGenerated.SuperExpression.class, JavaToKotlinConverterTestGenerated.Switch.class, JavaToKotlinConverterTestGenerated.SynchronizedStatement.class, JavaToKotlinConverterTestGenerated.ThisExpression.class, JavaToKotlinConverterTestGenerated.ThrowStatement.class, JavaToKotlinConverterTestGenerated.ToKotlinClasses.class, JavaToKotlinConverterTestGenerated.Trait.class, JavaToKotlinConverterTestGenerated.TryStatement.class, JavaToKotlinConverterTestGenerated.TryWithResource.class, JavaToKotlinConverterTestGenerated.TypeCastExpression.class, JavaToKotlinConverterTestGenerated.TypeParameters.class, JavaToKotlinConverterTestGenerated.VarArg.class, JavaToKotlinConverterTestGenerated.WhileStatement.class})
|
||||
public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConverterTest {
|
||||
public void testAllFilesPresentInAst() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast"), Pattern.compile("^(.+)\\.java$"), true);
|
||||
@@ -441,6 +441,19 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("j2k/tests/testData/ast/blocks")
|
||||
public static class Blocks extends AbstractJavaToKotlinConverterTest {
|
||||
public void testAllFilesPresentInBlocks() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/blocks"), Pattern.compile("^(.+)\\.java$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("Blocks.java")
|
||||
public void testBlocks() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/blocks/Blocks.java");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("j2k/tests/testData/ast/boxedType")
|
||||
public static class BoxedType extends AbstractJavaToKotlinConverterTest {
|
||||
public void testAllFilesPresentInBoxedType() throws Exception {
|
||||
@@ -1109,6 +1122,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
|
||||
doTest("j2k/tests/testData/ast/for/commonCaseForTest.java");
|
||||
}
|
||||
|
||||
@TestMetadata("forRangeWithBlock.java")
|
||||
public void testForRangeWithBlock() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/for/forRangeWithBlock.java");
|
||||
}
|
||||
|
||||
@TestMetadata("forRangeWithLE.java")
|
||||
public void testForRangeWithLE() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/for/forRangeWithLE.java");
|
||||
@@ -2809,6 +2827,7 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
|
||||
suite.addTestSuite(AssertStatement.class);
|
||||
suite.addTestSuite(AssignmentExpression.class);
|
||||
suite.addTestSuite(BinaryExpression.class);
|
||||
suite.addTestSuite(Blocks.class);
|
||||
suite.addTestSuite(BoxedType.class);
|
||||
suite.addTestSuite(BreakStatement.class);
|
||||
suite.addTestSuite(CallChainExpression.class);
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
//method
|
||||
void foo() {
|
||||
{
|
||||
int a = 1;
|
||||
bar(a);
|
||||
}
|
||||
|
||||
{
|
||||
int a = 2;
|
||||
bar(a);
|
||||
}
|
||||
|
||||
{
|
||||
bar(3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fun foo() {
|
||||
run {
|
||||
val a = 1
|
||||
bar(a)
|
||||
}
|
||||
|
||||
run {
|
||||
val a = 2
|
||||
bar(a)
|
||||
}
|
||||
|
||||
run { bar(3) }
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
{
|
||||
run {
|
||||
init()
|
||||
while (condition()) {
|
||||
body()
|
||||
{
|
||||
update()
|
||||
}
|
||||
update()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
//statement
|
||||
int[] array = new int[10];
|
||||
for (int i = 0; i < 10; i++) {array[i] = i;}
|
||||
@@ -0,0 +1,4 @@
|
||||
val array = IntArray(10)
|
||||
for (i in 0..10 - 1) {
|
||||
array[i] = i
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
//statement
|
||||
int[] array = new int[10];
|
||||
for (int i = 0; i < 10; i++) {array[i] = i;}
|
||||
for (int i = 0; i < 10; j++, i++) {
|
||||
System.out.println(i);
|
||||
System.out.println(j);
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
val array = IntArray(10)
|
||||
for (i in 0..10 - 1) {
|
||||
array[i] = i
|
||||
run {
|
||||
val i = 0
|
||||
while (i < 10) {
|
||||
System.out.println(i)
|
||||
System.out.println(j)
|
||||
j++
|
||||
i++
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
{
|
||||
run {
|
||||
val i = 0
|
||||
while (i < 0) {
|
||||
{
|
||||
run {
|
||||
val i = 1
|
||||
i++
|
||||
}
|
||||
{
|
||||
j++
|
||||
i++
|
||||
}
|
||||
j++
|
||||
i++
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
{
|
||||
run {
|
||||
val i = 0
|
||||
while (i < 0) {
|
||||
{}
|
||||
{
|
||||
j++
|
||||
i++
|
||||
}
|
||||
j++
|
||||
i++
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
{
|
||||
run {
|
||||
init()
|
||||
while (true) {
|
||||
body()
|
||||
{
|
||||
update()
|
||||
}
|
||||
update()
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
while (condition()) {
|
||||
body()
|
||||
{
|
||||
update()
|
||||
}
|
||||
}
|
||||
}
|
||||
while (condition()) {
|
||||
body()
|
||||
update()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
{
|
||||
run {
|
||||
init()
|
||||
while (condition()) {
|
||||
body()
|
||||
}
|
||||
while (condition()) body()
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
{
|
||||
run {
|
||||
val i = 0
|
||||
while (i < 0) {
|
||||
return i
|
||||
{
|
||||
j++
|
||||
i++
|
||||
}
|
||||
j++
|
||||
i++
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user