Support TypeQualifierDefault from JSR 305 for nullability qualifiers
#KT-10942 Fixed
This commit is contained in:
+56
@@ -20,12 +20,16 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
private val TYPE_QUALIFIER_NICKNAME_FQNAME = FqName("javax.annotation.meta.TypeQualifierNickname")
|
||||
private val TYPE_QUALIFIER_FQNAME = FqName("javax.annotation.meta.TypeQualifier")
|
||||
private val TYPE_QUALIFIER_DEFAULT_FQNAME = FqName("javax.annotation.meta.TypeQualifierDefault")
|
||||
|
||||
class AnnotationTypeQualifierResolver(storageManager: StorageManager) {
|
||||
private val resolvedNicknames =
|
||||
@@ -49,6 +53,58 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager) {
|
||||
|
||||
return resolveTypeQualifierNickname(annotationClass)
|
||||
}
|
||||
|
||||
enum class QualifierApplicabilityType {
|
||||
METHOD_RETURN_TYPE, VALUE_PARAMETER, FIELD, TYPE_USE
|
||||
}
|
||||
|
||||
class TypeQualifierWithApplicability(
|
||||
private val typeQualifier: AnnotationDescriptor,
|
||||
private val applicability: Int
|
||||
) {
|
||||
private fun isApplicableTo(elementType: QualifierApplicabilityType) = (applicability and (1 shl elementType.ordinal)) != 0
|
||||
|
||||
operator fun component1() = typeQualifier
|
||||
operator fun component2() = QualifierApplicabilityType.values().filter(this::isApplicableTo)
|
||||
}
|
||||
|
||||
fun resolveTypeQualifierDefaultAnnotation(annotationDescriptor: AnnotationDescriptor): TypeQualifierWithApplicability? {
|
||||
val typeQualifierDefaultAnnotatedClass =
|
||||
annotationDescriptor.annotationClass?.takeIf { it.annotations.hasAnnotation(TYPE_QUALIFIER_DEFAULT_FQNAME) }
|
||||
?: return null
|
||||
|
||||
val elementTypesMask =
|
||||
annotationDescriptor.annotationClass!!
|
||||
.annotations.findAnnotation(TYPE_QUALIFIER_DEFAULT_FQNAME)!!
|
||||
.allValueArguments
|
||||
.flatMap { (parameter, argument) ->
|
||||
if (parameter.name == JvmAnnotationNames.DEFAULT_ANNOTATION_MEMBER_NAME)
|
||||
argument.mapConstantToQualifierApplicabilityTypes()
|
||||
else
|
||||
emptyList()
|
||||
}
|
||||
.fold(0) { acc: Int, applicabilityType -> acc or (1 shl applicabilityType.ordinal) }
|
||||
|
||||
val typeQualifier =
|
||||
typeQualifierDefaultAnnotatedClass.annotations.firstNotNullResult(this::resolveTypeQualifierAnnotation)
|
||||
?: return null
|
||||
return TypeQualifierWithApplicability(typeQualifier, elementTypesMask)
|
||||
}
|
||||
|
||||
private fun ConstantValue<*>.mapConstantToQualifierApplicabilityTypes(): List<QualifierApplicabilityType> =
|
||||
when (this) {
|
||||
is ArrayValue -> value.flatMap { it.mapConstantToQualifierApplicabilityTypes() }
|
||||
is EnumValue -> listOfNotNull(
|
||||
when (value.name.identifier) {
|
||||
"METHOD" -> QualifierApplicabilityType.METHOD_RETURN_TYPE
|
||||
"FIELD" -> QualifierApplicabilityType.FIELD
|
||||
"PARAMETER" -> QualifierApplicabilityType.VALUE_PARAMETER
|
||||
"TYPE_USE" -> QualifierApplicabilityType.TYPE_USE
|
||||
else -> null
|
||||
}
|
||||
)
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private val ClassDescriptor.isAnnotatedWithTypeQualifier: Boolean
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ class LazyJavaPackageFragmentProvider(
|
||||
components: JavaResolverComponents
|
||||
) : PackageFragmentProvider {
|
||||
|
||||
private val c = LazyJavaResolverContext(components, TypeParameterResolver.EMPTY)
|
||||
private val c = LazyJavaResolverContext(components, TypeParameterResolver.EMPTY) { null }
|
||||
|
||||
private val packageFragments: MemoizedFunctionToNullable<FqName, LazyJavaPackageFragment> =
|
||||
c.storageManager.createMemoizedFunctionWithNullableValues {
|
||||
|
||||
@@ -17,10 +17,8 @@
|
||||
package org.jetbrains.kotlin.load.java.lazy
|
||||
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackagePartProvider
|
||||
import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.load.java.AnnotationTypeQualifierResolver
|
||||
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
||||
@@ -28,11 +26,14 @@ import org.jetbrains.kotlin.load.java.components.*
|
||||
import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeResolver
|
||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElementFactory
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.JavaTypeQualifiers
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifier
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.SignatureEnhancement
|
||||
import org.jetbrains.kotlin.load.kotlin.DeserializedDescriptorResolver
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import java.util.*
|
||||
|
||||
class JavaResolverComponents(
|
||||
val storageManager: StorageManager,
|
||||
@@ -66,10 +67,33 @@ class JavaResolverComponents(
|
||||
)
|
||||
}
|
||||
|
||||
class LazyJavaResolverContext(
|
||||
val components: JavaResolverComponents,
|
||||
val typeParameterResolver: TypeParameterResolver
|
||||
private typealias QualifierByApplicabilityType = EnumMap<AnnotationTypeQualifierResolver.QualifierApplicabilityType, NullabilityQualifier?>
|
||||
|
||||
class JavaTypeQualifiersByElementType(
|
||||
internal val nullabilityQualifiers: QualifierByApplicabilityType
|
||||
) {
|
||||
operator fun get(
|
||||
applicabilityType: AnnotationTypeQualifierResolver.QualifierApplicabilityType
|
||||
): JavaTypeQualifiers? =
|
||||
(
|
||||
nullabilityQualifiers[applicabilityType]
|
||||
?: nullabilityQualifiers[AnnotationTypeQualifierResolver.QualifierApplicabilityType.TYPE_USE]
|
||||
)?.let { JavaTypeQualifiers(it, null, isNotNullTypeParameter = false) }
|
||||
}
|
||||
|
||||
class LazyJavaResolverContext internal constructor(
|
||||
val components: JavaResolverComponents,
|
||||
val typeParameterResolver: TypeParameterResolver,
|
||||
internal val delegateForDefaultTypeQualifiers: Lazy<JavaTypeQualifiersByElementType?>
|
||||
) {
|
||||
constructor(
|
||||
components: JavaResolverComponents,
|
||||
typeParameterResolver: TypeParameterResolver,
|
||||
typeQualifiersComputation: () -> JavaTypeQualifiersByElementType?
|
||||
) : this(components, typeParameterResolver, lazy(LazyThreadSafetyMode.NONE, typeQualifiersComputation))
|
||||
|
||||
val defaultTypeQualifiers: JavaTypeQualifiersByElementType? by delegateForDefaultTypeQualifiers
|
||||
|
||||
val typeResolver = JavaTypeResolver(this, typeParameterResolver)
|
||||
|
||||
val storageManager: StorageManager
|
||||
@@ -80,14 +104,59 @@ class LazyJavaResolverContext(
|
||||
|
||||
fun LazyJavaResolverContext.child(
|
||||
typeParameterResolver: TypeParameterResolver
|
||||
) = LazyJavaResolverContext(components, typeParameterResolver)
|
||||
) = LazyJavaResolverContext(components, typeParameterResolver, delegateForDefaultTypeQualifiers)
|
||||
|
||||
fun LazyJavaResolverContext.computeNewDefaultTypeQualifiers(
|
||||
additionalAnnotations: Annotations
|
||||
): JavaTypeQualifiersByElementType? {
|
||||
val typeQualifierDefaults =
|
||||
additionalAnnotations.mapNotNull(components.annotationTypeQualifierResolver::resolveTypeQualifierDefaultAnnotation)
|
||||
|
||||
if (typeQualifierDefaults.isEmpty()) return defaultTypeQualifiers
|
||||
|
||||
val nullabilityQualifiers =
|
||||
defaultTypeQualifiers?.nullabilityQualifiers?.let(::QualifierByApplicabilityType)
|
||||
?: QualifierByApplicabilityType(AnnotationTypeQualifierResolver.QualifierApplicabilityType::class.java)
|
||||
|
||||
var wasUpdate = false
|
||||
for ((typeQualifier, applicableTo) in typeQualifierDefaults) {
|
||||
val nullability = components.signatureEnhancement.extractNullability(typeQualifier) ?: continue
|
||||
for (applicabilityType in applicableTo) {
|
||||
nullabilityQualifiers[applicabilityType] = nullability
|
||||
wasUpdate = true
|
||||
}
|
||||
}
|
||||
|
||||
return if (!wasUpdate) defaultTypeQualifiers else JavaTypeQualifiersByElementType(nullabilityQualifiers)
|
||||
}
|
||||
|
||||
fun LazyJavaResolverContext.replaceComponents(
|
||||
components: JavaResolverComponents
|
||||
) = LazyJavaResolverContext(components, typeParameterResolver)
|
||||
) = LazyJavaResolverContext(components, typeParameterResolver, delegateForDefaultTypeQualifiers)
|
||||
|
||||
fun LazyJavaResolverContext.child(
|
||||
private fun LazyJavaResolverContext.child(
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
typeParameterOwner: JavaTypeParameterListOwner?,
|
||||
typeParametersIndexOffset: Int = 0,
|
||||
delegateForTypeQualifiers: Lazy<JavaTypeQualifiersByElementType?>
|
||||
) = LazyJavaResolverContext(
|
||||
components,
|
||||
typeParameterOwner?.let { LazyJavaTypeParameterResolver(this, containingDeclaration, it, typeParametersIndexOffset) }
|
||||
?: typeParameterResolver,
|
||||
delegateForTypeQualifiers
|
||||
)
|
||||
|
||||
fun LazyJavaResolverContext.childForMethod(
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
typeParameterOwner: JavaTypeParameterListOwner,
|
||||
typeParametersIndexOffset: Int = 0
|
||||
) = this.child(LazyJavaTypeParameterResolver(this, containingDeclaration, typeParameterOwner, typeParametersIndexOffset))
|
||||
) = child(containingDeclaration, typeParameterOwner, typeParametersIndexOffset, delegateForDefaultTypeQualifiers)
|
||||
|
||||
fun LazyJavaResolverContext.childForClassOrPackage(
|
||||
containingDeclaration: ClassOrPackageFragmentDescriptor,
|
||||
typeParameterOwner: JavaTypeParameterListOwner? = null,
|
||||
typeParametersIndexOffset: Int = 0
|
||||
) = child(
|
||||
containingDeclaration, typeParameterOwner, typeParametersIndexOffset,
|
||||
lazy(LazyThreadSafetyMode.NONE) { computeNewDefaultTypeQualifiers(containingDeclaration.annotations) }
|
||||
)
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.load.java.components.JavaResolverCache
|
||||
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||
import org.jetbrains.kotlin.load.java.lazy.child
|
||||
import org.jetbrains.kotlin.load.java.lazy.childForClassOrPackage
|
||||
import org.jetbrains.kotlin.load.java.lazy.replaceComponents
|
||||
import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations
|
||||
import org.jetbrains.kotlin.load.java.lazy.types.toAttributes
|
||||
@@ -64,7 +64,7 @@ class LazyJavaClassDescriptor(
|
||||
private val PUBLIC_METHOD_NAMES_IN_OBJECT = setOf("equals", "hashCode", "getClass", "wait", "notify", "notifyAll", "toString")
|
||||
}
|
||||
|
||||
private val c: LazyJavaResolverContext = outerContext.child(this, jClass)
|
||||
private val c: LazyJavaResolverContext = outerContext.childForClassOrPackage(this, jClass)
|
||||
|
||||
init {
|
||||
c.components.javaResolverCache.recordClass(jClass, this)
|
||||
|
||||
+4
-3
@@ -37,7 +37,7 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.copyValueParameters
|
||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||
import org.jetbrains.kotlin.load.java.lazy.child
|
||||
import org.jetbrains.kotlin.load.java.lazy.childForMethod
|
||||
import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations
|
||||
import org.jetbrains.kotlin.load.java.lazy.types.toAttributes
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaArrayType
|
||||
@@ -86,6 +86,7 @@ class LazyJavaClassMemberScope(
|
||||
}
|
||||
|
||||
c.components.signatureEnhancement.enhanceSignatures(
|
||||
c,
|
||||
result.ifEmpty { listOfNotNull(createDefaultConstructor()) }
|
||||
).toList()
|
||||
}
|
||||
@@ -424,7 +425,7 @@ class LazyJavaClassMemberScope(
|
||||
val getter = DescriptorFactory.createDefaultGetter(propertyDescriptor, Annotations.EMPTY)
|
||||
propertyDescriptor.initialize(getter, null)
|
||||
|
||||
val returnType = givenType ?: computeMethodReturnType(method, annotations, c.child(propertyDescriptor, method))
|
||||
val returnType = givenType ?: computeMethodReturnType(method, annotations, c.childForMethod(propertyDescriptor, method))
|
||||
propertyDescriptor.setType(returnType, listOf(), getDispatchReceiverParameter(), null as KotlinType?)
|
||||
getter.initialize(returnType)
|
||||
|
||||
@@ -511,7 +512,7 @@ class LazyJavaClassMemberScope(
|
||||
)
|
||||
|
||||
|
||||
val c = c.child(constructorDescriptor, constructor, typeParametersIndexOffset = classDescriptor.declaredTypeParameters.size)
|
||||
val c = c.childForMethod(constructorDescriptor, constructor, typeParametersIndexOffset = classDescriptor.declaredTypeParameters.size)
|
||||
val valueParameters = resolveValueParameters(c, constructorDescriptor, constructor.valueParameters)
|
||||
val constructorTypeParameters =
|
||||
classDescriptor.declaredTypeParameters +
|
||||
|
||||
+6
-6
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
|
||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||
import org.jetbrains.kotlin.load.java.lazy.childForClassOrPackage
|
||||
import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaPackage
|
||||
@@ -31,9 +32,11 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.storage.getValue
|
||||
|
||||
class LazyJavaPackageFragment(
|
||||
private val c: LazyJavaResolverContext,
|
||||
outerContext: LazyJavaResolverContext,
|
||||
private val jPackage: JavaPackage
|
||||
) : PackageFragmentDescriptorImpl(c.module, jPackage.fqName) {
|
||||
) : PackageFragmentDescriptorImpl(outerContext.module, jPackage.fqName) {
|
||||
private val c = outerContext.childForClassOrPackage(this)
|
||||
|
||||
internal val binaryClasses by c.storageManager.createLazyValue {
|
||||
c.components.packageMapper.findPackageParts(fqName.asString()).mapNotNull { partName ->
|
||||
val classId = ClassId(fqName, Name.identifier(partName))
|
||||
@@ -49,10 +52,7 @@ class LazyJavaPackageFragment(
|
||||
onRecursiveCall = listOf()
|
||||
)
|
||||
|
||||
private val packageAnnotations = c.resolveAnnotations(jPackage)
|
||||
|
||||
// Test only method
|
||||
fun getPackageAnnotations() = packageAnnotations
|
||||
override val annotations = c.resolveAnnotations(jPackage)
|
||||
|
||||
internal fun getSubPackageFqNames(): List<FqName> = subPackages()
|
||||
|
||||
|
||||
+4
-4
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.load.java.components.TypeUsage
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||
import org.jetbrains.kotlin.load.java.lazy.child
|
||||
import org.jetbrains.kotlin.load.java.lazy.childForMethod
|
||||
import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations
|
||||
import org.jetbrains.kotlin.load.java.lazy.types.LazyJavaTypeAttributes
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaArrayType
|
||||
@@ -87,7 +87,7 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS
|
||||
|
||||
computeNonDeclaredFunctions(result, name)
|
||||
|
||||
c.components.signatureEnhancement.enhanceSignatures(result).toList()
|
||||
c.components.signatureEnhancement.enhanceSignatures(c, result).toList()
|
||||
}
|
||||
|
||||
open protected fun JavaMethodDescriptor.isVisibleAsFunction() = true
|
||||
@@ -114,7 +114,7 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS
|
||||
ownerDescriptor, annotations, method.name, c.components.sourceElementFactory.source(method)
|
||||
)
|
||||
|
||||
val c = c.child(functionDescriptorImpl, method)
|
||||
val c = c.childForMethod(functionDescriptorImpl, method)
|
||||
|
||||
val methodTypeParameters = method.typeParameters.map { p -> c.typeParameterResolver.resolveTypeParameter(p)!! }
|
||||
val valueParameters = resolveValueParameters(c, functionDescriptorImpl, method.valueParameters)
|
||||
@@ -246,7 +246,7 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS
|
||||
if (DescriptorUtils.isAnnotationClass(ownerDescriptor))
|
||||
properties.toList()
|
||||
else
|
||||
c.components.signatureEnhancement.enhanceSignatures(properties).toList()
|
||||
c.components.signatureEnhancement.enhanceSignatures(c, properties).toList()
|
||||
}
|
||||
|
||||
private fun resolveProperty(field: JavaField): PropertyDescriptor {
|
||||
|
||||
+64
-31
@@ -19,12 +19,17 @@ package org.jetbrains.kotlin.load.java.typeEnhancement
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
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
|
||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||
import org.jetbrains.kotlin.load.java.lazy.computeNewDefaultTypeQualifiers
|
||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.isJavaField
|
||||
import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
|
||||
import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -36,17 +41,40 @@ import org.jetbrains.kotlin.types.asFlexibleType
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.isFlexible
|
||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.util.*
|
||||
|
||||
class SignatureEnhancement(private val annotationTypeQualifierResolver: AnnotationTypeQualifierResolver) {
|
||||
fun <D : CallableMemberDescriptor> enhanceSignatures(platformSignatures: Collection<D>): Collection<D> {
|
||||
|
||||
fun extractNullability(annotationDescriptor: AnnotationDescriptor): NullabilityQualifier? {
|
||||
when (annotationDescriptor.annotationClass?.fqNameSafe) {
|
||||
in NULLABLE_ANNOTATIONS -> return NullabilityQualifier.NULLABLE
|
||||
in NOT_NULL_ANNOTATIONS -> return NullabilityQualifier.NOT_NULL
|
||||
}
|
||||
|
||||
val typeQualifier =
|
||||
annotationTypeQualifierResolver
|
||||
.resolveTypeQualifierAnnotation(annotationDescriptor)
|
||||
?.takeIf { it.annotationClass?.fqNameSafe == JAVAX_NONNULL_ANNOTATION }
|
||||
?: return null
|
||||
|
||||
return typeQualifier.allValueArguments.values.singleOrNull()?.value?.let {
|
||||
enumEntryDescriptor ->
|
||||
if (enumEntryDescriptor !is ClassDescriptor) return@let null
|
||||
if (enumEntryDescriptor.name.asString() == "ALWAYS") NullabilityQualifier.NOT_NULL else NullabilityQualifier.NULLABLE
|
||||
} ?: NullabilityQualifier.NOT_NULL
|
||||
}
|
||||
|
||||
|
||||
fun <D : CallableMemberDescriptor> enhanceSignatures(c: LazyJavaResolverContext, platformSignatures: Collection<D>): Collection<D> {
|
||||
return platformSignatures.map {
|
||||
it.enhanceSignature()
|
||||
it.enhanceSignature(c)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <D : CallableMemberDescriptor> D.enhanceSignature(): D {
|
||||
private fun <D : CallableMemberDescriptor> D.enhanceSignature(c: LazyJavaResolverContext): D {
|
||||
val outerScopeQualifiers = c.computeNewDefaultTypeQualifiers(annotations)
|
||||
// TODO type parameters
|
||||
// TODO use new type parameters while enhancing other types
|
||||
// TODO Propagation into generic type arguments
|
||||
@@ -62,7 +90,10 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
typeContainer =
|
||||
this.safeAs<FunctionDescriptor>()
|
||||
?.getUserData(JavaMethodDescriptor.ORIGINAL_VALUE_PARAMETER_FOR_EXTENSION_RECEIVER),
|
||||
isCovariant = false
|
||||
isCovariant = false,
|
||||
defaultTopLevelQualifiers =
|
||||
outerScopeQualifiers
|
||||
?.get(AnnotationTypeQualifierResolver.QualifierApplicabilityType.VALUE_PARAMETER)
|
||||
) { it.extensionReceiverParameter!!.type }.enhance()
|
||||
else null
|
||||
|
||||
@@ -81,12 +112,28 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
|
||||
val valueParameterEnhancements = valueParameters.map {
|
||||
p ->
|
||||
parts(typeContainer = p, isCovariant = false) { it.valueParameters[p.index].type }
|
||||
parts(
|
||||
typeContainer = p, isCovariant = false,
|
||||
defaultTopLevelQualifiers =
|
||||
outerScopeQualifiers
|
||||
?.get(AnnotationTypeQualifierResolver.QualifierApplicabilityType.VALUE_PARAMETER)
|
||||
) { it.valueParameters[p.index].type }
|
||||
.enhance(predefinedEnhancementInfo?.parametersInfo?.getOrNull(p.index))
|
||||
}
|
||||
|
||||
val returnTypeEnhancement =
|
||||
parts(typeContainer = this, isCovariant = true) { it.returnType!! }.enhance(predefinedEnhancementInfo?.returnTypeInfo)
|
||||
parts(
|
||||
typeContainer = this, isCovariant = true,
|
||||
defaultTopLevelQualifiers =
|
||||
outerScopeQualifiers?.get(
|
||||
if (this.safeAs<PropertyDescriptor>()?.isJavaField == true)
|
||||
AnnotationTypeQualifierResolver.QualifierApplicabilityType.FIELD
|
||||
else
|
||||
AnnotationTypeQualifierResolver.QualifierApplicabilityType.METHOD_RETURN_TYPE
|
||||
)
|
||||
|
||||
|
||||
) { it.returnType!! }.enhance(predefinedEnhancementInfo?.returnTypeInfo)
|
||||
|
||||
if ((receiverTypeEnhancement?.wereChanges ?: false)
|
||||
|| returnTypeEnhancement.wereChanges || valueParameterEnhancements.any { it.wereChanges }) {
|
||||
@@ -101,7 +148,8 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
private val typeContainer: Annotated?,
|
||||
private val fromOverride: KotlinType,
|
||||
private val fromOverridden: Collection<KotlinType>,
|
||||
private val isCovariant: Boolean
|
||||
private val isCovariant: Boolean,
|
||||
private val defaultTopLevelQualifiers: JavaTypeQualifiers?
|
||||
) {
|
||||
fun enhance(predefined: TypeEnhancementInfo? = null): PartEnhancementResult {
|
||||
val qualifiers = computeIndexedQualifiersForOverride()
|
||||
@@ -152,7 +200,10 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
|
||||
fun <T: Any> uniqueNotNull(x: T?, y: T?) = if (x == null || y == null || x == y) x ?: y else null
|
||||
|
||||
val nullability = composedAnnotation.extractNullability()
|
||||
val defaultTypeQualifier = defaultTopLevelQualifiers?.takeIf { isHeadTypeConstructor }
|
||||
val nullability =
|
||||
composedAnnotation.extractNullability()
|
||||
?: defaultTypeQualifier?.nullability
|
||||
|
||||
return JavaTypeQualifiers(
|
||||
nullability,
|
||||
@@ -168,28 +219,8 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
)
|
||||
}
|
||||
|
||||
private fun Annotations.extractNullability(): NullabilityQualifier? {
|
||||
for (annotationDescriptor in this) {
|
||||
when (annotationDescriptor.annotationClass?.fqNameSafe) {
|
||||
in NULLABLE_ANNOTATIONS -> return NullabilityQualifier.NULLABLE
|
||||
in NOT_NULL_ANNOTATIONS -> return NullabilityQualifier.NOT_NULL
|
||||
}
|
||||
|
||||
val typeQualifier =
|
||||
annotationTypeQualifierResolver
|
||||
.resolveTypeQualifierAnnotation(annotationDescriptor)
|
||||
?.takeIf { it.annotationClass?.fqNameSafe == JAVAX_NONNULL_ANNOTATION }
|
||||
?: continue
|
||||
|
||||
return typeQualifier.allValueArguments.values.singleOrNull()?.value?.let {
|
||||
enumEntryDescriptor ->
|
||||
if (enumEntryDescriptor !is ClassDescriptor) return@let null
|
||||
if (enumEntryDescriptor.name.asString() == "ALWAYS") NullabilityQualifier.NOT_NULL else NullabilityQualifier.NULLABLE
|
||||
} ?: NullabilityQualifier.NOT_NULL
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
private fun Annotations.extractNullability(): NullabilityQualifier? =
|
||||
this.firstNotNullResult(this@SignatureEnhancement::extractNullability)
|
||||
|
||||
private fun computeIndexedQualifiersForOverride(): (Int) -> JavaTypeQualifiers {
|
||||
fun KotlinType.toIndexed(): List<KotlinType> {
|
||||
@@ -292,6 +323,7 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
private fun <D : CallableMemberDescriptor> D.parts(
|
||||
typeContainer: Annotated?,
|
||||
isCovariant: Boolean,
|
||||
defaultTopLevelQualifiers: JavaTypeQualifiers?,
|
||||
collector: (D) -> KotlinType
|
||||
): SignatureParts {
|
||||
return SignatureParts(
|
||||
@@ -301,7 +333,8 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
collector(it as D)
|
||||
},
|
||||
isCovariant
|
||||
isCovariant,
|
||||
defaultTopLevelQualifiers
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user