Do not add container annotaions to type artificially

It was only used for type-related nullability/mutability
annotations and it was necessary to remove them
in the descriptor renderer (duplicating their fqnames there).
At the same time they're only needed for types enhancement
where they can be simply restored from type owners' descriptors

The testData changes are more or less correct: this kind of annotations
is bound both to types themselves and their use because of their targets
This commit is contained in:
Denis Zharkov
2017-06-16 14:50:13 +03:00
parent f877c82029
commit 57b7b91444
18 changed files with 84 additions and 139 deletions
@@ -18,10 +18,7 @@ package org.jetbrains.kotlin.load.java
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.resolveClassByFqName
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.storage.StorageManager
@@ -52,16 +49,6 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager) {
return resolveTypeQualifierNickname(annotationClass)
}
fun isTypeQualifier(moduleDescriptor: ModuleDescriptor, classFqName: FqName): Boolean {
val classDescriptor = moduleDescriptor.resolveClassByFqName(
classFqName, NoLookupLocation.FROM_JAVA_LOADER
) ?: return false
if (classDescriptor.isTypeQualifierAnnotation) return true
return resolveTypeQualifierNickname(classDescriptor) != null
}
}
private val ClassDescriptor.isAnnotatedWithTypeQualifier: Boolean
@@ -52,10 +52,3 @@ val READ_ONLY_ANNOTATIONS = listOf(
val MUTABLE_ANNOTATIONS = listOf(
JvmAnnotationNames.JETBRAINS_MUTABLE_ANNOTATION
)
// When these annotations appear on a declaration, they are copied to the _type_ of the declaration, becoming type annotations
// See also DescriptorRendererOptions#excludedTypeAnnotationClasses
val ANNOTATIONS_COPIED_TO_TYPES: Set<FqName> = listOf(
NULLABLE_ANNOTATIONS, NOT_NULL_ANNOTATIONS, READ_ONLY_ANNOTATIONS, MUTABLE_ANNOTATIONS,
listOf(JAVAX_NONNULL_ANNOTATION)
).flatMap { it }.toSet()
@@ -145,10 +145,8 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS
protected fun computeMethodReturnType(method: JavaMethod, annotations: Annotations, c: LazyJavaResolverContext): KotlinType {
val annotationMethod = method.containingClass.isAnnotationType
val returnTypeAttrs = LazyJavaTypeAttributes(
TypeUsage.COMMON, annotations,
isForAnnotationParameter = annotationMethod,
moduleDescriptor = c.module,
annotationTypeQualifierResolver = c.components.annotationTypeQualifierResolver
TypeUsage.COMMON,
isForAnnotationParameter = annotationMethod
)
return c.typeResolver.transformJavaType(method.returnType, returnTypeAttrs)
}
@@ -167,9 +165,7 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS
val annotations = c.resolveAnnotations(javaParameter)
val typeUsage =
LazyJavaTypeAttributes(
TypeUsage.COMMON, annotations,
annotationTypeQualifierResolver = c.components.annotationTypeQualifierResolver,
moduleDescriptor = c.module
TypeUsage.COMMON
)
val (outType, varargElementType) =
if (javaParameter.isVararg) {
@@ -289,9 +285,7 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS
val propertyType = c.typeResolver.transformJavaType(
field.type,
LazyJavaTypeAttributes(
TypeUsage.COMMON, annotations,
annotationTypeQualifierResolver = c.components.annotationTypeQualifierResolver,
moduleDescriptor = c.module
TypeUsage.COMMON
)
)
if (!isNotNullable) {
@@ -17,13 +17,7 @@
package org.jetbrains.kotlin.load.java.lazy.types
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.annotations.CompositeAnnotations
import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations
import org.jetbrains.kotlin.load.java.ANNOTATIONS_COPIED_TO_TYPES
import org.jetbrains.kotlin.load.java.AnnotationTypeQualifierResolver
import org.jetbrains.kotlin.load.java.components.TypeUsage
import org.jetbrains.kotlin.load.java.components.TypeUsage.COMMON
import org.jetbrains.kotlin.load.java.components.TypeUsage.SUPERTYPE
@@ -64,29 +58,27 @@ class JavaTypeResolver(
}
fun transformArrayType(arrayType: JavaArrayType, attr: JavaTypeAttributes, isVararg: Boolean = false): KotlinType {
return run {
val javaComponentType = arrayType.componentType
val primitiveType = (javaComponentType as? JavaPrimitiveType)?.type
if (primitiveType != null) {
val jetType = c.module.builtIns.getPrimitiveArrayKotlinType(primitiveType)
return@run if (attr.isForAnnotationParameter)
jetType
else KotlinTypeFactory.flexibleType(jetType, jetType.makeNullableAsSpecified(true))
}
val javaComponentType = arrayType.componentType
val primitiveType = (javaComponentType as? JavaPrimitiveType)?.type
if (primitiveType != null) {
val jetType = c.module.builtIns.getPrimitiveArrayKotlinType(primitiveType)
return if (attr.isForAnnotationParameter)
jetType
else KotlinTypeFactory.flexibleType(jetType, jetType.makeNullableAsSpecified(true))
}
val componentType = transformJavaType(javaComponentType,
COMMON.toAttributes(attr.isForAnnotationParameter))
val componentType = transformJavaType(javaComponentType,
COMMON.toAttributes(attr.isForAnnotationParameter))
if (attr.isForAnnotationParameter) {
val projectionKind = if (isVararg) OUT_VARIANCE else INVARIANT
return@run c.module.builtIns.getArrayType(projectionKind, componentType)
}
if (attr.isForAnnotationParameter) {
val projectionKind = if (isVararg) OUT_VARIANCE else INVARIANT
return c.module.builtIns.getArrayType(projectionKind, componentType)
}
KotlinTypeFactory.flexibleType(
c.module.builtIns.getArrayType(INVARIANT, componentType),
c.module.builtIns.getArrayType(OUT_VARIANCE, componentType).makeNullableAsSpecified(true)
)
}.replaceAnnotations(attr.typeAnnotations)
return KotlinTypeFactory.flexibleType(
c.module.builtIns.getArrayType(INVARIANT, componentType),
c.module.builtIns.getArrayType(OUT_VARIANCE, componentType).makeNullableAsSpecified(true)
)
}
private fun transformJavaClassifierType(javaType: JavaClassifierType, attr: JavaTypeAttributes): KotlinType {
@@ -113,7 +105,7 @@ class JavaTypeResolver(
}
private fun computeSimpleJavaClassifierType(javaType: JavaClassifierType, attr: JavaTypeAttributes): SimpleType? {
val annotations = CompositeAnnotations(listOf(LazyJavaAnnotations(c, javaType), attr.typeAnnotations))
val annotations = LazyJavaAnnotations(c, javaType)
val constructor = computeTypeConstructor(javaType, attr) ?: return null
val arguments = computeArguments(javaType, attr, constructor)
val isNullable = attr.isNullable()
@@ -294,7 +286,6 @@ interface JavaTypeAttributes {
val howThisTypeIsUsed: TypeUsage
val flexibility: JavaTypeFlexibility
get() = INFLEXIBLE
val typeAnnotations: Annotations
val isForAnnotationParameter: Boolean
get() = false
// Current type is upper bound of this type parameter
@@ -310,15 +301,8 @@ enum class JavaTypeFlexibility {
class LazyJavaTypeAttributes(
override val howThisTypeIsUsed: TypeUsage,
annotations: Annotations,
override val isForAnnotationParameter: Boolean = false,
private val annotationTypeQualifierResolver: AnnotationTypeQualifierResolver,
private val moduleDescriptor: ModuleDescriptor
): JavaTypeAttributes {
override val typeAnnotations = FilteredAnnotations(annotations) {
it in ANNOTATIONS_COPIED_TO_TYPES || annotationTypeQualifierResolver.isTypeQualifier(moduleDescriptor, it)
}
}
override val isForAnnotationParameter: Boolean = false
): JavaTypeAttributes
fun TypeUsage.toAttributes(
isForAnnotationParameter: Boolean = false,
@@ -326,8 +310,6 @@ fun TypeUsage.toAttributes(
) = object : JavaTypeAttributes {
override val howThisTypeIsUsed: TypeUsage = this@toAttributes
override val typeAnnotations: Annotations = Annotations.EMPTY
override val isForAnnotationParameter: Boolean = isForAnnotationParameter
override val upperBoundOfTypeParameter: TypeParameterDescriptor? = upperBoundForTypeParameter
}
@@ -18,7 +18,9 @@ package org.jetbrains.kotlin.load.java.typeEnhancement
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.annotations.composeAnnotations
import org.jetbrains.kotlin.load.java.*
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
@@ -54,7 +56,7 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
val receiverTypeEnhancement =
if (extensionReceiverParameter != null)
parts(isCovariant = false) { it.extensionReceiverParameter!!.type }.enhance()
parts(typeContainer = null, isCovariant = false) { it.extensionReceiverParameter!!.type }.enhance()
else null
@@ -72,11 +74,12 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
val valueParameterEnhancements = valueParameters.map {
p ->
parts(isCovariant = false) { it.valueParameters[p.index].type }
parts(typeContainer = p, isCovariant = false) { it.valueParameters[p.index].type }
.enhance(predefinedEnhancementInfo?.parametersInfo?.getOrNull(p.index))
}
val returnTypeEnhancement = parts(isCovariant = true) { it.returnType!! }.enhance(predefinedEnhancementInfo?.returnTypeInfo)
val returnTypeEnhancement =
parts(typeContainer = this, isCovariant = true) { it.returnType!! }.enhance(predefinedEnhancementInfo?.returnTypeInfo)
if ((receiverTypeEnhancement?.wereChanges ?: false)
|| returnTypeEnhancement.wereChanges || valueParameterEnhancements.any { it.wereChanges }) {
@@ -88,6 +91,7 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
}
private inner class SignatureParts(
private val typeContainer: Annotated?,
private val fromOverride: KotlinType,
private val fromOverridden: Collection<KotlinType>,
private val isCovariant: Boolean
@@ -129,12 +133,19 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
isNotNullTypeParameter = unwrap() is NotNullTypeParameter)
}
private fun KotlinType.extractQualifiersFromAnnotations(): JavaTypeQualifiers {
fun <T: Any> List<FqName>.ifPresent(qualifier: T) = if (any { annotations.findAnnotation(it) != null}) qualifier else null
private fun KotlinType.extractQualifiersFromAnnotations(isHeadTypeConstructor: Boolean): JavaTypeQualifiers {
val composedAnnotation =
if (isHeadTypeConstructor && typeContainer != null)
composeAnnotations(typeContainer.annotations, annotations)
else
annotations
fun <T: Any> List<FqName>.ifPresent(qualifier: T) =
if (any { composedAnnotation.findAnnotation(it) != null }) qualifier else null
fun <T: Any> uniqueNotNull(x: T?, y: T?) = if (x == null || y == null || x == y) x ?: y else null
val nullability = annotations.extractNullability()
val nullability = composedAnnotation.extractNullability()
return JavaTypeQualifiers(
nullability,
@@ -213,17 +224,20 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
val verticalSlice = indexedFromSupertypes.mapNotNull { it.getOrNull(index) }
// Only the head type constructor is safely co-variant
qualifiers.computeQualifiersForOverride(verticalSlice, isCovariant && isHeadTypeConstructor)
qualifiers.computeQualifiersForOverride(verticalSlice, isCovariant && isHeadTypeConstructor, isHeadTypeConstructor)
}
return { index -> computedResult.getOrElse(index) { JavaTypeQualifiers.NONE } }
}
private fun KotlinType.computeQualifiersForOverride(fromSupertypes: Collection<KotlinType>, isCovariant: Boolean): JavaTypeQualifiers {
private fun KotlinType.computeQualifiersForOverride(
fromSupertypes: Collection<KotlinType>, isCovariant: Boolean,
isHeadTypeConstructor: Boolean
): JavaTypeQualifiers {
val nullabilityFromSupertypes = fromSupertypes.mapNotNull { it.extractQualifiers().nullability }.toSet()
val mutabilityFromSupertypes = fromSupertypes.mapNotNull { it.extractQualifiers().mutability }.toSet()
val own = extractQualifiersFromAnnotations()
val own = extractQualifiersFromAnnotations(isHeadTypeConstructor)
val isAnyNonNullTypeParameter = own.isNotNullTypeParameter || fromSupertypes.any { it.extractQualifiers().isNotNullTypeParameter }
@@ -268,8 +282,13 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
private data class PartEnhancementResult(val type: KotlinType, val wereChanges: Boolean)
private fun <D : CallableMemberDescriptor> D.parts(isCovariant: Boolean, collector: (D) -> KotlinType): SignatureParts {
private fun <D : CallableMemberDescriptor> D.parts(
typeContainer: Annotated?,
isCovariant: Boolean,
collector: (D) -> KotlinType
): SignatureParts {
return SignatureParts(
typeContainer,
collector(this),
this.overriddenDescriptors.map {
@Suppress("UNCHECKED_CAST")