From d49b4f86fd733e3c84c03bcebc5fee997ac0ec62 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 4 Jun 2014 17:35:46 +0400 Subject: [PATCH] Java to Kotlin converter: even more smartness about nullability --- .../org/jetbrains/jet/j2k/ConstructorUtils.kt | 13 ++-- j2k/src/org/jetbrains/jet/j2k/Converter.kt | 62 ++++++++++++++++--- j2k/src/org/jetbrains/jet/j2k/Utils.kt | 18 ++---- .../jetbrains/jet/j2k/ast/LocalVariable.kt | 27 ++++---- .../org/jetbrains/jet/j2k/ast/Statements.kt | 7 +-- j2k/src/org/jetbrains/jet/j2k/ast/Types.kt | 2 + .../jet/j2k/visitors/ElementVisitor.kt | 2 +- .../JavaToKotlinConverterTestGenerated.java | 52 ++++++++++++++-- j2k/tests/testData/ast/issues/kt-824-isDir.kt | 2 +- .../nullability/FieldAssignedWithNull.java | 8 +++ .../ast/nullability/FieldAssignedWithNull.kt | 7 +++ .../nullability/FieldComparedWithNull.java | 10 +++ .../ast/nullability/FieldComparedWithNull.kt | 9 +++ .../nullability/FieldComparedWithNull2.java | 14 +++++ .../ast/nullability/FieldComparedWithNull2.kt | 8 +++ .../nullability/FieldComparedWithNull3.java | 12 ++++ .../ast/nullability/FieldComparedWithNull3.kt | 11 ++++ .../nullability/FieldComparedWithNull4.java | 11 ++++ .../ast/nullability/FieldComparedWithNull4.kt | 7 +++ .../ParameterComparedWithNull.java | 6 ++ .../nullability/ParameterComparedWithNull.kt | 5 ++ .../nullability/VariableAssignedWithNull.java | 8 +++ .../nullability/VariableAssignedWithNull.kt | 7 +++ .../nullability/VariableComparedWithNull.java | 8 +++ .../nullability/VariableComparedWithNull.kt | 7 +++ ....java => VariableInitializedWithNull.java} | 0 ...Null.kt => VariableInitializedWithNull.kt} | 0 ...> VariableInitializedWithTernaryNull.java} | 0 ... => VariableInitializedWithTernaryNull.kt} | 0 29 files changed, 273 insertions(+), 50 deletions(-) create mode 100644 j2k/tests/testData/ast/nullability/FieldAssignedWithNull.java create mode 100644 j2k/tests/testData/ast/nullability/FieldAssignedWithNull.kt create mode 100644 j2k/tests/testData/ast/nullability/FieldComparedWithNull.java create mode 100644 j2k/tests/testData/ast/nullability/FieldComparedWithNull.kt create mode 100644 j2k/tests/testData/ast/nullability/FieldComparedWithNull2.java create mode 100644 j2k/tests/testData/ast/nullability/FieldComparedWithNull2.kt create mode 100644 j2k/tests/testData/ast/nullability/FieldComparedWithNull3.java create mode 100644 j2k/tests/testData/ast/nullability/FieldComparedWithNull3.kt create mode 100644 j2k/tests/testData/ast/nullability/FieldComparedWithNull4.java create mode 100644 j2k/tests/testData/ast/nullability/FieldComparedWithNull4.kt create mode 100644 j2k/tests/testData/ast/nullability/ParameterComparedWithNull.java create mode 100644 j2k/tests/testData/ast/nullability/ParameterComparedWithNull.kt create mode 100644 j2k/tests/testData/ast/nullability/VariableAssignedWithNull.java create mode 100644 j2k/tests/testData/ast/nullability/VariableAssignedWithNull.kt create mode 100644 j2k/tests/testData/ast/nullability/VariableComparedWithNull.java create mode 100644 j2k/tests/testData/ast/nullability/VariableComparedWithNull.kt rename j2k/tests/testData/ast/nullability/{InitializedWithNull.java => VariableInitializedWithNull.java} (100%) rename j2k/tests/testData/ast/nullability/{InitializedWithNull.kt => VariableInitializedWithNull.kt} (100%) rename j2k/tests/testData/ast/nullability/{InitializedWithTernaryNull.java => VariableInitializedWithTernaryNull.java} (100%) rename j2k/tests/testData/ast/nullability/{InitializedWithTernaryNull.kt => VariableInitializedWithTernaryNull.kt} (100%) diff --git a/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt b/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt index a10604634dd..cc9330dfc5d 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt @@ -18,7 +18,6 @@ package org.jetbrains.jet.j2k import com.intellij.psi.* import java.util.LinkedHashSet -import com.intellij.psi.util.PsiUtil fun PsiMethod.isPrimaryConstructor(): Boolean { if (!isConstructor()) return false @@ -63,19 +62,21 @@ fun PsiClass.getPrimaryConstructor(): PsiMethod? { fun PsiElement.isInsidePrimaryConstructor(): Boolean = getContainingConstructor()?.isPrimaryConstructor() ?: false -fun PsiElement.getContainingConstructor(): PsiMethod? { +fun PsiElement.getContainingMethod(): PsiMethod? { var context = getContext() while (context != null) { val _context = context!! - if (_context is PsiMethod) { - return if (_context.isConstructor()) _context else null - } - + if (_context is PsiMethod) return _context context = _context.getContext() } return null } +fun PsiElement.getContainingConstructor(): PsiMethod? { + val method = getContainingMethod() + return if (method?.isConstructor() == true) method else null +} + fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean { val ref = getMethodExpression() if (ref.getCanonicalText() == "super") { diff --git a/j2k/src/org/jetbrains/jet/j2k/Converter.kt b/j2k/src/org/jetbrains/jet/j2k/Converter.kt index e3ac5b8e6dd..793fb9ff3d8 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Converter.kt @@ -315,16 +315,28 @@ public class Converter(val project: Project, val settings: ConverterSettings) { comments: MemberComments, membersToRemove: MutableSet): PrimaryConstructor { val params = constructor.getParameterList().getParameters() - val parameterToField = HashMap() + val parameterToField = HashMap>() val body = constructor.getBody() val block = if (body != null) { val statementsToRemove = HashSet() val usageReplacementMap = HashMap() for (parameter in params) { val (field, initializationStatement) = findBackingFieldForConstructorParameter(parameter, constructor) ?: continue - if (convertVariableType(field) != convertVariableType(parameter)) continue - parameterToField.put(parameter, field) + val fieldType = convertVariableType(field) + val parameterType = convertVariableType(parameter) + // types can be different only in nullability + val `type` = if (fieldType == parameterType) { + fieldType + } + else if (fieldType.toNotNullType() == parameterType.toNotNullType()) { + if (fieldType.isNullable) fieldType else parameterType // prefer nullable one + } + else { + continue + } + + parameterToField.put(parameter, field to `type`) statementsToRemove.add(initializationStatement) membersToRemove.add(field) @@ -345,13 +357,13 @@ public class Converter(val project: Project, val settings: ConverterSettings) { } val parameterList = ParameterList(params.map { - val field = parameterToField[it] - if (field == null) { + if (!parameterToField.containsKey(it)) { convertParameter(it) } else { + val (field, `type`) = parameterToField[it]!! Parameter(Identifier(field.getName()!!), - convertVariableType(it), + `type`, if (field.hasModifierProperty(PsiModifier.FINAL)) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var, convertModifiers(field).filter { ACCESS_MODIFIERS.contains(it) }) } @@ -362,7 +374,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) { private fun findBackingFieldForConstructorParameter(parameter: PsiParameter, constructor: PsiMethod): Pair? { val body = constructor.getBody() ?: return null - val refs = findExpressionReferences(parameter, body) + val refs = findVariableReferences(parameter, body) if (refs.any { PsiUtil.isAccessedForWriting(it) }) return null @@ -381,7 +393,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) { if (statement.getParent() != body) continue // and no other assignments to field should exist in the constructor - if (findExpressionReferences(field, body).any { it != assignee && PsiUtil.isAccessedForWriting(it) && isQualifierEmptyOrThis(it) }) continue + if (findVariableReferences(field, body).any { it != assignee && PsiUtil.isAccessedForWriting(it) && isQualifierEmptyOrThis(it) }) continue //TODO: check access to field before assignment return field to statement @@ -459,6 +471,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) { public fun convertVariableType(variable: PsiVariable): Type { var nullability = variable.nullabilityFromAnnotations() + if (nullability == Nullability.Default) { val initializer = variable.getInitializer() if (initializer != null) { @@ -471,9 +484,28 @@ public class Converter(val project: Project, val settings: ConverterSettings) { } } } + + if (nullability == Nullability.Default) { + val scope = usageScope(variable) + if (scope != null) { + if (findVariableReferences(variable, scope).any { isVariableNullableFromUsage(it) }) { + nullability = Nullability.Nullable + } + } + } + return convertType(variable.getType(), nullability) } + private fun usageScope(variable: PsiVariable): PsiElement? { + return when(variable) { + is PsiParameter -> variable.getDeclarationScope() + is PsiField -> if (variable.hasModifierProperty(PsiModifier.PRIVATE)) variable.getContainingClass() else variable.getContainingFile() + is PsiLocalVariable -> variable.getContainingMethod() + else -> null + } + } + private fun PsiExpression.nullability(): Nullability { return when (this) { is PsiLiteralExpression -> if (getValue() != null) Nullability.NotNull else Nullability.Nullable @@ -497,6 +529,20 @@ public class Converter(val project: Project, val settings: ConverterSettings) { } } + private fun isVariableNullableFromUsage(ref: PsiReferenceExpression): Boolean { + val parent = ref.getParent() ?: return false + if (parent is PsiAssignmentExpression && parent.getOperationTokenType() == JavaTokenType.EQ && ref == parent.getLExpression()) { + return parent.getRExpression()?.nullability() == Nullability.Nullable + } + else if (parent is PsiBinaryExpression) { + val operationType = parent.getOperationTokenType() + if (operationType == JavaTokenType.EQEQ || operationType == JavaTokenType.NE) { + val otherOperand = if (ref == parent.getLOperand()) parent.getROperand() else parent.getLOperand() + return otherOperand?.nullability() == Nullability.Nullable + } + } + return false + } private fun convertToNotNullableTypes(types: Array): List = types.map { convertType(it, Nullability.NotNull) } diff --git a/j2k/src/org/jetbrains/jet/j2k/Utils.kt b/j2k/src/org/jetbrains/jet/j2k/Utils.kt index f6980362c8e..3ae7152d322 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Utils.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Utils.kt @@ -17,28 +17,22 @@ package org.jetbrains.jet.j2k import org.jetbrains.jet.j2k.ast.Identifier -import com.intellij.psi.PsiElement -import com.intellij.psi.JavaRecursiveElementVisitor -import com.intellij.psi.PsiReferenceExpression -import com.intellij.psi.PsiLiteralExpression -import com.intellij.psi.PsiNewExpression import org.jetbrains.jet.j2k.ast.Field import org.jetbrains.jet.lang.types.expressions.OperatorConventions -import com.intellij.psi.PsiModifierListOwner import java.util.ArrayList -import com.intellij.psi.util.PsiUtil -import com.intellij.psi.PsiThisExpression import org.jetbrains.jet.j2k.ast.Nullability +import com.intellij.psi.* +import com.intellij.psi.util.PsiUtil fun quoteKeywords(packageName: String): String = packageName.split("\\.").map { Identifier(it).toKotlin() }.makeString(".") -fun findExpressionReferences(element: PsiElement, scope: PsiElement): Collection { +fun findVariableReferences(variable: PsiVariable, scope: PsiElement): Collection { class Visitor : JavaRecursiveElementVisitor() { val refs = ArrayList() override fun visitReferenceExpression(expression: PsiReferenceExpression) { super.visitReferenceExpression(expression) - if (expression.isReferenceTo(element)) { + if (expression.isReferenceTo(variable)) { refs.add(expression) } } @@ -49,8 +43,8 @@ fun findExpressionReferences(element: PsiElement, scope: PsiElement): Collection return visitor.refs } -fun PsiElement.countWriteAccesses(scope: PsiElement?): Int - = if (scope != null) findExpressionReferences(this, scope).count { PsiUtil.isAccessedForWriting(it) } else 0 +fun PsiVariable.countWriteAccesses(scope: PsiElement?): Int + = if (scope != null) findVariableReferences(this, scope).count { PsiUtil.isAccessedForWriting(it) } else 0 fun PsiModifierListOwner.nullabilityFromAnnotations(): Nullability { val annotations = getModifierList()?.getAnnotations() ?: return Nullability.Default diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt b/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt index fd4fe7e84e9..674dfe70dd2 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt @@ -19,20 +19,25 @@ package org.jetbrains.jet.j2k.ast import org.jetbrains.jet.j2k.ConverterSettings class LocalVariable( - val identifier: Identifier, - val modifiersSet: Set, - val javaType: Type, - val initializer: Expression, - val isVal: Boolean, - val settings: ConverterSettings + private val identifier: Identifier, + private val modifiers: Set, + private val typeCalculator: () -> Type /* we use lazy type calculation for better performance */, + private val initializer: Expression, + private val isVal: Boolean, + private val settings: ConverterSettings ) : Expression() { override fun toKotlin(): String { - if (initializer.isEmpty) { - return "${identifier.toKotlin()} : ${javaType.toKotlin()}" + val varVal = if (isVal) "val" else "var" + return if (initializer.isEmpty) { + "$varVal ${identifier.toKotlin()} : ${typeCalculator().toKotlin()}" + } + else { + val shouldSpecifyType = settings.specifyLocalVariableTypeByDefault + if (shouldSpecifyType) + "$varVal ${identifier.toKotlin()} : ${typeCalculator().toKotlin()} = ${initializer.toKotlin()}" + else + "$varVal ${identifier.toKotlin()} = ${initializer.toKotlin()}" } - - val shouldSpecifyType = settings.specifyLocalVariableTypeByDefault - return "${identifier.toKotlin()} ${if (shouldSpecifyType) ": ${javaType.toKotlin()} " else ""}= ${initializer.toKotlin()}" } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Statements.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Statements.kt index 9aaf66c0b5f..81e52416826 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Statements.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Statements.kt @@ -28,10 +28,7 @@ abstract class Statement() : Element { open class DeclarationStatement(val elements: List) : Statement() { override fun toKotlin(): String - = elements.filterIsInstance(javaClass()).map { convertDeclaration(it) }.makeString("\n") - - private fun convertDeclaration(v: LocalVariable): String - = (if (v.isVal) "val" else "var") + " " + v.toKotlin() + = elements.filterIsInstance(javaClass()).map { it.toKotlin() }.makeString("\n") } open class ExpressionListStatement(val expressions: List) : Expression() { @@ -53,7 +50,7 @@ open class IfStatement( ) : Expression() { override fun toKotlin(): String { val result: String = "if (" + condition.toKotlin() + ")\n" + thenStatement.toKotlin() - if (elseStatement != Statement.Empty) { + if (!elseStatement.isEmpty) { return result + "\nelse\n" + elseStatement.toKotlin() } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Types.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Types.kt index ae367f0a495..18e9d565615 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Types.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Types.kt @@ -69,6 +69,8 @@ trait Type : Element { override fun equals(other: Any?): Boolean = other is Type && other.toKotlin() == this.toKotlin() override fun hashCode(): Int = toKotlin().hashCode() + + override fun toString(): String = toKotlin() } open class ClassType(val `type`: Identifier, val parameters: List, nullability: Nullability, converter: Converter) diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt index 44465801fc0..03616073236 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt @@ -27,7 +27,7 @@ class ElementVisitor(public val converter: Converter) : JavaElementVisitor() { override fun visitLocalVariable(variable: PsiLocalVariable) { result = LocalVariable(Identifier(variable.getName()!!), converter.convertModifiers(variable), - converter.convertVariableType(variable), + { converter.convertVariableType(variable) }, converter.convertExpression(variable.getInitializer(), variable.getType()), converter.settings.forceLocalVariableImmutability || variable.hasModifierProperty(PsiModifier.FINAL), converter.settings) 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 21c4d0546c1..d5abbf8f57b 100644 --- a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java +++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java @@ -1780,19 +1780,59 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/nullability"), Pattern.compile("^(.+)\\.java$"), true); } + @TestMetadata("FieldAssignedWithNull.java") + public void testFieldAssignedWithNull() throws Exception { + doTest("j2k/tests/testData/ast/nullability/FieldAssignedWithNull.java"); + } + + @TestMetadata("FieldComparedWithNull.java") + public void testFieldComparedWithNull() throws Exception { + doTest("j2k/tests/testData/ast/nullability/FieldComparedWithNull.java"); + } + + @TestMetadata("FieldComparedWithNull2.java") + public void testFieldComparedWithNull2() throws Exception { + doTest("j2k/tests/testData/ast/nullability/FieldComparedWithNull2.java"); + } + + @TestMetadata("FieldComparedWithNull3.java") + public void testFieldComparedWithNull3() throws Exception { + doTest("j2k/tests/testData/ast/nullability/FieldComparedWithNull3.java"); + } + + @TestMetadata("FieldComparedWithNull4.java") + public void testFieldComparedWithNull4() throws Exception { + doTest("j2k/tests/testData/ast/nullability/FieldComparedWithNull4.java"); + } + @TestMetadata("FieldInitializedWithNull.java") public void testFieldInitializedWithNull() throws Exception { doTest("j2k/tests/testData/ast/nullability/FieldInitializedWithNull.java"); } - @TestMetadata("InitializedWithNull.java") - public void testInitializedWithNull() throws Exception { - doTest("j2k/tests/testData/ast/nullability/InitializedWithNull.java"); + @TestMetadata("ParameterComparedWithNull.java") + public void testParameterComparedWithNull() throws Exception { + doTest("j2k/tests/testData/ast/nullability/ParameterComparedWithNull.java"); } - @TestMetadata("InitializedWithTernaryNull.java") - public void testInitializedWithTernaryNull() throws Exception { - doTest("j2k/tests/testData/ast/nullability/InitializedWithTernaryNull.java"); + @TestMetadata("VariableAssignedWithNull.java") + public void testVariableAssignedWithNull() throws Exception { + doTest("j2k/tests/testData/ast/nullability/VariableAssignedWithNull.java"); + } + + @TestMetadata("VariableComparedWithNull.java") + public void testVariableComparedWithNull() throws Exception { + doTest("j2k/tests/testData/ast/nullability/VariableComparedWithNull.java"); + } + + @TestMetadata("VariableInitializedWithNull.java") + public void testVariableInitializedWithNull() throws Exception { + doTest("j2k/tests/testData/ast/nullability/VariableInitializedWithNull.java"); + } + + @TestMetadata("VariableInitializedWithTernaryNull.java") + public void testVariableInitializedWithTernaryNull() throws Exception { + doTest("j2k/tests/testData/ast/nullability/VariableInitializedWithTernaryNull.java"); } } diff --git a/j2k/tests/testData/ast/issues/kt-824-isDir.kt b/j2k/tests/testData/ast/issues/kt-824-isDir.kt index 5acf781d134..c5e9c7632b9 100644 --- a/j2k/tests/testData/ast/issues/kt-824-isDir.kt +++ b/j2k/tests/testData/ast/issues/kt-824-isDir.kt @@ -7,7 +7,7 @@ import java.io.File */ public class Test() { class object { - public fun isDir(parent: File): Boolean { + public fun isDir(parent: File?): Boolean { if (parent == null || !parent.exists()) { return false } diff --git a/j2k/tests/testData/ast/nullability/FieldAssignedWithNull.java b/j2k/tests/testData/ast/nullability/FieldAssignedWithNull.java new file mode 100644 index 00000000000..af80b085732 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/FieldAssignedWithNull.java @@ -0,0 +1,8 @@ +//file +class C { + private String s = ""; + + void foo() { + s = null + } +} diff --git a/j2k/tests/testData/ast/nullability/FieldAssignedWithNull.kt b/j2k/tests/testData/ast/nullability/FieldAssignedWithNull.kt new file mode 100644 index 00000000000..6d8550e67cf --- /dev/null +++ b/j2k/tests/testData/ast/nullability/FieldAssignedWithNull.kt @@ -0,0 +1,7 @@ +class C() { + private var s: String? = "" + + fun foo() { + s = null + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/FieldComparedWithNull.java b/j2k/tests/testData/ast/nullability/FieldComparedWithNull.java new file mode 100644 index 00000000000..b19c911c486 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/FieldComparedWithNull.java @@ -0,0 +1,10 @@ +//file +class C { + private String s = ""; + + void foo() { + if (s == null) { + System.out.print("null"); + } + } +} diff --git a/j2k/tests/testData/ast/nullability/FieldComparedWithNull.kt b/j2k/tests/testData/ast/nullability/FieldComparedWithNull.kt new file mode 100644 index 00000000000..10d88a97c62 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/FieldComparedWithNull.kt @@ -0,0 +1,9 @@ +class C() { + private var s: String? = "" + + fun foo() { + if (s == null) { + System.out.print("null") + } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/FieldComparedWithNull2.java b/j2k/tests/testData/ast/nullability/FieldComparedWithNull2.java new file mode 100644 index 00000000000..9103619d146 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/FieldComparedWithNull2.java @@ -0,0 +1,14 @@ +//file +class C { + private String s; + + public C(String s) { + this.s = s; + } + + void foo() { + if (s != null) { + System.out.print("not null"); + } + } +} diff --git a/j2k/tests/testData/ast/nullability/FieldComparedWithNull2.kt b/j2k/tests/testData/ast/nullability/FieldComparedWithNull2.kt new file mode 100644 index 00000000000..9b5e3dc0528 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/FieldComparedWithNull2.kt @@ -0,0 +1,8 @@ +class C(private var s: String?) { + + fun foo() { + if (s != null) { + System.out.print("not null") + } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/FieldComparedWithNull3.java b/j2k/tests/testData/ast/nullability/FieldComparedWithNull3.java new file mode 100644 index 00000000000..6da8f30a550 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/FieldComparedWithNull3.java @@ -0,0 +1,12 @@ +//file +class C { + public String s = ""; +} + +class D { + void foo(C c) { + if (null == c.s) { + System.out.println("null"); + } + } +} diff --git a/j2k/tests/testData/ast/nullability/FieldComparedWithNull3.kt b/j2k/tests/testData/ast/nullability/FieldComparedWithNull3.kt new file mode 100644 index 00000000000..6aae2579dcd --- /dev/null +++ b/j2k/tests/testData/ast/nullability/FieldComparedWithNull3.kt @@ -0,0 +1,11 @@ +class C() { + public var s: String? = "" +} + +class D() { + fun foo(c: C) { + if (null == c.s) { + System.out.println("null") + } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/FieldComparedWithNull4.java b/j2k/tests/testData/ast/nullability/FieldComparedWithNull4.java new file mode 100644 index 00000000000..1f129df21a4 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/FieldComparedWithNull4.java @@ -0,0 +1,11 @@ +//file +class C { + private String s; + + public C(String s) { + this.s = s; + if (s == null) { + System.out.print("null"); + } + } +} diff --git a/j2k/tests/testData/ast/nullability/FieldComparedWithNull4.kt b/j2k/tests/testData/ast/nullability/FieldComparedWithNull4.kt new file mode 100644 index 00000000000..95ca8178272 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/FieldComparedWithNull4.kt @@ -0,0 +1,7 @@ +class C(private var s: String?) { + { + if (s == null) { + System.out.print("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 new file mode 100644 index 00000000000..28e9e374a1c --- /dev/null +++ b/j2k/tests/testData/ast/nullability/ParameterComparedWithNull.java @@ -0,0 +1,6 @@ +//method +void foo(String s) { + if (s != null) { + zoo(s) + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/ParameterComparedWithNull.kt b/j2k/tests/testData/ast/nullability/ParameterComparedWithNull.kt new file mode 100644 index 00000000000..743fe1eedd4 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/ParameterComparedWithNull.kt @@ -0,0 +1,5 @@ +fun foo(s: String?) { + if (s != null) { + 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 new file mode 100644 index 00000000000..e0b15c2ebed --- /dev/null +++ b/j2k/tests/testData/ast/nullability/VariableAssignedWithNull.java @@ -0,0 +1,8 @@ +//method +// !specifyLocalVariableTypeByDefault: true +void foo(boolean b) { + String s = "abc"; + if (b) { + s = null + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/VariableAssignedWithNull.kt b/j2k/tests/testData/ast/nullability/VariableAssignedWithNull.kt new file mode 100644 index 00000000000..6aa4ea2f25e --- /dev/null +++ b/j2k/tests/testData/ast/nullability/VariableAssignedWithNull.kt @@ -0,0 +1,7 @@ +// !specifyLocalVariableTypeByDefault: true +fun foo(b: Boolean) { + val s: String? = "abc" + if (b) { + 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 new file mode 100644 index 00000000000..c024fa2650e --- /dev/null +++ b/j2k/tests/testData/ast/nullability/VariableComparedWithNull.java @@ -0,0 +1,8 @@ +//method +// !specifyLocalVariableTypeByDefault: true +void foo() { + String s = bar() + if (s != null) { + zoo(s) + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/VariableComparedWithNull.kt b/j2k/tests/testData/ast/nullability/VariableComparedWithNull.kt new file mode 100644 index 00000000000..c95cb3f308d --- /dev/null +++ b/j2k/tests/testData/ast/nullability/VariableComparedWithNull.kt @@ -0,0 +1,7 @@ +// !specifyLocalVariableTypeByDefault: true +fun foo() { + val s: String? = bar() + if (s != null) { + zoo(s) + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/InitializedWithNull.java b/j2k/tests/testData/ast/nullability/VariableInitializedWithNull.java similarity index 100% rename from j2k/tests/testData/ast/nullability/InitializedWithNull.java rename to j2k/tests/testData/ast/nullability/VariableInitializedWithNull.java diff --git a/j2k/tests/testData/ast/nullability/InitializedWithNull.kt b/j2k/tests/testData/ast/nullability/VariableInitializedWithNull.kt similarity index 100% rename from j2k/tests/testData/ast/nullability/InitializedWithNull.kt rename to j2k/tests/testData/ast/nullability/VariableInitializedWithNull.kt diff --git a/j2k/tests/testData/ast/nullability/InitializedWithTernaryNull.java b/j2k/tests/testData/ast/nullability/VariableInitializedWithTernaryNull.java similarity index 100% rename from j2k/tests/testData/ast/nullability/InitializedWithTernaryNull.java rename to j2k/tests/testData/ast/nullability/VariableInitializedWithTernaryNull.java diff --git a/j2k/tests/testData/ast/nullability/InitializedWithTernaryNull.kt b/j2k/tests/testData/ast/nullability/VariableInitializedWithTernaryNull.kt similarity index 100% rename from j2k/tests/testData/ast/nullability/InitializedWithTernaryNull.kt rename to j2k/tests/testData/ast/nullability/VariableInitializedWithTernaryNull.kt