diff --git a/src/org/jetbrains/jet/j2k/Converter.java b/src/org/jetbrains/jet/j2k/Converter.java index ba7b24d3bd6..aebf33da9ba 100644 --- a/src/org/jetbrains/jet/j2k/Converter.java +++ b/src/org/jetbrains/jet/j2k/Converter.java @@ -268,6 +268,7 @@ public class Converter { HashSet modifiersSet = new HashSet(); if (modifierList != null) { if (modifierList.hasModifierProperty(PsiModifier.FINAL)) modifiersSet.add(Modifier.FINAL); + if (modifierList.hasModifierProperty(PsiModifier.STATIC)) modifiersSet.add(Modifier.STATIC); if (modifierList.hasModifierProperty(PsiModifier.PUBLIC)) modifiersSet.add(Modifier.PUBLIC); if (modifierList.hasModifierProperty(PsiModifier.PROTECTED)) modifiersSet.add(Modifier.PROTECTED); if (modifierList.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) modifiersSet.add(Modifier.INTERNAL); diff --git a/src/org/jetbrains/jet/j2k/ast/Class.java b/src/org/jetbrains/jet/j2k/ast/Class.java index 4a9ca601c05..87c05308f31 100644 --- a/src/org/jetbrains/jet/j2k/ast/Class.java +++ b/src/org/jetbrains/jet/j2k/ast/Class.java @@ -10,10 +10,9 @@ import java.util.Set; /** * @author ignatov */ -public class Class extends Node { +public class Class extends Member { String TYPE = "class"; final Identifier myName; - private Set myModifiers; private final List myTypeParameters; private final List myExtendsTypes; private final List myImplementsTypes; @@ -74,13 +73,6 @@ 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(); @@ -96,9 +88,45 @@ public class Class extends Node { } boolean needOpenModifier() { - return getKind() != Kind.TRAIT && !myModifiers.contains(Modifier.FINAL); + return !myModifiers.contains(Modifier.FINAL); } + String bodyToKotlin() { + return classObjectToKotlin() + N + + AstUtil.joinNodes(getNonStatic(myFields), N) + N + + AstUtil.joinNodes(getNonStatic(methodsExceptConstructors()), N) + N + + AstUtil.joinNodes(getNonStatic(myInnerClasses), N) + N; + } + + private List getStatic(List members) { + List result = new LinkedList(); + for (Member m : members) + if (m.isStatic()) + result.add(m); + return result; + } + + private List getNonStatic(List members) { + List result = new LinkedList(); + for (Member m : members) + if (!m.isStatic()) + result.add(m); + return result; + } + + private String classObjectToKotlin() { + final List staticFields = getStatic(myFields); + final List staticMethods = getStatic(methodsExceptConstructors()); + final List staticInnerClasses = getStatic(myInnerClasses); + if (staticFields.size() + staticMethods.size() + staticInnerClasses.size() > 0) { + return "class" + SPACE + "object" + SPACE + "{" + N + + AstUtil.joinNodes(staticFields, N) + N + + AstUtil.joinNodes(staticMethods, N) + N + + AstUtil.joinNodes(staticInnerClasses, N) + N + + "}"; + } + return EMPTY; + } @NotNull @Override @@ -107,9 +135,7 @@ public class Class extends Node { implementTypesToKotlin() + typeParameterWhereToKotlin() + SPACE + "{" + N + - AstUtil.joinNodes(myFields, N) + N + - AstUtil.joinNodes(methodsExceptConstructors(), N) + N + - AstUtil.joinNodes(myInnerClasses, N) + N + + bodyToKotlin() + "}"; } } diff --git a/src/org/jetbrains/jet/j2k/ast/Field.java b/src/org/jetbrains/jet/j2k/ast/Field.java index 360466124e0..8efc6b4fb8a 100644 --- a/src/org/jetbrains/jet/j2k/ast/Field.java +++ b/src/org/jetbrains/jet/j2k/ast/Field.java @@ -10,9 +10,8 @@ import java.util.Set; /** * @author ignatov */ -public class Field extends Node { +public class Field extends Member { final Identifier myIdentifier; - private Set myModifiers; private final Type myType; final Element myInitializer; @@ -23,13 +22,6 @@ public class Field extends Node { myInitializer = initializer; } - 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(); @@ -43,6 +35,11 @@ public class Field extends Node { return EMPTY; } + @Override + public boolean isStatic() { + return myModifiers.contains(Modifier.STATIC); + } + @NotNull @Override public String toKotlin() { diff --git a/src/org/jetbrains/jet/j2k/ast/Function.java b/src/org/jetbrains/jet/j2k/ast/Function.java index ee8a9424d04..113b2acd129 100644 --- a/src/org/jetbrains/jet/j2k/ast/Function.java +++ b/src/org/jetbrains/jet/j2k/ast/Function.java @@ -10,9 +10,8 @@ import java.util.Set; /** * @author ignatov */ -public class Function extends Node { +public class Function extends Member { private final Identifier myName; - private Set myModifiers; private final Type myType; private final List myTypeParameters; final Element myParams; @@ -38,13 +37,6 @@ public class Function extends Node { return false; } - 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 - } - private String typeParameterWhereToKotlin() { if (hasWhere()) { List wheres = new LinkedList(); diff --git a/src/org/jetbrains/jet/j2k/ast/IMember.java b/src/org/jetbrains/jet/j2k/ast/IMember.java new file mode 100644 index 00000000000..98f4fb46a20 --- /dev/null +++ b/src/org/jetbrains/jet/j2k/ast/IMember.java @@ -0,0 +1,8 @@ +package org.jetbrains.jet.j2k.ast; + +/** + * @author ignatov + */ +public interface IMember extends INode { + public boolean isStatic(); +} diff --git a/src/org/jetbrains/jet/j2k/ast/Member.java b/src/org/jetbrains/jet/j2k/ast/Member.java new file mode 100644 index 00000000000..5ef2619092c --- /dev/null +++ b/src/org/jetbrains/jet/j2k/ast/Member.java @@ -0,0 +1,22 @@ +package org.jetbrains.jet.j2k.ast; + +import java.util.Set; + +/** + * @author ignatov + */ +public abstract class Member extends Node implements IMember { + protected Set myModifiers; + + protected 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 + } + + @Override + public boolean isStatic() { + return myModifiers.contains(Modifier.STATIC); + } +} diff --git a/src/org/jetbrains/jet/j2k/ast/Trait.java b/src/org/jetbrains/jet/j2k/ast/Trait.java index 4a357bbdd3e..7a373d74828 100644 --- a/src/org/jetbrains/jet/j2k/ast/Trait.java +++ b/src/org/jetbrains/jet/j2k/ast/Trait.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.j2k.ast; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.j2k.util.AstUtil; import java.util.List; import java.util.Set; @@ -14,6 +15,16 @@ public class Trait extends Class { TYPE = "trait"; } + boolean needOpenModifier() { + return false; + } + + String bodyToKotlin() { + return AstUtil.joinNodes(myFields, N) + N + + AstUtil.joinNodes(methodsExceptConstructors(), N) + N + + AstUtil.joinNodes(myInnerClasses, N) + N; + } + @NotNull @Override public Kind getKind() { diff --git a/test/org/jetbrains/jet/j2k/ast/ClassTest.java b/test/org/jetbrains/jet/j2k/ast/ClassTest.java index 96b5efcfbb8..7218f8d95ab 100644 --- a/test/org/jetbrains/jet/j2k/ast/ClassTest.java +++ b/test/org/jetbrains/jet/j2k/ast/ClassTest.java @@ -114,4 +114,32 @@ public class ClassTest extends JetTestCaseBase { public void testInternalClass() throws Exception { Assert.assertEquals(classToSingleLineKotlin("class Test {}"), "open class Test { }"); } + + public void testOneStaticMethod() throws Exception { + Assert.assertEquals( + classToSingleLineKotlin("final class S { static boolean staticF() { return true; } }"), + "class S { class object { fun staticF() : Boolean { return true } } }" + ); + } + + public void testTwoStaticMethod() throws Exception { + Assert.assertEquals( + classToSingleLineKotlin("final class S { static boolean sB() { return true; } static int sI() { return 1; } }"), + "class S { class object { fun sB() : Boolean { return true } fun sI() : Int { return 1 } } }" + ); + } + + public void testOneStaticMethodOneNonStatic() throws Exception { + Assert.assertEquals( + classToSingleLineKotlin("final class S { boolean sB() { return true; } static int sI() { return 1; } }"), + "class S { class object { fun sI() : Int { return 1 } } fun sB() : Boolean { return true } }" + ); + } + + public void testOneStaticFieldOneNonStatic() throws Exception { + Assert.assertEquals( + classToSingleLineKotlin("final class S { boolean sB() { return true; } static int myI = 10; }"), + "class S { class object { var myI : Int = 10 } fun sB() : Boolean { return true } }" + ); + } } diff --git a/test/org/jetbrains/jet/j2k/ast/TraitTest.java b/test/org/jetbrains/jet/j2k/ast/TraitTest.java index a835f20806d..da081b9102b 100644 --- a/test/org/jetbrains/jet/j2k/ast/TraitTest.java +++ b/test/org/jetbrains/jet/j2k/ast/TraitTest.java @@ -72,4 +72,20 @@ public class TraitTest extends JetTestCaseBase { public void testInternalInterface() throws Exception { Assert.assertEquals(classToSingleLineKotlin("interface Test {}"), "trait Test { }"); } + + public void testInterfaceWithStaticFields() throws Exception { + Assert.assertEquals(classToKotlin( + "public interface INode {" + + " public static final String IN = \"in\";" + + " public static final String AT = \"@\";" + + " public static final String COMMA_WITH_SPACE = COMMA + SPACE;" + + "}" + ), + "public trait INode {\n" + + "public val IN : String? = \"in\"\n" + + "public val AT : String? = \"@\"\n" + + "public val COMMA_WITH_SPACE : String? = (COMMA + SPACE)\n" + + "}" + ); + } } \ No newline at end of file