Further simplify Java annotation resolution

Filter annotations by FQ name, get rid of unneeded properties, lazy values,
static import some stuff
This commit is contained in:
Alexander Udalov
2015-04-13 16:11:35 +03:00
parent d7c810a4d0
commit 2271ca1e81
3 changed files with 38 additions and 27 deletions
@@ -21,10 +21,11 @@ import org.jetbrains.kotlin.load.java.lazy.descriptors.resolveAnnotation
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
class LazyJavaAnnotations( class LazyJavaAnnotations(
private val c: LazyJavaResolverContext, private val c: LazyJavaResolverContext,
val annotationOwner: JavaAnnotationOwner private val annotationOwner: JavaAnnotationOwner
) : Annotations { ) : Annotations {
private val annotationDescriptors = c.storageManager.createMemoizedFunctionWithNullableValues { private val annotationDescriptors = c.storageManager.createMemoizedFunctionWithNullableValues {
annotation: JavaAnnotation -> annotation: JavaAnnotation ->
@@ -38,5 +39,25 @@ class LazyJavaAnnotations(
override fun isEmpty() = !iterator().hasNext() override fun isEmpty() = !iterator().hasNext()
} }
class FilteredAnnotations(
private val delegate: Annotations,
private val fqNameFilter: (FqName) -> Boolean
) : Annotations {
override fun findAnnotation(fqName: FqName) =
if (fqNameFilter(fqName)) delegate.findAnnotation(fqName)
else null
override fun iterator() = delegate.sequence()
.filter { annotation ->
val descriptor = annotation.getType().getConstructor().getDeclarationDescriptor()
descriptor != null && DescriptorUtils.getFqName(descriptor).let { fqName ->
fqName.isSafe() && fqNameFilter(fqName.toSafe())
}
}
.iterator()
override fun isEmpty() = !iterator().hasNext()
}
fun LazyJavaResolverContext.resolveAnnotations(annotationsOwner: JavaAnnotationOwner): Annotations fun LazyJavaResolverContext.resolveAnnotations(annotationsOwner: JavaAnnotationOwner): Annotations
= LazyJavaAnnotations(this, annotationsOwner) = LazyJavaAnnotations(this, annotationsOwner)
@@ -149,7 +149,7 @@ public abstract class LazyJavaMemberScope(
protected fun computeMethodReturnType(method: JavaMethod, annotations: Annotations, c: LazyJavaResolverContext): JetType { protected fun computeMethodReturnType(method: JavaMethod, annotations: Annotations, c: LazyJavaResolverContext): JetType {
val annotationMethod = method.getContainingClass().isAnnotationType() val annotationMethod = method.getContainingClass().isAnnotationType()
val returnTypeAttrs = LazyJavaTypeAttributes( val returnTypeAttrs = LazyJavaTypeAttributes(
c, method, TypeUsage.MEMBER_SIGNATURE_COVARIANT, annotations, TypeUsage.MEMBER_SIGNATURE_COVARIANT, annotations,
allowFlexible = !annotationMethod, allowFlexible = !annotationMethod,
isForAnnotationParameter = annotationMethod isForAnnotationParameter = annotationMethod
) )
@@ -172,7 +172,7 @@ public abstract class LazyJavaMemberScope(
val (index, javaParameter) = pair val (index, javaParameter) = pair
val annotations = c.resolveAnnotations(javaParameter) val annotations = c.resolveAnnotations(javaParameter)
val typeUsage = LazyJavaTypeAttributes(c, javaParameter, TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT, annotations) val typeUsage = LazyJavaTypeAttributes(TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT, annotations)
val (outType, varargElementType) = val (outType, varargElementType) =
if (javaParameter.isVararg()) { if (javaParameter.isVararg()) {
val paramType = javaParameter.getType() as? JavaArrayType val paramType = javaParameter.getType() as? JavaArrayType
@@ -282,7 +282,7 @@ public abstract class LazyJavaMemberScope(
val allowFlexible = PLATFORM_TYPES && !(finalStatic && c.javaPropertyInitializerEvaluator.isNotNullCompileTimeConstant(field)) val allowFlexible = PLATFORM_TYPES && !(finalStatic && c.javaPropertyInitializerEvaluator.isNotNullCompileTimeConstant(field))
val propertyType = c.typeResolver.transformJavaType( val propertyType = c.typeResolver.transformJavaType(
field.getType(), field.getType(),
LazyJavaTypeAttributes(c, field, TypeUsage.MEMBER_SIGNATURE_INVARIANT, annotations, allowFlexible) LazyJavaTypeAttributes(TypeUsage.MEMBER_SIGNATURE_INVARIANT, annotations, allowFlexible)
) )
if ((!allowFlexible || !PLATFORM_TYPES) && finalStatic) { if ((!allowFlexible || !PLATFORM_TYPES) && finalStatic) {
return TypeUtils.makeNotNullable(propertyType) return TypeUtils.makeNotNullable(propertyType)
@@ -20,10 +20,10 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl import org.jetbrains.kotlin.load.java.JvmAnnotationNames.*
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.components.TypeUsage import org.jetbrains.kotlin.load.java.components.TypeUsage
import org.jetbrains.kotlin.load.java.components.TypeUsage.* import org.jetbrains.kotlin.load.java.components.TypeUsage.*
import org.jetbrains.kotlin.load.java.lazy.FilteredAnnotations
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
import org.jetbrains.kotlin.load.java.lazy.TypeParameterResolver import org.jetbrains.kotlin.load.java.lazy.TypeParameterResolver
import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeFlexibility.FLEXIBLE_LOWER_BOUND import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeFlexibility.FLEXIBLE_LOWER_BOUND
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.resolve.jvm.PLATFORM_TYPES import org.jetbrains.kotlin.resolve.jvm.PLATFORM_TYPES
import org.jetbrains.kotlin.resolve.scopes.JetScope import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.storage.get
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.Variance.INVARIANT import org.jetbrains.kotlin.types.Variance.INVARIANT
import org.jetbrains.kotlin.types.Variance.IN_VARIANCE import org.jetbrains.kotlin.types.Variance.IN_VARIANCE
@@ -364,35 +363,26 @@ enum class JavaTypeFlexibility {
} }
class LazyJavaTypeAttributes( class LazyJavaTypeAttributes(
c: LazyJavaResolverContext,
val annotationOwner: JavaAnnotationOwner,
override val howThisTypeIsUsed: TypeUsage, override val howThisTypeIsUsed: TypeUsage,
annotations: Annotations, annotations: Annotations,
override val allowFlexible: Boolean = true, override val allowFlexible: Boolean = true,
override val isForAnnotationParameter: Boolean = false override val isForAnnotationParameter: Boolean = false
): JavaTypeAttributes { ): JavaTypeAttributes {
override val typeAnnotations: Annotations by c.storageManager.createLazyValue { override val typeAnnotations = FilteredAnnotations(annotations) { it in ANNOTATIONS_COPIED_TO_TYPES }
AnnotationsImpl(JvmAnnotationNames.ANNOTATIONS_COPIED_TO_TYPES.map { fqName ->
annotations.findAnnotation(fqName)
}.filterNotNull())
}
override val howThisTypeIsUsedAccordingToAnnotations: TypeUsage by c.storageManager.createLazyValue { override val howThisTypeIsUsedAccordingToAnnotations: TypeUsage get() =
if (annotations.isMarkedReadOnly() && !annotations.isMarkedMutable()) if (hasAnnotation(JETBRAINS_READONLY_ANNOTATION) && !hasAnnotation(JETBRAINS_MUTABLE_ANNOTATION))
TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT
else else
TypeUsage.MEMBER_SIGNATURE_COVARIANT TypeUsage.MEMBER_SIGNATURE_COVARIANT
}
override val isMarkedNotNull: Boolean by c.storageManager.createLazyValue { override val isMarkedNotNull: Boolean get() = typeAnnotations.isMarkedNotNull()
annotationOwner.findAnnotation(JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION) != null
} private fun hasAnnotation(fqName: FqName) = typeAnnotations.findAnnotation(fqName) != null
} }
private fun Annotations.isMarkedReadOnly() = findAnnotation(JvmAnnotationNames.JETBRAINS_READONLY_ANNOTATION) != null internal fun Annotations.isMarkedNotNull() = findAnnotation(JETBRAINS_NOT_NULL_ANNOTATION) != null
private fun Annotations.isMarkedMutable() = findAnnotation(JvmAnnotationNames.JETBRAINS_MUTABLE_ANNOTATION) != null internal fun Annotations.isMarkedNullable() = findAnnotation(JETBRAINS_NULLABLE_ANNOTATION) != null
internal fun Annotations.isMarkedNotNull() = findAnnotation(JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION) != null
internal fun Annotations.isMarkedNullable() = findAnnotation(JvmAnnotationNames.JETBRAINS_NULLABLE_ANNOTATION) != null
fun TypeUsage.toAttributes(allowFlexible: Boolean = true, isForAnnotationParameter: Boolean = false) = object : JavaTypeAttributes { fun TypeUsage.toAttributes(allowFlexible: Boolean = true, isForAnnotationParameter: Boolean = false) = object : JavaTypeAttributes {
override val howThisTypeIsUsed: TypeUsage = this@toAttributes override val howThisTypeIsUsed: TypeUsage = this@toAttributes