diff --git a/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt b/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt index 9b84706beab..6fb8cd154e3 100644 --- a/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt @@ -89,19 +89,16 @@ class TypeConverter(val settings: ConverterSettings) { var nullability = method.nullabilityFromAnnotations() if (nullability == Nullability.Default) { - var isInAnonymousClass = false method.getBody()?.accept(object: JavaRecursiveElementVisitor() { - override fun visitAnonymousClass(aClass: PsiAnonymousClass) { - isInAnonymousClass = true - super.visitAnonymousClass(aClass) - isInAnonymousClass = false - } - override fun visitReturnStatement(statement: PsiReturnStatement) { - if (!isInAnonymousClass && statement.getReturnValue()?.nullability() == Nullability.Nullable) { + if (statement.getReturnValue()?.nullability() == Nullability.Nullable) { nullability = Nullability.Nullable } } + + override fun visitMethod(method: PsiMethod) { + // do not go inside any other method (e.g. in anonymous class) + } }) } @@ -129,7 +126,7 @@ class TypeConverter(val settings: ConverterSettings) { private fun PsiExpression.nullability(): Nullability { return when (this) { - is PsiLiteralExpression -> if (getValue() != null) Nullability.NotNull else Nullability.Nullable + is PsiLiteralExpression -> if (getType() != PsiType.NULL) Nullability.NotNull else Nullability.Nullable is PsiNewExpression -> Nullability.NotNull @@ -159,7 +156,7 @@ class TypeConverter(val settings: ConverterSettings) { val operationType = parent.getOperationTokenType() if (operationType == JavaTokenType.EQEQ || operationType == JavaTokenType.NE) { val otherOperand = if (usage == parent.getLOperand()) parent.getROperand() else parent.getLOperand() - return otherOperand?.nullability() == Nullability.Nullable + return otherOperand is PsiLiteralExpression && otherOperand.getType() == PsiType.NULL } } return false diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt b/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt index 81d4aa2c314..0772b6b23d3 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt @@ -16,7 +16,7 @@ package org.jetbrains.jet.j2k.ast -open class EnumConstant( +class EnumConstant( identifier: Identifier, members: MemberComments, modifiers: Set, diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt index ccec474dfe0..c14dd36538a 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Field.kt @@ -29,7 +29,15 @@ open class Field( val writingAccesses: Int ) : Member(comments, modifiers) { - fun modifiersToKotlin(): String { + override fun toKotlin(): String { + val declaration = commentsToKotlin() + modifiersToKotlin() + (if (isVal) "val " else "var ") + identifier.toKotlin() + " : " + `type`.toKotlin() + return if (initializer.isEmpty) + declaration + (if (isVal && !isStatic() && writingAccesses != 0) "" else " = " + getDefaultInitializer(this)) + else + declaration + " = " + initializer.toKotlin() + } + + private fun modifiersToKotlin(): String { val modifierList = ArrayList() if (modifiers.contains(Modifier.ABSTRACT)) { modifierList.add(Modifier.ABSTRACT) @@ -37,16 +45,6 @@ open class Field( modifiers.accessModifier()?.let { modifierList.add(it) } - return modifierList.toKotlin() + (if (isVal) "val " else "var ") - } - - override fun toKotlin(): String { - val declaration = commentsToKotlin() + modifiersToKotlin() + identifier.toKotlin() + " : " + `type`.toKotlin() - if (initializer.isEmpty) { - return declaration + (if (isVal && !isStatic() && writingAccesses != 0) "" else " = " + getDefaultInitializer(this)) - } - else { - return declaration + " = " + initializer.toKotlin() - } + return modifierList.toKotlin() } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Imports.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Imports.kt index e06faa4fa56..f939a873a5f 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Imports.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Imports.kt @@ -63,7 +63,7 @@ private fun filterImport(name: String, ref: PsiJavaCodeReferenceElement): String if (!JavaToKotlinClassMap.getInstance().mapPlatformClass(FqName(name)).isEmpty()) return null val target = ref.resolve() - if (target != null && target is KotlinLightClassForPackage) { + if (target is KotlinLightClassForPackage) { return quoteKeywords(target.getFqName().parent().toString()) + ".*" } diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt index c46d9d6fb29..ec77bc861d2 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt @@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.psi.psiUtil.getParentByType import org.jetbrains.jet.lang.psi.psiUtil.isExtensionDeclaration import org.jetbrains.jet.lang.psi.JetPropertyAccessor import com.intellij.psi.impl.light.LightField +import org.jetbrains.jet.lang.resolve.java.JvmAbi class ExpressionVisitor(private val converter: Converter, private val typeConverter: TypeConverter, @@ -159,15 +160,12 @@ class ExpressionVisitor(private val converter: Converter, val parameterCount = target.getParameterList().getParameters().size if (parameterCount == arguments.size) { val propertyName = Identifier(property.getName()!!, false) - var isExtension = false + val isExtension = property.isExtensionDeclaration() val propertyAccess = if (isTopLevel) { - if (property.isExtensionDeclaration()) { - isExtension = true + if (isExtension) QualifiedExpression(converter.convertExpression(arguments.firstOrNull()), propertyName) - } - else { + else propertyName - } } else { QualifiedExpression(converter.convertExpression(methodExpr.getQualifierExpression()), propertyName) @@ -312,7 +310,7 @@ class ExpressionVisitor(private val converter: Converter, identifier = Identifier("size", isNullable) } else if (qualifier != null) { - if (referencedName == "object$" || referencedName == "instance$") { + if (referencedName == JvmAbi.CLASS_OBJECT_FIELD || referencedName == JvmAbi.INSTANCE_FIELD) { val target = expression.getReference()?.resolve() if (target is LightField) { //TODO: should be KotlinLightField with check of origin here, see KT-5188 result = converter.convertExpression(qualifier) diff --git a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java index 03b390086ba..abcbf24944e 100644 --- a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java +++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java @@ -1245,6 +1245,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/function/overrideObject.java"); } + @TestMetadata("overrideObject2.java") + public void testOverrideObject2() throws Exception { + doTest("j2k/tests/testData/ast/function/overrideObject2.java"); + } + @TestMetadata("ownGenericParam.java") public void testOwnGenericParam() throws Exception { doTest("j2k/tests/testData/ast/function/ownGenericParam.java"); @@ -2176,6 +2181,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/settings"), Pattern.compile("^(.+)\\.java$"), true); } + @TestMetadata("forceLocalVariableImmutability.java") + public void testForceLocalVariableImmutability() throws Exception { + doTest("j2k/tests/testData/ast/settings/forceLocalVariableImmutability.java"); + } + @TestMetadata("openByDefault.java") public void testOpenByDefault() throws Exception { doTest("j2k/tests/testData/ast/settings/openByDefault.java"); diff --git a/j2k/tests/testData/KotlinApi.kt b/j2k/tests/testData/KotlinApi.kt index 82a38943ed2..62373cf504b 100644 --- a/j2k/tests/testData/KotlinApi.kt +++ b/j2k/tests/testData/KotlinApi.kt @@ -4,7 +4,7 @@ public open class KotlinClass { public var property: String = "" class object { - public fun statucFun(p: Int): Int = p + public fun staticFun(p: Int): Int = p public var staticVar: Int = 1 public var staticProperty: Int get() = 1 diff --git a/j2k/tests/testData/ast/function/overrideObject2.java b/j2k/tests/testData/ast/function/overrideObject2.java new file mode 100644 index 00000000000..47f71b84d43 --- /dev/null +++ b/j2k/tests/testData/ast/function/overrideObject2.java @@ -0,0 +1,24 @@ +//file +class Base {} + +class X extends Base { + @Override + public int hashCode() { + return super.hashCode(); + } + + @Override + public boolean equals(Object o) { + return super.equals(o); + } + + @Override + public String toString() { + return super.toString(); + } + + @Override + protected Object clone() throws CloneNotSupportedException { + return super.clone(); + } +} diff --git a/j2k/tests/testData/ast/function/overrideObject2.kt b/j2k/tests/testData/ast/function/overrideObject2.kt new file mode 100644 index 00000000000..38360355781 --- /dev/null +++ b/j2k/tests/testData/ast/function/overrideObject2.kt @@ -0,0 +1,19 @@ +class Base() + +class X() : Base() { + override fun hashCode(): Int { + return super.hashCode() + } + + override fun equals(other: Any?): Boolean { + return super.equals(o) + } + + override fun toString(): String { + return super.toString() + } + + protected fun clone(): Any { + return super.clone() + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/function/overrideObject3.java.todo b/j2k/tests/testData/ast/function/overrideObject3.java.todo new file mode 100644 index 00000000000..023db581ab2 --- /dev/null +++ b/j2k/tests/testData/ast/function/overrideObject3.java.todo @@ -0,0 +1,14 @@ +//file +class Base { + @Override + public boolean equals(Object o) { + return super.equals(o); + } +} + +class X extends Base { + @Override + public boolean equals(Object o) { + return super.equals(o); + } +} diff --git a/j2k/tests/testData/ast/function/overrideObject3.kt b/j2k/tests/testData/ast/function/overrideObject3.kt new file mode 100644 index 00000000000..94e655b81d6 --- /dev/null +++ b/j2k/tests/testData/ast/function/overrideObject3.kt @@ -0,0 +1,11 @@ +class Base() { + override fun equals(other: Any?): Boolean { + return super.equals(o) + } +} + +class X() : Base() { + override fun equals(o: Any?): Boolean { + return super.equals(o) + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/kotlinApiAccess/ClassObjectMembers.java b/j2k/tests/testData/ast/kotlinApiAccess/ClassObjectMembers.java index a22a7e21c52..d7b2a8ed1fe 100644 --- a/j2k/tests/testData/ast/kotlinApiAccess/ClassObjectMembers.java +++ b/j2k/tests/testData/ast/kotlinApiAccess/ClassObjectMembers.java @@ -5,6 +5,6 @@ class C { int foo() { KotlinClass.staticVar = KotlinClass.staticVar * 2; KotlinClass.object$.setStaticProperty(KotlinClass.object$.getStaticVar() + KotlinClass.object$.getStaticProperty()); - return KotlinClass.object$.statucFun(1); + return KotlinClass.object$.staticFun(1); } } diff --git a/j2k/tests/testData/ast/kotlinApiAccess/ClassObjectMembers.kt b/j2k/tests/testData/ast/kotlinApiAccess/ClassObjectMembers.kt index d161dc928a2..ad07fbb0584 100644 --- a/j2k/tests/testData/ast/kotlinApiAccess/ClassObjectMembers.kt +++ b/j2k/tests/testData/ast/kotlinApiAccess/ClassObjectMembers.kt @@ -4,6 +4,6 @@ class C() { fun foo(): Int { KotlinClass.staticVar = KotlinClass.staticVar * 2 KotlinClass.staticProperty = KotlinClass.staticVar + KotlinClass.staticProperty - return KotlinClass.statucFun(1) + return KotlinClass.staticFun(1) } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/kotlinApiAccess/GlobalValue1.java b/j2k/tests/testData/ast/kotlinApiAccess/GlobalValue1.java index 2135ee3ab95..6ea68555ad6 100644 --- a/j2k/tests/testData/ast/kotlinApiAccess/GlobalValue1.java +++ b/j2k/tests/testData/ast/kotlinApiAccess/GlobalValue1.java @@ -3,7 +3,7 @@ import kotlinApi.KotlinApiPackage; class C { int foo() { - KotlinApiPackage.setGlobalValue1(0) + KotlinApiPackage.setGlobalValue1(0); return KotlinApiPackage.getGlobalValue1(); } } diff --git a/j2k/tests/testData/ast/kotlinApiAccess/GlobalValue2.java b/j2k/tests/testData/ast/kotlinApiAccess/GlobalValue2.java index 81ebe699755..743a8fc3cfc 100644 --- a/j2k/tests/testData/ast/kotlinApiAccess/GlobalValue2.java +++ b/j2k/tests/testData/ast/kotlinApiAccess/GlobalValue2.java @@ -3,7 +3,7 @@ import kotlinApi.KotlinApiPackage; class C { int foo() { - KotlinApiPackage.setGlobalValue2(0) + KotlinApiPackage.setGlobalValue2(0); return KotlinApiPackage.getGlobalValue2(); } } diff --git a/j2k/tests/testData/ast/kotlinApiAccess/Property.java b/j2k/tests/testData/ast/kotlinApiAccess/Property.java index 396f99b1660..f6483b38668 100644 --- a/j2k/tests/testData/ast/kotlinApiAccess/Property.java +++ b/j2k/tests/testData/ast/kotlinApiAccess/Property.java @@ -4,6 +4,6 @@ import kotlinApi.* class C { void foo(KotlinClass k) { System.out.println(k.getProperty()); - k.setProperty("a") + k.setProperty("a"); } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/FieldAssignedWithNull.java b/j2k/tests/testData/ast/nullability/FieldAssignedWithNull.java index af80b085732..503fad6a977 100644 --- a/j2k/tests/testData/ast/nullability/FieldAssignedWithNull.java +++ b/j2k/tests/testData/ast/nullability/FieldAssignedWithNull.java @@ -3,6 +3,6 @@ class C { private String s = ""; void foo() { - s = null + s = null; } } diff --git a/j2k/tests/testData/ast/nullability/FieldInitializedWithNull.java b/j2k/tests/testData/ast/nullability/FieldInitializedWithNull.java index c44955232d7..1f27f47dce0 100644 --- a/j2k/tests/testData/ast/nullability/FieldInitializedWithNull.java +++ b/j2k/tests/testData/ast/nullability/FieldInitializedWithNull.java @@ -3,6 +3,6 @@ class C { private String s = null; void foo() { - s = "x" + s = "x"; } } diff --git a/j2k/tests/testData/ast/nullability/MethodInvokedWithNullArg.java b/j2k/tests/testData/ast/nullability/MethodInvokedWithNullArg.java index 3e616176614..bca6c435d52 100644 --- a/j2k/tests/testData/ast/nullability/MethodInvokedWithNullArg.java +++ b/j2k/tests/testData/ast/nullability/MethodInvokedWithNullArg.java @@ -3,6 +3,6 @@ class C { private void foo(String s){} void bar() { - foo(null) + foo(null); } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/MethodInvokedWithTernaryNullArg.java b/j2k/tests/testData/ast/nullability/MethodInvokedWithTernaryNullArg.java index d3e65b101b5..00bd9bb95ad 100644 --- a/j2k/tests/testData/ast/nullability/MethodInvokedWithTernaryNullArg.java +++ b/j2k/tests/testData/ast/nullability/MethodInvokedWithTernaryNullArg.java @@ -3,6 +3,6 @@ class C { private void foo(String s){} void bar(boolean b) { - foo(b ? "a" : null) + foo(b ? "a" : null); } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/MethodResultComparedWithNull.java b/j2k/tests/testData/ast/nullability/MethodResultComparedWithNull.java index 7a439558d6b..ae0528df953 100644 --- a/j2k/tests/testData/ast/nullability/MethodResultComparedWithNull.java +++ b/j2k/tests/testData/ast/nullability/MethodResultComparedWithNull.java @@ -6,7 +6,7 @@ interface I { class C { void foo(I i) { if (i.getString() == null) { - println("null") + println("null"); } } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/MethodReturnsNull.java b/j2k/tests/testData/ast/nullability/MethodReturnsNull.java index 44478fdb1d6..ec10e9235a5 100644 --- a/j2k/tests/testData/ast/nullability/MethodReturnsNull.java +++ b/j2k/tests/testData/ast/nullability/MethodReturnsNull.java @@ -2,10 +2,10 @@ class C { String foo(boolean b) { if (b) { - return "abc" + return "abc"; } else { - return null + return null; } } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/MethodReturnsNullInAnonymousClass.java b/j2k/tests/testData/ast/nullability/MethodReturnsNullInAnonymousClass.java index 4d0a1cbab02..06bf6c05d8f 100644 --- a/j2k/tests/testData/ast/nullability/MethodReturnsNullInAnonymousClass.java +++ b/j2k/tests/testData/ast/nullability/MethodReturnsNullInAnonymousClass.java @@ -1,9 +1,6 @@ -import java.lang.Override; -import java.lang.String; - //file interface Getter { - String get() + String get(); } class C { diff --git a/j2k/tests/testData/ast/nullability/MethodReturnsNullInAnonymousClass.kt b/j2k/tests/testData/ast/nullability/MethodReturnsNullInAnonymousClass.kt index 9acea5f077a..9dd3ed82b41 100644 --- a/j2k/tests/testData/ast/nullability/MethodReturnsNullInAnonymousClass.kt +++ b/j2k/tests/testData/ast/nullability/MethodReturnsNullInAnonymousClass.kt @@ -1,5 +1,3 @@ -import java.lang.Override - trait Getter { public fun get(): String } diff --git a/j2k/tests/testData/ast/nullability/MethodReturnsNullInLocalClass.java.todo b/j2k/tests/testData/ast/nullability/MethodReturnsNullInLocalClass.java.todo new file mode 100644 index 00000000000..a9de5ccb741 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/MethodReturnsNullInLocalClass.java.todo @@ -0,0 +1,10 @@ +//file +class C { + String foo() { + class Local { + String foo() { return null; } + }; + new Local().foo(); + return ""; + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/MethodReturnsTernaryNull.java b/j2k/tests/testData/ast/nullability/MethodReturnsTernaryNull.java index 57e25579403..e1d9cf4b187 100644 --- a/j2k/tests/testData/ast/nullability/MethodReturnsTernaryNull.java +++ b/j2k/tests/testData/ast/nullability/MethodReturnsTernaryNull.java @@ -1,6 +1,6 @@ //file class C { String foo(boolean b) { - return b ? "abc" : null + return b ? "abc" : null; } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/ParameterComparedWithNull.java b/j2k/tests/testData/ast/nullability/ParameterComparedWithNull.java index 28e9e374a1c..56be9343887 100644 --- a/j2k/tests/testData/ast/nullability/ParameterComparedWithNull.java +++ b/j2k/tests/testData/ast/nullability/ParameterComparedWithNull.java @@ -1,6 +1,6 @@ //method void foo(String s) { if (s != null) { - zoo(s) + zoo(s); } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/VariableAssignedWithNull.java b/j2k/tests/testData/ast/nullability/VariableAssignedWithNull.java index e0b15c2ebed..525ada24f9f 100644 --- a/j2k/tests/testData/ast/nullability/VariableAssignedWithNull.java +++ b/j2k/tests/testData/ast/nullability/VariableAssignedWithNull.java @@ -3,6 +3,6 @@ void foo(boolean b) { String s = "abc"; if (b) { - s = null + s = null; } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/VariableComparedWithNull.java b/j2k/tests/testData/ast/nullability/VariableComparedWithNull.java index c024fa2650e..0b1206661fd 100644 --- a/j2k/tests/testData/ast/nullability/VariableComparedWithNull.java +++ b/j2k/tests/testData/ast/nullability/VariableComparedWithNull.java @@ -1,8 +1,8 @@ //method // !specifyLocalVariableTypeByDefault: true void foo() { - String s = bar() + String s = bar(); if (s != null) { - zoo(s) + zoo(s); } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/VariableInitializedWithNull.java b/j2k/tests/testData/ast/nullability/VariableInitializedWithNull.java index 4ae405974ed..b8ff485ddd3 100644 --- a/j2k/tests/testData/ast/nullability/VariableInitializedWithNull.java +++ b/j2k/tests/testData/ast/nullability/VariableInitializedWithNull.java @@ -3,6 +3,6 @@ void foo(boolean b) { String s = null; if (b) { - s = "abc" + s = "abc"; } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/settings/forceLocalVariableImmutability.java b/j2k/tests/testData/ast/settings/forceLocalVariableImmutability.java new file mode 100644 index 00000000000..823fcf4b298 --- /dev/null +++ b/j2k/tests/testData/ast/settings/forceLocalVariableImmutability.java @@ -0,0 +1,7 @@ +//method +// !forceLocalVariableImmutability: false +public void foo() { + int i = 1; + String s = ""; + s += "a"; +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/settings/forceLocalVariableImmutability.kt b/j2k/tests/testData/ast/settings/forceLocalVariableImmutability.kt new file mode 100644 index 00000000000..7e3f8b9a73d --- /dev/null +++ b/j2k/tests/testData/ast/settings/forceLocalVariableImmutability.kt @@ -0,0 +1,6 @@ +// !forceLocalVariableImmutability: false +public fun foo() { + var i = 1 + var s = "" + s += "a" +} \ No newline at end of file