diff --git a/src/org/jetbrains/jet/j2k/Converter.java b/src/org/jetbrains/jet/j2k/Converter.java index 08b762da9e7..f7067cc5a7e 100644 --- a/src/org/jetbrains/jet/j2k/Converter.java +++ b/src/org/jetbrains/jet/j2k/Converter.java @@ -85,9 +85,26 @@ public class Converter { final List implementsTypes = typesToNotNullableTypeList(psiClass.getImplementsListTypes()); final List extendsTypes = typesToNotNullableTypeList(psiClass.getExtendsListTypes()); final IdentifierImpl name = new IdentifierImpl(psiClass.getName()); + final List baseClassParams = new LinkedList(); + +// for (PsiType t : psiClass.getExtendsListTypes()) +// if (t != null && t instanceof PsiClassType) { +// final PsiClass resolve = ((PsiClassType) t).resolve(); +// if (resolve != null) { + final SuperVisitor visitor = new SuperVisitor(); + psiClass.accept(visitor); + final HashSet resolvedSuperCallParameters = visitor.getResolvedSuperCallParameters(); + if (resolvedSuperCallParameters.size() == 1) + baseClassParams.addAll( + expressionsToExpressionList( + resolvedSuperCallParameters.toArray(new PsiExpressionList[1])[0].getExpressions() + ) + ); +// } +// } // we create primary constructor - if (!psiClass.isEnum() && !psiClass.isInterface() && getPrimaryConstructor(psiClass) == null) { + if (!psiClass.isEnum() && !psiClass.isInterface() && getPrimaryConstructorForThisCase(psiClass) == null) { final List finalOrWithEmptyInitializer = getFinalOrWithEmptyInitializer(fields); final Map initializers = new HashMap(); @@ -147,11 +164,11 @@ public class Converter { } if (psiClass.isInterface()) - return new Trait(name, modifiers, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields); + return new Trait(name, modifiers, typeParameters, extendsTypes, Collections.emptyList(), implementsTypes, innerClasses, methods, fields); if (psiClass.isEnum()) - return new Enum(name, modifiers, typeParameters, Collections.emptyList(), implementsTypes, + return new Enum(name, modifiers, typeParameters, Collections.emptyList(), Collections.emptyList(), implementsTypes, innerClasses, methods, fieldsToFieldListForEnums(psiClass.getAllFields())); - return new Class(name, modifiers, typeParameters, extendsTypes, implementsTypes, innerClasses, methods, fields); + return new Class(name, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, innerClasses, methods, fields); } private static String getDefaultInitializer(Field f) { @@ -219,7 +236,7 @@ public class Converter { } @Nullable - public static PsiMethod getPrimaryConstructor(PsiClass psiClass) { + public static PsiMethod getPrimaryConstructorForThisCase(PsiClass psiClass) { ThisVisitor tv = new ThisVisitor(); psiClass.accept(tv); return tv.getPrimaryConstructor(); @@ -233,7 +250,7 @@ public class Converter { if (parent.getConstructors().length == 1) return true; else { - PsiMethod c = getPrimaryConstructor(parent); // TODO: move up to classToClass() method + PsiMethod c = getPrimaryConstructorForThisCase(parent); // TODO: move up to classToClass() method if (c != null && c.hashCode() == constructor.hashCode()) return true; } @@ -241,6 +258,22 @@ public class Converter { return false; } + @Nullable + public static PsiMethod getPrimaryConstructor(@NotNull PsiClass psiClass) { // TODO + for (PsiMethod c : psiClass.getConstructors()) + if (isConstructorPrimary(c)) + return c; + return null; + } + + private static List removeEmpty(List statements) { + List result = new LinkedList(); + for (Statement s : statements) + if (s != Statement.EMPTY_STATEMENT && s != Expression.EMPTY_EXPRESSION) + result.add(s); + return result; + } + @NotNull private static Function methodToFunction(PsiMethod method, boolean notEmpty) { final IdentifierImpl identifier = new IdentifierImpl(method.getName()); @@ -257,14 +290,13 @@ public class Converter { if (method.isConstructor()) { // TODO: simplify boolean isPrimary = isConstructorPrimary(method); - return new Constructor( identifier, modifiers, type, typeParameters, params, - body, + new Block(removeEmpty(body.getStatements()), false), isPrimary ); } diff --git a/src/org/jetbrains/jet/j2k/ast/AnonymousClass.java b/src/org/jetbrains/jet/j2k/ast/AnonymousClass.java index adb95335884..66bc42d0340 100644 --- a/src/org/jetbrains/jet/j2k/ast/AnonymousClass.java +++ b/src/org/jetbrains/jet/j2k/ast/AnonymousClass.java @@ -14,6 +14,7 @@ public class AnonymousClass extends Class { Collections.emptySet(), Collections.emptyList(), Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), innerClasses, methods, diff --git a/src/org/jetbrains/jet/j2k/ast/Class.java b/src/org/jetbrains/jet/j2k/ast/Class.java index 6ee09365a96..a3b45d5bb70 100644 --- a/src/org/jetbrains/jet/j2k/ast/Class.java +++ b/src/org/jetbrains/jet/j2k/ast/Class.java @@ -9,12 +9,15 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; +import static org.jetbrains.jet.j2k.util.AstUtil.*; + /** * @author ignatov */ public class Class extends Member { String TYPE = "class"; final Identifier myName; + private final List myBaseClassParams; private final List myTypeParameters; private final List myExtendsTypes; private final List myImplementsTypes; @@ -23,8 +26,9 @@ public class Class extends Member { final List myFields; public Class(Identifier name, Set modifiers, List typeParameters, List extendsTypes, - List implementsTypes, List innerClasses, List methods, List fields) { + List baseClassParams, List implementsTypes, List innerClasses, List methods, List fields) { myName = name; + myBaseClassParams = baseClassParams; myModifiers = modifiers; myTypeParameters = typeParameters; myExtendsTypes = extendsTypes; @@ -70,7 +74,7 @@ public class Class extends Member { for (Element t : myTypeParameters) if (t instanceof TypeParameter) wheres.add(((TypeParameter) t).getWhereToKotlin()); - return SPACE + "where" + SPACE + AstUtil.join(wheres, COMMA_WITH_SPACE) + SPACE; + return SPACE + "where" + SPACE + join(wheres, COMMA_WITH_SPACE) + SPACE; } return EMPTY; } @@ -112,14 +116,23 @@ public class Class extends Member { return myTypeParameters.size() > 0 ? "<" + AstUtil.joinNodes(myTypeParameters, COMMA_WITH_SPACE) + ">" : EMPTY; } + List baseClassSignatureWithParams() { + if (TYPE.equals("class") && myExtendsTypes.size() == 1) { + LinkedList result = new LinkedList(); + result.add(myExtendsTypes.get(0).toKotlin() + "(" + joinNodes(myBaseClassParams, COMMA_WITH_SPACE) + ")"); + return result; + } else + return nodesToKotlin(myExtendsTypes); + } + String implementTypesToKotlin() { - List allTypes = new LinkedList() { + List allTypes = new LinkedList() { { - addAll(myExtendsTypes); - addAll(myImplementsTypes); + addAll(baseClassSignatureWithParams()); + addAll(nodesToKotlin(myImplementsTypes)); } }; - return allTypes.size() == 0 ? EMPTY : SPACE + COLON + SPACE + AstUtil.joinNodes(allTypes, COMMA_WITH_SPACE); + return allTypes.size() == 0 ? EMPTY : SPACE + COLON + SPACE + join(allTypes, COMMA_WITH_SPACE); } String modifiersToKotlin() { @@ -134,7 +147,7 @@ public class Class extends Member { modifierList.add(Modifier.OPEN); if (modifierList.size() > 0) - return AstUtil.join(modifierList, SPACE) + SPACE; + return join(modifierList, SPACE) + SPACE; return EMPTY; } diff --git a/src/org/jetbrains/jet/j2k/ast/Enum.java b/src/org/jetbrains/jet/j2k/ast/Enum.java index e7c7dd0867f..1b16eda4613 100644 --- a/src/org/jetbrains/jet/j2k/ast/Enum.java +++ b/src/org/jetbrains/jet/j2k/ast/Enum.java @@ -11,8 +11,8 @@ import java.util.Set; * @author ignatov */ public class Enum extends Class { - 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); + public Enum(Identifier name, Set modifiers, List typeParameters, List extendsTypes, List baseClassParams, List implementsTypes, List innerClasses, List methods, List fields) { + super(name, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, innerClasses, methods, fields); } @Nullable diff --git a/src/org/jetbrains/jet/j2k/ast/Trait.java b/src/org/jetbrains/jet/j2k/ast/Trait.java index 9f58a557785..efc17f38466 100644 --- a/src/org/jetbrains/jet/j2k/ast/Trait.java +++ b/src/org/jetbrains/jet/j2k/ast/Trait.java @@ -7,8 +7,8 @@ import java.util.Set; * @author ignatov */ public class Trait extends Class { - 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); + public Trait(Identifier name, Set modifiers, List typeParameters, List extendsTypes, List baseClassParams, List implementsTypes, List innerClasses, List methods, List fields) { + super(name, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, innerClasses, methods, fields); TYPE = "trait"; } diff --git a/src/org/jetbrains/jet/j2k/util/AstUtil.java b/src/org/jetbrains/jet/j2k/util/AstUtil.java index a4ad4b7f869..7b2c391fe3c 100644 --- a/src/org/jetbrains/jet/j2k/util/AstUtil.java +++ b/src/org/jetbrains/jet/j2k/util/AstUtil.java @@ -31,7 +31,7 @@ public class AstUtil { return join(array.toArray(new String[array.size()]), delimiter); } - private static List nodesToKotlin(List nodes) { + public static List nodesToKotlin(List nodes) { List result = new LinkedList(); for (INode n : nodes) result.add(n.toKotlin()); diff --git a/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java b/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java index ed1a81428e4..c7a823f0849 100644 --- a/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java +++ b/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java @@ -164,12 +164,13 @@ public class ExpressionVisitor extends StatementVisitor implements Visitor { @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); - myResult = // TODO: not resolved - new MethodCallExpression( - expressionToExpression(expression.getMethodExpression()), - elementToElement(expression.getArgumentList()), - typeToType(expression.getType()).isNullable() - ); + if (!SuperVisitor.isSuper(expression.getMethodExpression()) || !isInsidePrimaryConstructor(expression)) + myResult = // TODO: not resolved + new MethodCallExpression( + expressionToExpression(expression.getMethodExpression()), + elementToElement(expression.getArgumentList()), + typeToType(expression.getType()).isNullable() + ); } @Override @@ -305,7 +306,7 @@ public class ExpressionVisitor extends StatementVisitor implements Visitor { return false; } - private boolean isInsidePrimaryConstructor(PsiReferenceExpression expression) { + private boolean isInsidePrimaryConstructor(PsiExpression expression) { PsiElement context = expression.getContext(); while (context != null) { if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) diff --git a/src/org/jetbrains/jet/j2k/visitors/SuperVisitor.java b/src/org/jetbrains/jet/j2k/visitors/SuperVisitor.java new file mode 100644 index 00000000000..27106702e96 --- /dev/null +++ b/src/org/jetbrains/jet/j2k/visitors/SuperVisitor.java @@ -0,0 +1,38 @@ +package org.jetbrains.jet.j2k.visitors; + +import com.intellij.psi.*; + +import java.util.HashSet; + + +/** + * @author ignatov + */ +public class SuperVisitor extends JavaRecursiveElementVisitor { + private HashSet myResolvedSuperCallParameters; + + public SuperVisitor() { + myResolvedSuperCallParameters = new HashSet(); + } + + public HashSet getResolvedSuperCallParameters() { + return myResolvedSuperCallParameters; + } + + @Override + public void visitMethodCallExpression(PsiMethodCallExpression expression) { + super.visitMethodCallExpression(expression); + if (isSuper(expression.getMethodExpression())) + myResolvedSuperCallParameters.add(expression.getArgumentList()); + } + + static boolean isSuper(PsiReference r) { + if (r.getCanonicalText().equals("super")) { + final PsiElement baseConstructor = r.resolve(); + if (baseConstructor != null && baseConstructor instanceof PsiMethod && ((PsiMethod) baseConstructor).isConstructor()) { + return true; + } + } + return false; + } +} diff --git a/src/org/jetbrains/jet/j2k/visitors/ThisVisitor.java b/src/org/jetbrains/jet/j2k/visitors/ThisVisitor.java index 96569d20a09..feea2f69e21 100644 --- a/src/org/jetbrains/jet/j2k/visitors/ThisVisitor.java +++ b/src/org/jetbrains/jet/j2k/visitors/ThisVisitor.java @@ -14,10 +14,6 @@ import java.util.HashSet; public class ThisVisitor extends JavaRecursiveElementVisitor { HashSet myResolvedConstructors = new HashSet(); - public HashSet getResult() { - return myResolvedConstructors; - } - @Override public void visitReferenceExpression(PsiReferenceExpression expression) { for (PsiReference r : expression.getReferences()) diff --git a/testData/ast/class/class/abstractClassShape.kt b/testData/ast/class/class/abstractClassShape.kt index d6500a6c9a5..fff165180c7 100644 --- a/testData/ast/class/class/abstractClassShape.kt +++ b/testData/ast/class/class/abstractClassShape.kt @@ -7,6 +7,4 @@ open public fun getColor() : String? { return color } abstract open public fun area() : Double -{ -} } \ No newline at end of file diff --git a/testData/ast/class/class/extendsOneClassAndImplementsOneInterface.kt b/testData/ast/class/class/extendsOneClassAndImplementsOneInterface.kt index 99eb1856528..7206c054962 100644 --- a/testData/ast/class/class/extendsOneClassAndImplementsOneInterface.kt +++ b/testData/ast/class/class/extendsOneClassAndImplementsOneInterface.kt @@ -1,2 +1,2 @@ -class A() : Base, I { +class A() : Base(), I { } \ No newline at end of file diff --git a/testData/ast/class/class/extendsOneClassAndImplementsSeveralInterfaces.kt b/testData/ast/class/class/extendsOneClassAndImplementsSeveralInterfaces.kt index 25348484337..7812e054bda 100644 --- a/testData/ast/class/class/extendsOneClassAndImplementsSeveralInterfaces.kt +++ b/testData/ast/class/class/extendsOneClassAndImplementsSeveralInterfaces.kt @@ -1,2 +1,2 @@ -class A() : Base, I0, I1, I2 { +class A() : Base(), I0, I1, I2 { } \ No newline at end of file diff --git a/testData/ast/class/class/simpleInheritance.kt b/testData/ast/class/class/simpleInheritance.kt index 7292c1b424c..7bf6ef80f75 100644 --- a/testData/ast/class/class/simpleInheritance.kt +++ b/testData/ast/class/class/simpleInheritance.kt @@ -1,2 +1,2 @@ -class A() : Base { +class A() : Base() { } \ No newline at end of file diff --git a/testData/ast/constructors/file/allCallsPrimary.kt b/testData/ast/constructors/file/allCallsPrimary.kt index e564d45ba6e..1ba1404eccd 100644 --- a/testData/ast/constructors/file/allCallsPrimary.kt +++ b/testData/ast/constructors/file/allCallsPrimary.kt @@ -9,8 +9,6 @@ val __ = C(arg1, 0, 0) return __ } } -{ -} } public open class User() { class object { diff --git a/testData/ast/function/file/override.kt b/testData/ast/function/file/override.kt index 7a355e48c06..d895be5bb27 100644 --- a/testData/ast/function/file/override.kt +++ b/testData/ast/function/file/override.kt @@ -2,7 +2,7 @@ open class A() { open fun a() : Unit { } } -class B() : A { +class B() : A() { override fun a() : Unit { } } \ No newline at end of file diff --git a/testData/ast/function/file/overrideAndOpen.kt b/testData/ast/function/file/overrideAndOpen.kt index ee0eca7b214..678a37a4a70 100644 --- a/testData/ast/function/file/overrideAndOpen.kt +++ b/testData/ast/function/file/overrideAndOpen.kt @@ -2,11 +2,11 @@ open class A() { open fun foo() : Unit { } } -open class B() : A { +open class B() : A() { override fun foo() : Unit { } } -open class C() : B { +open class C() : B() { override fun foo() : Unit { } } \ No newline at end of file diff --git a/testData/ast/identifier/file/finalFieldReference.kt b/testData/ast/identifier/file/finalFieldReference.kt index 7ae0f871828..215a03c5f83 100644 --- a/testData/ast/identifier/file/finalFieldReference.kt +++ b/testData/ast/identifier/file/finalFieldReference.kt @@ -2,7 +2,7 @@ open class `$$$$$`() { } open class `$`() { } -open class `$$`(`$$$$` : `$$$$$`?) : `$` { +open class `$$`(`$$$$` : `$$$$$`?) : `$`() { val `$$$` : `$$$$$`? open public fun `$$$$$$`() : `$$$$$`? { return `$$$` diff --git a/testData/ast/superExpression/class/classAextendsB.jav b/testData/ast/superExpression/class/classAextendsB.jav index b50235108d0..6f07978fe79 100644 --- a/testData/ast/superExpression/class/classAextendsB.jav +++ b/testData/ast/superExpression/class/classAextendsB.jav @@ -1,11 +1,12 @@ class B { - void call() {} + B(int i) {} + int call() {return 1;} } class A extends B { A() { - super(); + super(10); } - void call() { return super.call(); } + int call() { return super.call(); } } \ No newline at end of file diff --git a/testData/ast/superExpression/class/classAextendsB.kt b/testData/ast/superExpression/class/classAextendsB.kt index bbc73d9ba14..b9c5e29b288 100644 --- a/testData/ast/superExpression/class/classAextendsB.kt +++ b/testData/ast/superExpression/class/classAextendsB.kt @@ -1,12 +1,10 @@ -open class B() { -open fun call() : Unit { +open class B(i : Int) { +open fun call() : Int { +return 1 } } -open class A() : B { -override fun call() : Unit { +open class A() : B(10) { +override fun call() : Int { return super.call() } -{ -super() -} } \ No newline at end of file diff --git a/testData/ast/superExpression/file/classAdotSuperFoo.kt b/testData/ast/superExpression/file/classAdotSuperFoo.kt index bdff091103c..a6495ce0571 100644 --- a/testData/ast/superExpression/file/classAdotSuperFoo.kt +++ b/testData/ast/superExpression/file/classAdotSuperFoo.kt @@ -1,7 +1,7 @@ open class Base() { open fun foo() : Unit } -open class A() : Base { +open class A() : Base() { open class C() { open fun test() : Unit { super@A.foo() diff --git a/testData/ast/thisExpression/file/classAdotThisFoo.kt b/testData/ast/thisExpression/file/classAdotThisFoo.kt index 92197edc7c6..615b3b5dc0a 100644 --- a/testData/ast/thisExpression/file/classAdotThisFoo.kt +++ b/testData/ast/thisExpression/file/classAdotThisFoo.kt @@ -2,7 +2,7 @@ open class Base() { open fun foo() : Unit { } } -open class A() : Base { +open class A() : Base() { open class C() { open fun test() : Unit { this@A.foo() diff --git a/testData/ast/typeParameters/class/classDoubleParametrizationWithTwoBoundsWithExtending.kt b/testData/ast/typeParameters/class/classDoubleParametrizationWithTwoBoundsWithExtending.kt index ee954ff1105..f40a6cda574 100644 --- a/testData/ast/typeParameters/class/classDoubleParametrizationWithTwoBoundsWithExtending.kt +++ b/testData/ast/typeParameters/class/classDoubleParametrizationWithTwoBoundsWithExtending.kt @@ -1,2 +1,2 @@ -class CC() : A where T : Comparable?, K : Collection? { +class CC() : A() where T : Comparable?, K : Collection? { } \ No newline at end of file diff --git a/testData/ast/typeParameters/class/classParametrizationWithTwoBoundsWithExtending.kt b/testData/ast/typeParameters/class/classParametrizationWithTwoBoundsWithExtending.kt index e7c258a0f24..e05e75db415 100644 --- a/testData/ast/typeParameters/class/classParametrizationWithTwoBoundsWithExtending.kt +++ b/testData/ast/typeParameters/class/classParametrizationWithTwoBoundsWithExtending.kt @@ -1,2 +1,2 @@ -class C() : A where T : Comparable? { +class C() : A() where T : Comparable? { } \ No newline at end of file