From 7c2473a5efe53a099a0c8f7b0a940a80fbd1d993 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Tue, 3 Jun 2014 22:43:43 +0400 Subject: [PATCH] Java to Kotlin conversion: fixed a few bugs related to modifiers #KT-4424 Fixed --- j2k/src/org/jetbrains/jet/j2k/Converter.kt | 36 +++++++++---------- j2k/src/org/jetbrains/jet/j2k/ast/Class.kt | 21 ++++------- .../org/jetbrains/jet/j2k/ast/Constructors.kt | 4 +-- j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt | 2 -- j2k/src/org/jetbrains/jet/j2k/ast/Field.kt | 7 ++-- j2k/src/org/jetbrains/jet/j2k/ast/Function.kt | 7 ++-- j2k/src/org/jetbrains/jet/j2k/ast/Members.kt | 1 - j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt | 17 ++------- j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt | 9 ++++- .../JavaToKotlinConverterTestGenerated.java | 5 +++ ...ByDefault.java.todo => openByDefault.java} | 0 .../testData/ast/settings/openByDefault.kt | 34 ++++++++++++++++++ .../testData/ast/trait/abstactInterface.kt | 2 +- .../testData/ast/trait/interfaceWithFields.kt | 6 ++-- .../trait/interfaceWithMethodDeclaration.kt | 4 +-- 15 files changed, 88 insertions(+), 67 deletions(-) rename j2k/tests/testData/ast/settings/{openByDefault.java.todo => openByDefault.java} (100%) create mode 100644 j2k/tests/testData/ast/settings/openByDefault.kt diff --git a/j2k/src/org/jetbrains/jet/j2k/Converter.kt b/j2k/src/org/jetbrains/jet/j2k/Converter.kt index 2c8bbaccaaa..08f8da6a5b7 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Converter.kt @@ -137,6 +137,10 @@ public class Converter(val project: Project, val settings: ConverterSettings) { } } + if (settings.openByDefault && !modifiers.contains(Modifier.FINAL)) { + modifiers.add(Modifier.OPEN) + } + return Class(this, name, getComments(psiClass), modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, classBodyElements) } } @@ -231,16 +235,17 @@ public class Converter(val project: Project, val settings: ConverterSettings) { methodReturnType = method.getReturnType() val returnType = convertType(method.getReturnType(), method.isAnnotatedAsNotNull()) - val modifiers = HashSet(convertModifierList(method.getModifierList())) + val modifiers = convertModifierList(method.getModifierList()) val containingClass = method.getContainingClass() - if (containingClass != null && containingClass.isInterface()) { - modifiers.remove(Modifier.ABSTRACT) - } if (containingClass != null && (containingClass.hasModifierProperty(PsiModifier.FINAL) || containingClass.isEnum())) { modifiers.add(Modifier.FINAL) } + if (isOverride(method)) { + modifiers.add(Modifier.OVERRIDE) + } + if (settings.openByDefault && !modifiers.contains(Modifier.ABSTRACT) && !modifiers.contains(Modifier.FINAL) && @@ -248,11 +253,6 @@ public class Converter(val project: Project, val settings: ConverterSettings) { modifiers.add(Modifier.OPEN) } - if (isOverride(method)) { - modifiers.add(Modifier.OVERRIDE) - modifiers.remove(Modifier.OPEN) - } - val comments = getComments(method) if (method.isConstructor()) { @@ -268,7 +268,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) { val params = convertParameterList(method.getParameterList()) val typeParameterList = convertTypeParameterList(method.getTypeParameterList()) val block = convertBlock(method.getBody()) - return Function(this, Identifier(method.getName()), comments, modifiers, returnType, typeParameterList, params, block) + return Function(this, Identifier(method.getName()), comments, modifiers, returnType, typeParameterList, params, block, containingClass?.isInterface() ?: false) } } finally { @@ -494,12 +494,13 @@ public class Converter(val project: Project, val settings: ConverterSettings) { return Identifier(identifier.getText()!!) } - public fun convertModifierList(modifierList: PsiModifierList?): Set { - if (modifierList == null) return setOf() + public fun convertModifierList(modifierList: PsiModifierList?): MutableSet { + if (modifierList == null) return HashSet() val modifiersSet = HashSet() - if (modifierList.hasExplicitModifier(PsiModifier.ABSTRACT)) + //TODO: map + if (modifierList.hasModifierProperty(PsiModifier.ABSTRACT)) modifiersSet.add(Modifier.ABSTRACT) if (modifierList.hasModifierProperty(PsiModifier.FINAL)) @@ -508,16 +509,13 @@ public class Converter(val project: Project, val settings: ConverterSettings) { if (modifierList.hasModifierProperty(PsiModifier.STATIC)) modifiersSet.add(Modifier.STATIC) - if (modifierList.hasExplicitModifier(PsiModifier.PUBLIC)) + if (modifierList.hasModifierProperty(PsiModifier.PUBLIC)) modifiersSet.add(Modifier.PUBLIC) - if (modifierList.hasExplicitModifier(PsiModifier.PROTECTED)) + if (modifierList.hasModifierProperty(PsiModifier.PROTECTED)) modifiersSet.add(Modifier.PROTECTED) - if (modifierList.hasExplicitModifier(PsiModifier.PACKAGE_LOCAL)) - modifiersSet.add(Modifier.INTERNAL) - - if (modifierList.hasExplicitModifier(PsiModifier.PRIVATE)) + if (modifierList.hasModifierProperty(PsiModifier.PRIVATE)) modifiersSet.add(Modifier.PRIVATE) return modifiersSet diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt index 5de27d0b5f3..268fe1d8cfa 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt @@ -17,7 +17,6 @@ package org.jetbrains.jet.j2k.ast import org.jetbrains.jet.j2k.Converter -import java.util.HashSet import java.util.ArrayList open class Class( @@ -80,27 +79,21 @@ open class Class( " : " + allTypes.makeString(", ") } - protected fun modifiersToKotlin(): String { + protected open fun modifiersToKotlin(): String { val modifierList = ArrayList() - val modifier = modifiers.accessModifier() - if (modifier != null) { - modifierList.add(modifier) - } - if (isAbstract()) { + + modifiers.accessModifier()?.let { modifierList.add(it) } + + if (modifiers.contains(Modifier.ABSTRACT)) { modifierList.add(Modifier.ABSTRACT) } - else if (needsOpenModifier()) { + else if (modifiers.contains(Modifier.OPEN)) { modifierList.add(Modifier.OPEN) } + return modifierList.toKotlin() } - protected open fun isDefinitelyFinal(): Boolean - = modifiers.contains(Modifier.FINAL) - - protected open fun needsOpenModifier(): Boolean - = !isDefinitelyFinal() && converter.settings.openByDefault - fun bodyToKotlin(): String { val innerBody = classMembers.nonStaticMembers.toKotlin() + primaryConstructorBodyToKotlin() + classObjectToKotlin() return if (innerBody.trim().isNotEmpty()) " {" + innerBody + "}" else "" diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt index 61cddf5d166..cb1404f028a 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt @@ -26,7 +26,7 @@ abstract class Constructor( modifiers: Set, parameterList: ParameterList, block: Block -) : Function(converter, Identifier.Empty, comments, modifiers, Type.Empty, TypeParameterList.Empty, parameterList, block) +) : Function(converter, Identifier.Empty, comments, modifiers, Type.Empty, TypeParameterList.Empty, parameterList, block, false) class PrimaryConstructor(converter: Converter, comments: MemberComments, @@ -61,6 +61,6 @@ class SecondaryConstructor(converter: Converter, typeParameters.addAll(containingClass.typeParameterList.parameters) return Function(converter, Identifier("init"), MemberComments.Empty, modifiers, ClassType(containingClass.name, typeParameters, false, converter), - TypeParameterList(typeParameters), parameterList, block) + TypeParameterList(typeParameters), parameterList, block, false) } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt index 9519b1b9a20..b30e6bfd203 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt @@ -34,8 +34,6 @@ class Enum( override fun primaryConstructorSignatureToKotlin(): String = classMembers.primaryConstructor?.signatureToKotlin() ?: "" - override fun isDefinitelyFinal() = true - override fun toKotlin(): String { return modifiersToKotlin() + "enum class " + name.toKotlin() + diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt index e0d5f557235..13b17d439c3 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt @@ -30,14 +30,11 @@ open class Field( fun modifiersToKotlin(): String { val modifierList = ArrayList() - if (isAbstract()) { + if (modifiers.contains(Modifier.ABSTRACT)) { modifierList.add(Modifier.ABSTRACT) } - val modifier = modifiers.accessModifier() - if (modifier != null) { - modifierList.add(modifier) - } + modifiers.accessModifier()?.let { modifierList.add(it) } return modifierList.toKotlin() + (if (isVal()) "val " else "var ") } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt index b99f5884393..a2f9a1e06e1 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt @@ -27,7 +27,8 @@ open class Function( val `type`: Type, val typeParameterList: TypeParameterList, val parameterList: ParameterList, - var block: Block? + var block: Block?, + val isInTrait: Boolean ) : Member(comments, modifiers) { private fun modifiersToKotlin(): String { @@ -42,11 +43,11 @@ open class Function( resultingModifiers.add(accessModifier) } - if (isAbstract()) { + if (modifiers.contains(Modifier.ABSTRACT) && !isInTrait) { resultingModifiers.add(Modifier.ABSTRACT) } - if (modifiers.contains(Modifier.OPEN)) { + if (modifiers.contains(Modifier.OPEN) && !isOverride) { resultingModifiers.add(Modifier.OPEN) } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Members.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Members.kt index 7982f2f6cb9..746eb79237d 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Members.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Members.kt @@ -25,7 +25,6 @@ class MemberComments(elements: List) : WhiteSpaceSeparatedElementList(e } abstract class Member(val comments: MemberComments, val modifiers: Set) : Element { - fun isAbstract(): Boolean = modifiers.contains(Modifier.ABSTRACT) fun isStatic(): Boolean = modifiers.contains(Modifier.STATIC) fun commentsToKotlin(): String = comments.toKotlin() } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt index 4fb6cab8f80..cdcd3f7421d 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt @@ -16,37 +16,26 @@ package org.jetbrains.jet.j2k.ast -import org.jetbrains.jet.j2k.ast.Modifier.PUBLIC -import org.jetbrains.jet.j2k.ast.Modifier.PROTECTED -import org.jetbrains.jet.j2k.ast.Modifier.PRIVATE -import org.jetbrains.jet.j2k.ast.Modifier.INTERNAL - enum class Modifier(val name: String) { PUBLIC: Modifier("public") PROTECTED: Modifier("protected") PRIVATE: Modifier("private") - INTERNAL: Modifier("internal") STATIC: Modifier("static") ABSTRACT: Modifier("abstract") FINAL: Modifier("final") OPEN: Modifier("open") OVERRIDE: Modifier("override") - public fun toKotlin(): String? { - return when(this) { - INTERNAL -> null - else -> name - } - } + public fun toKotlin(): String = name } -val ACCESS_MODIFIERS = setOf(PUBLIC, PROTECTED, PRIVATE, INTERNAL) +val ACCESS_MODIFIERS = setOf(Modifier.PUBLIC, Modifier.PROTECTED, Modifier.PRIVATE) fun Collection.accessModifier(): Modifier? { return firstOrNull { ACCESS_MODIFIERS.contains(it) } } fun Collection.toKotlin(): String - = if (isNotEmpty()) map { it.toKotlin() }.filterNotNull().makeString(" ") + " " else "" + = if (isNotEmpty()) map { it.toKotlin() }.makeString(" ") + " " else "" diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt index 0799dc50d27..4238c0bde6d 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt @@ -17,6 +17,7 @@ package org.jetbrains.jet.j2k.ast import org.jetbrains.jet.j2k.Converter +import java.util.ArrayList class Trait( converter: Converter, @@ -35,5 +36,11 @@ class Trait( get() = "trait" override fun primaryConstructorSignatureToKotlin() = "" - override fun needsOpenModifier() = false + + override fun modifiersToKotlin(): String { + val modifierList = ArrayList() + modifiers.accessModifier()?.let { modifierList.add(it) } + return modifierList.toKotlin() + } + } 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 c15823a3576..15596129836 100644 --- a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java +++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java @@ -1982,6 +1982,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/settings"), Pattern.compile("^(.+)\\.java$"), true); } + @TestMetadata("openByDefault.java") + public void testOpenByDefault() throws Exception { + doTest("j2k/tests/testData/ast/settings/openByDefault.java"); + } + @TestMetadata("specifyLocalVariableTypeByDefault.java") public void testSpecifyLocalVariableTypeByDefault() throws Exception { doTest("j2k/tests/testData/ast/settings/specifyLocalVariableTypeByDefault.java"); diff --git a/j2k/tests/testData/ast/settings/openByDefault.java.todo b/j2k/tests/testData/ast/settings/openByDefault.java similarity index 100% rename from j2k/tests/testData/ast/settings/openByDefault.java.todo rename to j2k/tests/testData/ast/settings/openByDefault.java diff --git a/j2k/tests/testData/ast/settings/openByDefault.kt b/j2k/tests/testData/ast/settings/openByDefault.kt new file mode 100644 index 00000000000..a801e876617 --- /dev/null +++ b/j2k/tests/testData/ast/settings/openByDefault.kt @@ -0,0 +1,34 @@ +// !openByDefault: true + +open class A() { + open fun foo1() { + } + private fun foo2() { + } + fun foo3() { + } +} + +class B() { + fun foo() { + } +} + +abstract class C() { + abstract fun foo() +} + +trait I { + public fun foo() +} + +open class D() : I { + override fun foo() { + } +} + +enum class E { + fun foo(): Int { + return 0 + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/trait/abstactInterface.kt b/j2k/tests/testData/ast/trait/abstactInterface.kt index 988db5e9373..3906f3bee7e 100644 --- a/j2k/tests/testData/ast/trait/abstactInterface.kt +++ b/j2k/tests/testData/ast/trait/abstactInterface.kt @@ -1 +1 @@ -abstract trait I \ No newline at end of file +trait I \ No newline at end of file diff --git a/j2k/tests/testData/ast/trait/interfaceWithFields.kt b/j2k/tests/testData/ast/trait/interfaceWithFields.kt index 1cd7c1bb0ac..0aa03719bf7 100644 --- a/j2k/tests/testData/ast/trait/interfaceWithFields.kt +++ b/j2k/tests/testData/ast/trait/interfaceWithFields.kt @@ -1,7 +1,7 @@ trait INode { class object { - val IN: String = "in" - val AT: String = "@" - val COMMA_WITH_SPACE: String = COMMA + SPACE + public val IN: String = "in" + public val AT: String = "@" + public val COMMA_WITH_SPACE: String = COMMA + SPACE } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/trait/interfaceWithMethodDeclaration.kt b/j2k/tests/testData/ast/trait/interfaceWithMethodDeclaration.kt index 7379723f17b..7c80ad34f56 100644 --- a/j2k/tests/testData/ast/trait/interfaceWithMethodDeclaration.kt +++ b/j2k/tests/testData/ast/trait/interfaceWithMethodDeclaration.kt @@ -1,4 +1,4 @@ trait INode { - fun getTag(): Tag - fun toKotlin(): String + public fun getTag(): Tag + public fun toKotlin(): String } \ No newline at end of file