Flexible types added to JDR

So far they act exactly like inflexible ones
This commit is contained in:
Andrey Breslav
2014-06-20 18:02:51 +04:00
parent ad8de070fa
commit e268e74fa3
3 changed files with 88 additions and 6 deletions
@@ -45,6 +45,7 @@ import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.jet.lang.resolve.java.resolver.ExternalSignatureResolver
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils
import org.jetbrains.jet.utils.*
import org.jetbrains.jet.lang.resolve.java.PLATFORM_TYPES
public abstract class LazyJavaMemberScope(
protected val c: LazyJavaResolverContextWithTypes,
@@ -180,12 +181,12 @@ public abstract class LazyJavaMemberScope(
val paramType = javaParameter.getType()
assert (paramType is JavaArrayType, "Vararg parameter should be an array: $paramType")
val arrayType = c.typeResolver.transformArrayType(paramType as JavaArrayType, typeUsage, true)
val outType = TypeUtils.makeNotNullable(arrayType)
val outType = if (PLATFORM_TYPES) arrayType else TypeUtils.makeNotNullable(arrayType)
Pair(outType, KotlinBuiltIns.getInstance().getArrayElementType(outType))
}
else {
val jetType = c.typeResolver.transformJavaType(javaParameter.getType(), typeUsage)
if (jetType.isNullable() && c.hasNotNullAnnotation(javaParameter))
if (!PLATFORM_TYPES && jetType.isNullable() && c.hasNotNullAnnotation(javaParameter))
Pair(TypeUtils.makeNotNullable(jetType), null)
else Pair(jetType, null)
}
@@ -285,7 +286,7 @@ public abstract class LazyJavaMemberScope(
private fun getPropertyType(field: JavaField): JetType {
// Fields do not have their own generic parameters
val propertyType = c.typeResolver.transformJavaType(field.getType(), LazyJavaTypeAttributes(c, field, TypeUsage.MEMBER_SIGNATURE_INVARIANT))
if (field.isFinal() && field.isStatic()) {
if (!PLATFORM_TYPES && field.isFinal() && field.isStatic()) {
return TypeUtils.makeNotNullable(propertyType)
}
return propertyType
@@ -31,6 +31,8 @@ import org.jetbrains.jet.lang.resolve.java.lazy.*
import org.jetbrains.jet.storage.*
import java.util.HashSet
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
import org.jetbrains.jet.lang.resolve.java.PLATFORM_TYPES
import org.jetbrains.jet.lang.resolve.java.lazy.types.Flexibility.*
class LazyJavaTypeResolver(
private val c: LazyJavaResolverContext,
@@ -45,7 +47,9 @@ class LazyJavaTypeResolver(
assert(jetType != null, "Primitive type is not found: " + canonicalText)
return jetType!!
}
is JavaClassifierType -> LazyJavaClassifierType(javaType, attr)
is JavaClassifierType -> if (PLATFORM_TYPES)
LazyFlexibleJavaClassifierType(javaType, attr)
else LazyJavaClassifierType(javaType, attr)
is JavaArrayType -> transformArrayType(javaType, attr)
else -> throw UnsupportedOperationException("Unsupported type: " + javaType)
}
@@ -62,7 +66,16 @@ class LazyJavaTypeResolver(
val howArgumentTypeIsUsed = if (isVararg) MEMBER_SIGNATURE_CONTRAVARIANT else TYPE_ARGUMENT
val componentType = transformJavaType(javaComponentType, howArgumentTypeIsUsed.toAttributes())
return TypeUtils.makeNullableAsSpecified(KotlinBuiltIns.getInstance().getArrayType(projectionKind, componentType), !attr.isMarkedNotNull)
val result = KotlinBuiltIns.getInstance().getArrayType(projectionKind, componentType)
return if (PLATFORM_TYPES)
DelegatingFlexibleType(
KotlinBuiltIns.getInstance().getArrayType(INVARIANT, componentType),
TypeUtils.makeNullable(
KotlinBuiltIns.getInstance().getArrayType(OUT_VARIANCE, componentType)
)
)
else
TypeUtils.makeNullableAsSpecified(result, !attr.isMarkedNotNull)
}
private class LazyStarProjection(
@@ -95,6 +108,9 @@ class LazyJavaTypeResolver(
val javaToKotlinClassMap = JavaToKotlinClassMap.getInstance()
val howThisTypeIsUsedEffectively = when {
attr.flexibility == FLEXIBLE_LOWER_BOUND -> MEMBER_SIGNATURE_COVARIANT
attr.flexibility == FLEXIBLE_UPPER_BOUND -> MEMBER_SIGNATURE_CONTRAVARIANT
// This case has to be checked before isMarkedReadOnly/isMarkedMutable, because those two are slow
// not mapped, we don't care about being marked mutable/read-only
javaToKotlinClassMap.mapPlatformClass(fqName).isEmpty() -> attr.howThisTypeIsUsed
@@ -220,7 +236,12 @@ class LazyJavaTypeResolver(
return (descriptor as ClassDescriptor).getMemberScope(getArguments())
}
private val _nullable = c.storageManager.createLazyValue {
private val _nullable = c.storageManager.createLazyValue @nullable{
(): Boolean ->
when (attr.flexibility) {
FLEXIBLE_LOWER_BOUND -> return@nullable false
FLEXIBLE_UPPER_BOUND -> return@nullable true
}
!attr.isMarkedNotNull &&
// 'L extends List<T>' in Java is a List<T> in Kotlin, not a List<T?>
// nullability will be taken care of in individual member signatures
@@ -238,12 +259,45 @@ class LazyJavaTypeResolver(
}
override fun isNullable(): Boolean = _nullable()
}
private open class DelegatingFlexibleType(
override val lowerBound: JetType,
override val upperBound: JetType
) : DelegatingType(), FlexibleType {
override fun getDelegate() = lowerBound
override fun toString() = "('$lowerBound'..'$upperBound')"
}
/*
* For a java type like java.util.List<Foo>
* lowerBound = MutableList<Foo>
* upperBound = List<Foo?>
*/
private inner class LazyFlexibleJavaClassifierType(
javaType: JavaClassifierType,
attr: JavaTypeAttributes
) : DelegatingFlexibleType(
LazyJavaClassifierType(javaType, attr.toFlexible(FLEXIBLE_LOWER_BOUND)),
LazyJavaClassifierType(javaType, attr.toFlexible(FLEXIBLE_UPPER_BOUND))
)
}
trait JavaTypeAttributes {
val howThisTypeIsUsed: TypeUsage
val howThisTypeIsUsedAccordingToAnnotations: TypeUsage
val isMarkedNotNull: Boolean
open val flexibility: Flexibility
get() = INFLEXIBLE
}
fun JavaTypeAttributes.isFlexible() = flexibility != INFLEXIBLE
enum class Flexibility {
INFLEXIBLE
FLEXIBLE_UPPER_BOUND
FLEXIBLE_LOWER_BOUND
}
class LazyJavaTypeAttributes(
@@ -266,3 +320,8 @@ fun TypeUsage.toAttributes() = object : JavaTypeAttributes {
get() = howThisTypeIsUsed
override val isMarkedNotNull: Boolean = false
}
fun JavaTypeAttributes.toFlexible(flexibility: Flexibility) =
object : JavaTypeAttributes by this {
override val flexibility = flexibility
}