diff --git a/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt b/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt index 83cb378260e..75c6e6e9945 100644 --- a/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt @@ -38,6 +38,12 @@ class TypeConverter(val settings: ConverterSettings) { } public fun convertVariableType(variable: PsiVariable): Type { + return convertType(variable.getType(), variableNullability(variable)) + } + + public fun variableNullability(variable: PsiVariable): Nullability { + if (variable is PsiEnumConstant) return Nullability.NotNull + var nullability = variable.nullabilityFromAnnotations() if (nullability == Nullability.Default) { @@ -82,7 +88,7 @@ class TypeConverter(val settings: ConverterSettings) { } } - return convertType(variable.getType(), nullability) + return nullability } public fun convertMethodReturnType(method: PsiMethod): Type { @@ -160,7 +166,7 @@ class TypeConverter(val settings: ConverterSettings) { } } else if (parent is PsiVariable && usage == parent.getInitializer() && parent.isEffectivelyFinal()) { - return convertVariableType(parent).isNullable + return variableNullability(parent) == Nullability.Nullable } return false } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Types.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Types.kt index 5346dae31f3..04ef39e0ba6 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Types.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Types.kt @@ -74,7 +74,7 @@ trait Type : Element { override fun toString(): String = toKotlin() } -open class ClassType(val `type`: Identifier, val parameters: List, nullability: Nullability, settings: ConverterSettings) +class ClassType(val `type`: Identifier, val parameters: List, nullability: Nullability, settings: ConverterSettings) : MayBeNullableType(nullability, settings) { override fun toKotlin(): String { @@ -110,22 +110,22 @@ class ArrayType(val elementType: Type, nullability: Nullability, settings: Conve override fun toNullableType(): Type = ArrayType(elementType, Nullability.Nullable, settings) } -open class InProjectionType(val bound: Type) : NotNullType { +class InProjectionType(val bound: Type) : NotNullType { override fun toKotlin(): String = "in " + bound.toKotlin() } -open class OutProjectionType(val bound: Type) : NotNullType { +class OutProjectionType(val bound: Type) : NotNullType { override fun toKotlin(): String = "out " + bound.toKotlin() } -open class StarProjectionType() : NotNullType { +class StarProjectionType() : NotNullType { override fun toKotlin(): String = "*" } -open class PrimitiveType(val `type`: Identifier) : NotNullType { +class PrimitiveType(val `type`: Identifier) : NotNullType { override fun toKotlin(): String = `type`.toKotlin() } -open class VarArgType(val `type`: Type) : NotNullType { +class VarArgType(val `type`: Type) : NotNullType { override fun toKotlin(): String = `type`.toKotlin() } diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt index ec77bc861d2..7f132a268fa 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt @@ -358,8 +358,7 @@ class ExpressionVisitor(private val converter: Converter, private fun PsiReference.nullability(): Nullability { val target = resolve() return when(target) { - is PsiEnumConstant -> Nullability.NotNull - is PsiModifierListOwner -> target.nullabilityFromAnnotations() + is PsiVariable -> typeConverter.variableNullability(target) else -> Nullability.Default } } 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 12d5fcbff9d..62505f2840f 100644 --- a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java +++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java @@ -16,17 +16,14 @@ package org.jetbrains.jet.j2k.test; -import junit.framework.Assert; import junit.framework.Test; import junit.framework.TestSuite; - -import java.io.File; -import java.util.regex.Pattern; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.test.InnerTestClasses; import org.jetbrains.jet.test.TestMetadata; -import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterTest; +import java.io.File; +import java.util.regex.Pattern; /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @@ -1961,6 +1958,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/nullability/MethodReturnsTernaryNull.java"); } + @TestMetadata("NullableVariableDotAccess.java") + public void testNullableVariableDotAccess() throws Exception { + doTest("j2k/tests/testData/ast/nullability/NullableVariableDotAccess.java"); + } + @TestMetadata("ParameterComparedWithNull.java") public void testParameterComparedWithNull() throws Exception { doTest("j2k/tests/testData/ast/nullability/ParameterComparedWithNull.java"); diff --git a/j2k/tests/testData/ast/callChainExpression/libraryMethodCallFromInstance-settings.kt b/j2k/tests/testData/ast/callChainExpression/libraryMethodCallFromInstance-settings.kt index 05b3060358c..3a175bc155e 100644 --- a/j2k/tests/testData/ast/callChainExpression/libraryMethodCallFromInstance-settings.kt +++ b/j2k/tests/testData/ast/callChainExpression/libraryMethodCallFromInstance-settings.kt @@ -12,8 +12,8 @@ class Library() { class User() { fun main() { val lib: Library = Library() - lib?.call() - lib?.getString()?.isEmpty() + lib.call() + lib.getString()?.isEmpty() Library().call() Library().getString()?.isEmpty() diff --git a/j2k/tests/testData/ast/issues/kt-824-isDir.kt b/j2k/tests/testData/ast/issues/kt-824-isDir.kt index c5e9c7632b9..a723949070d 100644 --- a/j2k/tests/testData/ast/issues/kt-824-isDir.kt +++ b/j2k/tests/testData/ast/issues/kt-824-isDir.kt @@ -8,11 +8,11 @@ import java.io.File public class Test() { class object { public fun isDir(parent: File?): Boolean { - if (parent == null || !parent.exists()) { + if (parent == null || !parent?.exists()!!) { return false } val result = true - if (parent.isDirectory()) { + if (parent?.isDirectory()!!) { return true } else return false diff --git a/j2k/tests/testData/ast/nullability/NullableVariableDotAccess.java b/j2k/tests/testData/ast/nullability/NullableVariableDotAccess.java new file mode 100644 index 00000000000..f7bdd1825d5 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/NullableVariableDotAccess.java @@ -0,0 +1,6 @@ +//method +int foo(String s, boolean b) { + if (s == null) System.out.println("null") + if (b) return s.length(); + return 10; +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/NullableVariableDotAccess.kt b/j2k/tests/testData/ast/nullability/NullableVariableDotAccess.kt new file mode 100644 index 00000000000..3ff962a6c18 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/NullableVariableDotAccess.kt @@ -0,0 +1,7 @@ +fun foo(s: String?, b: Boolean): Int { + if (s == null) + System.out.println("null") + if (b) + return s?.length()!! + return 10 +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/prefixOperator/nullableIf.kt b/j2k/tests/testData/ast/prefixOperator/nullableIf.kt index 0f8d7276176..209e96d341b 100644 --- a/j2k/tests/testData/ast/prefixOperator/nullableIf.kt +++ b/j2k/tests/testData/ast/prefixOperator/nullableIf.kt @@ -1,3 +1,3 @@ val s = null -if (!s.isEmpty()) { +if (!s?.isEmpty()!!) { } \ No newline at end of file