example with customer builder added,

initial support for constructors added
This commit is contained in:
Sergey Ignatov
2011-11-08 14:23:30 +04:00
parent 33f3350bb0
commit 39112d6327
50 changed files with 259 additions and 73 deletions
+1 -1
View File
@@ -8,4 +8,4 @@ disable-sandbox:
cd ~/.IdeaIC11/system/ && mv plugins-sandbox plugins-sandbox.tmp cd ~/.IdeaIC11/system/ && mv plugins-sandbox plugins-sandbox.tmp
enable-sandbox: enable-sandbox:
cd ~/.IdeaIC11/system/ && mv plugins-sandbox.tmp ./plugins-sandbox cd ~/.IdeaIC11/system/ && rm -rf plugins-sandbox && mv plugins-sandbox.tmp ./plugins-sandbox
+9 -2
View File
@@ -135,15 +135,22 @@ public class Converter {
if (method.getParent() instanceof PsiClass && ((PsiClass) method.getParent()).isInterface()) if (method.getParent() instanceof PsiClass && ((PsiClass) method.getParent()).isInterface())
modifiers.remove(Modifier.ABSTRACT); modifiers.remove(Modifier.ABSTRACT);
if (method.isConstructor())
if (method.isConstructor()) {
boolean isPrimary = false;
if (method.getParent() instanceof PsiClass && ((PsiClass) method.getParent()).getConstructors().length == 1)
isPrimary = true;
return new Constructor( return new Constructor(
identifier, identifier,
modifiers, modifiers,
type, type,
typeParameters, typeParameters,
params, params,
body body,
isPrimary
); );
}
return new Function( return new Function(
identifier, identifier,
modifiers, modifiers,
+29 -3
View File
@@ -1,6 +1,7 @@
package org.jetbrains.jet.j2k.ast; package org.jetbrains.jet.j2k.ast;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.j2k.util.AstUtil; import org.jetbrains.jet.j2k.util.AstUtil;
import java.util.LinkedList; import java.util.LinkedList;
@@ -32,6 +33,29 @@ public class Class extends Member {
myFields = fields; myFields = fields;
} }
@Nullable
private Constructor getPrimaryConstructor() {
for (Function m : myMethods)
if (m.getKind() == Kind.CONSTRUCTOR)
if (((Constructor) m).isPrimary())
return (Constructor) m;
return null;
}
String primaryConstructorSignatureToKotlin() {
Constructor maybeConstructor = getPrimaryConstructor();
if (maybeConstructor != null)
return maybeConstructor.primarySignatureToKotlin();
return "(" + ")";
}
String primaryConstructorBodyToKotlin() {
Constructor maybeConstructor = getPrimaryConstructor();
if (maybeConstructor != null)
return maybeConstructor.primaryBodyToKotlin();
return EMPTY;
}
private boolean hasWhere() { private boolean hasWhere() {
for (Element t : myTypeParameters) for (Element t : myTypeParameters)
if (t instanceof TypeParameter && ((TypeParameter) t).hasWhere()) if (t instanceof TypeParameter && ((TypeParameter) t).hasWhere())
@@ -99,8 +123,10 @@ public class Class extends Member {
} }
String bodyToKotlin() { String bodyToKotlin() {
return SPACE + "{" + N + classObjectToKotlin() + N + return SPACE + "{" + N +
classObjectToKotlin() + N +
AstUtil.joinNodes(getNonStatic(myFields), N) + N + AstUtil.joinNodes(getNonStatic(myFields), N) + N +
primaryConstructorBodyToKotlin() + N +
AstUtil.joinNodes(getNonStatic(methodsExceptConstructors()), N) + N + AstUtil.joinNodes(getNonStatic(methodsExceptConstructors()), N) + N +
AstUtil.joinNodes(getNonStatic(myInnerClasses), N) + N + AstUtil.joinNodes(getNonStatic(myInnerClasses), N) + N +
"}"; "}";
@@ -139,9 +165,9 @@ public class Class extends Member {
@NotNull @NotNull
@Override @Override
public String toKotlin() { public String toKotlin() {
return modifiersToKotlin() + TYPE + SPACE + myName.toKotlin() + typeParametersToKotlin() + return modifiersToKotlin() + TYPE + SPACE + myName.toKotlin() + typeParametersToKotlin() + primaryConstructorSignatureToKotlin() +
implementTypesToKotlin() + implementTypesToKotlin() +
typeParameterWhereToKotlin() + typeParameterWhereToKotlin() +
bodyToKotlin(); bodyToKotlin();
} }
} }
+17 -2
View File
@@ -9,11 +9,26 @@ import java.util.Set;
* @author ignatov * @author ignatov
*/ */
public class Constructor extends Function { public class Constructor extends Function {
public Constructor(Identifier identifier, Set<String> modifiers, Type type, List<Element> typeParameters, Element params, Block block) { private boolean myIsPrimary;
public Constructor(Identifier identifier, Set<String> modifiers, Type type, List<Element> typeParameters, Element params, Block block, boolean isPrimary) {
super(identifier, modifiers, type, typeParameters, params, block); super(identifier, modifiers, type, typeParameters, params, block);
myIsPrimary = isPrimary;
} }
public String primary() { public String primarySignatureToKotlin() {
return "(" + myParams.toKotlin() + ")";
}
public String primaryBodyToKotlin() {
return myBlock.toKotlin();
}
public boolean isPrimary() {
return myIsPrimary;
}
public String privatePrimaryToKotlin() {
return modifiersToKotlin() + "(" + myParams.toKotlin() + ")" + SPACE + myBlock.toKotlin(); return modifiersToKotlin() + "(" + myParams.toKotlin() + ")" + SPACE + myBlock.toKotlin();
} }
+2 -2
View File
@@ -26,7 +26,7 @@ public class Enum extends Class {
private String primaryConstructorToKotlin() { private String primaryConstructorToKotlin() {
Constructor maybeConstructor = getPrimaryConstructor(); Constructor maybeConstructor = getPrimaryConstructor();
if (maybeConstructor != null) if (maybeConstructor != null)
return maybeConstructor.primary(); return maybeConstructor.privatePrimaryToKotlin();
return EMPTY; return EMPTY;
} }
@@ -45,4 +45,4 @@ public class Enum extends Class {
AstUtil.joinNodes(myInnerClasses, N) + N + AstUtil.joinNodes(myInnerClasses, N) + N +
"}"; "}";
} }
} }
+5
View File
@@ -14,6 +14,11 @@ public class Trait extends Class {
TYPE = "trait"; TYPE = "trait";
} }
@Override
String primaryConstructorSignatureToKotlin() {
return EMPTY;
}
boolean needOpenModifier() { boolean needOpenModifier() {
return false; return false;
} }
@@ -229,10 +229,33 @@ public class ExpressionVisitor extends StatementVisitor implements Visitor {
@Override @Override
public void visitReferenceExpression(PsiReferenceExpression expression) { public void visitReferenceExpression(PsiReferenceExpression expression) {
super.visitReferenceExpression(expression); super.visitReferenceExpression(expression);
boolean hasDollar = false;
final PsiReference reference = expression.getReference();
if (reference != null) {
final PsiElement resolvedReference = reference.resolve();
if (resolvedReference != null) {
if (resolvedReference instanceof PsiField) {
final PsiModifierList modifierList = ((PsiField) resolvedReference).getModifierList();
if (modifierList != null && modifierList.hasExplicitModifier(PsiModifier.FINAL)) {
PsiElement context = expression.getContext();
while (context != null) {
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
hasDollar = true;
break;
}
context = context.getContext();
}
}
}
}
}
boolean isNullable = typeToType(expression.getType()).isNullable(); boolean isNullable = typeToType(expression.getType()).isNullable();
final IdentifierImpl identifier = hasDollar ? new IdentifierImpl("$" + expression.getReferenceName(), isNullable) : new IdentifierImpl(expression.getReferenceName(), isNullable);
myResult = new CallChainExpression( myResult = new CallChainExpression(
expressionToExpression(expression.getQualifierExpression()), expressionToExpression(expression.getQualifierExpression()),
new IdentifierImpl(expression.getReferenceName(), isNullable) // TODO: if type exists so id is nullable identifier // TODO: if type exists so id is nullable
); );
} }
@@ -47,15 +47,20 @@ public class JavaToKotlinConverterTest extends LightDaemonAnalyzerTestCase {
else if (javaFile.getParent().endsWith("/class")) actual = classToKotlin(javaCode); else if (javaFile.getParent().endsWith("/class")) actual = classToKotlin(javaCode);
else if (javaFile.getParent().endsWith("/file")) actual = fileToKotlin(javaCode); else if (javaFile.getParent().endsWith("/file")) actual = fileToKotlin(javaCode);
assert !actual.equals(""); assert !actual.equals("") : "Specify what is it: file, class, method, statement or expression";
final File tmp = new File(kotlinPath + ".tmp"); final File tmp = new File(kotlinPath + ".tmp");
if (!expected.equals(actual)) if (!expected.equals(actual)) writeStringToFile(tmp, actual);
writeStringToFile(tmp, actual); if (expected.equals(actual) && tmp.exists()) tmp.delete();
if (expected.equals(actual) && tmp.exists())
tmp.delete();
Assert.assertEquals(expected, actual); Assert.assertEquals(expected, actual);
} }
@Override
protected void setUp() throws Exception {
super.setUp();
}
@NotNull @NotNull
protected String getTestFilePath() { protected String getTestFilePath() {
return myDataPath + File.separator + myName + ".jav"; return myDataPath + File.separator + myName + ".jav";
@@ -114,7 +119,7 @@ public class JavaToKotlinConverterTest extends LightDaemonAnalyzerTestCase {
@NotNull @NotNull
protected String methodToKotlin(String text) throws IOException { protected String methodToKotlin(String text) throws IOException {
String result = classToKotlin("final class C {" + text + "}") String result = classToKotlin("final class C {" + text + "}")
.replaceAll("class C \\{", ""); .replaceAll("class C\\(\\) \\{", "");
result = result.substring(0, result.lastIndexOf("}")); result = result.substring(0, result.lastIndexOf("}"));
return prettify(result); return prettify(result);
} }
@@ -1,10 +1,10 @@
namespace { namespace {
open class Library { open class Library() {
class object { class object {
val ourOut : PrintStream? val ourOut : PrintStream?
} }
} }
open class User { open class User() {
open fun main() : Unit { open fun main() : Unit {
Library.ourOut?.print() Library.ourOut?.print()
} }
@@ -1,5 +1,5 @@
namespace { namespace {
open class Library { open class Library() {
class object { class object {
open fun call() : Unit { open fun call() : Unit {
} }
@@ -8,7 +8,7 @@ return ""
} }
} }
} }
open class User { open class User() {
open fun main() : Unit { open fun main() : Unit {
Library.call() Library.call()
Library.getString()?.isEmpty() Library.getString()?.isEmpty()
@@ -1,12 +1,12 @@
namespace { namespace {
open class Library { open class Library() {
open fun call() : Unit { open fun call() : Unit {
} }
open fun getString() : String? { open fun getString() : String? {
return "" return ""
} }
} }
open class User { open class User() {
open fun main() : Unit { open fun main() : Unit {
var lib : Library? = Library() var lib : Library? = Library()
lib?.call() lib?.call()
@@ -1,8 +1,8 @@
namespace { namespace {
open class Library { open class Library() {
public val myString : String? public val myString : String?
} }
open class User { open class User() {
open fun main() : Unit { open fun main() : Unit {
Library.myString?.isEmpty() Library.myString?.isEmpty()
} }
+1 -1
View File
@@ -1,4 +1,4 @@
abstract open class A { abstract open class A() {
abstract open fun callme() : Unit abstract open fun callme() : Unit
open fun callmetoo() : Unit { open fun callmetoo() : Unit {
print("This is a concrete method.") print("This is a concrete method.")
@@ -1,5 +1,7 @@
abstract open class Shape { abstract open class Shape() {
public var color : String? public var color : String?
{
}
open public fun setColor(c : String?) : Unit { open public fun setColor(c : String?) : Unit {
color = c color = c
} }
+1 -1
View File
@@ -1,2 +1,2 @@
open class Test { open class Test() {
} }
@@ -1,4 +1,4 @@
class T { class T() {
open fun main() : Unit { open fun main() : Unit {
} }
open fun i() : Int { open fun i() : Int {
+1 -1
View File
@@ -1,4 +1,4 @@
class T { class T() {
var a : String? = "abc" var a : String? = "abc"
var b : Int = 10 var b : Int = 10
} }
@@ -1,4 +1,4 @@
class T { class T() {
var a : String? var a : String?
var b : String? var b : String?
var c : String? = "abc" var c : String? = "abc"
+1 -1
View File
@@ -1,2 +1,2 @@
class A { class A() {
} }
@@ -1,2 +1,2 @@
class A : Base, I { class A() : Base, I {
} }
@@ -1,2 +1,2 @@
class A : Base, I0, I1, I2 { class A() : Base, I0, I1, I2 {
} }
+1 -1
View File
@@ -1,2 +1,2 @@
class Test { class Test() {
} }
+1 -1
View File
@@ -1,2 +1,2 @@
class Entry<K, V> { class Entry<K, V>() {
} }
+2 -2
View File
@@ -1,4 +1,4 @@
class A { class A() {
class B { class B() {
} }
} }
+2 -2
View File
@@ -1,6 +1,6 @@
class S { class S() {
class object { class object {
open class Inner { open class Inner() {
} }
} }
} }
+1 -1
View File
@@ -1,2 +1,2 @@
open class Test { open class Test() {
} }
@@ -1,4 +1,4 @@
class S { class S() {
class object { class object {
var myI : Int = 10 var myI : Int = 10
} }
+1 -1
View File
@@ -1,4 +1,4 @@
class S { class S() {
class object { class object {
open fun staticF() : Boolean { open fun staticF() : Boolean {
return true return true
@@ -1,4 +1,4 @@
class S { class S() {
class object { class object {
open fun sI() : Int { open fun sI() : Int {
return 1 return 1
+1 -1
View File
@@ -1,2 +1,2 @@
private open class Test { private open class Test() {
} }
+1 -1
View File
@@ -1,2 +1,2 @@
protected open class Test { protected open class Test() {
} }
+1 -1
View File
@@ -1,2 +1,2 @@
public open class Test { public open class Test() {
} }
@@ -1,2 +1,2 @@
class A : Base { class A() : Base {
} }
+1 -1
View File
@@ -1,4 +1,4 @@
class S { class S() {
class object { class object {
open fun sB() : Boolean { open fun sB() : Boolean {
return true return true
+1 -1
View File
@@ -1,5 +1,5 @@
namespace { namespace {
public open class MyClass { public open class MyClass() {
open private fun init(arg1 : Int, arg2 : Int, arg3 : Int) : Unit { open private fun init(arg1 : Int, arg2 : Int, arg3 : Int) : Unit {
} }
} }
@@ -0,0 +1,54 @@
package org.test.customer
class Customer {
public final String _firstName;
public final String _lastName;
Customer(String first, String last) {
doSmthBefore();
_firstName = first;
_lastName = last;
doSmthAfter();
}
public String getFirstName() {
return _firstName;
}
public String getLastName() {
return _lastName;
}
private void doSmthBefore() {}
private void doSmthAfter() {}
}
class CustomerBuilder {
public String _firstName = "Homer";
public String _lastName = "Simpson";
public CustomerBuilder WithFirstName(String firstName) {
_firstName = firstName;
return this;
}
public CustomerBuilder WithLastName(String lastName) {
_lastName = lastName;
return this;
}
public Customer Build() {
return new Customer(_firstName, _lastName);
}
}
public class User {
public static void main(Array[String] args) {
Customer customer = new CustomerBuilder()
.WithFirstName("Homer")
.WithLastName("Simpson")
.Build();
System.out.println(customer.getFirstName());
System.out.println(customer.getLastName());
}
}
@@ -0,0 +1,46 @@
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
}
open public fun getLastName() : String? {
return _lastName
}
open private fun doSmthBefore() : Unit {
}
open private fun doSmthAfter() : Unit {
}
}
open class CustomerBuilder() {
public var _firstName : String? = "Homer"
public var _lastName : String? = "Simpson"
open public fun WithFirstName(firstName : String?) : CustomerBuilder? {
_firstName = firstName
return this
}
open public fun WithLastName(lastName : String?) : CustomerBuilder? {
_lastName = lastName
return this
}
open public fun Build() : Customer? {
return org.test.customer.Customer(_firstName, _lastName)
}
}
public open class User() {
class object {
open public fun main() : Unit {
var customer : Customer? = org.test.customer.CustomerBuilder().WithFirstName("Homer")?.WithLastName("Simpson")?.Build()
System.`out`?.println(customer?.getFirstName())
System.`out`?.println(customer?.getLastName())
}
}
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
namespace test { namespace test {
class C { class C() {
} }
} }
+2 -2
View File
@@ -1,6 +1,6 @@
namespace { namespace {
class A { class A() {
} }
class B { class B() {
} }
} }
@@ -1,4 +1,4 @@
namespace test { namespace test {
open class C { open class C() {
} }
} }
+2 -2
View File
@@ -1,9 +1,9 @@
namespace { namespace {
open class A { open class A() {
open fun a() : Unit { open fun a() : Unit {
} }
} }
class B : A { class B() : A {
override fun a() : Unit { override fun a() : Unit {
} }
} }
@@ -1,13 +1,13 @@
namespace { namespace {
open class A { open class A() {
open fun foo() : Unit { open fun foo() : Unit {
} }
} }
open class B : A { open class B() : A {
override fun foo() : Unit { override fun foo() : Unit {
} }
} }
open class C : B { open class C() : B {
override fun foo() : Unit { override fun foo() : Unit {
} }
} }
@@ -1,7 +1,7 @@
namespace org.test { namespace org.test {
open class Library { open class Library() {
} }
open class User { open class User() {
open fun main() : Unit { open fun main() : Unit {
var lib : Library? = org.test.Library() var lib : Library? = org.test.Library()
} }
@@ -1,8 +1,11 @@
open class B { open class B() {
open fun call() : Unit { open fun call() : Unit {
} }
} }
open class A : B { open class A() : B {
{
super()
}
override fun call() : Unit { override fun call() : Unit {
return super.call() return super.call()
} }
@@ -1,9 +1,9 @@
namespace { namespace {
open class Base { open class Base() {
open fun foo() : Unit open fun foo() : Unit
} }
open class A : Base { open class A() : Base {
open class C { open class C() {
open fun test() : Unit { open fun test() : Unit {
super@A.foo() super@A.foo()
} }
@@ -1,10 +1,10 @@
namespace { namespace {
open class Base { open class Base() {
open fun foo() : Unit { open fun foo() : Unit {
} }
} }
open class A : Base { open class A() : Base {
open class C { open class C() {
open fun test() : Unit { open fun test() : Unit {
this@A.foo() this@A.foo()
} }
@@ -1,2 +1,2 @@
class CC<T : INode?, K : Node?> : A where T : Comparable<in T?>?, K : Collection<in K?>? { class CC<T : INode?, K : Node?>() : A where T : Comparable<in T?>?, K : Collection<in K?>? {
} }
@@ -1,2 +1,2 @@
class C<T : INode?> where T : Comparable<in T?>? { class C<T : INode?>() where T : Comparable<in T?>? {
} }
@@ -1,2 +1,2 @@
class C<T : INode?> : A where T : Comparable<in T?>? { class C<T : INode?>() : A where T : Comparable<in T?>? {
} }
@@ -1,2 +1,2 @@
class Comparable<T> { class Comparable<T>() {
} }