From c2480d1183df186c291405c3e81ad3b10de7189e Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 20 Jul 2015 16:09:43 +0300 Subject: [PATCH] Java to Kotlin annotation retention mapping + new test + JvmLoader test adaptation --- .../kotlin/codegen/AnnotationCodegen.java | 26 +++---- .../annotations/JavaAnnotationConstructors.kt | 4 +- .../annotations/options/javaretention.kt | 35 +++++++++ .../annotations/options/javaretention.txt | 64 ++++++++++++++++ .../annotations/AnnotationRetentions.java | 43 +++++++++++ .../annotations/AnnotationRetentions.txt | 37 ++++++++++ .../checkers/JetDiagnosticsTestGenerated.java | 6 ++ .../jvm/compiler/LoadJavaTestGenerated.java | 6 ++ ...mRuntimeDescriptorLoaderTestGenerated.java | 6 ++ .../kotlin/load/java/JvmAnnotationNames.java | 1 + .../java/components/JavaAnnotationMapper.kt | 74 +++++++++++++++---- .../kotlin/builtins/KotlinBuiltIns.java | 30 ++++++-- .../annotations/AnnotationRetention.kt | 23 ++++++ 13 files changed, 316 insertions(+), 39 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/annotations/options/javaretention.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/options/javaretention.txt create mode 100644 compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.java create mode 100644 compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.txt create mode 100644 core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationRetention.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index 3f25b4e3422..815d0479def 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -21,10 +21,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.descriptors.*; -import org.jetbrains.kotlin.descriptors.annotations.Annotated; -import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor; -import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.kotlin.descriptors.annotations.AnnotationTarget; +import org.jetbrains.kotlin.descriptors.annotations.*; import org.jetbrains.kotlin.load.java.JvmAnnotationNames; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.resolve.AnnotationTargetChecker; @@ -371,16 +368,13 @@ public abstract class AnnotationCodegen { value.accept(argumentVisitor, null); } - private enum KotlinRetention { - SOURCE(RetentionPolicy.SOURCE), - BINARY(RetentionPolicy.CLASS), - RUNTIME(RetentionPolicy.RUNTIME); + private static final Map annotationRetentionMap = + new EnumMap(AnnotationRetention.class); - final RetentionPolicy mapped; - - KotlinRetention(RetentionPolicy mapped) { - this.mapped = mapped; - } + static { + annotationRetentionMap.put(AnnotationRetention.SOURCE, RetentionPolicy.SOURCE); + annotationRetentionMap.put(AnnotationRetention.BINARY, RetentionPolicy.CLASS); + annotationRetentionMap.put(AnnotationRetention.RUNTIME, RetentionPolicy.RUNTIME); } @Nullable @@ -421,10 +415,8 @@ public abstract class AnnotationCodegen { JetType classObjectType = getClassObjectType(enumEntry); if (classObjectType != null) { if ("kotlin/annotation/AnnotationRetention".equals(typeMapper.mapType(classObjectType).getInternalName())) { - String entryName = enumEntry.getName().asString(); - for (KotlinRetention retention : KotlinRetention.values()) { - if (retention.name().equals(entryName)) return retention.mapped; - } + AnnotationRetention retention = AnnotationRetention.valueOf(enumEntry.getName().asString()); + return annotationRetentionMap.get(retention); } } } diff --git a/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.kt b/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.kt index 460d3c5adf9..98a8f9d9e4e 100644 --- a/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.kt +++ b/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.kt @@ -1,8 +1,8 @@ import java.lang.annotation.* -@java.lang.annotation.Retention(RetentionPolicy.CLASS) +@java.lang.annotation.Retention(RetentionPolicy.CLASS) annotation class my -Retention(RetentionPolicy.RUNTIME) +Retention(RetentionPolicy.RUNTIME) Target(ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR) annotation class my1 \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/options/javaretention.kt b/compiler/testData/diagnostics/tests/annotations/options/javaretention.kt new file mode 100644 index 00000000000..f15b34e170d --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/options/javaretention.kt @@ -0,0 +1,35 @@ +// FILE: AnnotationRetentions.java + +import java.lang.annotation.*; + +public class AnnotationRetentions { + + public @interface BaseAnnotation { + + } + + @Retention(RetentionPolicy.SOURCE) + public @interface SourceAnnotation { + + } + + @Retention(RetentionPolicy.CLASS) + public @interface BinaryAnnotation { + + } + + @Retention(RetentionPolicy.RUNTIME) + public @interface RuntimeAnnotation { + + } +} + +// FILE: AnnotationRetentions.kt + +AnnotationRetentions.BaseAnnotation class BaseClass + +AnnotationRetentions.SourceAnnotation class SourceClass + +AnnotationRetentions.BinaryAnnotation class BinaryClass + +AnnotationRetentions.RuntimeAnnotation class RuntimeClass diff --git a/compiler/testData/diagnostics/tests/annotations/options/javaretention.txt b/compiler/testData/diagnostics/tests/annotations/options/javaretention.txt new file mode 100644 index 00000000000..945f1dff240 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/options/javaretention.txt @@ -0,0 +1,64 @@ +package + +public open class AnnotationRetentions { + public constructor AnnotationRetentions() + 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 + + public final class BaseAnnotation : kotlin.Annotation { + public constructor BaseAnnotation() + 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.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 { + 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 { + 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 + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +AnnotationRetentions.BaseAnnotation() internal final class BaseClass { + public constructor BaseClass() + 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 +} + +AnnotationRetentions.BinaryAnnotation() internal final class BinaryClass { + public constructor BinaryClass() + 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 +} + +AnnotationRetentions.RuntimeAnnotation() internal final class RuntimeClass { + public constructor RuntimeClass() + 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 +} + +AnnotationRetentions.SourceAnnotation() internal final class SourceClass { + public constructor SourceClass() + 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 +} diff --git a/compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.java b/compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.java new file mode 100644 index 00000000000..4cd708aca38 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.java @@ -0,0 +1,43 @@ +// SKIP_IN_RUNTIME_TEST + +package test; + +import java.lang.annotation.*; + +public class AnnotationRetentions { + + public @interface BaseAnnotation { + + } + + @Retention(RetentionPolicy.SOURCE) + public @interface SourceAnnotation { + + } + + @Retention(RetentionPolicy.CLASS) + public @interface BinaryAnnotation { + + } + + @Retention(RetentionPolicy.RUNTIME) + public @interface RuntimeAnnotation { + + } + + @BaseAnnotation class BaseClass { + + } + + @SourceAnnotation class SourceClass { + + } + + @BinaryAnnotation class BinaryClass { + + } + + @RuntimeAnnotation class RuntimeClass { + + } +} \ No newline at end of file diff --git a/compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.txt b/compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.txt new file mode 100644 index 00000000000..8c2d0f9d99a --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.txt @@ -0,0 +1,37 @@ +package test + +public open class AnnotationRetentions { + public constructor AnnotationRetentions() + + public final class BaseAnnotation : kotlin.Annotation { + public constructor BaseAnnotation() + } + + test.AnnotationRetentions.BaseAnnotation() public/*package*/ open inner class BaseClass { + public/*package*/ constructor BaseClass() + } + + kotlin.annotation.annotation(retention = AnnotationRetention.BINARY) public final class BinaryAnnotation : kotlin.Annotation { + public constructor BinaryAnnotation() + } + + test.AnnotationRetentions.BinaryAnnotation() public/*package*/ open inner class BinaryClass { + public/*package*/ constructor BinaryClass() + } + + kotlin.annotation.annotation(retention = AnnotationRetention.RUNTIME) public final class RuntimeAnnotation : kotlin.Annotation { + public constructor RuntimeAnnotation() + } + + test.AnnotationRetentions.RuntimeAnnotation() public/*package*/ open inner class RuntimeClass { + public/*package*/ constructor RuntimeClass() + } + + kotlin.annotation.annotation(retention = AnnotationRetention.SOURCE) public final class SourceAnnotation : kotlin.Annotation { + public constructor SourceAnnotation() + } + + public/*package*/ open inner class SourceClass { + public/*package*/ constructor SourceClass() + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index ca049caf9b2..3880a5008dc 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -1016,6 +1016,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("javaretention.kt") + public void testJavaretention() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/javaretention.kt"); + doTest(fileName); + } + @TestMetadata("repeatable.kt") public void testRepeatable() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/repeatable.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java index 57b8d005e5e..5f3d8ca1bee 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java @@ -327,6 +327,12 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTestCompiledJava(fileName); } + @TestMetadata("AnnotationRetentions.java") + public void testAnnotationRetentions() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.java"); + doTestCompiledJava(fileName); + } + @TestMetadata("AnnotationTargets.java") public void testAnnotationTargets() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/annotations/AnnotationTargets.java"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java index 538f65a201e..367ba6ae77f 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java @@ -3378,6 +3378,12 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD doTest(fileName); } + @TestMetadata("AnnotationRetentions.java") + public void testAnnotationRetentions() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/annotations/AnnotationRetentions.java"); + doTest(fileName); + } + @TestMetadata("AnnotationTargets.java") public void testAnnotationTargets() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/annotations/AnnotationTargets.java"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java index 8fcb16d049d..05a5a6eae81 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java @@ -39,6 +39,7 @@ public final class JvmAnnotationNames { public static final String DATA_FIELD_NAME = "data"; public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value"); public static final Name TARGET_ANNOTATION_MEMBER_NAME = Name.identifier("allowedTargets"); + public static final Name RETENTION_ANNOTATION_PARAMETER_NAME = Name.identifier("retention"); public static final FqName JETBRAINS_NOT_NULL_ANNOTATION = new FqName("org.jetbrains.annotations.NotNull"); public static final FqName JETBRAINS_NULLABLE_ANNOTATION = new FqName("org.jetbrains.annotations.Nullable"); 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 d643771bee1..2eec87e5677 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 @@ -37,47 +37,79 @@ import org.jetbrains.kotlin.types.JetType import org.jetbrains.kotlin.descriptors.annotations.AnnotationTarget import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.descriptors.annotations.AnnotationRetention import org.jetbrains.kotlin.storage.StorageManager +import java.lang.annotation.Retention import java.lang.annotation.Target import java.util.* -import kotlin.annotation public object JavaAnnotationMapper { - private val targetClassId = ClassId.topLevel(FqName(javaClass().getCanonicalName())) + private val javaTargetFqName = FqName(javaClass().canonicalName) + private val javaRetentionFqName = FqName(javaClass().canonicalName) public fun mapJavaAnnotation(annotation: JavaAnnotation, c: LazyJavaResolverContext): AnnotationDescriptor? = when (annotation.classId) { - targetClassId -> JavaTargetAnnotationDescriptor(annotation, c, c.module.builtIns) + ClassId.topLevel(javaTargetFqName) -> JavaTargetAnnotationDescriptor(annotation, c) + ClassId.topLevel(javaRetentionFqName) -> JavaRetentionAnnotationDescriptor(annotation, c) else -> null } public val kotlinToJavaNameMap: Map = - mapOf(KotlinBuiltIns.FQ_NAMES.target to FqName(javaClass().getCanonicalName())) + mapOf(KotlinBuiltIns.FQ_NAMES.target to javaTargetFqName, + KotlinBuiltIns.FQ_NAMES.annotation to javaRetentionFqName) - public val javaToKotlinNameMap: Map = kotlinToJavaNameMap.map { it.value to it.key }.toMap() + public val javaToKotlinNameMap: Map = + mapOf(javaTargetFqName to KotlinBuiltIns.FQ_NAMES.target, + javaRetentionFqName to KotlinBuiltIns.FQ_NAMES.annotation) } -class JavaTargetAnnotationDescriptor( +abstract class AbstractJavaAnnotationDescriptor( annotation: JavaAnnotation, - c: LazyJavaResolverContext, - val builtIns: KotlinBuiltIns + private val kotlinAnnotationClassDescriptor: ClassDescriptor ): AnnotationDescriptor { + override fun getType() = kotlinAnnotationClassDescriptor.defaultType + + protected val valueParameters: List + get() = kotlinAnnotationClassDescriptor.constructors.single().valueParameters + + protected val firstArgument: JavaAnnotationArgument? = annotation.arguments.firstOrNull() +} + +class JavaRetentionAnnotationDescriptor( + annotation: JavaAnnotation, + c: LazyJavaResolverContext +): AbstractJavaAnnotationDescriptor(annotation, c.module.builtIns.annotationAnnotation) { private val valueArguments = c.storageManager.createLazyValue { - val firstArgument = annotation.arguments.firstOrNull() val targetArgument = when (firstArgument) { - is JavaArrayAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(firstArgument.getElements(), builtIns) - is JavaEnumValueAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(listOf(firstArgument), builtIns) + is JavaEnumValueAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaRetentionArgument(firstArgument, c.module.builtIns) else -> return@createLazyValue emptyMap>() } - val parameterDescriptor = builtIns.targetAnnotation.constructors.firstOrNull()?.valueParameters?.firstOrNull() + val parameterDescriptor = valueParameters.firstOrNull { + it.name == JvmAnnotationNames.RETENTION_ANNOTATION_PARAMETER_NAME + } parameterDescriptor?.let { mapOf(it to targetArgument) } ?: emptyMap() } override fun getAllValueArguments() = valueArguments() +} - override fun getType() = builtIns.targetAnnotation.defaultType +class JavaTargetAnnotationDescriptor( + annotation: JavaAnnotation, + c: LazyJavaResolverContext +): AbstractJavaAnnotationDescriptor(annotation, c.module.builtIns.targetAnnotation) { + + private val valueArguments = 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) + else -> return@createLazyValue emptyMap>() + } + mapOf(valueParameters.single() to targetArgument) + } + + override fun getAllValueArguments() = valueArguments() } public object JavaAnnotationTargetMapper { @@ -101,11 +133,25 @@ public object JavaAnnotationTargetMapper { // Map arguments: java.lang.annotation.Target -> kotlin.annotation.target val kotlinTargets = arguments.filterIsInstance() .flatMap { mapJavaTargetArgumentByName(it.resolve()?.name?.asString()) } - .map { builtIns.getAnnotationTargetEnumEntry(Name.identifier(it.name())) } + .map { builtIns.getAnnotationTargetEnumEntry(it) } .filterNotNull() .map { EnumValue(it) } val parameterDescriptor = DescriptorResolverUtils.getAnnotationParameterByName(JvmAnnotationNames.TARGET_ANNOTATION_MEMBER_NAME, builtIns.targetAnnotation) return ArrayValue(kotlinTargets, parameterDescriptor?.type ?: ErrorUtils.createErrorType("Error: AnnotationTarget[]"), builtIns) } + + private val retentionNameList = mapOf("RUNTIME" to AnnotationRetention.RUNTIME, + "CLASS" to AnnotationRetention.BINARY, + "SOURCE" to AnnotationRetention.SOURCE + ) + + public 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(it) } + } + } + } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java index 4acc58de32d..ea95b2c9552 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java @@ -22,10 +22,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.functions.BuiltInFictitiousFunctionClassFactory; import org.jetbrains.kotlin.descriptors.*; -import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl; -import org.jetbrains.kotlin.descriptors.annotations.Annotations; -import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl; +import org.jetbrains.kotlin.descriptors.annotations.*; import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl; import org.jetbrains.kotlin.name.FqName; @@ -182,6 +179,7 @@ public class KotlinBuiltIns { public final FqName target = annotationName("target"); public final FqName annotation = annotationName("annotation"); public final FqName annotationTarget = annotationName("AnnotationTarget"); + public final FqName annotationRetention = annotationName("AnnotationRetention"); public final FqNameUnsafe kClass = new FqName("kotlin.reflect.KClass").toUnsafe(); @@ -400,11 +398,31 @@ public class KotlinBuiltIns { } @Nullable - public ClassDescriptor getAnnotationTargetEnumEntry(@NotNull Name name) { - ClassifierDescriptor result = getAnnotationTargetEnum().getUnsubstitutedInnerClassesScope().getClassifier(name, UsageLocation.NO_LOCATION); + public ClassDescriptor getAnnotationTargetEnumEntry(@NotNull AnnotationTarget target) { + ClassifierDescriptor result = getAnnotationTargetEnum().getUnsubstitutedInnerClassesScope().getClassifier( + Name.identifier(target.name()), UsageLocation.NO_LOCATION + ); return result instanceof ClassDescriptor ? (ClassDescriptor) result : null; } + @NotNull + public ClassDescriptor getAnnotationRetentionEnum() { + return getAnnotationClassByName(FQ_NAMES.annotationRetention.shortName()); + } + + @Nullable + public ClassDescriptor getAnnotationRetentionEnumEntry(@NotNull AnnotationRetention retention) { + ClassifierDescriptor result = getAnnotationRetentionEnum().getUnsubstitutedInnerClassesScope().getClassifier( + Name.identifier(retention.name()), UsageLocation.NO_LOCATION + ); + return result instanceof ClassDescriptor ? (ClassDescriptor) result : null; + } + + @NotNull + public ClassDescriptor getAnnotationAnnotation() { + return getAnnotationClassByName(FQ_NAMES.annotation.shortName()); + } + @NotNull public ClassDescriptor getString() { return getBuiltInClassByName("String"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationRetention.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationRetention.kt new file mode 100644 index 00000000000..42db1d70591 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationRetention.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.descriptors.annotations + +public enum class AnnotationRetention { + RUNTIME, + BINARY, + SOURCE +} \ No newline at end of file