Java to Kotlin converter: better treatment of nullable expressions

This commit is contained in:
Valentin Kipyatkov
2014-06-09 15:37:12 +04:00
parent 14efefedd6
commit 1491e0e5a7
10 changed files with 104 additions and 13 deletions
@@ -35,10 +35,11 @@ open class MethodCallExpression(
}
class object {
fun build(receiver: Expression, methodName: String, arguments: List<Expression> = ArrayList()): MethodCallExpression {
public fun build(receiver: Expression, methodName: String, arguments: List<Expression> = ArrayList()): MethodCallExpression {
return MethodCallExpression(QualifiedExpression(receiver, Identifier(methodName, false)),
arguments,
ArrayList(), false)
listOf(),
false)
}
}
}
@@ -34,6 +34,7 @@ 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
import org.jetbrains.jet.lang.psi.JetNullableType
class ExpressionVisitor(private val converter: Converter,
private val typeConverter: TypeConverter,
@@ -91,7 +92,7 @@ class ExpressionVisitor(private val converter: Converter,
override fun visitClassObjectAccessExpression(expression: PsiClassObjectAccessExpression) {
val typeElement = converter.convertTypeElement(expression.getOperand())
result = MethodCallExpression(Identifier("javaClass"), listOf(), listOf(typeElement.`type`.toNotNullType()), true)
result = MethodCallExpression(Identifier("javaClass"), listOf(), listOf(typeElement.`type`.toNotNullType()), false)
}
override fun visitConditionalExpression(expression: PsiConditionalExpression) {
@@ -152,6 +153,9 @@ class ExpressionVisitor(private val converter: Converter,
val methodExpr = expression.getMethodExpression()
val arguments = expression.getArgumentList().getExpressions()
val target = methodExpr.resolve()
val isNullable = if (target is PsiMethod) typeConverter.convertMethodReturnType(target).isNullable else false
val typeArguments = typeConverter.convertTypes(expression.getTypeArguments())
if (target is KotlinLightMethod) {
val origin = target.origin
val isTopLevel = origin?.getParentByType(javaClass<JetClassOrObject>(), true) == null
@@ -159,7 +163,7 @@ class ExpressionVisitor(private val converter: Converter,
val property = if (origin is JetProperty) origin else origin.getParent() as JetProperty
val parameterCount = target.getParameterList().getParameters().size
if (parameterCount == arguments.size) {
val propertyName = Identifier(property.getName()!!, false)
val propertyName = Identifier(property.getName()!!, isNullable)
val isExtension = property.isExtensionDeclaration()
val propertyAccess = if (isTopLevel) {
if (isExtension)
@@ -191,18 +195,17 @@ class ExpressionVisitor(private val converter: Converter,
val qualifier = converter.convertExpression(arguments.firstOrNull())
MethodCallExpression(QualifiedExpression(qualifier, Identifier(origin.getName()!!, false)),
convertArguments(expression, isExtension = true),
typeConverter.convertTypes(expression.getTypeArguments()),
typeConverter.convertType(expression.getType()).isNullable)
typeArguments,
isNullable)
}
else {
MethodCallExpression(Identifier(origin.getName()!!, false),
convertArguments(expression),
typeConverter.convertTypes(expression.getTypeArguments()),
typeConverter.convertType(expression.getType()).isNullable)
typeArguments,
isNullable)
}
return
}
}
}
@@ -216,8 +219,8 @@ class ExpressionVisitor(private val converter: Converter,
result = MethodCallExpression(converter.convertExpression(methodExpr),
convertArguments(expression),
typeConverter.convertTypes(expression.getTypeArguments()),
typeConverter.convertType(expression.getType()).isNullable)
typeArguments,
isNullable)
}
private fun isObjectEquals(method: PsiMethod): Boolean {
@@ -16,14 +16,17 @@
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 java.io.File;
import java.util.regex.Pattern;
import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@@ -1596,6 +1599,16 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
doTest("j2k/tests/testData/ast/kotlinApiAccess/ClassObjectMembers.java");
}
@TestMetadata("CorrectFunNullabilityDetected.java")
public void testCorrectFunNullabilityDetected() throws Exception {
doTest("j2k/tests/testData/ast/kotlinApiAccess/CorrectFunNullabilityDetected.java");
}
@TestMetadata("CorrectNullabilityDetected.java")
public void testCorrectNullabilityDetected() throws Exception {
doTest("j2k/tests/testData/ast/kotlinApiAccess/CorrectNullabilityDetected.java");
}
@TestMetadata("ExtensionFunction.java")
public void testExtensionFunction() throws Exception {
doTest("j2k/tests/testData/ast/kotlinApiAccess/ExtensionFunction.java");
@@ -1958,6 +1971,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
doTest("j2k/tests/testData/ast/nullability/MethodReturnsTernaryNull.java");
}
@TestMetadata("NullableMethodDotAccess.java")
public void testNullableMethodDotAccess() throws Exception {
doTest("j2k/tests/testData/ast/nullability/NullableMethodDotAccess.java");
}
@TestMetadata("NullableVariableDotAccess.java")
public void testNullableVariableDotAccess() throws Exception {
doTest("j2k/tests/testData/ast/nullability/NullableVariableDotAccess.java");
+10
View File
@@ -2,6 +2,7 @@ package kotlinApi
public open class KotlinClass {
public var property: String = ""
public var nullableProperty: String? = ""
class object {
public fun staticFun(p: Int): Int = p
@@ -9,10 +10,19 @@ public open class KotlinClass {
public var staticProperty: Int
get() = 1
set(value) {}
public fun nullableStaticFun(p: Int?): Int? = p
public var nullableStaticVar: Int? = 1
}
}
public trait KotlinTrait {
public fun nullableFun(): String?
public fun notNullableFun(): String
}
public fun globalFunction(s: String): String = s
public fun nullableGlobalFunction(s: String?): String? = s
public fun globalGenericFunction<T>(t: T): T = t
public fun Int.extensionFunction(): String = toString()
@@ -0,0 +1,8 @@
//file
import kotlinApi.*
class A {
int foo(KotlinTrait t) {
return t.nullableFun().length() + t.notNullableFun().length();
}
}
@@ -0,0 +1,7 @@
import kotlinApi.*
class A() {
fun foo(t: KotlinTrait): Int {
return t.nullableFun()?.length()!! + t.notNullableFun().length()
}
}
@@ -0,0 +1,15 @@
//file
import kotlinApi.*;
class A {
int foo(KotlinClass c) {
return c.getNullableProperty().length()
+ c.getProperty().length()
+ KotlinClass.object$.getNullableStaticVar()
+ KotlinClass.object$.getStaticVar()
+ KotlinClass.object$.nullableStaticFun(1)
+ KotlinClass.object$.staticFun(1)
+ KotlinApiPackage.nullableGlobalFunction("").length()
+ KotlinApiPackage.globalFunction("").length();
}
}
@@ -0,0 +1,7 @@
import kotlinApi.*
class A() {
fun foo(c: KotlinClass): Int {
return c.nullableProperty?.length()!! + c.property.length() + KotlinClass.nullableStaticVar!! + KotlinClass.staticVar + KotlinClass.nullableStaticFun(1)!! + KotlinClass.staticFun(1) + nullableGlobalFunction("")?.length()!! + globalFunction("").length()
}
}
@@ -0,0 +1,10 @@
//file
class C {
String getString(boolean b) {
return b ? "a" : null;
}
int foo() {
return getString(true).length();
}
}
@@ -0,0 +1,12 @@
class C() {
fun getString(b: Boolean): String? {
return if (b)
"a"
else
null
}
fun foo(): Int {
return getString(true)?.length()!!
}
}