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:
@@ -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.
|
||||||
|
|||||||
+53
-59
@@ -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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user