From 1d64b61a8f69a7ea669288c85033286edfb0741d Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 4 Jul 2017 14:14:36 +0300 Subject: [PATCH] J2K AnnotationDescriptor, refactor implementations --- .../lazy/descriptors/LazyAnnotations.kt | 31 ++++---------- .../java/components/JavaAnnotationMapper.kt | 42 +++++++------------ .../LazyJavaAnnotationDescriptor.kt | 33 +++++---------- .../java/typeEnhancement/typeEnhancement.kt | 9 ++-- ...escriptor.java => AnnotationDescriptor.kt} | 26 ++++-------- .../inspections/UnusedSymbolInspection.kt | 2 +- 6 files changed, 52 insertions(+), 91 deletions(-) rename core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/{AnnotationDescriptor.java => AnnotationDescriptor.kt} (54%) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt index ad59d3fd215..f67c94ed9e8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.lazy.LazyEntity import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.source.toSourceElement import org.jetbrains.kotlin.storage.StorageManager +import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.types.isError abstract class LazyAnnotationsContext( @@ -112,39 +113,27 @@ class LazyAnnotationDescriptor( c.trace.record(BindingContext.ANNOTATION, annotationEntry, this) } - private val type = c.storageManager.createLazyValue { - c.annotationResolver.resolveAnnotationType( - scope, - annotationEntry, - c.trace - ) + override val type by c.storageManager.createLazyValue { + c.annotationResolver.resolveAnnotationType(scope, annotationEntry, c.trace) } - private val valueArguments = c.storageManager.createLazyValue { - computeValueArguments() - } + override val source = annotationEntry.toSourceElement() - private val source = annotationEntry.toSourceElement() - - val scope = if (c.scope.ownerDescriptor is PackageFragmentDescriptor) { + private val scope = if (c.scope.ownerDescriptor is PackageFragmentDescriptor) { LexicalScope.Base(c.scope, FileDescriptorForVisibilityChecks(source, c.scope.ownerDescriptor)) } else { c.scope } - override fun getType() = type() - - override fun getAllValueArguments() = valueArguments() - - private fun computeValueArguments(): Map> { + override val allValueArguments by c.storageManager.createLazyValue { val resolutionResults = c.annotationResolver.resolveAnnotationCall(annotationEntry, scope, c.trace) AnnotationResolverImpl.checkAnnotationType(annotationEntry, c.trace, resolutionResults) - if (!resolutionResults.isSingleResult) return mapOf() + if (!resolutionResults.isSingleResult) return@createLazyValue emptyMap>() @Suppress("UNCHECKED_CAST") - return resolutionResults.resultingCall.valueArguments + resolutionResults.resultingCall.valueArguments .mapValues { val (valueParameter, resolvedArgument) = it if (resolvedArgument == null) null else c.annotationResolver.getAnnotationArgumentValue(c.trace, valueParameter, resolvedArgument) @@ -152,10 +141,8 @@ class LazyAnnotationDescriptor( .filterValues { it != null } as Map> } - override fun getSource() = source - override fun forceResolveAllContents() { - ForceResolveUtil.forceResolveAllContents(getType()) + ForceResolveUtil.forceResolveAllContents(type) allValueArguments } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/JavaAnnotationMapper.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/JavaAnnotationMapper.kt index 79b18dc0899..9f09d478a5c 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/JavaAnnotationMapper.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/JavaAnnotationMapper.kt @@ -33,7 +33,9 @@ import org.jetbrains.kotlin.resolve.constants.ArrayValue import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory import org.jetbrains.kotlin.resolve.constants.EnumValue +import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.types.ErrorUtils +import org.jetbrains.kotlin.types.SimpleType import java.lang.annotation.Documented import java.lang.annotation.Retention import java.lang.annotation.Target @@ -98,41 +100,37 @@ open class JavaAnnotationDescriptor( annotation: JavaAnnotation?, private val kotlinAnnotationClassDescriptor: ClassDescriptor ): 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 fun getSource() = source + override val type: SimpleType get() = kotlinAnnotationClassDescriptor.defaultType protected val valueParameters: List get() = kotlinAnnotationClassDescriptor.constructors.single().valueParameters protected val firstArgument: JavaAnnotationArgument? = annotation?.arguments?.firstOrNull() - override fun getAllValueArguments() = emptyMap?>() + override val allValueArguments: Map> get() = emptyMap() } class JavaDeprecatedAnnotationDescriptor( annotation: JavaAnnotation?, c: LazyJavaResolverContext ): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.deprecatedAnnotation) { - - private val valueArguments = c.storageManager.createLazyValue { + override val allValueArguments: Map> by c.storageManager.createLazyValue { val parameterDescriptor = valueParameters.firstOrNull { 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( annotation: JavaAnnotation, c: LazyJavaResolverContext ): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.targetAnnotation) { - - private val valueArguments = c.storageManager.createLazyValue { + override val allValueArguments by c.storageManager.createLazyValue { val targetArgument = when (firstArgument) { is JavaArrayAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(firstArgument.getElements(), c.module.builtIns) is JavaEnumValueAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(listOf(firstArgument), c.module.builtIns) @@ -140,24 +138,16 @@ class JavaTargetAnnotationDescriptor( } mapOf(valueParameters.single() to targetArgument) } - - override fun getAllValueArguments() = valueArguments() } class JavaRetentionAnnotationDescriptor( annotation: JavaAnnotation, c: LazyJavaResolverContext ): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.retentionAnnotation) { - - private val valueArguments = c.storageManager.createLazyValue { - val retentionArgument = when (firstArgument) { - is JavaEnumValueAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaRetentionArgument(firstArgument, c.module.builtIns) - else -> return@createLazyValue emptyMap>() - } - mapOf(valueParameters.single() to retentionArgument) + override val allValueArguments by c.storageManager.createLazyValue { + val retentionArgument = JavaAnnotationTargetMapper.mapJavaRetentionArgument(firstArgument, c.module.builtIns) + retentionArgument?.let { mapOf(valueParameters.single() to it) }.orEmpty() } - - override fun getAllValueArguments() = valueArguments() } object JavaAnnotationTargetMapper { @@ -177,7 +167,7 @@ object JavaAnnotationTargetMapper { fun mapJavaTargetArgumentByName(argumentName: String?): Set = targetNameLists[argumentName] ?: emptySet() - fun mapJavaTargetArguments(arguments: List, builtIns: KotlinBuiltIns): ConstantValue<*>? { + internal fun mapJavaTargetArguments(arguments: List, builtIns: KotlinBuiltIns): ConstantValue<*> { // Map arguments: java.lang.annotation.Target -> kotlin.annotation.Target val kotlinTargets = arguments.filterIsInstance() .flatMap { mapJavaTargetArgumentByName(it.resolve()?.name?.asString()) } @@ -195,11 +185,11 @@ object JavaAnnotationTargetMapper { "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 return (element as? JavaEnumValueAnnotationArgument)?.let { retentionNameList[it.resolve()?.name?.asString()]?.let { - (builtIns.getAnnotationRetentionEnumEntry(it) as? ClassDescriptor)?.let(::EnumValue) + builtIns.getAnnotationRetentionEnumEntry(it)?.let(::EnumValue) } } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt index 93be51475b9..8d6833acec6 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt @@ -37,19 +37,20 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass +import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.utils.keysToMapExceptNulls class LazyJavaAnnotationDescriptor( private val c: LazyJavaResolverContext, - val javaAnnotation: JavaAnnotation + private val javaAnnotation: JavaAnnotation ) : AnnotationDescriptor { private val fqName = c.storageManager.createNullableLazyValue { 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 annotationClass = JavaToKotlinClassMap.mapJavaToKotlin(fqName, c.module.builtIns) ?: javaAnnotation.resolve()?.let { javaClass -> c.components.moduleClassResolver.resolveClass(javaClass) } @@ -57,27 +58,17 @@ class LazyJavaAnnotationDescriptor( 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) - override fun getType(): KotlinType = type() - - private val allValueArguments = c.storageManager.createLazyValue { - computeValueArguments() - } - - override fun getAllValueArguments() = allValueArguments() - - override fun getSource() = source - - private fun computeValueArguments(): Map> { - val constructors = getAnnotationClass().constructors - if (constructors.isEmpty()) return mapOf() + override val allValueArguments by c.storageManager.createLazyValue { + val constructors = annotationClass!!.constructors + if (constructors.isEmpty()) return@createLazyValue emptyMap>() val nameToArg = javaAnnotation.arguments.associateBy { it.name } - return constructors.first().valueParameters.keysToMapExceptNulls { valueParameter -> + constructors.first().valueParameters.keysToMapExceptNulls { valueParameter -> var javaAnnotationArgument = nameToArg[valueParameter.name] if (javaAnnotationArgument == null && valueParameter.name == DEFAULT_ANNOTATION_MEMBER_NAME) { javaAnnotationArgument = nameToArg[null] @@ -87,8 +78,6 @@ class LazyJavaAnnotationDescriptor( } } - private fun getAnnotationClass() = annotationClass!! - private fun resolveAnnotationArgument(argument: JavaAnnotationArgument?): ConstantValue<*>? { return when (argument) { is JavaLiteralAnnotationArgument -> factory.createConstantValue(argument.value) @@ -105,9 +94,9 @@ class LazyJavaAnnotationDescriptor( } private fun resolveFromArray(argumentName: Name, elements: List): 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 { argument -> resolveAnnotationArgument(argument) ?: factory.createNullValue() @@ -123,7 +112,7 @@ class LazyJavaAnnotationDescriptor( val enumClass = c.components.moduleClassResolver.resolveClass(containingJavaClass) ?: return null 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) } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/typeEnhancement.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/typeEnhancement.kt index cd14c87a112..cda86430c3d 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/typeEnhancement.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/typeEnhancement.kt @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.load.java.typeEnhancement import org.jetbrains.kotlin.descriptors.ClassDescriptor 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.AnnotationWithTarget 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.name.FqName import org.jetbrains.kotlin.platform.JavaToKotlinClassMap +import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.createProjection import org.jetbrains.kotlin.types.typeUtil.isTypeParameter @@ -205,9 +208,9 @@ private class EnhancedTypeAnnotations(private val fqNameToMatch: FqName) : Annot private object EnhancedTypeAnnotationDescriptor : AnnotationDescriptor { private fun throwError(): Nothing = error("No methods should be called on this descriptor. Only its presence matters") - override fun getType() = throwError() - override fun getAllValueArguments() = throwError() - override fun getSource() = throwError() + override val type: KotlinType get() = throwError() + override val allValueArguments: Map> get() = throwError() + override val source: SourceElement get() = throwError() override fun toString() = "[EnhancedType]" } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationDescriptor.kt similarity index 54% rename from core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationDescriptor.java rename to core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationDescriptor.kt index 1c5d996d564..7635195b5fe 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationDescriptor.kt @@ -14,25 +14,17 @@ * limitations under the License. */ -package org.jetbrains.kotlin.descriptors.annotations; +package org.jetbrains.kotlin.descriptors.annotations -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.ReadOnly; -import org.jetbrains.kotlin.descriptors.SourceElement; -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; -import org.jetbrains.kotlin.resolve.constants.ConstantValue; -import org.jetbrains.kotlin.types.KotlinType; +import org.jetbrains.kotlin.descriptors.SourceElement +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +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 { - @NotNull - KotlinType getType(); + val allValueArguments: Map> - @NotNull - @ReadOnly - Map> getAllValueArguments(); - - @NotNull - SourceElement getSource(); + val source: SourceElement } diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt index 7eccea6d0ea..b5cc48e27a5 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt @@ -119,7 +119,7 @@ class UnusedSymbolInspection : AbstractKotlinInspection() { // variation of IDEA's AnnotationUtil.checkAnnotatedUsingPatterns() private fun checkAnnotatedUsingPatterns(annotated: Annotated, annotationPatterns: Collection): Boolean { val annotationsPresent = annotated.annotations - .map(AnnotationDescriptor::getType) + .map(AnnotationDescriptor::type) .filterNot(KotlinType::isError) .mapNotNull { it.constructor.declarationDescriptor?.let { descriptor -> DescriptorUtils.getFqName(descriptor).asString()