Remove laziness from LazyJavaTypeResolver.

This laziness was removed because main client of JavaTypeResolver is LazyJavaMemberScope. And this scope run enhance signatures which run resolve for this types.
This commit is contained in:
Stanislav Erokhin
2016-06-03 21:40:03 +03:00
parent e5aa8ebe7c
commit c30754ae3c
4 changed files with 196 additions and 198 deletions
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * Copyright 2010-2016 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@ class LazyJavaTypeResolver(
is JavaPrimitiveType -> { is JavaPrimitiveType -> {
val primitiveType = javaType.type val primitiveType = javaType.type
if (primitiveType != null) c.module.builtIns.getPrimitiveKotlinType(primitiveType) if (primitiveType != null) c.module.builtIns.getPrimitiveKotlinType(primitiveType)
else c.module.builtIns.getUnitType() else c.module.builtIns.unitType
} }
is JavaClassifierType -> transformJavaClassifierType(javaType, attr) is JavaClassifierType -> transformJavaClassifierType(javaType, attr)
is JavaArrayType -> transformArrayType(javaType, attr) is JavaArrayType -> transformArrayType(javaType, attr)
@@ -61,27 +61,6 @@ class LazyJavaTypeResolver(
} }
} }
private fun transformJavaClassifierType(javaType: JavaClassifierType, attr: JavaTypeAttributes): KotlinType {
val allowFlexible = attr.allowFlexible && attr.howThisTypeIsUsed != SUPERTYPE
val lowerAttr = if (allowFlexible) attr.toFlexible(FLEXIBLE_LOWER_BOUND) else attr
val upperAttr = if (allowFlexible) attr.toFlexible(FLEXIBLE_UPPER_BOUND) else attr
return if (javaType.isRaw) {
RawTypeImpl(LazyJavaClassifierType(javaType, lowerAttr.toRawBound(RawBound.LOWER)),
LazyJavaClassifierType(javaType, upperAttr.toRawBound(RawBound.UPPER)))
}
else if (allowFlexible) {
KotlinTypeFactory.flexibleType(
LazyJavaClassifierType(javaType, lowerAttr),
LazyJavaClassifierType(javaType, upperAttr)
)
}
else {
LazyJavaClassifierType(javaType, attr)
}
}
fun transformArrayType(arrayType: JavaArrayType, attr: JavaTypeAttributes, isVararg: Boolean = false): KotlinType { fun transformArrayType(arrayType: JavaArrayType, attr: JavaTypeAttributes, isVararg: Boolean = false): KotlinType {
return run { return run {
val javaComponentType = arrayType.componentType val javaComponentType = arrayType.componentType
@@ -108,26 +87,49 @@ class LazyJavaTypeResolver(
}.replaceAnnotations(attr.typeAnnotations) }.replaceAnnotations(attr.typeAnnotations)
} }
private inner class LazyJavaClassifierType( private fun transformJavaClassifierType(javaType: JavaClassifierType, attr: JavaTypeAttributes): KotlinType {
private val javaType: JavaClassifierType, fun errorType() = ErrorUtils.createErrorType("Unresolved java class ${javaType.presentableText}")
private val attr: JavaTypeAttributes
) : AbstractLazyType(c.storageManager) {
override val annotations = CompositeAnnotations(listOf(LazyJavaAnnotations(c, javaType), attr.typeAnnotations))
private val classifier: JavaClassifier? get() = javaType.classifier val allowFlexible = attr.allowFlexible && attr.howThisTypeIsUsed != SUPERTYPE
val isRaw = javaType.isRaw
if (!javaType.isRaw && !allowFlexible) {
return computeSimpleJavaClassifierType(javaType, attr) ?: errorType()
}
override fun computeTypeConstructor(): TypeConstructor { fun computeBound(lower: Boolean) = computeSimpleJavaClassifierType(javaType, attr.computeAttributes(allowFlexible, isRaw, forLower = lower))
val classifier = classifier ?: return createNotFoundClass()
val lower = computeBound(lower = true) ?: return errorType()
val upper = computeBound(lower = false) ?: return errorType()
return if (javaType.isRaw) {
RawTypeImpl(lower, upper)
}
else {
KotlinTypeFactory.flexibleType(lower, upper)
}
}
private fun computeSimpleJavaClassifierType(javaType: JavaClassifierType, attr: JavaTypeAttributes): SimpleType? {
val annotations = CompositeAnnotations(listOf(LazyJavaAnnotations(c, javaType), attr.typeAnnotations))
val constructor = computeTypeConstructor(javaType, attr) ?: return null
val arguments = computeArguments(javaType, attr, constructor)
val isNullable = isNullable(javaType, attr)
val memberScope = AbstractLazyType.computeMemberScope(constructor, arguments)
return KotlinTypeFactory.simpleType(annotations, constructor, arguments, isNullable, memberScope)
}
private fun computeTypeConstructor(javaType: JavaClassifierType, attr: JavaTypeAttributes): TypeConstructor? {
val classifier = javaType.classifier ?: return createNotFoundClass(javaType)
return when (classifier) { return when (classifier) {
is JavaClass -> { is JavaClass -> {
val fqName = classifier.fqName.sure { "Class type should have a FQ name: $classifier" } val fqName = classifier.fqName.sure { "Class type should have a FQ name: $classifier" }
val classData = mapKotlinClass(fqName) ?: c.components.moduleClassResolver.resolveClass(classifier) val classData = mapKotlinClass(javaType, attr, fqName) ?: c.components.moduleClassResolver.resolveClass(classifier)
classData?.typeConstructor ?: createNotFoundClass() classData?.typeConstructor ?: createNotFoundClass(javaType)
} }
is JavaTypeParameter -> { is JavaTypeParameter -> {
typeParameterResolver.resolveTypeParameter(classifier)?.typeConstructor typeParameterResolver.resolveTypeParameter(classifier)?.typeConstructor
?: ErrorUtils.createErrorTypeConstructor("Unresolved Java type parameter: " + javaType.presentableText)
} }
else -> throw IllegalStateException("Unknown classifier kind: $classifier") else -> throw IllegalStateException("Unknown classifier kind: $classifier")
} }
@@ -137,12 +139,12 @@ class LazyJavaTypeResolver(
// So we just take the canonical text of the type (which seems to be the only option at the moment), erase all type arguments // So we just take the canonical text of the type (which seems to be the only option at the moment), erase all type arguments
// and treat the resulting qualified name as if it references a simple top-level class. // and treat the resulting qualified name as if it references a simple top-level class.
// Note that this makes MISSING_DEPENDENCY_CLASS diagnostic messages not as precise as they could be in some corner cases. // Note that this makes MISSING_DEPENDENCY_CLASS diagnostic messages not as precise as they could be in some corner cases.
private fun createNotFoundClass(): TypeConstructor { private fun createNotFoundClass(javaType: JavaClassifierType): TypeConstructor {
val classId = parseCanonicalFqNameIgnoringTypeArguments(javaType.canonicalText) val classId = parseCanonicalFqNameIgnoringTypeArguments(javaType.canonicalText)
return c.components.deserializedDescriptorResolver.components.notFoundClasses.get(classId, listOf(0)) return c.components.deserializedDescriptorResolver.components.notFoundClasses.get(classId, listOf(0))
} }
private fun mapKotlinClass(fqName: FqName): ClassDescriptor? { private fun mapKotlinClass(javaType: JavaClassifierType, attr: JavaTypeAttributes, fqName: FqName): ClassDescriptor? {
if (attr.isForAnnotationParameter && fqName == JAVA_LANG_CLASS_FQ_NAME) { if (attr.isForAnnotationParameter && fqName == JAVA_LANG_CLASS_FQ_NAME) {
return c.components.reflectionTypes.kClass return c.components.reflectionTypes.kClass
} }
@@ -181,6 +183,8 @@ class LazyJavaTypeResolver(
private fun JavaClassifierType.argumentsMakeSenseOnlyForMutableContainer( private fun JavaClassifierType.argumentsMakeSenseOnlyForMutableContainer(
readOnlyContainer: ClassDescriptor readOnlyContainer: ClassDescriptor
): Boolean { ): Boolean {
fun JavaType?.isSuperWildcard(): Boolean = (this as? JavaWildcardType)?.let { it.bound != null && !it.isExtends } ?: false
if (!typeArguments.lastOrNull().isSuperWildcard()) return false if (!typeArguments.lastOrNull().isSuperWildcard()) return false
val mutableLastParameterVariance = JavaToKotlinClassMap.INSTANCE.convertReadOnlyToMutable(readOnlyContainer) val mutableLastParameterVariance = JavaToKotlinClassMap.INSTANCE.convertReadOnlyToMutable(readOnlyContainer)
.typeConstructor.parameters.lastOrNull()?.variance ?: return false .typeConstructor.parameters.lastOrNull()?.variance ?: return false
@@ -188,20 +192,18 @@ class LazyJavaTypeResolver(
return mutableLastParameterVariance != OUT_VARIANCE return mutableLastParameterVariance != OUT_VARIANCE
} }
private fun JavaType?.isSuperWildcard(): Boolean = (this as? JavaWildcardType)?.let { it.bound != null && !it.isExtends } ?: false fun computeArguments(javaType: JavaClassifierType, attr: JavaTypeAttributes, constructor: TypeConstructor): List<TypeProjection> {
val eraseTypeParameters = run {
private fun eraseTypeParameters(): Boolean { if (attr.rawBound != RawBound.NOT_RAW) return@run true
if (attr.rawBound != RawBound.NOT_RAW) return true
// This option is needed because sometimes we get weird versions of JDK classes in the class path, // This option is needed because sometimes we get weird versions of JDK classes in the class path,
// such as collections with no generics, so the Java types are not raw, formally, but they don't match with // such as collections with no generics, so the Java types are not raw, formally, but they don't match with
// their Kotlin analogs, so we treat them as raw to avoid exceptions // their Kotlin analogs, so we treat them as raw to avoid exceptions
return javaType.typeArguments.isEmpty() && !constructor.parameters.isEmpty() javaType.typeArguments.isEmpty() && !constructor.parameters.isEmpty()
} }
override fun computeArguments(): List<TypeProjection> {
val typeParameters = constructor.parameters val typeParameters = constructor.parameters
if (eraseTypeParameters()) { if (eraseTypeParameters) {
return typeParameters.map { return typeParameters.map {
parameter -> parameter ->
// Some activity for preventing recursion in cases like `class A<T extends A, F extends T>` // Some activity for preventing recursion in cases like `class A<T extends A, F extends T>`
@@ -271,26 +273,22 @@ class LazyJavaTypeResolver(
return this != typeParameter.variance return this != typeParameter.variance
} }
private val nullable = c.storageManager.createLazyValue l@ { private fun isNullable(javaType: JavaClassifierType, attr: JavaTypeAttributes): Boolean {
if (attr.flexibility == FLEXIBLE_LOWER_BOUND) return@l false if (attr.flexibility == FLEXIBLE_LOWER_BOUND) return false
if (attr.flexibility == FLEXIBLE_UPPER_BOUND) return@l true if (attr.flexibility == FLEXIBLE_UPPER_BOUND) return true
!attr.isMarkedNotNull && return !attr.isMarkedNotNull &&
// 'L extends List<T>' in Java is a List<T> in Kotlin, not a List<T?> // '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 // nullability will be taken care of in individual member signatures
when (classifier) { when (javaType.classifier) {
is JavaTypeParameter -> { is JavaTypeParameter -> {
attr.howThisTypeIsUsed !in setOf(TYPE_ARGUMENT, UPPER_BOUND, SUPERTYPE_ARGUMENT, SUPERTYPE) attr.howThisTypeIsUsed !in setOf(TYPE_ARGUMENT, UPPER_BOUND, SUPERTYPE_ARGUMENT, SUPERTYPE)
} }
is JavaClass, is JavaClass,
null -> attr.howThisTypeIsUsed !in setOf(TYPE_ARGUMENT, SUPERTYPE_ARGUMENT, SUPERTYPE) null -> attr.howThisTypeIsUsed !in setOf(TYPE_ARGUMENT, SUPERTYPE_ARGUMENT, SUPERTYPE)
else -> error("Unknown classifier: ${classifier}") else -> error("Unknown classifier: ${javaType.classifier}")
} }
} }
override val isMarkedNullable: Boolean get() = nullable()
}
} }
internal fun makeStarProjection( internal fun makeStarProjection(
@@ -372,14 +370,10 @@ fun TypeUsage.toAttributes(
override val upperBoundOfTypeParameter: TypeParameterDescriptor? = upperBoundForTypeParameter override val upperBoundOfTypeParameter: TypeParameterDescriptor? = upperBoundForTypeParameter
} }
fun JavaTypeAttributes.toFlexible(flexibility: JavaTypeFlexibility) = fun JavaTypeAttributes.computeAttributes(allowFlexible: Boolean, isRaw: Boolean, forLower: Boolean) =
object : JavaTypeAttributes by this { object : JavaTypeAttributes by this {
override val flexibility = flexibility override val flexibility = if (!allowFlexible) INFLEXIBLE else if(forLower) FLEXIBLE_LOWER_BOUND else FLEXIBLE_UPPER_BOUND
} override val rawBound = if (!isRaw) RawBound.NOT_RAW else if(forLower) RawBound.LOWER else RawBound.UPPER
fun JavaTypeAttributes.toRawBound(rawBound: RawBound) =
object : JavaTypeAttributes by this {
override val rawBound = rawBound
} }
@@ -85,8 +85,10 @@ class RawTypeImpl(lowerBound: SimpleType, upperBound: SimpleType) : FlexibleType
internal object RawSubstitution : TypeSubstitution() { internal object RawSubstitution : TypeSubstitution() {
override fun get(key: KotlinType) = TypeProjectionImpl(eraseType(key)) override fun get(key: KotlinType) = TypeProjectionImpl(eraseType(key))
private val lowerTypeAttr = TypeUsage.MEMBER_SIGNATURE_INVARIANT.toAttributes().toRawBound(RawBound.LOWER) private val lowerTypeAttr = TypeUsage.MEMBER_SIGNATURE_INVARIANT.toAttributes()
private val upperTypeAttr = TypeUsage.MEMBER_SIGNATURE_INVARIANT.toAttributes().toRawBound(RawBound.UPPER) .computeAttributes(allowFlexible = false, isRaw = true, forLower = true)
private val upperTypeAttr = TypeUsage.MEMBER_SIGNATURE_INVARIANT.toAttributes()
.computeAttributes(allowFlexible = false, isRaw = true, forLower = false)
fun eraseType(type: KotlinType): KotlinType { fun eraseType(type: KotlinType): KotlinType {
val declaration = type.constructor.declarationDescriptor val declaration = type.constructor.declarationDescriptor
@@ -35,16 +35,7 @@ abstract class AbstractLazyType(storageManager: StorageManager) : SimpleType(),
protected abstract fun computeArguments(): List<TypeProjection> protected abstract fun computeArguments(): List<TypeProjection>
override val memberScope by storageManager.createLazyValue { computeMemberScope() } override val memberScope by storageManager.createLazyValue { computeMemberScope(constructor, arguments) }
fun computeMemberScope(): MemberScope {
val descriptor = constructor.declarationDescriptor
return when (descriptor) {
is TypeParameterDescriptor -> descriptor.getDefaultType().memberScope
is ClassDescriptor -> descriptor.getMemberScope(TypeConstructorSubstitution.create(constructor, arguments))
else -> throw IllegalStateException("Unsupported classifier: $descriptor")
}
}
override val isMarkedNullable: Boolean get() = false override val isMarkedNullable: Boolean get() = false
@@ -63,4 +54,15 @@ abstract class AbstractLazyType(storageManager: StorageManager) : SimpleType(),
else "$constructor<not-computed>" else "$constructor<not-computed>"
else -> super.toString() else -> super.toString()
} }
companion object {
fun computeMemberScope(constructor: TypeConstructor, arguments: List<TypeProjection>): MemberScope {
val descriptor = constructor.declarationDescriptor
return when (descriptor) {
is TypeParameterDescriptor -> descriptor.getDefaultType().memberScope
is ClassDescriptor -> descriptor.getMemberScope(TypeConstructorSubstitution.create(constructor, arguments))
else -> throw IllegalStateException("Unsupported classifier: $descriptor")
}
}
}
} }