diff --git a/src/org/jetbrains/jet/j2k/Converter.java b/src/org/jetbrains/jet/j2k/Converter.java index a38dda7620e..ba7b24d3bd6 100644 --- a/src/org/jetbrains/jet/j2k/Converter.java +++ b/src/org/jetbrains/jet/j2k/Converter.java @@ -41,6 +41,7 @@ public class Converter { private static Class classToClass(PsiClass psiClass) { final List methods = methodsToFunctionList(psiClass.getMethods(), true); + final Set modifiers = modifiersListToModifiersSet(psiClass.getModifierList()); final List innerClasses = classesToClassList(psiClass.getAllInnerClasses()); final List fields = fieldsToFieldList(psiClass.getAllFields()); final List typeParameters = elementsToElementList(psiClass.getTypeParameters()); @@ -53,10 +54,10 @@ public class Converter { final IdentifierImpl name = new IdentifierImpl(psiClass.getName()); if (psiClass.isInterface()) - return new Trait(name, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields); + return new Trait(name, modifiers, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields); if (psiClass.isEnum()) - return new Enum(name, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields); - return new Class(name, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields); + return new Enum(name, modifiers, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields); + return new Class(name, modifiers, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields); } private static List fieldsToFieldList(PsiField[] fields) { diff --git a/src/org/jetbrains/jet/j2k/ast/Class.java b/src/org/jetbrains/jet/j2k/ast/Class.java index 24f7fc63bd5..4a9ca601c05 100644 --- a/src/org/jetbrains/jet/j2k/ast/Class.java +++ b/src/org/jetbrains/jet/j2k/ast/Class.java @@ -5,6 +5,7 @@ import org.jetbrains.jet.j2k.util.AstUtil; import java.util.LinkedList; import java.util.List; +import java.util.Set; /** * @author ignatov @@ -12,6 +13,7 @@ import java.util.List; public class Class extends Node { String TYPE = "class"; final Identifier myName; + private Set myModifiers; private final List myTypeParameters; private final List myExtendsTypes; private final List myImplementsTypes; @@ -19,8 +21,10 @@ public class Class extends Node { final List myMethods; final List myFields; - public Class(Identifier name, List typeParameters, List extendsTypes, List implementsTypes, List innerClasses, List methods, List fields) { + public Class(Identifier name, Set modifiers, List typeParameters, List extendsTypes, + List implementsTypes, List innerClasses, List methods, List fields) { myName = name; + myModifiers = modifiers; myTypeParameters = typeParameters; myExtendsTypes = extendsTypes; myImplementsTypes = implementsTypes; @@ -70,10 +74,36 @@ public class Class extends Node { return allTypes.size() == 0 ? EMPTY : SPACE + COLON + SPACE + AstUtil.joinNodes(allTypes, COMMA_WITH_SPACE); } + private String accessModifier() { + for (String m : myModifiers) + if (m.equals(Modifier.PUBLIC) || m.equals(Modifier.PROTECTED) || m.equals(Modifier.PRIVATE)) + return m; + return EMPTY; // package local converted to internal, but we use internal by default + } + + String modifiersToKotlin() { + List modifierList = new LinkedList(); + + modifierList.add(accessModifier()); + + if (needOpenModifier()) + modifierList.add(Modifier.OPEN); + + if (modifierList.size() > 0) + return AstUtil.join(modifierList, SPACE) + SPACE; + + return EMPTY; + } + + boolean needOpenModifier() { + return getKind() != Kind.TRAIT && !myModifiers.contains(Modifier.FINAL); + } + + @NotNull @Override public String toKotlin() { - return TYPE + SPACE + myName.toKotlin() + typeParametersToKotlin() + + return modifiersToKotlin() + TYPE + SPACE + myName.toKotlin() + typeParametersToKotlin() + implementTypesToKotlin() + typeParameterWhereToKotlin() + SPACE + "{" + N + diff --git a/src/org/jetbrains/jet/j2k/ast/Enum.java b/src/org/jetbrains/jet/j2k/ast/Enum.java index dd6db4da722..6a0fd5a3524 100644 --- a/src/org/jetbrains/jet/j2k/ast/Enum.java +++ b/src/org/jetbrains/jet/j2k/ast/Enum.java @@ -5,13 +5,14 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.j2k.util.AstUtil; import java.util.List; +import java.util.Set; /** * @author ignatov */ public class Enum extends Class { - public Enum(Identifier name, List typeParameters, List extendsTypes, List implementsTypes, List innerClasses, List methods, List fields) { - super(name, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields); + public Enum(Identifier name, Set modifiers, List typeParameters, List extendsTypes, List implementsTypes, List innerClasses, List methods, List fields) { + super(name, modifiers, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields); } @Nullable @@ -29,11 +30,10 @@ public class Enum extends Class { return EMPTY; } - @NotNull @Override public String toKotlin() { - return "enum" + SPACE + myName.toKotlin() + typeParametersToKotlin() + primaryConstructorToKotlin() + implementTypesToKotlin() + SPACE + "{" + N + + return modifiersToKotlin() + "enum" + SPACE + myName.toKotlin() + typeParametersToKotlin() + primaryConstructorToKotlin() + implementTypesToKotlin() + SPACE + "{" + N + AstUtil.joinNodes(myFields, N) + N + AstUtil.joinNodes(methodsExceptConstructors(), N) + N + AstUtil.joinNodes(myInnerClasses, N) + N + diff --git a/src/org/jetbrains/jet/j2k/ast/INode.java b/src/org/jetbrains/jet/j2k/ast/INode.java index e0f8323f77f..4cc77364390 100644 --- a/src/org/jetbrains/jet/j2k/ast/INode.java +++ b/src/org/jetbrains/jet/j2k/ast/INode.java @@ -13,6 +13,6 @@ public interface INode { public Kind getKind(); public enum Kind { - UNDEFINED, TYPE, CONSTRUCTOR, BREAK, CONTINUE, VARARG, + UNDEFINED, TYPE, CONSTRUCTOR, BREAK, CONTINUE, VARARG, TRAIT, } } diff --git a/src/org/jetbrains/jet/j2k/ast/Trait.java b/src/org/jetbrains/jet/j2k/ast/Trait.java index 484f5dcbc93..4a357bbdd3e 100644 --- a/src/org/jetbrains/jet/j2k/ast/Trait.java +++ b/src/org/jetbrains/jet/j2k/ast/Trait.java @@ -1,13 +1,22 @@ package org.jetbrains.jet.j2k.ast; +import org.jetbrains.annotations.NotNull; + import java.util.List; +import java.util.Set; /** * @author ignatov */ public class Trait extends Class { - public Trait(Identifier name, List typeParameters, List extendsTypes, List implementsTypes, List innerClasses, List methods, List fields) { - super(name, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields); + public Trait(Identifier name, Set modifiers, List typeParameters, List extendsTypes, List implementsTypes, List innerClasses, List methods, List fields) { + super(name, modifiers, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields); TYPE = "trait"; } + + @NotNull + @Override + public Kind getKind() { + return Kind.TRAIT; + } } diff --git a/test/org/jetbrains/jet/j2k/FileTest.java b/test/org/jetbrains/jet/j2k/FileTest.java index 8d5a8f6a92c..fe4d2d074f6 100644 --- a/test/org/jetbrains/jet/j2k/FileTest.java +++ b/test/org/jetbrains/jet/j2k/FileTest.java @@ -47,14 +47,21 @@ public class FileTest extends JetTestCaseBase { public void testPackageWithClass() throws Exception { Assert.assertEquals( - toSingleLine(fileToKotlin("package test; class C {}")), + toSingleLine(fileToKotlin("package test; final class C {}")), "namespace test { class C { } }" ); } + public void testPackageWithOpenClass() throws Exception { + Assert.assertEquals( + toSingleLine(fileToKotlin("package test; class C {}")), + "namespace test { open class C { } }" + ); + } + public void testPackageWithClasses() throws Exception { Assert.assertEquals( - toSingleLine(fileToKotlin("class A {} class B {}")), + toSingleLine(fileToKotlin("final class A {} final class B {}")), "namespace { class A { } class B { } }"); } } diff --git a/test/org/jetbrains/jet/j2k/JetTestCaseBase.java b/test/org/jetbrains/jet/j2k/JetTestCaseBase.java index e47ef7c7cf8..813c9de4000 100644 --- a/test/org/jetbrains/jet/j2k/JetTestCaseBase.java +++ b/test/org/jetbrains/jet/j2k/JetTestCaseBase.java @@ -93,7 +93,6 @@ public abstract class JetTestCaseBase extends LightDaemonAnalyzerTestCase { String result = prettify(Converter.fileToFile(javaFile).toKotlin()).replaceAll("namespace \\{", ""); result = result.substring(0, result.lastIndexOf("}")); return prettify(result); - } @NotNull @@ -107,7 +106,7 @@ public abstract class JetTestCaseBase extends LightDaemonAnalyzerTestCase { } String methodToKotlin(String text) throws IOException { - String result = classToKotlin("class C {" + text + "}") + String result = classToKotlin("final class C {" + text + "}") .replaceAll("class C \\{", ""); result = result.substring(0, result.lastIndexOf("}")); return prettify(result); diff --git a/test/org/jetbrains/jet/j2k/ast/ClassTest.java b/test/org/jetbrains/jet/j2k/ast/ClassTest.java index 61f49eae934..96b5efcfbb8 100644 --- a/test/org/jetbrains/jet/j2k/ast/ClassTest.java +++ b/test/org/jetbrains/jet/j2k/ast/ClassTest.java @@ -90,4 +90,28 @@ public class ClassTest extends JetTestCaseBase { "class A : Base, I0, I1, I2 { }" ); } + + public void testClass() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("class Test {}"), "open class Test { }"); + } + + public void testFinalClass() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("final class Test {}"), "class Test { }"); + } + + public void testPublicClass() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("public class Test {}"), "public open class Test { }"); + } + + public void testProtectedClass() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("protected class Test {}"), "protected open class Test { }"); + } + + public void testPivateClass() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("private class Test {}"), "private open class Test { }"); + } + + public void testInternalClass() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("class Test {}"), "open class Test { }"); + } } diff --git a/test/org/jetbrains/jet/j2k/ast/EnumTest.java b/test/org/jetbrains/jet/j2k/ast/EnumTest.java index ee36bd1df0d..67ebb370101 100644 --- a/test/org/jetbrains/jet/j2k/ast/EnumTest.java +++ b/test/org/jetbrains/jet/j2k/ast/EnumTest.java @@ -91,6 +91,22 @@ public class EnumTest extends JetTestCaseBase { ); } + public void testPublicEnum() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("public enum Test {}"), "public enum Test { }"); + } + + public void testProtectedEnum() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("protected enum Test {}"), "protected enum Test { }"); + } + + public void testPrivateEnum() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("private enum Test {}"), "private enum Test { }"); + } + + public void testInternalEnum() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("enum Test {}"), "enum Test { }"); + } + // public void testTwoConstructors() throws Exception { // Assert.assertEquals( // classToKotlin( diff --git a/test/org/jetbrains/jet/j2k/ast/TraitTest.java b/test/org/jetbrains/jet/j2k/ast/TraitTest.java index 4e228eb53eb..4bdeb7b6b37 100644 --- a/test/org/jetbrains/jet/j2k/ast/TraitTest.java +++ b/test/org/jetbrains/jet/j2k/ast/TraitTest.java @@ -56,4 +56,20 @@ public class TraitTest extends JetTestCaseBase { "trait A : I0, I1, I2 { }" ); } -} + + public void testPublicInterface() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("public interface Test {}"), "public trait Test { }"); + } + + public void testProtectedInterface() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("protected interface Test {}"), "protected trait Test { }"); + } + + public void testPrivateInterface() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("private interface Test {}"), "private trait Test { }"); + } + + public void testInternalInterface() throws Exception { + Assert.assertEquals(classToSingleLineKotlin("interface Test {}"), "trait Test { }"); + } +} \ No newline at end of file