From e268e74fa39ac81a406928e0b11c195d680de02d Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 20 Jun 2014 18:02:51 +0400 Subject: [PATCH] Flexible types added to JDR So far they act exactly like inflexible ones --- .../lazy/descriptors/LazyJavaMemberScope.kt | 7 +- .../java/lazy/types/LazyJavaTypeResolver.kt | 65 ++++++++++++++++++- .../jetbrains/jet/lang/types/flexibleTypes.kt | 22 +++++++ 3 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 core/descriptors/src/org/jetbrains/jet/lang/types/flexibleTypes.kt diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt index 9438cb2cad0..b06a8743d52 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt @@ -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 diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/types/LazyJavaTypeResolver.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/types/LazyJavaTypeResolver.kt index 11642afe09e..aa419eb2616 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/types/LazyJavaTypeResolver.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/types/LazyJavaTypeResolver.kt @@ -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' in Java is a List in Kotlin, not a List // 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 + * lowerBound = MutableList + * upperBound = List + */ + 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 + } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/flexibleTypes.kt b/core/descriptors/src/org/jetbrains/jet/lang/types/flexibleTypes.kt new file mode 100644 index 00000000000..239c74f6ce6 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/flexibleTypes.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.types + +public trait FlexibleType : JetType { + val lowerBound: JetType + val upperBound: JetType +} \ No newline at end of file