From e76c3d4e9eb906bfa975c17155b0b90e6bb8ce1a Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 25 Jun 2014 20:34:45 +0400 Subject: [PATCH] Java to Kotlin converter: no intermediate __ variable in factory function if body is simple --- j2k/src/org/jetbrains/jet/j2k/Converter.kt | 70 ++++++++++++------- j2k/tests/testData/ast/class/kt-639.kt | 6 +- .../ast/comments/commentsForConstructors.kt | 3 +- .../ast/constructors/allCallsPrimary.kt | 6 +- .../ast/constructors/genericIdentifier.kt | 3 +- .../testData/ast/constructors/identifier.kt | 3 +- .../ast/constructors/parameterModification.kt | 3 +- .../ast/constructors/privateConstructors.kt | 6 +- .../ast/constructors/withManyDefaultParams.kt | 6 +- j2k/tests/testData/ast/issues/kt-638.kt | 3 +- 10 files changed, 56 insertions(+), 53 deletions(-) diff --git a/j2k/src/org/jetbrains/jet/j2k/Converter.kt b/j2k/src/org/jetbrains/jet/j2k/Converter.kt index 68e97c44eaa..c61df36b51c 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Converter.kt @@ -254,16 +254,23 @@ public class Converter private(val project: Project, val settings: ConverterSett } } - val initializer = MethodCallExpression.buildNotNull(null, className.name, finalOrWithEmptyInitializerFields.map { initializers[it]!! }) - initializer.assignNoPrototype() - val localVar = LocalVariable(FactoryFunction.tempValIdentifier(), - Annotations.Empty, - Modifiers.Empty, - null, - initializer, - true).assignNoPrototype() - statements.add(0, DeclarationStatement(listOf(localVar)).assignNoPrototype()) - statements.add(ReturnStatement(FactoryFunction.tempValIdentifier()).assignNoPrototype()) + val initializer = MethodCallExpression.buildNotNull(null, + className.name, + finalOrWithEmptyInitializerFields.map { initializers[it]!! }).assignNoPrototype() + if (statements.isNotEmpty()) { + val localVar = LocalVariable(FactoryFunction.tempValIdentifier(), + Annotations.Empty, + Modifiers.Empty, + null, + initializer, + true).assignNoPrototype() + statements.add(0, DeclarationStatement(listOf(localVar)).assignNoPrototype()) + statements.add(ReturnStatement(FactoryFunction.tempValIdentifier()).assignNoPrototype()) + } + else { + statements.add(ReturnStatement(initializer).assignNoPrototype()) + } + factoryFunction.body = Block(statements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype()).assignNoPrototype() } @@ -282,27 +289,36 @@ public class Converter private(val project: Project, val settings: ConverterSett private fun correctFactoryFunctions(classBody: ClassBody, className: String) { for (factoryFunction in classBody.factoryFunctions()) { val body = factoryFunction.body!! - val statements = ArrayList(body.statements) - - // searching for other constructor call in form "this(...)" - // it's not necessary the first statement because of statements inserted for writable parameters - for (i in statements.indices) { - val statement = statements[i] - if (statement is MethodCallExpression) { - if ((statement.methodExpression as? Identifier)?.name == "this") { - val constructorCall = MethodCallExpression.buildNotNull(null, className, statement.arguments).assignPrototypesFrom(statement) - val localVar = LocalVariable(FactoryFunction.tempValIdentifier(), Annotations.Empty, Modifiers.Empty, null, constructorCall, true).assignNoPrototype() - statements[i] = DeclarationStatement(listOf(localVar)).assignNoPrototype() - break - } - } - } - - statements.add(ReturnStatement(FactoryFunction.tempValIdentifier()).assignNoPrototype()) + val statements = correctFactoryFunctionStatements(body, className) factoryFunction.body = Block(statements, body.lBrace, body.rBrace).assignPrototypesFrom(body) } } + private fun correctFactoryFunctionStatements(body: Block, className: String): List { + val statements = ArrayList(body.statements) + + // searching for other constructor call in form "this(...)" + // it's not necessary the first statement because of statements inserted for writable parameters + for (i in statements.indices) { + val statement = statements[i] + if (statement is MethodCallExpression) { + if ((statement.methodExpression as? Identifier)?.name == "this") { + val constructorCall = MethodCallExpression.buildNotNull(null, className, statement.arguments).assignPrototypesFrom(statement) + if (i == statements.lastIndex) { // constructor call is the last statement - no intermediate variable needed + statements[i] = ReturnStatement(constructorCall).assignNoPrototype() + return statements + } + val localVar = LocalVariable(FactoryFunction.tempValIdentifier(), Annotations.Empty, Modifiers.Empty, null, constructorCall, true).assignNoPrototype() + statements[i] = DeclarationStatement(listOf(localVar)).assignNoPrototype() + break + } + } + } + + statements.add(ReturnStatement(FactoryFunction.tempValIdentifier()).assignNoPrototype()) + return statements + } + private fun convertInitializer(initializer: PsiClassInitializer): Initializer { return Initializer(convertBlock(initializer.getBody()), convertModifiers(initializer)).assignPrototype(initializer) } diff --git a/j2k/tests/testData/ast/class/kt-639.kt b/j2k/tests/testData/ast/class/kt-639.kt index 5d2309c1685..4a34310adf7 100644 --- a/j2k/tests/testData/ast/class/kt-639.kt +++ b/j2k/tests/testData/ast/class/kt-639.kt @@ -5,12 +5,10 @@ import java.util.HashMap class Test private() { class object { fun create(): Test { - val __ = Test() - return __ + return Test() } fun create(s: String): Test { - val __ = Test() - return __ + return Test() } } } diff --git a/j2k/tests/testData/ast/comments/commentsForConstructors.kt b/j2k/tests/testData/ast/comments/commentsForConstructors.kt index ea3646185fd..d59c1250e69 100644 --- a/j2k/tests/testData/ast/comments/commentsForConstructors.kt +++ b/j2k/tests/testData/ast/comments/commentsForConstructors.kt @@ -10,8 +10,7 @@ class A// this is a primary constructor // this is a secondary constructor fun create(): A { - val __ = A(1) - return __ + return A(1) } // end of secondary constructor body } } diff --git a/j2k/tests/testData/ast/constructors/allCallsPrimary.kt b/j2k/tests/testData/ast/constructors/allCallsPrimary.kt index f60af54d579..e6ced935f21 100644 --- a/j2k/tests/testData/ast/constructors/allCallsPrimary.kt +++ b/j2k/tests/testData/ast/constructors/allCallsPrimary.kt @@ -2,13 +2,11 @@ class C(arg1: Int, arg2: Int, arg3: Int) { class object { fun create(arg1: Int, arg2: Int): C { - val __ = C(arg1, arg2, 0) - return __ + return C(arg1, arg2, 0) } fun create(arg1: Int): C { - val __ = C(arg1, 0, 0) - return __ + return C(arg1, 0, 0) } } } diff --git a/j2k/tests/testData/ast/constructors/genericIdentifier.kt b/j2k/tests/testData/ast/constructors/genericIdentifier.kt index 7566ae2abc2..55266db039e 100644 --- a/j2k/tests/testData/ast/constructors/genericIdentifier.kt +++ b/j2k/tests/testData/ast/constructors/genericIdentifier.kt @@ -8,8 +8,7 @@ public class Identifier private(private val myName: T, private val myHasDolla class object { public fun create(name: T): Identifier { - val __ = Identifier(name, false) - return __ + return Identifier(name, false) } public fun create(name: T, isNullable: Boolean): Identifier { diff --git a/j2k/tests/testData/ast/constructors/identifier.kt b/j2k/tests/testData/ast/constructors/identifier.kt index 8f624da0568..a7144fa3d94 100644 --- a/j2k/tests/testData/ast/constructors/identifier.kt +++ b/j2k/tests/testData/ast/constructors/identifier.kt @@ -8,8 +8,7 @@ public class Identifier private(private val myName: String, private val myHasDol class object { public fun create(name: String): Identifier { - val __ = Identifier(name, false) - return __ + return Identifier(name, false) } public fun create(name: String, isNullable: Boolean): Identifier { diff --git a/j2k/tests/testData/ast/constructors/parameterModification.kt b/j2k/tests/testData/ast/constructors/parameterModification.kt index de7024b5f62..c02ef0d78d0 100644 --- a/j2k/tests/testData/ast/constructors/parameterModification.kt +++ b/j2k/tests/testData/ast/constructors/parameterModification.kt @@ -20,8 +20,7 @@ class C(arg1: Int, arg2: Int, arg3: Int) { } fun create(arg1: Int): C { - val __ = C(arg1, 0, 0) - return __ + return C(arg1, 0, 0) } } } diff --git a/j2k/tests/testData/ast/constructors/privateConstructors.kt b/j2k/tests/testData/ast/constructors/privateConstructors.kt index 60c966bb8ac..ca99c27862e 100644 --- a/j2k/tests/testData/ast/constructors/privateConstructors.kt +++ b/j2k/tests/testData/ast/constructors/privateConstructors.kt @@ -2,13 +2,11 @@ class C private(arg1: Int, arg2: Int, arg3: Int) { class object { private fun create(arg1: Int, arg2: Int): C { - val __ = C(arg1, arg2, 0) - return __ + return C(arg1, arg2, 0) } public fun create(arg1: Int): C { - val __ = C(arg1, 0, 0) - return __ + return C(arg1, 0, 0) } } } diff --git a/j2k/tests/testData/ast/constructors/withManyDefaultParams.kt b/j2k/tests/testData/ast/constructors/withManyDefaultParams.kt index 3569aea6b12..91b9fed7541 100644 --- a/j2k/tests/testData/ast/constructors/withManyDefaultParams.kt +++ b/j2k/tests/testData/ast/constructors/withManyDefaultParams.kt @@ -2,13 +2,11 @@ public class Test private(private val myName: String, var a: Boolean, var b: Dou class object { public fun create(): Test { - val __ = Test(0, false, 0.toDouble(), 0.toFloat(), 0, 0, 0, ' ') - return __ + return Test(0, false, 0.toDouble(), 0.toFloat(), 0, 0, 0, ' ') } public fun create(name: String): Test { - val __ = Test(foo(name), false, 0.toDouble(), 0.toFloat(), 0, 0, 0, ' ') - return __ + return Test(foo(name), false, 0.toDouble(), 0.toFloat(), 0, 0, 0, ' ') } fun foo(n: String): String { diff --git a/j2k/tests/testData/ast/issues/kt-638.kt b/j2k/tests/testData/ast/issues/kt-638.kt index 5401cdb5559..9e08fbd3e6f 100644 --- a/j2k/tests/testData/ast/issues/kt-638.kt +++ b/j2k/tests/testData/ast/issues/kt-638.kt @@ -8,8 +8,7 @@ public class Identifier private(private val myName: T, private val myHasDolla class object { public fun create(name: T): Identifier { - val __ = Identifier(name, false) - return __ + return Identifier(name, false) } public fun create(name: T, isNullable: Boolean): Identifier {