another one case with constructors supported

This commit is contained in:
Sergey Ignatov
2011-11-14 14:29:58 +04:00
parent fdf18e85fc
commit 548d89ef4e
45 changed files with 319 additions and 56 deletions
+105 -5
View File
@@ -7,12 +7,10 @@ import org.jetbrains.jet.j2k.ast.*;
import org.jetbrains.jet.j2k.ast.Class;
import org.jetbrains.jet.j2k.ast.Enum;
import org.jetbrains.jet.j2k.ast.Modifier;
import org.jetbrains.jet.j2k.util.AstUtil;
import org.jetbrains.jet.j2k.visitors.*;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.*;
/**
* @author ignatov
@@ -45,6 +43,39 @@ public class Converter {
);
}
private static List<Field> getFinalOrWithEmptyInitializer(List<? extends Field> fields) {
List<Field> result = new LinkedList<Field>();
for (Field f : fields)
if (f.isFinal() || f.getInitializer().toKotlin().isEmpty())
result.add(f);
return result;
}
private static List<Parameter> createParametersFromFields(List<? extends Field> fields) {
List<Parameter> result = new LinkedList<Parameter>();
for (Field f : fields)
result.add(new Parameter(f.getIdentifier(), f.getType()));
return result;
}
private static List<Statement> createInitStatementsFromFields(List<? extends Field> fields) {
List<Statement> result = new LinkedList<Statement>();
for (Field f : fields) {
final String identifierToKotlin = f.getIdentifier().toKotlin();
result.add(new DummyStringStatement("this." + identifierToKotlin + " = " + identifierToKotlin));
}
return result;
}
private static String createPrimaryConstructorInvocation(String s, List<? extends Field> fields, Map<String, String> initializers) {
List<String> result = new LinkedList<String>();
for (Field f : fields) {
final String id = f.getIdentifier().toKotlin();
result.add(initializers.get(id));
}
return s + "(" + AstUtil.join(result, ", ") + ")";
}
public static Class classToClass(PsiClass psiClass) {
final Set<String> modifiers = modifiersListToModifiersSet(psiClass.getModifierList());
final List<Class> innerClasses = classesToClassList(psiClass.getAllInnerClasses());
@@ -53,8 +84,68 @@ public class Converter {
final List<Element> typeParameters = elementsToElementList(psiClass.getTypeParameters());
final List<Type> implementsTypes = typesToNotNullableTypeList(psiClass.getImplementsListTypes());
final List<Type> extendsTypes = typesToNotNullableTypeList(psiClass.getExtendsListTypes());
final IdentifierImpl name = new IdentifierImpl(psiClass.getName());
// we create primary constructor
if (!psiClass.isEnum() && getPrimaryConstructor(psiClass) == null) {
final List<Field> finalOrWithEmptyInitializer = getFinalOrWithEmptyInitializer(fields);
final Map<String, String> initializers = new HashMap<String, String>();
for (Field f : finalOrWithEmptyInitializer) {
String init = getDefaultInitializer(f);
initializers.put(f.getIdentifier().toKotlin(), init);
}
for (final Function f : methods) {
// and modify secondaries
if (f.getKind() == INode.Kind.CONSTRUCTOR && !((Constructor) f).isPrimary()) {
final List<Statement> newStatements = new LinkedList<Statement>();
for (Statement s : f.getBlock().getStatements()) {
boolean isRemoved = false;
if (s.getKind() == INode.Kind.ASSINGNMENT_EXPRESSION) {
final AssignmentExpression assignmentExpression = (AssignmentExpression) s;
if (assignmentExpression.getLeft().getKind() == INode.Kind.CALL_CHAIN) {
for (Field fo : finalOrWithEmptyInitializer) {
final String id = fo.getIdentifier().toKotlin();
if (((CallChainExpression) assignmentExpression.getLeft()).getIdentifier().toKotlin().endsWith(id)) {
initializers.put(id, assignmentExpression.getRight().toKotlin());
isRemoved = true;
}
}
}
}
if (!isRemoved) {
newStatements.add(s);
}
}
newStatements.add(
0,
new DummyStringStatement(
"val __ = " + createPrimaryConstructorInvocation(
name.toKotlin(),
finalOrWithEmptyInitializer,
initializers)));
f.setBlock(new Block(newStatements));
}
}
methods.add(
new Constructor(
Identifier.EMPTY_IDENTIFIER,
new HashSet<String>(),
new ClassType(name, false),
new LinkedList<Element>(),
new ParameterList(createParametersFromFields(finalOrWithEmptyInitializer)),
new Block(createInitStatementsFromFields(finalOrWithEmptyInitializer)),
true
)
);
}
if (psiClass.isInterface())
return new Trait(name, modifiers, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields);
if (psiClass.isEnum())
@@ -63,6 +154,15 @@ public class Converter {
return new Class(name, modifiers, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields);
}
private static String getDefaultInitializer(Field f) {
if (f.getType().isNullable()) return "null";
final String typeToKotlin = f.getType().toKotlin();
if (typeToKotlin.equals("Boolean")) return "false";
if (typeToKotlin.equals("Int")) return "0";
return "TYPE: " + typeToKotlin + " HAVEN'T DEFAULT VALUE";
}
// TODO: hack for enums
private static List<Field> fieldsToFieldListForEnums(PsiField[] fields) {
List<Field> result = new LinkedList<Field>();
@@ -10,6 +10,14 @@ public class AssignmentExpression extends Expression {
private final Expression myRight;
private final String myOp;
public Expression getLeft() {
return myLeft;
}
public Expression getRight() {
return myRight;
}
public AssignmentExpression(Expression left, Expression right, String op) {
myLeft = left;
myRight = right;
@@ -21,4 +29,10 @@ public class AssignmentExpression extends Expression {
public String toKotlin() {
return myLeft.toKotlin() + SPACE + myOp + SPACE + myRight.toKotlin();
}
@NotNull
@Override
public Kind getKind() {
return Kind.ASSINGNMENT_EXPRESSION;
}
}
@@ -9,6 +9,16 @@ public class CallChainExpression extends Expression {
private Expression myExpression;
private Expression myIdentifier;
public Expression getIdentifier() {
return myIdentifier;
}
@NotNull
@Override
public Kind getKind() {
return Kind.CALL_CHAIN;
}
public CallChainExpression(Expression expression, Expression identifier) {
myExpression = expression;
myIdentifier = identifier;
+2 -2
View File
@@ -52,7 +52,7 @@ public class Class extends Member {
String primaryConstructorBodyToKotlin() {
Constructor maybeConstructor = getPrimaryConstructor();
if (maybeConstructor != null)
if (maybeConstructor != null && !maybeConstructor.getBlock().isEmpty())
return maybeConstructor.primaryBodyToKotlin();
return EMPTY;
}
@@ -150,10 +150,10 @@ public class Class extends Member {
String bodyToKotlin() {
return SPACE + "{" + N +
AstUtil.joinNodes(getNonStatic(myFields), N) + N +
primaryConstructorBodyToKotlin() + N +
classObjectToKotlin() + N +
AstUtil.joinNodes(getNonStatic(methodsExceptConstructors()), N) + N +
AstUtil.joinNodes(getNonStatic(myInnerClasses), N) + N +
primaryConstructorBodyToKotlin() + N +
"}";
}
@@ -0,0 +1,20 @@
package org.jetbrains.jet.j2k.ast;
import org.jetbrains.annotations.NotNull;
/**
* @author ignatov
*/
public class DummyStringStatement extends Statement {
private String myString;
public DummyStringStatement(String string) {
myString = string;
}
@NotNull
@Override
public String toKotlin() {
return myString;
}
}
+16
View File
@@ -22,6 +22,18 @@ public class Field extends Member {
myInitializer = initializer;
}
public Element getInitializer() {
return myInitializer;
}
public Identifier getIdentifier() {
return myIdentifier;
}
public Type getType() {
return myType;
}
String modifiersToKotlin() {
List<String> modifierList = new LinkedList<String>();
@@ -43,6 +55,10 @@ public class Field extends Member {
return myModifiers.contains(Modifier.STATIC);
}
public boolean isFinal() {
return myModifiers.contains(Modifier.FINAL);
}
@NotNull
@Override
public String toKotlin() {
+7 -1
View File
@@ -15,7 +15,13 @@ public class Function extends Member {
private final Type myType;
private final List<Element> myTypeParameters;
final Element myParams;
final Block myBlock;
// TODO: maybe remove it?
public void setBlock(Block block) {
myBlock = block;
}
Block myBlock;
public Function(Identifier name, Set<String> modifiers, Type type, List<Element> typeParameters, Element params, Block block) {
myName = name;
+1 -1
View File
@@ -13,6 +13,6 @@ public interface INode {
public Kind getKind();
public enum Kind {
UNDEFINED, TYPE, CONSTRUCTOR, BREAK, CONTINUE, VARARG, TRAIT,
UNDEFINED, TYPE, CONSTRUCTOR, BREAK, CONTINUE, VARARG, TRAIT, ASSINGNMENT_EXPRESSION, CALL_CHAIN,
}
}
+2 -2
View File
@@ -6,10 +6,10 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov
*/
public class Parameter extends Expression {
private final IdentifierImpl myIdentifier;
private final Identifier myIdentifier;
private final Type myType;
public Parameter(IdentifierImpl identifier, Type type) {
public Parameter(Identifier identifier, Type type) {
myIdentifier = identifier;
myType = type;
}
@@ -1,7 +1,10 @@
open class Library() {
open class Library(ourOut : PrintStream?) {
class object {
val ourOut : PrintStream?
}
{
this.ourOut = ourOut
}
}
open class User() {
open fun main() : Unit {
@@ -1,5 +1,8 @@
open class Library() {
open class Library(myString : String?) {
public val myString : String?
{
this.myString = myString
}
}
open class User() {
open fun main() : Unit {
@@ -1,7 +1,5 @@
abstract open class Shape() {
public var color : String?
{
}
open public fun setColor(c : String?) : Unit {
color = c
}
@@ -9,4 +7,6 @@ open public fun getColor() : String? {
return color
}
abstract open public fun area() : Double
{
}
}
@@ -1,5 +1,9 @@
class T() {
class T(a : String?, b : String?) {
var a : String?
var b : String?
var c : String? = "abc"
{
this.a = a
this.b = b
}
}
@@ -1,6 +1,4 @@
open class C(arg1 : Int, arg2 : Int, arg3 : Int) {
{
}
class object {
open fun init(arg1 : Int, arg2 : Int) : C {
val __ = C(arg1, arg2, 0)
@@ -11,6 +9,8 @@ val __ = C(arg1, 0, 0)
return __
}
}
{
}
}
public open class User() {
class object {
@@ -2,11 +2,6 @@ open class C(arg1 : Int) {
val myArg1 : Int
var myArg2 : Int
var myArg3 : Int
{
$myArg1 = arg1
$myArg2 = 0
$myArg3 = 0
}
class object {
open fun init(arg1 : Int, arg2 : Int, arg3 : Int) : C {
val __ = C(arg1)
@@ -21,6 +16,11 @@ __.myArg3 = 0
return __
}
}
{
$myArg1 = arg1
$myArg2 = 0
$myArg3 = 0
}
}
public open class User() {
class object {
@@ -2,12 +2,6 @@ namespace org.test.customer {
open class Customer(first : String?, last : String?) {
public val _firstName : String?
public val _lastName : String?
{
doSmthBefore()
$_firstName = first
$_lastName = last
doSmthAfter()
}
open public fun getFirstName() : String? {
return _firstName
}
@@ -18,6 +12,12 @@ open private fun doSmthBefore() : Unit {
}
open private fun doSmthAfter() : Unit {
}
{
doSmthBefore()
$_firstName = first
$_lastName = last
doSmthAfter()
}
}
open class CustomerBuilder() {
public var _firstName : String? = "Homer"
@@ -0,0 +1,33 @@
public class Identifier {
private final String myName;
private boolean myHasDollar;
private boolean myNullable = true;
public Identifier(String name) {
myName = name;
}
public Identifier(String name, boolean isNullable) {
myName = name;
myNullable = isNullable;
}
public Identifier(String name, boolean hasDollar, boolean isNullable) {
myName = name;
myHasDollar = hasDollar;
myNullable = isNullable;
}
@Override
public String getName() {
return myName;
}
}
public class User {
public static void main() {
Identifier i1 = new Identifier("name", false, true);
Identifier i2 = new Identifier("name", false);
Identifier i3 = new Identifier("name");
}
}
@@ -0,0 +1,37 @@
public open class Identifier(myName : String?, myHasDollar : Boolean) {
private val myName : String?
private var myHasDollar : Boolean
private var myNullable : Boolean = true
class object {
open public fun init(name : String?) : Identifier {
val __ = Identifier(name, false)
return __
}
open public fun init(name : String?, isNullable : Boolean) : Identifier {
val __ = Identifier(name, false)
__.myNullable = isNullable
return __
}
open public fun init(name : String?, hasDollar : Boolean, isNullable : Boolean) : Identifier {
val __ = Identifier(name, hasDollar)
__.myNullable = isNullable
return __
}
}
open public fun getName() : String? {
return myName
}
{
this.myName = myName
this.myHasDollar = myHasDollar
}
}
public open class User() {
class object {
open public fun main() : Unit {
var i1 : Identifier? = Identifier.init("name", false, true)
var i2 : Identifier? = Identifier.init("name", false)
var i3 : Identifier? = Identifier.init("name")
}
}
}
@@ -1,11 +1,11 @@
enum Color {
WHITE(21)
BLACK(22)
RED(23)
YELLOW(24)
BLUE(25)
enum Color(c: Int) {
WHITE : Color(21)
BLACK : Color(22)
RED : Color(23)
YELLOW : Color(24)
BLUE : Color(25)
private var code : Int
open private (c : Int) {
{
$code = c
}
open public fun getCode() : Int {
@@ -0,0 +1,3 @@
class C {
Foo f;
}
+3
View File
@@ -0,0 +1,3 @@
class C {
private Foo f;
}
@@ -0,0 +1,3 @@
class C {
protected Foo f;
}
+3
View File
@@ -0,0 +1,3 @@
class C {
public Foo f;
}
+3
View File
@@ -0,0 +1,3 @@
class C {
final Foo f = new Foo(1, 2);
}
+3
View File
@@ -0,0 +1,3 @@
class C {
Foo f = new Foo(1, 2);
}
@@ -0,0 +1,3 @@
class C {
Foo f;
}
@@ -1 +0,0 @@
Foo f;
@@ -1 +0,0 @@
var f : Foo?
@@ -1 +0,0 @@
private Foo f;
@@ -1 +0,0 @@
private var f : Foo?
@@ -1 +0,0 @@
protected Foo f;
@@ -1 +0,0 @@
protected var f : Foo?
@@ -1 +0,0 @@
public Foo f;
-1
View File
@@ -1 +0,0 @@
public var f : Foo?
@@ -1 +0,0 @@
final Foo f = new Foo(1, 2);
-1
View File
@@ -1 +0,0 @@
val f : Foo? = Foo(1, 2)
@@ -1 +0,0 @@
Foo f = new Foo(1, 2);
-1
View File
@@ -1 +0,0 @@
var f : Foo? = Foo(1, 2)
@@ -1 +0,0 @@
Foo f;
@@ -1 +0,0 @@
var f : Foo?
@@ -4,10 +4,10 @@ open class `$`() {
}
open class `$$`(`$$$$` : `$$$$$`?) : `$` {
val `$$$` : `$$$$$`?
{
$`$$$` = `$$$$`
}
open public fun `$$$$$$`() : `$$$$$`? {
return `$$$`
}
{
$`$$$` = `$$$$`
}
}
@@ -3,10 +3,10 @@ open fun call() : Unit {
}
}
open class A() : B {
{
super()
}
override fun call() : Unit {
return super.call()
}
{
super()
}
}
@@ -4,4 +4,9 @@ val IN : String? = "in"
val AT : String? = "@"
val COMMA_WITH_SPACE : String? = (COMMA + SPACE)
}
{
this.IN = IN
this.AT = AT
this.COMMA_WITH_SPACE = COMMA_WITH_SPACE
}
}
@@ -4,4 +4,9 @@ public val IN : String? = "in"
public val AT : String? = "@"
public val COMMA_WITH_SPACE : String? = (COMMA + SPACE)
}
{
this.IN = IN
this.AT = AT
this.COMMA_WITH_SPACE = COMMA_WITH_SPACE
}
}