diff --git a/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinAction.java b/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinAction.java index 243274acf76..58b622a95d1 100644 --- a/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinAction.java +++ b/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinAction.java @@ -27,6 +27,7 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import org.jetbrains.jet.j2k.Converter; +import org.jetbrains.jet.j2k.J2kPackage; import java.util.List; @@ -39,7 +40,7 @@ public class JavaToKotlinAction extends AnAction { assert virtualFiles != null; final Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext()); assert project != null; - final Converter converter = new Converter(project); + final Converter converter = new Converter(project, J2kPackage.getPluginSettings()); int result = Messages.showYesNoCancelDialog(project, "Would you like to backup Java files?", "Backup", diff --git a/idea/src/org/jetbrains/jet/plugin/conversion/copy/JavaCopyPastePostProcessor.java b/idea/src/org/jetbrains/jet/plugin/conversion/copy/JavaCopyPastePostProcessor.java index c93195cbe68..4bdb7609757 100644 --- a/idea/src/org/jetbrains/jet/plugin/conversion/copy/JavaCopyPastePostProcessor.java +++ b/idea/src/org/jetbrains/jet/plugin/conversion/copy/JavaCopyPastePostProcessor.java @@ -28,6 +28,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.j2k.Converter; +import org.jetbrains.jet.j2k.J2kPackage; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.plugin.editor.JetEditorOptions; @@ -116,7 +117,7 @@ public class JavaCopyPastePostProcessor implements CopyPastePostProcessor = Sets.newHashSet()!! @@ -47,35 +47,35 @@ public open class Converter(val project: Project) { private val javaToKotlinClassMap: JavaToKotlinClassMap = JavaToKotlinClassMap.getInstance() - public open var methodReturnType: PsiType? = null + public var methodReturnType: PsiType? = null private set - public open fun addFlag(flag: J2KConverterFlags): Boolean { + public fun addFlag(flag: J2KConverterFlags): Boolean { return flags?.add(flag)!! } - public open fun hasFlag(flag: J2KConverterFlags): Boolean { + public fun hasFlag(flag: J2KConverterFlags): Boolean { return flags?.contains(flag)!! } - public open fun setClassIdentifiers(identifiers: MutableSet) { + public fun setClassIdentifiers(identifiers: MutableSet) { classIdentifiersSet = identifiers } - public open fun getClassIdentifiers(): Set { + public fun getClassIdentifiers(): Set { return Collections.unmodifiableSet(classIdentifiersSet) } - public open fun clearClassIdentifiers() { + public fun clearClassIdentifiers() { classIdentifiersSet.clear() } - public open fun elementToKotlin(element: PsiElement): String { + public fun elementToKotlin(element: PsiElement): String { val kElement = topElementToElement(element) return kElement?.toKotlin() ?: "" } - public open fun topElementToElement(element: PsiElement?): Node? = when(element) { + public fun topElementToElement(element: PsiElement?): Node? = when(element) { is PsiJavaFile -> fileToFile(element) is PsiClass -> classToClass(element) is PsiMethod -> methodToFunction(element) @@ -86,11 +86,11 @@ public open class Converter(val project: Project) { else -> null } - public open fun fileToFile(javaFile: PsiJavaFile): File { + public fun fileToFile(javaFile: PsiJavaFile): File { return fileToFile(javaFile, Collections.emptyList()) } - public open fun fileToFileWithCompatibilityImport(javaFile: PsiJavaFile): File { + public fun fileToFileWithCompatibilityImport(javaFile: PsiJavaFile): File { return fileToFile(javaFile, Collections.singletonList("kotlin.compatibility.*")) } @@ -124,7 +124,7 @@ public open class Converter(val project: Project) { return File(quoteKeywords(javaFile.getPackageName()), imports, body, createMainFunction(javaFile)) } - public open fun anonymousClassToAnonymousClass(anonymousClass: PsiAnonymousClass): AnonymousClass { + public fun anonymousClassToAnonymousClass(anonymousClass: PsiAnonymousClass): AnonymousClass { return AnonymousClass(this, getMembers(anonymousClass)) } @@ -352,26 +352,26 @@ public open class Converter(val project: Project) { return false } - public open fun blockToBlock(block: PsiCodeBlock?, notEmpty: Boolean): Block { + public fun blockToBlock(block: PsiCodeBlock?, notEmpty: Boolean): Block { if (block == null) return Block.EMPTY_BLOCK return Block(removeEmpty(statementsToStatementList(block.getChildren())), notEmpty) } - public open fun blockToBlock(block: PsiCodeBlock?): Block { + public fun blockToBlock(block: PsiCodeBlock?): Block { return blockToBlock(block, true) } - public open fun statementsToStatementList(statements: Array): List { + public fun statementsToStatementList(statements: Array): List { return statements.filterNot { it is PsiWhiteSpace }.map { statementToStatement(it) } } - public open fun statementsToStatementList(statements: List): List { + public fun statementsToStatementList(statements: List): List { return statements.filterNot { it is PsiWhiteSpace }.map { statementToStatement(it) } } - public open fun statementToStatement(s: PsiElement?): Element { + public fun statementToStatement(s: PsiElement?): Element { if (s == null) return Statement.EMPTY_STATEMENT @@ -380,14 +380,14 @@ public open class Converter(val project: Project) { return statementVisitor.getResult() } - public open fun expressionsToExpressionList(expressions: Array): List { + public fun expressionsToExpressionList(expressions: Array): List { val result = ArrayList() for (e : PsiExpression? in expressions) result.add(expressionToExpression(e)) return result } - public open fun expressionToExpression(e: PsiExpression?): Expression { + public fun expressionToExpression(e: PsiExpression?): Expression { if (e == null) return Expression.EMPTY_EXPRESSION @@ -396,7 +396,7 @@ public open class Converter(val project: Project) { return expressionVisitor.getResult() } - public open fun elementToElement(e: PsiElement?): Element { + public fun elementToElement(e: PsiElement?): Element { if (e == null) return Element.EMPTY_ELEMENT @@ -405,7 +405,7 @@ public open class Converter(val project: Project) { return elementVisitor.getResult() } - public open fun elementsToElementList(elements: Array): List { + public fun elementsToElementList(elements: Array): List { val result = ArrayList() for (element in elements) { result.add(elementToElement(element)) @@ -413,14 +413,14 @@ public open class Converter(val project: Project) { return result } - public open fun typeElementToTypeElement(element: PsiTypeElement?): TypeElement { + public fun typeElementToTypeElement(element: PsiTypeElement?): TypeElement { return TypeElement(if (element == null) EmptyType() else typeToType(element.getType())) } - public open fun typeToType(`type`: PsiType?): Type { + public fun typeToType(`type`: PsiType?): Type { if (`type` == null) return EmptyType() @@ -429,11 +429,11 @@ public open class Converter(val project: Project) { return typeVisitor.getResult() } - public open fun typesToTypeList(types: Array): List { + public fun typesToTypeList(types: Array): List { return types.map { typeToType(it) } } - public open fun typeToType(`type`: PsiType?, notNull: Boolean): Type { + public fun typeToType(`type`: PsiType?, notNull: Boolean): Type { val result: Type = typeToType(`type`) if (notNull) { return result.convertedToNotNull() @@ -450,17 +450,17 @@ public open class Converter(val project: Project) { return result } - public open fun parametersToParameterList(parameters: Array): List { + public fun parametersToParameterList(parameters: Array): List { return parameters.map { parameterToParameter(it) } } - public open fun parameterToParameter(parameter: PsiParameter, forceNotNull: Boolean = false): Parameter { + public fun parameterToParameter(parameter: PsiParameter, forceNotNull: Boolean = false): Parameter { return Parameter(Identifier(parameter.getName()!!), typeToType(parameter.getType(), forceNotNull || isAnnotatedAsNotNull(parameter.getModifierList())), true) } - public open fun argumentsToExpressionList(expression: PsiCallExpression): List { + public fun argumentsToExpressionList(expression: PsiCallExpression): List { val argumentList: PsiExpressionList? = expression.getArgumentList() val arguments: Array = (if (argumentList != null) argumentList.getExpressions() @@ -485,7 +485,7 @@ public open class Converter(val project: Project) { return result } - public open fun expressionToExpression(argument: PsiExpression?, expectedType: PsiType?): Expression { + public fun expressionToExpression(argument: PsiExpression?, expectedType: PsiType?): Expression { if (argument == null) return Identifier.EMPTY_IDENTIFIER diff --git a/j2k/src/org/jetbrains/jet/j2k/ConverterSettings.kt b/j2k/src/org/jetbrains/jet/j2k/ConverterSettings.kt new file mode 100644 index 00000000000..dfdf47fe485 --- /dev/null +++ b/j2k/src/org/jetbrains/jet/j2k/ConverterSettings.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.j2k + +public class ConverterSettings( + val forceNotNullTypes: Boolean, + val forceLocalVariableImmutability: Boolean, + val specifyLocalVariableTypeByDefault: Boolean +) {} + +public val PluginSettings: ConverterSettings = ConverterSettings( + forceNotNullTypes = true, + forceLocalVariableImmutability = true, + specifyLocalVariableTypeByDefault = false +) + +public val TestSettings: ConverterSettings = ConverterSettings( + forceNotNullTypes = false, + forceLocalVariableImmutability = false, + specifyLocalVariableTypeByDefault = true +) diff --git a/j2k/src/org/jetbrains/jet/j2k/JavaToKotlinTranslator.kt b/j2k/src/org/jetbrains/jet/j2k/JavaToKotlinTranslator.kt index 80d3243812e..199f6a8547d 100644 --- a/j2k/src/org/jetbrains/jet/j2k/JavaToKotlinTranslator.kt +++ b/j2k/src/org/jetbrains/jet/j2k/JavaToKotlinTranslator.kt @@ -96,7 +96,7 @@ object JavaToKotlinTranslator { fun generateKotlinCode(javaCode: String): String { val file = createFile(javaCode) if (file is PsiJavaFile) { - val converter = Converter(file.getProject()) + val converter = Converter(file.getProject(), TestSettings) setClassIdentifiers(converter, file) return prettify(converter.fileToFile(file).toKotlin()) } @@ -106,7 +106,7 @@ object JavaToKotlinTranslator { fun generateKotlinCodeWithCompatibilityImport(javaCode: String): String { val file = createFile(javaCode) if (file is PsiJavaFile) { - val converter = Converter(file.getProject()) + val converter = Converter(file.getProject(), TestSettings) setClassIdentifiers(converter, file) return prettify(converter.fileToFileWithCompatibilityImport(file).toKotlin()) } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/CallChainExpression.kt b/j2k/src/org/jetbrains/jet/j2k/ast/CallChainExpression.kt index c588b91ec50..4a93bf15894 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/CallChainExpression.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/CallChainExpression.kt @@ -24,13 +24,9 @@ public class CallChainExpression(val expression: Expression, val identifier: Exp public override fun toKotlin(): String { if (!expression.isEmpty()) { - return expression.toKotlin() + (if (expression.isNullable() && !forceDotCall) "?." else ".") + identifier.toKotlin() + return expression.toKotlin() + (if (expression.isNullable()) "?." else ".") + identifier.toKotlin() } return identifier.toKotlin() } - - class object { - public var forceDotCall: Boolean = true - } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt b/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt index 6799f371834..5fa34666a3e 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt @@ -25,18 +25,15 @@ public class LocalVariable(val identifier: Identifier, val initializer: Expression, val converter: Converter) : Expression() { - public fun isImmutable(): Boolean = forceImmutable || modifiersSet.contains(Modifier.FINAL) + public fun isImmutable(): Boolean = + converter.settings.forceLocalVariableImmutability || modifiersSet.contains(Modifier.FINAL) override fun toKotlin(): String { if (initializer.isEmpty()) { return "${identifier.toKotlin()} : ${javaType.toKotlin()}" } - return "${identifier.toKotlin()} ${if (specifyTypeExplicitly) ": ${javaType.toKotlin()} " else ""}= ${initializer.toKotlin()}" - } - - class object { - public var specifyTypeExplicitly: Boolean = false - public var forceImmutable: Boolean = true + val shouldSpecifyType = converter.settings.specifyLocalVariableTypeByDefault + return "${identifier.toKotlin()} ${if (shouldSpecifyType) ": ${javaType.toKotlin()} " else ""}= ${initializer.toKotlin()}" } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/types/Type.kt b/j2k/src/org/jetbrains/jet/j2k/ast/types/Type.kt index b2b6e27ae0f..7ea56872546 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/types/Type.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/types/Type.kt @@ -21,7 +21,8 @@ import org.jetbrains.jet.j2k.Converter public fun Type.isPrimitive(): Boolean = this is PrimitiveType -public abstract class MayBeNullableType(override public val nullable: Boolean, val converter: Converter): Type { +public abstract class MayBeNullableType(nullable: Boolean, val converter: Converter): Type { + override public val nullable: Boolean = !converter.settings.forceNotNullTypes && nullable } public trait NotNullType : Type { @@ -39,13 +40,6 @@ public trait Type : Element { } protected fun isNullableStr(): String? { - return (if (nullable && !forceNotNullTypes) - "?" - else - "") - } - - class object { - public var forceNotNullTypes: Boolean = true + return if (nullable) "?" else "" } } diff --git a/j2k/tests/test/org/jetbrains/jet/j2k/test/BasicConverterTestSuite.java b/j2k/tests/test/org/jetbrains/jet/j2k/test/BasicConverterTestSuite.java index e228c1837b8..79ef5bc4269 100644 --- a/j2k/tests/test/org/jetbrains/jet/j2k/test/BasicConverterTestSuite.java +++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/BasicConverterTestSuite.java @@ -18,9 +18,7 @@ package org.jetbrains.jet.j2k.test; import junit.framework.Test; import junit.framework.TestSuite; -import org.jetbrains.jet.j2k.ast.CallChainExpression; -import org.jetbrains.jet.j2k.ast.LocalVariable; -import org.jetbrains.jet.j2k.ast.types.Type; +import org.jetbrains.jet.j2k.J2kPackage; import static org.jetbrains.jet.j2k.test.TestPackage.suiteForDirectory; @@ -32,15 +30,12 @@ public class BasicConverterTestSuite { public static Test suite() { TestSuite suite = new TestSuite(); suite.addTest(suiteForDirectory("j2k/tests/testData", "/ast", new NamedTestFactory() { + @Override public Test createTest(String dataPath, String name) { //noinspection JUnitTestCaseWithNoTests - return new StandaloneJavaToKotlinConverterTest(dataPath, name) { + return new StandaloneJavaToKotlinConverterTest(dataPath, name, J2kPackage.getTestSettings()) { @Override protected void runTest() { - CallChainExpression.forceDotCall = false; - LocalVariable.specifyTypeExplicitly = true; - LocalVariable.forceImmutable = false; - Type.forceNotNullTypes = false; super.runTest(); } }; diff --git a/j2k/tests/test/org/jetbrains/jet/j2k/test/ConverterTestSuiteForPlugin.java b/j2k/tests/test/org/jetbrains/jet/j2k/test/ConverterTestSuiteForPlugin.java index 8eb50478998..075ec826631 100644 --- a/j2k/tests/test/org/jetbrains/jet/j2k/test/ConverterTestSuiteForPlugin.java +++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/ConverterTestSuiteForPlugin.java @@ -18,9 +18,7 @@ package org.jetbrains.jet.j2k.test; import junit.framework.Test; import junit.framework.TestSuite; -import org.jetbrains.jet.j2k.ast.CallChainExpression; -import org.jetbrains.jet.j2k.ast.LocalVariable; -import org.jetbrains.jet.j2k.ast.types.Type; +import org.jetbrains.jet.j2k.J2kPackage; import static org.jetbrains.jet.j2k.test.TestPackage.suiteForDirectory; @@ -32,15 +30,12 @@ public class ConverterTestSuiteForPlugin { TestSuite suite = new TestSuite(); suite.addTest(suiteForDirectory("j2k/tests/testData", "/plugin", new NamedTestFactory() { + @Override public Test createTest(String dataPath, String name) { //noinspection JUnitTestCaseWithNoTests - return new StandaloneJavaToKotlinConverterTest(dataPath, name) { + return new StandaloneJavaToKotlinConverterTest(dataPath, name, J2kPackage.getPluginSettings()) { @Override protected void runTest() { - CallChainExpression.forceDotCall = true; - LocalVariable.specifyTypeExplicitly = false; - LocalVariable.forceImmutable = true; - Type.forceNotNullTypes = true; super.runTest(); } }; diff --git a/j2k/tests/test/org/jetbrains/jet/j2k/test/StandaloneJavaToKotlinConverterTest.kt b/j2k/tests/test/org/jetbrains/jet/j2k/test/StandaloneJavaToKotlinConverterTest.kt index bda9bf8a16e..c4bc9365086 100644 --- a/j2k/tests/test/org/jetbrains/jet/j2k/test/StandaloneJavaToKotlinConverterTest.kt +++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/StandaloneJavaToKotlinConverterTest.kt @@ -31,12 +31,15 @@ import org.jetbrains.jet.j2k.JavaToKotlinTranslator import org.jetbrains.jet.ConfigurationKind import org.jetbrains.jet.JetTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations import com.intellij.testFramework.UsefulTestCase +import org.jetbrains.jet.j2k.ConverterSettings -public abstract class StandaloneJavaToKotlinConverterTest(val dataPath: String, val name: String) : UsefulTestCase() { +public abstract class StandaloneJavaToKotlinConverterTest(val dataPath: String, + val name: String, + val settings: ConverterSettings) : UsefulTestCase() { protected override fun runTest(): Unit { val jetCoreEnvironment = createEnvironmentWithMockJdkAndIdeaAnnotations(getTestRootDisposable(), ConfigurationKind.JDK_ONLY) - val converter = Converter(jetCoreEnvironment.getProject()) + val converter = Converter(jetCoreEnvironment.getProject(), settings) val javaPath = "j2k/tests/testData/" + getTestFilePath() val kotlinPath = javaPath.replace(".jav", ".kt") val kotlinFile = File(kotlinPath)