diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index 2f176994840..3f25b4e3422 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -24,8 +24,10 @@ 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.load.java.JvmAnnotationNames; import org.jetbrains.kotlin.name.FqName; +import org.jetbrains.kotlin.resolve.AnnotationTargetChecker; import org.jetbrains.kotlin.resolve.constants.*; import org.jetbrains.kotlin.resolve.constants.StringValue; import org.jetbrains.kotlin.types.Flexibility; @@ -34,8 +36,10 @@ import org.jetbrains.kotlin.types.TypeUtils; import org.jetbrains.kotlin.types.TypesPackage; import org.jetbrains.org.objectweb.asm.*; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.util.*; import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getClassObjectType; @@ -123,6 +127,7 @@ public abstract class AnnotationCodegen { ClassDescriptor classDescriptor = (ClassDescriptor) annotated; if (classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) { generateRetentionAnnotation(classDescriptor, annotationDescriptorsAlreadyPresent); + generateTargetAnnotation(classDescriptor, annotationDescriptorsAlreadyPresent); } } } @@ -166,6 +171,47 @@ public abstract class AnnotationCodegen { generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotationClass); } + private static final Map annotationTargetMap = + new EnumMap(AnnotationTarget.class); + + static { + annotationTargetMap.put(AnnotationTarget.PACKAGE, ElementType.PACKAGE); + annotationTargetMap.put(AnnotationTarget.CLASSIFIER, ElementType.TYPE); + annotationTargetMap.put(AnnotationTarget.ANNOTATION_CLASS, ElementType.ANNOTATION_TYPE); + annotationTargetMap.put(AnnotationTarget.CONSTRUCTOR, ElementType.CONSTRUCTOR); + annotationTargetMap.put(AnnotationTarget.LOCAL_VARIABLE, ElementType.LOCAL_VARIABLE); + annotationTargetMap.put(AnnotationTarget.FUNCTION, ElementType.METHOD); + annotationTargetMap.put(AnnotationTarget.PROPERTY_GETTER, ElementType.METHOD); + annotationTargetMap.put(AnnotationTarget.PROPERTY_SETTER, ElementType.METHOD); + annotationTargetMap.put(AnnotationTarget.FIELD, ElementType.FIELD); + annotationTargetMap.put(AnnotationTarget.VALUE_PARAMETER, ElementType.PARAMETER); + } + + private void generateTargetAnnotation(@NotNull ClassDescriptor classDescriptor, @NotNull Set annotationDescriptorsAlreadyPresent) { + String descriptor = Type.getType(Target.class).getDescriptor(); + if (!annotationDescriptorsAlreadyPresent.add(descriptor)) return; + Set targets = AnnotationTargetChecker.INSTANCE$.possibleTargetSet(classDescriptor); + Set javaTargets; + if (targets == null) { + javaTargets = getJavaTargetList(classDescriptor); + if (javaTargets == null) return; + } + else { + javaTargets = EnumSet.noneOf(ElementType.class); + for (AnnotationTarget target : targets) { + if (annotationTargetMap.get(target) == null) continue; + javaTargets.add(annotationTargetMap.get(target)); + } + } + AnnotationVisitor visitor = visitAnnotation(descriptor, true); + AnnotationVisitor arrayVisitor = visitor.visitArray("value"); + for (ElementType javaTarget : javaTargets) { + arrayVisitor.visitEnum(null, Type.getType(ElementType.class).getDescriptor(), javaTarget.name()); + } + arrayVisitor.visitEnd(); + visitor.visitEnd(); + } + private void generateRetentionAnnotation(@NotNull ClassDescriptor classDescriptor, @NotNull Set annotationDescriptorsAlreadyPresent) { RetentionPolicy policy = getRetentionPolicy(classDescriptor); String descriptor = Type.getType(Retention.class).getDescriptor(); @@ -337,18 +383,46 @@ public abstract class AnnotationCodegen { } } + @Nullable + private Set getJavaTargetList(ClassDescriptor descriptor) { + AnnotationDescriptor targetAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Target.class.getName())); + if (targetAnnotation != null) { + Collection> valueArguments = targetAnnotation.getAllValueArguments().values(); + if (!valueArguments.isEmpty()) { + ConstantValue compileTimeConstant = valueArguments.iterator().next(); + if (compileTimeConstant instanceof ArrayValue) { + List> values = ((ArrayValue) compileTimeConstant).getValue(); + Set result = EnumSet.noneOf(ElementType.class); + for (ConstantValue value : values) { + if (value instanceof EnumValue) { + ClassDescriptor enumEntry = ((EnumValue) value).getValue(); + JetType classObjectType = getClassObjectType(enumEntry); + if (classObjectType != null) { + if ("java/lang/annotation/ElementType".equals(typeMapper.mapType(classObjectType).getInternalName())) { + result.add(ElementType.valueOf(enumEntry.getName().asString())); + } + } + } + } + return result; + } + } + } + return null; + } + @NotNull private RetentionPolicy getRetentionPolicy(@NotNull Annotated descriptor) { AnnotationDescriptor kotlinAnnotation = descriptor.getAnnotations().findAnnotation(KotlinBuiltIns.FQ_NAMES.annotation); if (kotlinAnnotation != null) { - for (Map.Entry> argument: kotlinAnnotation.getAllValueArguments().entrySet()) { + for (Map.Entry> argument : kotlinAnnotation.getAllValueArguments().entrySet()) { if ("retention".equals(argument.getKey().getName().asString()) && argument.getValue() instanceof EnumValue) { ClassDescriptor enumEntry = ((EnumValue) argument.getValue()).getValue(); 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()) { + for (KotlinRetention retention : KotlinRetention.values()) { if (retention.name().equals(entryName)) return retention.mapped; } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationTargetChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationTargetChecker.kt index 889bd290abc..598685f938b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationTargetChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationTargetChecker.kt @@ -27,33 +27,13 @@ import org.jetbrains.kotlin.resolve.constants.ArrayValue import org.jetbrains.kotlin.resolve.constants.EnumValue import org.jetbrains.kotlin.types.JetType import org.jetbrains.kotlin.types.TypeUtils +import java.lang.annotation.ElementType import java.util.* +import org.jetbrains.kotlin.descriptors.annotations.AnnotationTarget +import kotlin.annotation public object AnnotationTargetChecker { - // NOTE: this enum must have the same entries with kotlin.annotation.AnnotationTarget - public enum class Target(val description: String, val isDefault: Boolean = true) { - PACKAGE("package"), - CLASSIFIER("classifier"), - ANNOTATION_CLASS("annotation class"), - TYPE_PARAMETER("type parameter", false), - PROPERTY("property"), - FIELD("field"), - LOCAL_VARIABLE("local variable"), - VALUE_PARAMETER("value parameter"), - CONSTRUCTOR("constructor"), - FUNCTION("function"), - PROPERTY_GETTER("getter"), - PROPERTY_SETTER("setter"), - TYPE("type usage", false), - EXPRESSION("expression", false), - FILE("file", false) - } - - private val DEFAULT_TARGET_LIST = Target.values().filter { it.isDefault }.map { it.name() } - - private val ALL_TARGET_LIST = Target.values().map { it.name() } - public fun check(annotated: JetAnnotated, trace: BindingTrace, descriptor: ClassDescriptor? = null) { if (annotated is JetTypeParameter) return // TODO: support type parameter annotations val actualTargets = getActualTargetList(annotated, descriptor) @@ -82,7 +62,7 @@ public object AnnotationTargetChecker { public fun checkExpression(expression: JetExpression, trace: BindingTrace) { for (entry in expression.getAnnotationEntries()) { - checkAnnotationEntry(entry, listOf(Target.EXPRESSION), trace) + checkAnnotationEntry(entry, listOf(AnnotationTarget.EXPRESSION), trace) } if (expression is JetFunctionLiteralExpression) { for (parameter in expression.getValueParameters()) { @@ -91,51 +71,55 @@ public object AnnotationTargetChecker { } } - private fun possibleTargetList(entry: JetAnnotationEntry, trace: BindingTrace): List { - val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: return DEFAULT_TARGET_LIST - // For descriptor with error type, all targets are considered as possible - if (descriptor.getType().isError()) return ALL_TARGET_LIST - val classDescriptor = TypeUtils.getClassDescriptor(descriptor.getType()) ?: return DEFAULT_TARGET_LIST + public fun possibleTargetSet(classDescriptor: ClassDescriptor): Set? { val targetEntryDescriptor = classDescriptor.getAnnotations().findAnnotation(KotlinBuiltIns.FQ_NAMES.target) - ?: return DEFAULT_TARGET_LIST + ?: return null val valueArguments = targetEntryDescriptor.getAllValueArguments() - val valueArgument = valueArguments.entrySet().firstOrNull()?.getValue() as? ArrayValue ?: return DEFAULT_TARGET_LIST - return valueArgument.value.filterIsInstance().map { it.value.getName().asString() } + val valueArgument = valueArguments.entrySet().firstOrNull()?.getValue() as? ArrayValue ?: return null + return valueArgument.value.filterIsInstance().map { + AnnotationTarget.valueOrNull(it.value.getName().asString()) + }.filterNotNull().toSet() } - private fun checkAnnotationEntry(entry: JetAnnotationEntry, actualTargets: List, trace: BindingTrace) { - val possibleTargets = possibleTargetList(entry, trace) - for (actualTarget in actualTargets) { - if (actualTarget.name() in possibleTargets) return - } + private fun possibleTargetSet(entry: JetAnnotationEntry, trace: BindingTrace): Set { + val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: return AnnotationTarget.DEFAULT_TARGET_SET + // For descriptor with error type, all targets are considered as possible + if (descriptor.getType().isError()) return AnnotationTarget.ALL_TARGET_SET + val classDescriptor = TypeUtils.getClassDescriptor(descriptor.getType()) ?: return AnnotationTarget.DEFAULT_TARGET_SET + return possibleTargetSet(classDescriptor) ?: AnnotationTarget.DEFAULT_TARGET_SET + } + + private fun checkAnnotationEntry(entry: JetAnnotationEntry, actualTargets: List, trace: BindingTrace) { + val possibleTargets = possibleTargetSet(entry, trace) + if (actualTargets.any { it in possibleTargets }) return trace.report(Errors.WRONG_ANNOTATION_TARGET.on(entry, actualTargets.firstOrNull()?.description ?: "unidentified target")) } - private fun getActualTargetList(annotated: JetAnnotated, descriptor: ClassDescriptor?): List { + private fun getActualTargetList(annotated: JetAnnotated, descriptor: ClassDescriptor?): List { if (annotated is JetClassOrObject) { - if (annotated is JetEnumEntry) return listOf(Target.PROPERTY, Target.FIELD) + if (annotated is JetEnumEntry) return listOf(AnnotationTarget.PROPERTY, AnnotationTarget.FIELD) return if (descriptor?.getKind() == ClassKind.ANNOTATION_CLASS) { - listOf(Target.ANNOTATION_CLASS, Target.CLASSIFIER) + listOf(AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASSIFIER) } else { - listOf(Target.CLASSIFIER) + listOf(AnnotationTarget.CLASSIFIER) } } if (annotated is JetProperty) { - return if (annotated.isLocal()) listOf(Target.LOCAL_VARIABLE) else listOf(Target.PROPERTY, Target.FIELD) + return if (annotated.isLocal()) listOf(AnnotationTarget.LOCAL_VARIABLE) else listOf(AnnotationTarget.PROPERTY, AnnotationTarget.FIELD) } if (annotated is JetParameter) { - return if (annotated.hasValOrVar()) listOf(Target.PROPERTY, Target.FIELD) else listOf(Target.VALUE_PARAMETER) + return if (annotated.hasValOrVar()) listOf(AnnotationTarget.PROPERTY, AnnotationTarget.FIELD) else listOf(AnnotationTarget.VALUE_PARAMETER) } - if (annotated is JetConstructor<*>) return listOf(Target.CONSTRUCTOR) - if (annotated is JetFunction) return listOf(Target.FUNCTION) + if (annotated is JetConstructor<*>) return listOf(AnnotationTarget.CONSTRUCTOR) + if (annotated is JetFunction) return listOf(AnnotationTarget.FUNCTION) if (annotated is JetPropertyAccessor) { - return if (annotated.isGetter()) listOf(Target.PROPERTY_GETTER) else listOf(Target.PROPERTY_SETTER) + return if (annotated.isGetter()) listOf(AnnotationTarget.PROPERTY_GETTER) else listOf(AnnotationTarget.PROPERTY_SETTER) } - if (annotated is JetPackageDirective) return listOf(Target.PACKAGE) - if (annotated is JetTypeReference) return listOf(Target.TYPE) - if (annotated is JetFile) return listOf(Target.FILE) - if (annotated is JetTypeParameter) return listOf(Target.TYPE_PARAMETER) + if (annotated is JetPackageDirective) return listOf(AnnotationTarget.PACKAGE) + if (annotated is JetTypeReference) return listOf(AnnotationTarget.TYPE) + if (annotated is JetFile) return listOf(AnnotationTarget.FILE) + if (annotated is JetTypeParameter) return listOf(AnnotationTarget.TYPE_PARAMETER) return listOf() } } \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/annotation.java b/compiler/testData/compileJavaAgainstKotlin/targets/annotation.java new file mode 100644 index 00000000000..af701eeac59 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/annotation.java @@ -0,0 +1,9 @@ +package test; + +@meta @interface MyAnn { + +} + +@meta class My { + +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/annotation.javaerr.txt b/compiler/testData/compileJavaAgainstKotlin/targets/annotation.javaerr.txt new file mode 100644 index 00000000000..496546b7bf8 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/annotation.javaerr.txt @@ -0,0 +1,2 @@ +annotation.java:7:1:compiler.err.annotation.type.not.applicable + diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/annotation.kt b/compiler/testData/compileJavaAgainstKotlin/targets/annotation.kt new file mode 100644 index 00000000000..a560c088c9e --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/annotation.kt @@ -0,0 +1,4 @@ +package test + +target(AnnotationTarget.ANNOTATION_CLASS) +annotation class meta \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/annotation.txt b/compiler/testData/compileJavaAgainstKotlin/targets/annotation.txt new file mode 100644 index 00000000000..c67a9aad096 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/annotation.txt @@ -0,0 +1,9 @@ +package test + +test.meta() public/*package*/ final class MyAnn : kotlin.Annotation { + public/*package*/ constructor MyAnn() +} + +kotlin.annotation.target(allowedTargets = {AnnotationTarget.ANNOTATION_CLASS}) kotlin.annotation.annotation() java.lang.annotation.Target(value = {ElementType.ANNOTATION_TYPE}) internal final class meta : kotlin.Annotation { + public constructor meta() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/base.java b/compiler/testData/compileJavaAgainstKotlin/targets/base.java new file mode 100644 index 00000000000..afa45c0c6ab --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/base.java @@ -0,0 +1,8 @@ +package test; + +@base class My { + + @base int foo(@base int i) { + return i + 1; + } +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/base.kt b/compiler/testData/compileJavaAgainstKotlin/targets/base.kt new file mode 100644 index 00000000000..b0691602b5e --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/base.kt @@ -0,0 +1,3 @@ +package test + +annotation class base \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/base.txt b/compiler/testData/compileJavaAgainstKotlin/targets/base.txt new file mode 100644 index 00000000000..13302e3e361 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/base.txt @@ -0,0 +1,10 @@ +package test + +test.base() public/*package*/ open class My { + public/*package*/ constructor My() + test.base() public/*package*/ open fun foo(/*0*/ test.base() kotlin.Int): kotlin.Int +} + +kotlin.annotation.annotation() internal final class base : kotlin.Annotation { + public constructor base() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/classifier.java b/compiler/testData/compileJavaAgainstKotlin/targets/classifier.java new file mode 100644 index 00000000000..786a75cace4 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/classifier.java @@ -0,0 +1,8 @@ +package test; + +@classifier class My { + + @classifier int foo() { + return 1; + } +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/classifier.javaerr.txt b/compiler/testData/compileJavaAgainstKotlin/targets/classifier.javaerr.txt new file mode 100644 index 00000000000..f935f54bbca --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/classifier.javaerr.txt @@ -0,0 +1 @@ +classifier.java:5:5:compiler.err.annotation.type.not.applicable diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/classifier.kt b/compiler/testData/compileJavaAgainstKotlin/targets/classifier.kt new file mode 100644 index 00000000000..42ed393d490 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/classifier.kt @@ -0,0 +1,4 @@ +package test + +target(AnnotationTarget.CLASSIFIER) +annotation class classifier \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/classifier.txt b/compiler/testData/compileJavaAgainstKotlin/targets/classifier.txt new file mode 100644 index 00000000000..e78c36e3bfa --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/classifier.txt @@ -0,0 +1,5 @@ +package test + +kotlin.annotation.target(allowedTargets = {AnnotationTarget.CLASSIFIER}) kotlin.annotation.annotation() java.lang.annotation.Target(value = {ElementType.TYPE}) internal final class classifier : kotlin.Annotation { + public constructor classifier() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/constructor.java b/compiler/testData/compileJavaAgainstKotlin/targets/constructor.java new file mode 100644 index 00000000000..5e7c693be7f --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/constructor.java @@ -0,0 +1,10 @@ +package test; + +class My { + + @constructor My() {} + + @constructor int foo() { + return 1; + } +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/constructor.javaerr.txt b/compiler/testData/compileJavaAgainstKotlin/targets/constructor.javaerr.txt new file mode 100644 index 00000000000..7a80dcd0a10 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/constructor.javaerr.txt @@ -0,0 +1,3 @@ +constructor.java:7:5:compiler.err.annotation.type.not.applicable + + diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/constructor.kt b/compiler/testData/compileJavaAgainstKotlin/targets/constructor.kt new file mode 100644 index 00000000000..f30855bce29 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/constructor.kt @@ -0,0 +1,4 @@ +package test + +target(AnnotationTarget.CONSTRUCTOR) +annotation class constructor \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/constructor.txt b/compiler/testData/compileJavaAgainstKotlin/targets/constructor.txt new file mode 100644 index 00000000000..ce1e8b0164d --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/constructor.txt @@ -0,0 +1,5 @@ +package test + +kotlin.annotation.target(allowedTargets = {AnnotationTarget.CONSTRUCTOR}) kotlin.annotation.annotation() java.lang.annotation.Target(value = {ElementType.CONSTRUCTOR}) internal final class constructor : kotlin.Annotation { + public constructor constructor() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/empty.java b/compiler/testData/compileJavaAgainstKotlin/targets/empty.java new file mode 100644 index 00000000000..3ba7c8f7e80 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/empty.java @@ -0,0 +1,8 @@ +package test; + +@empty class My { + + @empty int foo(@empty int i) { + return i + 1; + } +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/empty.javaerr.txt b/compiler/testData/compileJavaAgainstKotlin/targets/empty.javaerr.txt new file mode 100644 index 00000000000..b48349025fb --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/empty.javaerr.txt @@ -0,0 +1,4 @@ +empty.java:3:1:compiler.err.annotation.type.not.applicable +empty.java:5:20:compiler.err.annotation.type.not.applicable +empty.java:5:5:compiler.err.annotation.type.not.applicable + diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/empty.kt b/compiler/testData/compileJavaAgainstKotlin/targets/empty.kt new file mode 100644 index 00000000000..baf723a676d --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/empty.kt @@ -0,0 +1,4 @@ +package test + +target() +annotation class empty diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/empty.txt b/compiler/testData/compileJavaAgainstKotlin/targets/empty.txt new file mode 100644 index 00000000000..0dd05225d23 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/empty.txt @@ -0,0 +1,5 @@ +package test + +kotlin.annotation.target(allowedTargets = {}) kotlin.annotation.annotation() java.lang.annotation.Target(value = {}) internal final class empty : kotlin.Annotation { + public constructor empty() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/field.java b/compiler/testData/compileJavaAgainstKotlin/targets/field.java new file mode 100644 index 00000000000..cca6d2eb004 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/field.java @@ -0,0 +1,7 @@ +package test; + +class My { + @field int prop; + + @field int get() { return prop; } +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/field.javaerr.txt b/compiler/testData/compileJavaAgainstKotlin/targets/field.javaerr.txt new file mode 100644 index 00000000000..75d28283491 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/field.javaerr.txt @@ -0,0 +1,4 @@ +field.java:6:5:compiler.err.annotation.type.not.applicable + + + diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/field.kt b/compiler/testData/compileJavaAgainstKotlin/targets/field.kt new file mode 100644 index 00000000000..121f11551c2 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/field.kt @@ -0,0 +1,4 @@ +package test + +target(AnnotationTarget.FIELD) +annotation class field diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/field.txt b/compiler/testData/compileJavaAgainstKotlin/targets/field.txt new file mode 100644 index 00000000000..65c95f1a64a --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/field.txt @@ -0,0 +1,5 @@ +package test + +kotlin.annotation.target(allowedTargets = {AnnotationTarget.FIELD}) kotlin.annotation.annotation() java.lang.annotation.Target(value = {ElementType.FIELD}) internal final class field : kotlin.Annotation { + public constructor field() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/function.java b/compiler/testData/compileJavaAgainstKotlin/targets/function.java new file mode 100644 index 00000000000..e7c96c8b5db --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/function.java @@ -0,0 +1,8 @@ +package test; + +@function class My { + + @function int foo() { + return 1; + } +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/function.javaerr.txt b/compiler/testData/compileJavaAgainstKotlin/targets/function.javaerr.txt new file mode 100644 index 00000000000..68ddefc0953 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/function.javaerr.txt @@ -0,0 +1,2 @@ +function.java:3:1:compiler.err.annotation.type.not.applicable + diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/function.kt b/compiler/testData/compileJavaAgainstKotlin/targets/function.kt new file mode 100644 index 00000000000..149d5a6feb5 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/function.kt @@ -0,0 +1,4 @@ +package test + +target(AnnotationTarget.FUNCTION) +annotation class function \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/function.txt b/compiler/testData/compileJavaAgainstKotlin/targets/function.txt new file mode 100644 index 00000000000..89291920462 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/function.txt @@ -0,0 +1,5 @@ +package test + +kotlin.annotation.target(allowedTargets = {AnnotationTarget.FUNCTION}) kotlin.annotation.annotation() java.lang.annotation.Target(value = {ElementType.METHOD}) internal final class function : kotlin.Annotation { + public constructor function() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/getter.java b/compiler/testData/compileJavaAgainstKotlin/targets/getter.java new file mode 100644 index 00000000000..2e1ad2d6d59 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/getter.java @@ -0,0 +1,8 @@ +package test; + +@getter class My { + + @getter int foo() { + return 1; + } +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/getter.javaerr.txt b/compiler/testData/compileJavaAgainstKotlin/targets/getter.javaerr.txt new file mode 100644 index 00000000000..4bd2d1e6808 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/getter.javaerr.txt @@ -0,0 +1,3 @@ +getter.java:3:1:compiler.err.annotation.type.not.applicable + + diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/getter.kt b/compiler/testData/compileJavaAgainstKotlin/targets/getter.kt new file mode 100644 index 00000000000..d4f36ed4e5b --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/getter.kt @@ -0,0 +1,4 @@ +package test + +target(AnnotationTarget.PROPERTY_GETTER) +annotation class getter \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/getter.txt b/compiler/testData/compileJavaAgainstKotlin/targets/getter.txt new file mode 100644 index 00000000000..2cb31f08715 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/getter.txt @@ -0,0 +1,5 @@ +package test + +kotlin.annotation.target(allowedTargets = {AnnotationTarget.PROPERTY_GETTER}) kotlin.annotation.annotation() java.lang.annotation.Target(value = {ElementType.METHOD}) internal final class getter : kotlin.Annotation { + public constructor getter() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/local.java b/compiler/testData/compileJavaAgainstKotlin/targets/local.java new file mode 100644 index 00000000000..5ee8a3ada6d --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/local.java @@ -0,0 +1,9 @@ +package test; + +class My { + + int foo(@local int i) { + @local int j = i + 1; + return j; + } +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/local.javaerr.txt b/compiler/testData/compileJavaAgainstKotlin/targets/local.javaerr.txt new file mode 100644 index 00000000000..f63c7f473bc --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/local.javaerr.txt @@ -0,0 +1,3 @@ +local.java:5:13:compiler.err.annotation.type.not.applicable + + diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/local.kt b/compiler/testData/compileJavaAgainstKotlin/targets/local.kt new file mode 100644 index 00000000000..22315fd2751 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/local.kt @@ -0,0 +1,4 @@ +package test + +target(AnnotationTarget.LOCAL_VARIABLE) +annotation class local diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/local.txt b/compiler/testData/compileJavaAgainstKotlin/targets/local.txt new file mode 100644 index 00000000000..7731a09f388 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/local.txt @@ -0,0 +1,5 @@ +package test + +kotlin.annotation.target(allowedTargets = {AnnotationTarget.LOCAL_VARIABLE}) kotlin.annotation.annotation() java.lang.annotation.Target(value = {ElementType.LOCAL_VARIABLE}) internal final class local : kotlin.Annotation { + public constructor local() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/multiple.java b/compiler/testData/compileJavaAgainstKotlin/targets/multiple.java new file mode 100644 index 00000000000..d0de4cf9b3a --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/multiple.java @@ -0,0 +1,8 @@ +package test; + +@multiple class My { + + @multiple int foo(@multiple int i) { + return i + 1; + } +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/multiple.javaerr.txt b/compiler/testData/compileJavaAgainstKotlin/targets/multiple.javaerr.txt new file mode 100644 index 00000000000..0cf4373322b --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/multiple.javaerr.txt @@ -0,0 +1,2 @@ +multiple.java:5:23:compiler.err.annotation.type.not.applicable + diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/multiple.kt b/compiler/testData/compileJavaAgainstKotlin/targets/multiple.kt new file mode 100644 index 00000000000..e6917422932 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/multiple.kt @@ -0,0 +1,4 @@ +package test + +target(AnnotationTarget.CLASSIFIER, AnnotationTarget.FUNCTION) +annotation class multiple diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/multiple.txt b/compiler/testData/compileJavaAgainstKotlin/targets/multiple.txt new file mode 100644 index 00000000000..2a3a8c4e794 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/multiple.txt @@ -0,0 +1,5 @@ +package test + +kotlin.annotation.target(allowedTargets = {AnnotationTarget.CLASSIFIER, AnnotationTarget.FUNCTION}) kotlin.annotation.annotation() java.lang.annotation.Target(value = {ElementType.TYPE, ElementType.METHOD}) internal final class multiple : kotlin.Annotation { + public constructor multiple() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/package-info.java b/compiler/testData/compileJavaAgainstKotlin/targets/package-info.java new file mode 100644 index 00000000000..660755836c1 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/package-info.java @@ -0,0 +1,5 @@ +@pck package test; + +@pck class My { + +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/package-info.javaerr.txt b/compiler/testData/compileJavaAgainstKotlin/targets/package-info.javaerr.txt new file mode 100644 index 00000000000..c4f5202f765 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/package-info.javaerr.txt @@ -0,0 +1,2 @@ +package-info.java:3:1:compiler.err.annotation.type.not.applicable + diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/package-info.kt b/compiler/testData/compileJavaAgainstKotlin/targets/package-info.kt new file mode 100644 index 00000000000..4cddc103b42 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/package-info.kt @@ -0,0 +1,4 @@ +package test + +target(AnnotationTarget.PACKAGE) +annotation class pck \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/package-info.txt b/compiler/testData/compileJavaAgainstKotlin/targets/package-info.txt new file mode 100644 index 00000000000..e1012210dd7 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/package-info.txt @@ -0,0 +1,8 @@ +package test + +test.pck() public/*package*/ interface `package-info` { +} + +kotlin.annotation.target(allowedTargets = {AnnotationTarget.PACKAGE}) kotlin.annotation.annotation() java.lang.annotation.Target(value = {ElementType.PACKAGE}) internal final class pck : kotlin.Annotation { + public constructor pck() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/parameter.java b/compiler/testData/compileJavaAgainstKotlin/targets/parameter.java new file mode 100644 index 00000000000..7b6579c617c --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/parameter.java @@ -0,0 +1,8 @@ +package test; + +@parameter class My { + + @parameter int foo(@parameter int i) { + return i + 1; + } +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/parameter.javaerr.txt b/compiler/testData/compileJavaAgainstKotlin/targets/parameter.javaerr.txt new file mode 100644 index 00000000000..b69bcb7eec8 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/parameter.javaerr.txt @@ -0,0 +1,2 @@ +parameter.java:3:1:compiler.err.annotation.type.not.applicable +parameter.java:5:5:compiler.err.annotation.type.not.applicable diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/parameter.kt b/compiler/testData/compileJavaAgainstKotlin/targets/parameter.kt new file mode 100644 index 00000000000..a0480e339b7 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/parameter.kt @@ -0,0 +1,4 @@ +package test + +target(AnnotationTarget.VALUE_PARAMETER) +annotation class parameter diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/parameter.txt b/compiler/testData/compileJavaAgainstKotlin/targets/parameter.txt new file mode 100644 index 00000000000..b96cb99dc91 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/parameter.txt @@ -0,0 +1,5 @@ +package test + +kotlin.annotation.target(allowedTargets = {AnnotationTarget.VALUE_PARAMETER}) kotlin.annotation.annotation() java.lang.annotation.Target(value = {ElementType.PARAMETER}) internal final class parameter : kotlin.Annotation { + public constructor parameter() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/property.java b/compiler/testData/compileJavaAgainstKotlin/targets/property.java new file mode 100644 index 00000000000..d283ecf8802 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/property.java @@ -0,0 +1,7 @@ +package test; + +class My { + @property int prop; + + @property int get() { return prop; } +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/property.javaerr.txt b/compiler/testData/compileJavaAgainstKotlin/targets/property.javaerr.txt new file mode 100644 index 00000000000..254a611f5cb --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/property.javaerr.txt @@ -0,0 +1,4 @@ +property.java:4:5:compiler.err.annotation.type.not.applicable +property.java:6:5:compiler.err.annotation.type.not.applicable + + diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/property.kt b/compiler/testData/compileJavaAgainstKotlin/targets/property.kt new file mode 100644 index 00000000000..8dfbeda314f --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/property.kt @@ -0,0 +1,4 @@ +package test + +target(AnnotationTarget.PROPERTY) +annotation class property diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/property.txt b/compiler/testData/compileJavaAgainstKotlin/targets/property.txt new file mode 100644 index 00000000000..636e36d33b1 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/property.txt @@ -0,0 +1,5 @@ +package test + +kotlin.annotation.target(allowedTargets = {AnnotationTarget.PROPERTY}) kotlin.annotation.annotation() java.lang.annotation.Target(value = {}) internal final class property : kotlin.Annotation { + public constructor property() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/setter.java b/compiler/testData/compileJavaAgainstKotlin/targets/setter.java new file mode 100644 index 00000000000..d92426551b7 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/setter.java @@ -0,0 +1,8 @@ +package test; + +@setter class My { + + @setter int foo() { + return 1; + } +} \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/setter.javaerr.txt b/compiler/testData/compileJavaAgainstKotlin/targets/setter.javaerr.txt new file mode 100644 index 00000000000..7147fea29cc --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/setter.javaerr.txt @@ -0,0 +1,3 @@ +setter.java:3:1:compiler.err.annotation.type.not.applicable + + diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/setter.kt b/compiler/testData/compileJavaAgainstKotlin/targets/setter.kt new file mode 100644 index 00000000000..8d1a40ba08a --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/setter.kt @@ -0,0 +1,4 @@ +package test + +target(AnnotationTarget.PROPERTY_SETTER) +annotation class setter \ No newline at end of file diff --git a/compiler/testData/compileJavaAgainstKotlin/targets/setter.txt b/compiler/testData/compileJavaAgainstKotlin/targets/setter.txt new file mode 100644 index 00000000000..a9afdf028d3 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/targets/setter.txt @@ -0,0 +1,5 @@ +package test + +kotlin.annotation.target(allowedTargets = {AnnotationTarget.PROPERTY_SETTER}) kotlin.annotation.annotation() java.lang.annotation.Target(value = {ElementType.METHOD}) internal final class setter : kotlin.Annotation { + public constructor setter() +} diff --git a/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.txt b/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.txt index bb382d11bd2..873cccd65d5 100644 --- a/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.txt +++ b/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.txt @@ -7,7 +7,7 @@ kotlin.annotation.annotation() internal final class my : kotlin.Annotation { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -kotlin.annotation.annotation() java.lang.annotation.Target(value = {ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR}) internal final class my1 : kotlin.Annotation { +kotlin.annotation.annotation() internal final class my1 : kotlin.Annotation { public constructor my1() 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/ArrayOfEnumInParam.txt b/compiler/testData/loadJava/compiledJava/annotations/ArrayOfEnumInParam.txt index b1052c7af49..08cd4f72ffe 100644 --- a/compiler/testData/loadJava/compiledJava/annotations/ArrayOfEnumInParam.txt +++ b/compiler/testData/loadJava/compiledJava/annotations/ArrayOfEnumInParam.txt @@ -2,7 +2,7 @@ package test public interface ArrayOfEnumInParam { - java.lang.annotation.Target(value = {ElementType.FIELD, ElementType.CONSTRUCTOR}) public final class targetAnnotation : kotlin.Annotation { + public final class targetAnnotation : kotlin.Annotation { public constructor targetAnnotation(/*0*/ value: kotlin.String) public final val value: kotlin.String public abstract fun value(): kotlin.String diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileJavaAgainstKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileJavaAgainstKotlinTestGenerated.java index 3498cf44ba1..c460efef005 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileJavaAgainstKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileJavaAgainstKotlinTestGenerated.java @@ -553,4 +553,97 @@ public class CompileJavaAgainstKotlinTestGenerated extends AbstractCompileJavaAg doTest(fileName); } } + + @TestMetadata("compiler/testData/compileJavaAgainstKotlin/targets") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Targets extends AbstractCompileJavaAgainstKotlinTest { + public void testAllFilesPresentInTargets() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/compileJavaAgainstKotlin/targets"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("annotation.kt") + public void testAnnotation() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/annotation.kt"); + doTest(fileName); + } + + @TestMetadata("base.kt") + public void testBase() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/base.kt"); + doTest(fileName); + } + + @TestMetadata("classifier.kt") + public void testClassifier() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/classifier.kt"); + doTest(fileName); + } + + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/constructor.kt"); + doTest(fileName); + } + + @TestMetadata("empty.kt") + public void testEmpty() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/empty.kt"); + doTest(fileName); + } + + @TestMetadata("field.kt") + public void testField() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/field.kt"); + doTest(fileName); + } + + @TestMetadata("function.kt") + public void testFunction() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/function.kt"); + doTest(fileName); + } + + @TestMetadata("getter.kt") + public void testGetter() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/getter.kt"); + doTest(fileName); + } + + @TestMetadata("local.kt") + public void testLocal() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/local.kt"); + doTest(fileName); + } + + @TestMetadata("multiple.kt") + public void testMultiple() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/multiple.kt"); + doTest(fileName); + } + + @TestMetadata("package-info.kt") + public void testPackage_info() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/package-info.kt"); + doTest(fileName); + } + + @TestMetadata("parameter.kt") + public void testParameter() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/parameter.kt"); + doTest(fileName); + } + + @TestMetadata("property.kt") + public void testProperty() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/property.kt"); + doTest(fileName); + } + + @TestMetadata("setter.kt") + public void testSetter() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/targets/setter.kt"); + doTest(fileName); + } + } } diff --git a/compiler/tests/org/jetbrains/kotlin/test/util/RecursiveDescriptorComparator.java b/compiler/tests/org/jetbrains/kotlin/test/util/RecursiveDescriptorComparator.java index b43c957a1b4..7d4d4802e98 100644 --- a/compiler/tests/org/jetbrains/kotlin/test/util/RecursiveDescriptorComparator.java +++ b/compiler/tests/org/jetbrains/kotlin/test/util/RecursiveDescriptorComparator.java @@ -41,6 +41,7 @@ import org.junit.Assert; import java.io.File; import java.lang.annotation.Retention; +import java.lang.annotation.Target; import java.util.*; import static org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry; @@ -52,6 +53,7 @@ public class RecursiveDescriptorComparator { static { excludedAnnotations.add(new FqName(ExpectedLoadErrorsUtil.ANNOTATION_CLASS_NAME)); excludedAnnotations.add(new FqName(Retention.class.getName())); + excludedAnnotations.add(new FqName(Target.class.getName())); } private static final DescriptorRenderer DEFAULT_RENDERER = DescriptorRenderer.Companion.withOptions( diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationTarget.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationTarget.kt new file mode 100644 index 00000000000..b28ae42d64e --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationTarget.kt @@ -0,0 +1,57 @@ +/* + * 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 + +import java.util.* +import kotlin.annotation + +// NOTE: this enum must have the same entries with kotlin.annotation.AnnotationTarget +public enum class AnnotationTarget(val description: String, val isDefault: Boolean = true) { + PACKAGE("package"), + CLASSIFIER("classifier"), + ANNOTATION_CLASS("annotation class"), + TYPE_PARAMETER("type parameter", false), + PROPERTY("property"), + FIELD("field"), + LOCAL_VARIABLE("local variable"), + VALUE_PARAMETER("value parameter"), + CONSTRUCTOR("constructor"), + FUNCTION("function"), + PROPERTY_GETTER("getter"), + PROPERTY_SETTER("setter"), + TYPE("type usage", false), + EXPRESSION("expression", false), + FILE("file", false); + + companion object { + + private val map = HashMap() + + init { + for (target in AnnotationTarget.values()) { + map[target.name()] = target + } + } + + public fun valueOrNull(name: String): AnnotationTarget? = map[name] + + public val DEFAULT_TARGET_SET: Set = values().filter { it.isDefault }.toSet() + + public val ALL_TARGET_SET: Set = values().toSet() + + } +} \ No newline at end of file