Java to Kotlin converter: added nullability calculation caching
This commit is contained in:
@@ -20,8 +20,11 @@ import org.jetbrains.jet.j2k.ast.Type
|
||||
import org.jetbrains.jet.j2k.ast.Nullability
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.jet.j2k.visitors.TypeVisitor
|
||||
import java.util.HashMap
|
||||
|
||||
class TypeConverter(val settings: ConverterSettings) {
|
||||
private val nullabilityCache = HashMap<PsiElement, Nullability>()
|
||||
|
||||
public fun convertType(`type`: PsiType?, nullability: Nullability = Nullability.Default): Type {
|
||||
if (`type` == null) return Type.Empty
|
||||
|
||||
@@ -33,15 +36,21 @@ class TypeConverter(val settings: ConverterSettings) {
|
||||
}
|
||||
}
|
||||
|
||||
public fun convertTypes(types: Array<PsiType>): List<Type> {
|
||||
return types.map { convertType(it) }
|
||||
}
|
||||
public fun convertTypes(types: Array<PsiType>): List<Type>
|
||||
= types.map { convertType(it) }
|
||||
|
||||
public fun convertVariableType(variable: PsiVariable): Type {
|
||||
return convertType(variable.getType(), variableNullability(variable))
|
||||
}
|
||||
public fun convertVariableType(variable: PsiVariable): Type
|
||||
= convertType(variable.getType(), variableNullability(variable))
|
||||
|
||||
public fun variableNullability(variable: PsiVariable): Nullability {
|
||||
val cached = nullabilityCache[variable]
|
||||
if (cached != null) return cached
|
||||
val value = variableNullabilityNoCache(variable)
|
||||
nullabilityCache[variable] = value
|
||||
return value
|
||||
}
|
||||
|
||||
private fun variableNullabilityNoCache(variable: PsiVariable): Nullability {
|
||||
if (variable is PsiEnumConstant) return Nullability.NotNull
|
||||
|
||||
var nullability = variable.nullabilityFromAnnotations()
|
||||
@@ -91,7 +100,18 @@ class TypeConverter(val settings: ConverterSettings) {
|
||||
return nullability
|
||||
}
|
||||
|
||||
public fun convertMethodReturnType(method: PsiMethod): Type {
|
||||
public fun convertMethodReturnType(method: PsiMethod): Type
|
||||
= convertType(method.getReturnType(), methodNullability(method))
|
||||
|
||||
public fun methodNullability(method: PsiMethod): Nullability {
|
||||
val cached = nullabilityCache[method]
|
||||
if (cached != null) return cached
|
||||
val value = methodNullabilityNoCache(method)
|
||||
nullabilityCache[method] = value
|
||||
return value
|
||||
}
|
||||
|
||||
private fun methodNullabilityNoCache(method: PsiMethod): Nullability {
|
||||
var nullability = method.nullabilityFromAnnotations()
|
||||
|
||||
if (nullability == Nullability.Default) {
|
||||
@@ -117,7 +137,7 @@ class TypeConverter(val settings: ConverterSettings) {
|
||||
}
|
||||
}
|
||||
|
||||
return convertType(method.getReturnType(), nullability)
|
||||
return nullability
|
||||
}
|
||||
|
||||
private fun searchScope(element: PsiElement): PsiElement? {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.jet.j2k.ast
|
||||
|
||||
import org.jetbrains.jet.j2k.Converter
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.jet.j2k.ConverterSettings
|
||||
|
||||
@@ -29,12 +28,14 @@ enum class Nullability {
|
||||
Default
|
||||
}
|
||||
|
||||
fun Nullability.isNullable(settings: ConverterSettings) = when(this) {
|
||||
Nullability.Nullable -> true
|
||||
Nullability.NotNull -> false
|
||||
Nullability.Default -> !settings.forceNotNullTypes
|
||||
}
|
||||
|
||||
abstract class MayBeNullableType(nullability: Nullability, val settings: ConverterSettings) : Type {
|
||||
override val isNullable: Boolean = when (nullability) {
|
||||
Nullability.Nullable -> true
|
||||
Nullability.NotNull -> false
|
||||
Nullability.Default -> !settings.forceNotNullTypes
|
||||
}
|
||||
override val isNullable: Boolean = nullability.isNullable(settings)
|
||||
}
|
||||
|
||||
trait NotNullType : Type {
|
||||
|
||||
@@ -34,7 +34,6 @@ 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,
|
||||
@@ -153,7 +152,7 @@ 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 isNullable = if (target is PsiMethod) typeConverter.methodNullability(target).isNullable(converter.settings) else false
|
||||
val typeArguments = typeConverter.convertTypes(expression.getTypeArguments())
|
||||
|
||||
if (target is KotlinLightMethod) {
|
||||
@@ -295,7 +294,8 @@ class ExpressionVisitor(private val converter: Converter,
|
||||
}
|
||||
|
||||
override fun visitReferenceExpression(expression: PsiReferenceExpression) {
|
||||
val isNullable = typeConverter.convertType(expression.getType(), expression.nullability()).isNullable
|
||||
val target = expression.getReference()?.resolve()
|
||||
val isNullable = if (target is PsiVariable) typeConverter.variableNullability(target).isNullable(converter.settings) else false
|
||||
val referencedName = expression.getReferenceName()!!
|
||||
var identifier: Expression = Identifier(referencedName, isNullable)
|
||||
val qualifier = expression.getQualifierExpression()
|
||||
@@ -314,7 +314,6 @@ class ExpressionVisitor(private val converter: Converter,
|
||||
}
|
||||
else if (qualifier != null) {
|
||||
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)
|
||||
return
|
||||
@@ -322,8 +321,6 @@ class ExpressionVisitor(private val converter: Converter,
|
||||
}
|
||||
}
|
||||
else {
|
||||
val target = expression.getReference()?.resolve()
|
||||
|
||||
if (target is PsiClass) {
|
||||
if (PrimitiveType.values() any { it.getTypeName().asString() == target.getName() }) {
|
||||
result = Identifier(target.getQualifiedName()!!, false)
|
||||
@@ -358,14 +355,6 @@ class ExpressionVisitor(private val converter: Converter,
|
||||
result = QualifiedExpression(converter.convertExpression(qualifier), identifier)
|
||||
}
|
||||
|
||||
private fun PsiReference.nullability(): Nullability {
|
||||
val target = resolve()
|
||||
return when(target) {
|
||||
is PsiVariable -> typeConverter.variableNullability(target)
|
||||
else -> Nullability.Default
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitSuperExpression(expression: PsiSuperExpression) {
|
||||
val qualifier = expression.getQualifier()
|
||||
result = SuperExpression(if (qualifier != null) Identifier(qualifier.getQualifiedName()!!) else Identifier.Empty)
|
||||
|
||||
Reference in New Issue
Block a user