diff --git a/compiler/testData/diagnostics/tests/annotations/options/javaDocumented.txt b/compiler/testData/diagnostics/tests/annotations/options/javaDocumented.txt index 88503712f2e..4520700ffe5 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/javaDocumented.txt +++ b/compiler/testData/diagnostics/tests/annotations/options/javaDocumented.txt @@ -6,7 +6,7 @@ public open class DocumentedAnnotations { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String - java.lang.annotation.Documented() kotlin.annotation.annotation(mustBeDocumented = true) public final class DocAnn : kotlin.Annotation { + kotlin.annotation.MustBeDocumented() public final class DocAnn : kotlin.Annotation { public constructor DocAnn() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int @@ -20,7 +20,7 @@ public open class DocumentedAnnotations { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } - java.lang.annotation.Documented() kotlin.annotation.annotation(mustBeDocumented = true, retention = AnnotationRetention.RUNTIME) public final class RunDocAnn : kotlin.Annotation { + kotlin.annotation.MustBeDocumented() kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final class RunDocAnn : kotlin.Annotation { public constructor RunDocAnn() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int diff --git a/compiler/testData/diagnostics/tests/annotations/options/javaretention.txt b/compiler/testData/diagnostics/tests/annotations/options/javaretention.txt index 945f1dff240..6e348bd3363 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/javaretention.txt +++ b/compiler/testData/diagnostics/tests/annotations/options/javaretention.txt @@ -13,21 +13,21 @@ public open class AnnotationRetentions { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } - kotlin.annotation.annotation(retention = AnnotationRetention.BINARY) public final class BinaryAnnotation : kotlin.Annotation { + kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final class BinaryAnnotation : kotlin.Annotation { public constructor BinaryAnnotation() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } - kotlin.annotation.annotation(retention = AnnotationRetention.RUNTIME) public final class RuntimeAnnotation : kotlin.Annotation { + kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final class RuntimeAnnotation : kotlin.Annotation { public constructor RuntimeAnnotation() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } - kotlin.annotation.annotation(retention = AnnotationRetention.SOURCE) public final class SourceAnnotation : kotlin.Annotation { + kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) public final class SourceAnnotation : kotlin.Annotation { public constructor SourceAnnotation() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int diff --git a/compiler/testData/diagnostics/testsWithJava8/annotations/javaRepeatable.txt b/compiler/testData/diagnostics/testsWithJava8/annotations/javaRepeatable.txt index 09ef9013468..a4703d5b948 100644 --- a/compiler/testData/diagnostics/testsWithJava8/annotations/javaRepeatable.txt +++ b/compiler/testData/diagnostics/testsWithJava8/annotations/javaRepeatable.txt @@ -7,7 +7,7 @@ RepeatableAnnotation() RepeatableAnnotation() internal final class My { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -java.lang.annotation.Repeatable(value = RepeatableAnnotations::class) kotlin.annotation.annotation(repeatable = true) public final class RepeatableAnnotation : kotlin.Annotation { +kotlin.annotation.Repeatable() public final class RepeatableAnnotation : kotlin.Annotation { public constructor RepeatableAnnotation() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int diff --git a/compiler/testData/diagnostics/testsWithJava8/annotations/javaRepeatableRetention.txt b/compiler/testData/diagnostics/testsWithJava8/annotations/javaRepeatableRetention.txt index 0228d156a9c..da9e22cbe12 100644 --- a/compiler/testData/diagnostics/testsWithJava8/annotations/javaRepeatableRetention.txt +++ b/compiler/testData/diagnostics/testsWithJava8/annotations/javaRepeatableRetention.txt @@ -7,7 +7,7 @@ RepeatableAnnotation() RepeatableAnnotation() internal final class My { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -java.lang.annotation.Repeatable(value = RepeatableAnnotations::class) kotlin.annotation.annotation(repeatable = true, retention = AnnotationRetention.RUNTIME) public final class RepeatableAnnotation : kotlin.Annotation { +kotlin.annotation.Repeatable() kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final class RepeatableAnnotation : kotlin.Annotation { public constructor RepeatableAnnotation() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int diff --git a/compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.txt b/compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.txt index 8c2d0f9d99a..c98eb250c12 100644 --- a/compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.txt +++ b/compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.txt @@ -11,7 +11,7 @@ public open class AnnotationRetentions { public/*package*/ constructor BaseClass() } - kotlin.annotation.annotation(retention = AnnotationRetention.BINARY) public final class BinaryAnnotation : kotlin.Annotation { + kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final class BinaryAnnotation : kotlin.Annotation { public constructor BinaryAnnotation() } @@ -19,7 +19,7 @@ public open class AnnotationRetentions { public/*package*/ constructor BinaryClass() } - kotlin.annotation.annotation(retention = AnnotationRetention.RUNTIME) public final class RuntimeAnnotation : kotlin.Annotation { + kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final class RuntimeAnnotation : kotlin.Annotation { public constructor RuntimeAnnotation() } @@ -27,7 +27,7 @@ public open class AnnotationRetentions { public/*package*/ constructor RuntimeClass() } - kotlin.annotation.annotation(retention = AnnotationRetention.SOURCE) public final class SourceAnnotation : kotlin.Annotation { + kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) public final class SourceAnnotation : kotlin.Annotation { public constructor SourceAnnotation() } 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 7f5fa70b7a3..3f41c4e4e30 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 @@ -38,17 +38,20 @@ import java.util.EnumSet public object JavaAnnotationMapper { - private val JAVA_TARGET_FQ_NAME = FqName(javaClass().canonicalName) - private val JAVA_RETENTION_FQ_NAME = FqName(javaClass().canonicalName) - private val JAVA_DEPRECATED_FQ_NAME = FqName(javaClass().canonicalName) - private val JAVA_DOCUMENTED_FQ_NAME = FqName(javaClass().canonicalName) + private val JAVA_TARGET_FQ_NAME = FqName(Target::class.java.canonicalName) + private val JAVA_RETENTION_FQ_NAME = FqName(Retention::class.java.canonicalName) + private val JAVA_DEPRECATED_FQ_NAME = FqName(Deprecated::class.java.canonicalName) + private val JAVA_DOCUMENTED_FQ_NAME = FqName(Documented::class.java.canonicalName) // Java8-specific thing private val JAVA_REPEATABLE_FQ_NAME = FqName("java.lang.annotation.Repeatable") public fun mapOrResolveJavaAnnotation(annotation: JavaAnnotation, c: LazyJavaResolverContext): AnnotationDescriptor? = when (annotation.classId) { ClassId.topLevel(JAVA_TARGET_FQ_NAME) -> JavaTargetAnnotationDescriptor(annotation, c) - ClassId.topLevel(JAVA_RETENTION_FQ_NAME), ClassId.topLevel(JAVA_DEPRECATED_FQ_NAME) -> null + ClassId.topLevel(JAVA_RETENTION_FQ_NAME) -> JavaRetentionAnnotationDescriptor(annotation, c) + ClassId.topLevel(JAVA_REPEATABLE_FQ_NAME) -> JavaAnnotationDescriptor(c, annotation, c.module.builtIns.repeatableAnnotation) + ClassId.topLevel(JAVA_DOCUMENTED_FQ_NAME) -> JavaAnnotationDescriptor(c, annotation, c.module.builtIns.mustBeDocumentedAnnotation) + ClassId.topLevel(JAVA_DEPRECATED_FQ_NAME) -> null else -> c.resolveAnnotation(annotation) } @@ -56,19 +59,6 @@ public object JavaAnnotationMapper { annotationOwner: JavaAnnotationOwner, c: LazyJavaResolverContext ): AnnotationDescriptor? { - if (kotlinName == KotlinBuiltIns.FQ_NAMES.annotation) { - // Construct kotlin.annotation.annotation from Retention & Repeatable - val retentionAnnotation = annotationOwner.findAnnotation(JAVA_RETENTION_FQ_NAME) - val repeatableAnnotation = annotationOwner.findAnnotation(JAVA_REPEATABLE_FQ_NAME) - val documentedAnnotation = annotationOwner.findAnnotation(JAVA_DOCUMENTED_FQ_NAME) - return if (retentionAnnotation != null || repeatableAnnotation != null || documentedAnnotation != null) { - JavaRetentionRepeatableAnnotationDescriptor(retentionAnnotation, repeatableAnnotation != null, - documentedAnnotation != null, c) - } - else { - null - } - } if (kotlinName == KotlinBuiltIns.FQ_NAMES.deprecated) { val javaAnnotation = annotationOwner.findAnnotation(JAVA_DEPRECATED_FQ_NAME) if (javaAnnotation != null || annotationOwner.isDeprecatedInJavaDoc) { @@ -84,17 +74,20 @@ public object JavaAnnotationMapper { // kotlin.annotation.annotation is treated separately private val kotlinToJavaNameMap: Map = - mapOf(KotlinBuiltIns.FQ_NAMES.target to JAVA_TARGET_FQ_NAME) + mapOf(KotlinBuiltIns.FQ_NAMES.target to JAVA_TARGET_FQ_NAME, + KotlinBuiltIns.FQ_NAMES.retention to JAVA_RETENTION_FQ_NAME, + KotlinBuiltIns.FQ_NAMES.repeatable to JAVA_REPEATABLE_FQ_NAME, + KotlinBuiltIns.FQ_NAMES.mustBeDocumented to JAVA_DOCUMENTED_FQ_NAME) public val javaToKotlinNameMap: Map = mapOf(JAVA_TARGET_FQ_NAME to KotlinBuiltIns.FQ_NAMES.target, - JAVA_RETENTION_FQ_NAME to KotlinBuiltIns.FQ_NAMES.annotation, + JAVA_RETENTION_FQ_NAME to KotlinBuiltIns.FQ_NAMES.retention, JAVA_DEPRECATED_FQ_NAME to KotlinBuiltIns.FQ_NAMES.deprecated, - JAVA_REPEATABLE_FQ_NAME to KotlinBuiltIns.FQ_NAMES.annotation, - JAVA_DOCUMENTED_FQ_NAME to KotlinBuiltIns.FQ_NAMES.annotation) + JAVA_REPEATABLE_FQ_NAME to KotlinBuiltIns.FQ_NAMES.repeatable, + JAVA_DOCUMENTED_FQ_NAME to KotlinBuiltIns.FQ_NAMES.mustBeDocumented) } -abstract class AbstractJavaAnnotationDescriptor( +open class JavaAnnotationDescriptor( c: LazyJavaResolverContext, annotation: JavaAnnotation?, private val kotlinAnnotationClassDescriptor: ClassDescriptor @@ -109,12 +102,14 @@ abstract class AbstractJavaAnnotationDescriptor( get() = kotlinAnnotationClassDescriptor.constructors.single().valueParameters protected val firstArgument: JavaAnnotationArgument? = annotation?.arguments?.firstOrNull() + + override fun getAllValueArguments() = emptyMap?>() } class JavaDeprecatedAnnotationDescriptor( annotation: JavaAnnotation?, c: LazyJavaResolverContext -): AbstractJavaAnnotationDescriptor(c, annotation, c.module.builtIns.deprecatedAnnotation) { +): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.deprecatedAnnotation) { private val valueArguments = c.storageManager.createLazyValue { val parameterDescriptor = valueParameters.firstOrNull { @@ -126,41 +121,10 @@ class JavaDeprecatedAnnotationDescriptor( override fun getAllValueArguments() = valueArguments() } -class JavaRetentionRepeatableAnnotationDescriptor( - retentionAnnotation: JavaAnnotation?, - repeatable: Boolean, - documented: Boolean, - c: LazyJavaResolverContext -): AbstractJavaAnnotationDescriptor(c, retentionAnnotation, c.module.builtIns.annotationAnnotation) { - - private val valueArguments = c.storageManager.createLazyValue { - val retentionArgument = when (firstArgument) { - is JavaEnumValueAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaRetentionArgument(firstArgument, c.module.builtIns) - else -> null - } - val retentionParameterDescriptor = valueParameters.first { - it.name == JvmAnnotationNames.RETENTION_ANNOTATION_PARAMETER_NAME - } - val repeatableArgument = if (repeatable) BooleanValue(true, c.module.builtIns) else null - val repeatableParameterDescriptor = valueParameters.first { - it.name == JvmAnnotationNames.REPEATABLE_ANNOTATION_PARAMETER_NAME - } - val documentedArgument = if (documented) BooleanValue(true, c.module.builtIns) else null - val documentedParameterDescriptor = valueParameters.first { - it.name == JvmAnnotationNames.DOCUMENTED_ANNOTATION_PARAMETER_NAME - } - (retentionArgument?.let { mapOf(retentionParameterDescriptor to it) } ?: emptyMap()) + - (repeatableArgument?.let { mapOf(repeatableParameterDescriptor to it) } ?: emptyMap()) + - (documentedArgument?.let { mapOf(documentedParameterDescriptor to it) } ?: emptyMap()) - } - - override fun getAllValueArguments() = valueArguments() -} - class JavaTargetAnnotationDescriptor( annotation: JavaAnnotation, c: LazyJavaResolverContext -): AbstractJavaAnnotationDescriptor(c, annotation, c.module.builtIns.targetAnnotation) { +): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.targetAnnotation) { private val valueArguments = c.storageManager.createLazyValue { val targetArgument = when (firstArgument) { @@ -174,6 +138,22 @@ class JavaTargetAnnotationDescriptor( 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 fun getAllValueArguments() = valueArguments() +} + public object JavaAnnotationTargetMapper { private val targetNameLists = mapOf("PACKAGE" to EnumSet.noneOf(KotlinTarget::class.java), "TYPE" to EnumSet.of(KotlinTarget.CLASSIFIER, KotlinTarget.FILE), diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt index 6f93c1c2c25..83f77a1a8c2 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt @@ -181,14 +181,22 @@ private fun Annotated.isAnnotationPropertyTrue(name: String, defaultValue: Boole return repeatableArgumentValue.value } -public fun Annotated.isRepeatableAnnotation(): Boolean = isAnnotationPropertyTrue("repeatable") +public fun Annotated.isRepeatableAnnotation(): Boolean = + annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.repeatable) != null + // deprecated + || isAnnotationPropertyTrue("repeatable") -public fun Annotated.isDocumentedAnnotation(): Boolean = isAnnotationPropertyTrue("mustBeDocumented") +public fun Annotated.isDocumentedAnnotation(): Boolean = + annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.mustBeDocumented) != null + // deprecated + || isAnnotationPropertyTrue("mustBeDocumented") public fun Annotated.getAnnotationRetention(): KotlinRetention? { - val annotationEntryDescriptor = annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.annotation) ?: return null + val annotationEntryDescriptor = annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.retention) ?: + // deprecated + annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.annotation) ?: return null val retentionArgumentValue = annotationEntryDescriptor.allValueArguments.entrySet().firstOrNull { - "retention" == it.key.name.asString() + it.key.name.asString() in setOf("value", "retention") }?.getValue() as? EnumValue ?: return null return KotlinRetention.valueOf(retentionArgumentValue.value.name.asString()) }