J2K AnnotationDescriptor, refactor implementations

This commit is contained in:
Alexander Udalov
2017-07-04 14:14:36 +03:00
parent 7ec67505c5
commit 1d64b61a8f
6 changed files with 52 additions and 91 deletions
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.lazy.LazyEntity
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.source.toSourceElement import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.isError
abstract class LazyAnnotationsContext( abstract class LazyAnnotationsContext(
@@ -112,39 +113,27 @@ class LazyAnnotationDescriptor(
c.trace.record(BindingContext.ANNOTATION, annotationEntry, this) c.trace.record(BindingContext.ANNOTATION, annotationEntry, this)
} }
private val type = c.storageManager.createLazyValue { override val type by c.storageManager.createLazyValue {
c.annotationResolver.resolveAnnotationType( c.annotationResolver.resolveAnnotationType(scope, annotationEntry, c.trace)
scope,
annotationEntry,
c.trace
)
} }
private val valueArguments = c.storageManager.createLazyValue { override val source = annotationEntry.toSourceElement()
computeValueArguments()
}
private val source = annotationEntry.toSourceElement() private val scope = if (c.scope.ownerDescriptor is PackageFragmentDescriptor) {
val scope = if (c.scope.ownerDescriptor is PackageFragmentDescriptor) {
LexicalScope.Base(c.scope, FileDescriptorForVisibilityChecks(source, c.scope.ownerDescriptor)) LexicalScope.Base(c.scope, FileDescriptorForVisibilityChecks(source, c.scope.ownerDescriptor))
} }
else { else {
c.scope c.scope
} }
override fun getType() = type() override val allValueArguments by c.storageManager.createLazyValue {
override fun getAllValueArguments() = valueArguments()
private fun computeValueArguments(): Map<ValueParameterDescriptor, ConstantValue<*>> {
val resolutionResults = c.annotationResolver.resolveAnnotationCall(annotationEntry, scope, c.trace) val resolutionResults = c.annotationResolver.resolveAnnotationCall(annotationEntry, scope, c.trace)
AnnotationResolverImpl.checkAnnotationType(annotationEntry, c.trace, resolutionResults) AnnotationResolverImpl.checkAnnotationType(annotationEntry, c.trace, resolutionResults)
if (!resolutionResults.isSingleResult) return mapOf() if (!resolutionResults.isSingleResult) return@createLazyValue emptyMap<ValueParameterDescriptor, ConstantValue<*>>()
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return resolutionResults.resultingCall.valueArguments resolutionResults.resultingCall.valueArguments
.mapValues { val (valueParameter, resolvedArgument) = it .mapValues { val (valueParameter, resolvedArgument) = it
if (resolvedArgument == null) null if (resolvedArgument == null) null
else c.annotationResolver.getAnnotationArgumentValue(c.trace, valueParameter, resolvedArgument) else c.annotationResolver.getAnnotationArgumentValue(c.trace, valueParameter, resolvedArgument)
@@ -152,10 +141,8 @@ class LazyAnnotationDescriptor(
.filterValues { it != null } as Map<ValueParameterDescriptor, ConstantValue<*>> .filterValues { it != null } as Map<ValueParameterDescriptor, ConstantValue<*>>
} }
override fun getSource() = source
override fun forceResolveAllContents() { override fun forceResolveAllContents() {
ForceResolveUtil.forceResolveAllContents(getType()) ForceResolveUtil.forceResolveAllContents(type)
allValueArguments allValueArguments
} }
@@ -33,7 +33,9 @@ import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
import org.jetbrains.kotlin.resolve.constants.EnumValue import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.SimpleType
import java.lang.annotation.Documented import java.lang.annotation.Documented
import java.lang.annotation.Retention import java.lang.annotation.Retention
import java.lang.annotation.Target import java.lang.annotation.Target
@@ -98,41 +100,37 @@ open class JavaAnnotationDescriptor(
annotation: JavaAnnotation?, annotation: JavaAnnotation?,
private val kotlinAnnotationClassDescriptor: ClassDescriptor private val kotlinAnnotationClassDescriptor: ClassDescriptor
): AnnotationDescriptor { ): AnnotationDescriptor {
private val source = annotation?.let { c.components.sourceElementFactory.source(it) } ?: SourceElement.NO_SOURCE override val source: SourceElement = annotation?.let { c.components.sourceElementFactory.source(it) } ?: SourceElement.NO_SOURCE
override fun getType() = kotlinAnnotationClassDescriptor.defaultType override val type: SimpleType get() = kotlinAnnotationClassDescriptor.defaultType
override fun getSource() = source
protected val valueParameters: List<ValueParameterDescriptor> protected val valueParameters: List<ValueParameterDescriptor>
get() = kotlinAnnotationClassDescriptor.constructors.single().valueParameters get() = kotlinAnnotationClassDescriptor.constructors.single().valueParameters
protected val firstArgument: JavaAnnotationArgument? = annotation?.arguments?.firstOrNull() protected val firstArgument: JavaAnnotationArgument? = annotation?.arguments?.firstOrNull()
override fun getAllValueArguments() = emptyMap<ValueParameterDescriptor, ConstantValue<*>?>() override val allValueArguments: Map<ValueParameterDescriptor, ConstantValue<*>> get() = emptyMap()
} }
class JavaDeprecatedAnnotationDescriptor( class JavaDeprecatedAnnotationDescriptor(
annotation: JavaAnnotation?, annotation: JavaAnnotation?,
c: LazyJavaResolverContext c: LazyJavaResolverContext
): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.deprecatedAnnotation) { ): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.deprecatedAnnotation) {
override val allValueArguments: Map<ValueParameterDescriptor, ConstantValue<*>> by c.storageManager.createLazyValue {
private val valueArguments = c.storageManager.createLazyValue {
val parameterDescriptor = valueParameters.firstOrNull { val parameterDescriptor = valueParameters.firstOrNull {
it.name == JavaAnnotationMapper.DEPRECATED_ANNOTATION_MESSAGE it.name == JavaAnnotationMapper.DEPRECATED_ANNOTATION_MESSAGE
} }
parameterDescriptor?.let { mapOf(it to ConstantValueFactory(c.module.builtIns).createConstantValue("Deprecated in Java")) } ?: emptyMap() parameterDescriptor?.let {
mapOf(it to ConstantValueFactory(c.module.builtIns).createStringValue("Deprecated in Java"))
}.orEmpty()
} }
override fun getAllValueArguments() = valueArguments()
} }
class JavaTargetAnnotationDescriptor( class JavaTargetAnnotationDescriptor(
annotation: JavaAnnotation, annotation: JavaAnnotation,
c: LazyJavaResolverContext c: LazyJavaResolverContext
): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.targetAnnotation) { ): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.targetAnnotation) {
override val allValueArguments by c.storageManager.createLazyValue {
private val valueArguments = c.storageManager.createLazyValue {
val targetArgument = when (firstArgument) { val targetArgument = when (firstArgument) {
is JavaArrayAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(firstArgument.getElements(), c.module.builtIns) is JavaArrayAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(firstArgument.getElements(), c.module.builtIns)
is JavaEnumValueAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(listOf(firstArgument), c.module.builtIns) is JavaEnumValueAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(listOf(firstArgument), c.module.builtIns)
@@ -140,24 +138,16 @@ class JavaTargetAnnotationDescriptor(
} }
mapOf(valueParameters.single() to targetArgument) mapOf(valueParameters.single() to targetArgument)
} }
override fun getAllValueArguments() = valueArguments()
} }
class JavaRetentionAnnotationDescriptor( class JavaRetentionAnnotationDescriptor(
annotation: JavaAnnotation, annotation: JavaAnnotation,
c: LazyJavaResolverContext c: LazyJavaResolverContext
): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.retentionAnnotation) { ): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.retentionAnnotation) {
override val allValueArguments by c.storageManager.createLazyValue {
private val valueArguments = c.storageManager.createLazyValue { val retentionArgument = JavaAnnotationTargetMapper.mapJavaRetentionArgument(firstArgument, c.module.builtIns)
val retentionArgument = when (firstArgument) { retentionArgument?.let { mapOf(valueParameters.single() to it) }.orEmpty()
is JavaEnumValueAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaRetentionArgument(firstArgument, c.module.builtIns)
else -> return@createLazyValue emptyMap<ValueParameterDescriptor, ConstantValue<*>>()
}
mapOf(valueParameters.single() to retentionArgument)
} }
override fun getAllValueArguments() = valueArguments()
} }
object JavaAnnotationTargetMapper { object JavaAnnotationTargetMapper {
@@ -177,7 +167,7 @@ object JavaAnnotationTargetMapper {
fun mapJavaTargetArgumentByName(argumentName: String?): Set<KotlinTarget> = targetNameLists[argumentName] ?: emptySet() fun mapJavaTargetArgumentByName(argumentName: String?): Set<KotlinTarget> = targetNameLists[argumentName] ?: emptySet()
fun mapJavaTargetArguments(arguments: List<JavaAnnotationArgument>, builtIns: KotlinBuiltIns): ConstantValue<*>? { internal fun mapJavaTargetArguments(arguments: List<JavaAnnotationArgument>, builtIns: KotlinBuiltIns): ConstantValue<*> {
// Map arguments: java.lang.annotation.Target -> kotlin.annotation.Target // Map arguments: java.lang.annotation.Target -> kotlin.annotation.Target
val kotlinTargets = arguments.filterIsInstance<JavaEnumValueAnnotationArgument>() val kotlinTargets = arguments.filterIsInstance<JavaEnumValueAnnotationArgument>()
.flatMap { mapJavaTargetArgumentByName(it.resolve()?.name?.asString()) } .flatMap { mapJavaTargetArgumentByName(it.resolve()?.name?.asString()) }
@@ -195,11 +185,11 @@ object JavaAnnotationTargetMapper {
"SOURCE" to KotlinRetention.SOURCE "SOURCE" to KotlinRetention.SOURCE
) )
fun mapJavaRetentionArgument(element: JavaAnnotationArgument, builtIns: KotlinBuiltIns): ConstantValue<*>? { internal fun mapJavaRetentionArgument(element: JavaAnnotationArgument?, builtIns: KotlinBuiltIns): ConstantValue<*>? {
// Map argument: java.lang.annotation.Retention -> kotlin.annotation.annotation // Map argument: java.lang.annotation.Retention -> kotlin.annotation.annotation
return (element as? JavaEnumValueAnnotationArgument)?.let { return (element as? JavaEnumValueAnnotationArgument)?.let {
retentionNameList[it.resolve()?.name?.asString()]?.let { retentionNameList[it.resolve()?.name?.asString()]?.let {
(builtIns.getAnnotationRetentionEnumEntry(it) as? ClassDescriptor)?.let(::EnumValue) builtIns.getAnnotationRetentionEnumEntry(it)?.let(::EnumValue)
} }
} }
} }
@@ -37,19 +37,20 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.utils.keysToMapExceptNulls import org.jetbrains.kotlin.utils.keysToMapExceptNulls
class LazyJavaAnnotationDescriptor( class LazyJavaAnnotationDescriptor(
private val c: LazyJavaResolverContext, private val c: LazyJavaResolverContext,
val javaAnnotation: JavaAnnotation private val javaAnnotation: JavaAnnotation
) : AnnotationDescriptor { ) : AnnotationDescriptor {
private val fqName = c.storageManager.createNullableLazyValue { private val fqName = c.storageManager.createNullableLazyValue {
javaAnnotation.classId?.asSingleFqName() javaAnnotation.classId?.asSingleFqName()
} }
private val type = c.storageManager.createLazyValue { override val type by c.storageManager.createLazyValue {
val fqName = fqName() ?: return@createLazyValue ErrorUtils.createErrorType("No fqName: $javaAnnotation") val fqName = fqName() ?: return@createLazyValue ErrorUtils.createErrorType("No fqName: $javaAnnotation")
val annotationClass = JavaToKotlinClassMap.mapJavaToKotlin(fqName, c.module.builtIns) val annotationClass = JavaToKotlinClassMap.mapJavaToKotlin(fqName, c.module.builtIns)
?: javaAnnotation.resolve()?.let { javaClass -> c.components.moduleClassResolver.resolveClass(javaClass) } ?: javaAnnotation.resolve()?.let { javaClass -> c.components.moduleClassResolver.resolveClass(javaClass) }
@@ -57,27 +58,17 @@ class LazyJavaAnnotationDescriptor(
annotationClass.defaultType annotationClass.defaultType
} }
private val source = c.components.sourceElementFactory.source(javaAnnotation) override val source = c.components.sourceElementFactory.source(javaAnnotation)
private val factory = ConstantValueFactory(c.module.builtIns) private val factory = ConstantValueFactory(c.module.builtIns)
override fun getType(): KotlinType = type() override val allValueArguments by c.storageManager.createLazyValue {
val constructors = annotationClass!!.constructors
private val allValueArguments = c.storageManager.createLazyValue { if (constructors.isEmpty()) return@createLazyValue emptyMap<ValueParameterDescriptor, ConstantValue<*>>()
computeValueArguments()
}
override fun getAllValueArguments() = allValueArguments()
override fun getSource() = source
private fun computeValueArguments(): Map<ValueParameterDescriptor, ConstantValue<*>> {
val constructors = getAnnotationClass().constructors
if (constructors.isEmpty()) return mapOf()
val nameToArg = javaAnnotation.arguments.associateBy { it.name } val nameToArg = javaAnnotation.arguments.associateBy { it.name }
return constructors.first().valueParameters.keysToMapExceptNulls { valueParameter -> constructors.first().valueParameters.keysToMapExceptNulls { valueParameter ->
var javaAnnotationArgument = nameToArg[valueParameter.name] var javaAnnotationArgument = nameToArg[valueParameter.name]
if (javaAnnotationArgument == null && valueParameter.name == DEFAULT_ANNOTATION_MEMBER_NAME) { if (javaAnnotationArgument == null && valueParameter.name == DEFAULT_ANNOTATION_MEMBER_NAME) {
javaAnnotationArgument = nameToArg[null] javaAnnotationArgument = nameToArg[null]
@@ -87,8 +78,6 @@ class LazyJavaAnnotationDescriptor(
} }
} }
private fun getAnnotationClass() = annotationClass!!
private fun resolveAnnotationArgument(argument: JavaAnnotationArgument?): ConstantValue<*>? { private fun resolveAnnotationArgument(argument: JavaAnnotationArgument?): ConstantValue<*>? {
return when (argument) { return when (argument) {
is JavaLiteralAnnotationArgument -> factory.createConstantValue(argument.value) is JavaLiteralAnnotationArgument -> factory.createConstantValue(argument.value)
@@ -105,9 +94,9 @@ class LazyJavaAnnotationDescriptor(
} }
private fun resolveFromArray(argumentName: Name, elements: List<JavaAnnotationArgument>): ConstantValue<*>? { private fun resolveFromArray(argumentName: Name, elements: List<JavaAnnotationArgument>): ConstantValue<*>? {
if (getType().isError) return null if (type.isError) return null
val valueParameter = DescriptorResolverUtils.getAnnotationParameterByName(argumentName, getAnnotationClass()) ?: return null val valueParameter = DescriptorResolverUtils.getAnnotationParameterByName(argumentName, annotationClass!!) ?: return null
val values = elements.map { val values = elements.map {
argument -> resolveAnnotationArgument(argument) ?: factory.createNullValue() argument -> resolveAnnotationArgument(argument) ?: factory.createNullValue()
@@ -123,7 +112,7 @@ class LazyJavaAnnotationDescriptor(
val enumClass = c.components.moduleClassResolver.resolveClass(containingJavaClass) ?: return null val enumClass = c.components.moduleClassResolver.resolveClass(containingJavaClass) ?: return null
val classifier = enumClass.unsubstitutedInnerClassesScope.getContributedClassifier(element.name, NoLookupLocation.FROM_JAVA_LOADER) val classifier = enumClass.unsubstitutedInnerClassesScope.getContributedClassifier(element.name, NoLookupLocation.FROM_JAVA_LOADER)
if (classifier !is ClassDescriptor) return null as? ClassDescriptor ?: return null
return factory.createEnumValue(classifier) return factory.createEnumValue(classifier)
} }
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.load.java.typeEnhancement
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -30,6 +32,7 @@ import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifier.NOT_N
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifier.NULLABLE import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifier.NULLABLE
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.createProjection import org.jetbrains.kotlin.types.typeUtil.createProjection
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
@@ -205,9 +208,9 @@ private class EnhancedTypeAnnotations(private val fqNameToMatch: FqName) : Annot
private object EnhancedTypeAnnotationDescriptor : AnnotationDescriptor { private object EnhancedTypeAnnotationDescriptor : AnnotationDescriptor {
private fun throwError(): Nothing = error("No methods should be called on this descriptor. Only its presence matters") private fun throwError(): Nothing = error("No methods should be called on this descriptor. Only its presence matters")
override fun getType() = throwError() override val type: KotlinType get() = throwError()
override fun getAllValueArguments() = throwError() override val allValueArguments: Map<ValueParameterDescriptor, ConstantValue<*>> get() = throwError()
override fun getSource() = throwError() override val source: SourceElement get() = throwError()
override fun toString() = "[EnhancedType]" override fun toString() = "[EnhancedType]"
} }
@@ -14,25 +14,17 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.descriptors.annotations; package org.jetbrains.kotlin.descriptors.annotations
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.annotations.ReadOnly; import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.SourceElement; import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
import org.jetbrains.kotlin.types.KotlinType;
import java.util.Map; interface AnnotationDescriptor {
val type: KotlinType
public interface AnnotationDescriptor { val allValueArguments: Map<ValueParameterDescriptor, ConstantValue<*>>
@NotNull
KotlinType getType();
@NotNull val source: SourceElement
@ReadOnly
Map<ValueParameterDescriptor, ConstantValue<?>> getAllValueArguments();
@NotNull
SourceElement getSource();
} }
@@ -119,7 +119,7 @@ class UnusedSymbolInspection : AbstractKotlinInspection() {
// variation of IDEA's AnnotationUtil.checkAnnotatedUsingPatterns() // variation of IDEA's AnnotationUtil.checkAnnotatedUsingPatterns()
private fun checkAnnotatedUsingPatterns(annotated: Annotated, annotationPatterns: Collection<String>): Boolean { private fun checkAnnotatedUsingPatterns(annotated: Annotated, annotationPatterns: Collection<String>): Boolean {
val annotationsPresent = annotated.annotations val annotationsPresent = annotated.annotations
.map(AnnotationDescriptor::getType) .map(AnnotationDescriptor::type)
.filterNot(KotlinType::isError) .filterNot(KotlinType::isError)
.mapNotNull { it.constructor.declarationDescriptor?.let { descriptor -> .mapNotNull { it.constructor.declarationDescriptor?.let { descriptor ->
DescriptorUtils.getFqName(descriptor).asString() DescriptorUtils.getFqName(descriptor).asString()