Binary or runtime repeatable annotations are not allowed for JVM. Some tests fixed accordingly.

This commit is contained in:
Mikhail Glukhikh
2015-07-30 14:31:10 +03:00
parent f51107b502
commit dfaed3fef3
26 changed files with 104 additions and 75 deletions
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.codegen;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.*; import org.jetbrains.kotlin.descriptors.annotations.*;
@@ -27,6 +26,7 @@ import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.resolve.AnnotationChecker; import org.jetbrains.kotlin.resolve.AnnotationChecker;
import org.jetbrains.kotlin.resolve.constants.*; import org.jetbrains.kotlin.resolve.constants.*;
import org.jetbrains.kotlin.resolve.constants.StringValue; import org.jetbrains.kotlin.resolve.constants.StringValue;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage;
import org.jetbrains.kotlin.types.Flexibility; import org.jetbrains.kotlin.types.Flexibility;
import org.jetbrains.kotlin.types.JetType; import org.jetbrains.kotlin.types.JetType;
import org.jetbrains.kotlin.types.TypeUtils; import org.jetbrains.kotlin.types.TypeUtils;
@@ -407,20 +407,9 @@ public abstract class AnnotationCodegen {
@NotNull @NotNull
private RetentionPolicy getRetentionPolicy(@NotNull Annotated descriptor) { private RetentionPolicy getRetentionPolicy(@NotNull Annotated descriptor) {
AnnotationDescriptor kotlinAnnotation = descriptor.getAnnotations().findAnnotation(KotlinBuiltIns.FQ_NAMES.annotation); KotlinRetention retention = DescriptorUtilPackage.getAnnotationRetention(descriptor);
if (kotlinAnnotation != null) { if (retention != null) {
for (Map.Entry<ValueParameterDescriptor, ConstantValue<?>> argument : kotlinAnnotation.getAllValueArguments().entrySet()) { return annotationRetentionMap.get(retention);
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())) {
KotlinRetention retention = KotlinRetention.valueOf(enumEntry.getName().asString());
return annotationRetentionMap.get(retention);
}
}
}
}
} }
AnnotationDescriptor retentionAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Retention.class.getName())); AnnotationDescriptor retentionAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Retention.class.getName()));
if (retentionAnnotation != null) { if (retentionAnnotation != null) {
@@ -58,6 +58,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
MAP.put(ErrorsJvm.POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION, "Only named arguments are available for Java annotations"); MAP.put(ErrorsJvm.POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION, "Only named arguments are available for Java annotations");
MAP.put(ErrorsJvm.DEPRECATED_ANNOTATION_METHOD_CALL, "Annotation methods are deprecated. Use property instead"); MAP.put(ErrorsJvm.DEPRECATED_ANNOTATION_METHOD_CALL, "Annotation methods are deprecated. Use property instead");
MAP.put(ErrorsJvm.DEPRECATED_JAVA_ANNOTATION, "This annotation is deprecated in Kotlin. Use ''{0}'' instead", Renderers.TO_STRING); MAP.put(ErrorsJvm.DEPRECATED_JAVA_ANNOTATION, "This annotation is deprecated in Kotlin. Use ''{0}'' instead", Renderers.TO_STRING);
MAP.put(ErrorsJvm.NON_SOURCE_REPEATED_ANNOTATION, "Only annotations with SOURCE retention can be repeated on JVM platform");
MAP.put(ErrorsJvm.NO_REFLECTION_IN_CLASS_PATH, "Call uses reflection API which is not found in compilation classpath. " + MAP.put(ErrorsJvm.NO_REFLECTION_IN_CLASS_PATH, "Call uses reflection API which is not found in compilation classpath. " +
"Make sure you have kotlin-reflect.jar in the classpath"); "Make sure you have kotlin-reflect.jar in the classpath");
@@ -56,6 +56,7 @@ public interface ErrorsJvm {
DiagnosticFactory0<JetExpression> POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<JetExpression> POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetElement> DEPRECATED_ANNOTATION_METHOD_CALL = DiagnosticFactory0.create(WARNING); DiagnosticFactory0<JetElement> DEPRECATED_ANNOTATION_METHOD_CALL = DiagnosticFactory0.create(WARNING);
DiagnosticFactory1<JetAnnotationEntry, FqName> DEPRECATED_JAVA_ANNOTATION = DiagnosticFactory1.create(WARNING); DiagnosticFactory1<JetAnnotationEntry, FqName> DEPRECATED_JAVA_ANNOTATION = DiagnosticFactory1.create(WARNING);
DiagnosticFactory0<JetAnnotationEntry> NON_SOURCE_REPEATED_ANNOTATION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetElement> TRAIT_CANT_CALL_DEFAULT_METHOD_VIA_SUPER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<JetElement> TRAIT_CANT_CALL_DEFAULT_METHOD_VIA_SUPER = DiagnosticFactory0.create(ERROR);
@@ -20,6 +20,8 @@ import org.jetbrains.kotlin.cfg.WhenChecker
import org.jetbrains.kotlin.container.StorageComponentContainer import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.useImpl import org.jetbrains.kotlin.container.useImpl
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.jvm.RuntimeAssertionsTypeChecker import org.jetbrains.kotlin.jvm.RuntimeAssertionsTypeChecker
@@ -43,6 +45,8 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability
import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention
import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation
import org.jetbrains.kotlin.resolve.jvm.calls.checkers.NeedSyntheticChecker import org.jetbrains.kotlin.resolve.jvm.calls.checkers.NeedSyntheticChecker
import org.jetbrains.kotlin.resolve.jvm.calls.checkers.ReflectionAPICallChecker import org.jetbrains.kotlin.resolve.jvm.calls.checkers.ReflectionAPICallChecker
import org.jetbrains.kotlin.resolve.jvm.calls.checkers.TraitDefaultMethodCallChecker import org.jetbrains.kotlin.resolve.jvm.calls.checkers.TraitDefaultMethodCallChecker
@@ -75,7 +79,10 @@ public object JvmPlatformConfigurator : PlatformConfigurator(
JavaNullabilityWarningsChecker(), JavaNullabilityWarningsChecker(),
RuntimeAssertionsTypeChecker RuntimeAssertionsTypeChecker
), ),
additionalSymbolUsageValidators = listOf()
additionalSymbolUsageValidators = listOf(),
additionalAnnotationChecker = RepeatableAnnotationChecker
) { ) {
override fun configure(container: StorageComponentContainer) { override fun configure(container: StorageComponentContainer) {
@@ -85,6 +92,21 @@ public object JvmPlatformConfigurator : PlatformConfigurator(
} }
} }
public object RepeatableAnnotationChecker: AdditionalAnnotationChecker {
override fun checkEntries(entries: List<JetAnnotationEntry>, actualTargets: List<KotlinTarget>, trace: BindingTrace) {
val entryTypes: MutableSet<JetType> = hashSetOf()
for (entry in entries) {
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue
val classDescriptor = TypeUtils.getClassDescriptor(descriptor.type) ?: continue
if (!entryTypes.add(descriptor.type)
&& classDescriptor.isRepeatableAnnotation()
&& classDescriptor.getAnnotationRetention() != KotlinRetention.SOURCE) {
trace.report(ErrorsJvm.NON_SOURCE_REPEATED_ANNOTATION.on(entry));
}
}
}
}
public class LocalFunInlineChecker : DeclarationChecker { public class LocalFunInlineChecker : DeclarationChecker {
override fun check( override fun check(
@@ -27,10 +27,12 @@ import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.types.JetType import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.resolve.constants.BooleanValue import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation
public object AnnotationChecker { public object AnnotationChecker {
public var additionalChecker: AdditionalAnnotationChecker? = null
public fun check(annotated: JetAnnotated, trace: BindingTrace, descriptor: ClassDescriptor? = null) { public fun check(annotated: JetAnnotated, trace: BindingTrace, descriptor: ClassDescriptor? = null) {
if (annotated is JetTypeParameter) return // TODO: support type parameter annotations if (annotated is JetTypeParameter) return // TODO: support type parameter annotations
val actualTargets = getActualTargetList(annotated, descriptor) val actualTargets = getActualTargetList(annotated, descriptor)
@@ -64,24 +66,17 @@ public object AnnotationChecker {
} }
} }
private fun isRepeatable(classDescriptor: ClassDescriptor): Boolean {
val annotationEntryDescriptor = classDescriptor.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.annotation) ?: return false
val repeatableArgumentValue = annotationEntryDescriptor.allValueArguments.entrySet().firstOrNull {
"repeatable" == it.key.name.asString()
}?.getValue() as? BooleanValue ?: return false
return repeatableArgumentValue.value
}
private fun checkEntries(entries: List<JetAnnotationEntry>, actualTargets: List<KotlinTarget>, trace: BindingTrace) { private fun checkEntries(entries: List<JetAnnotationEntry>, actualTargets: List<KotlinTarget>, trace: BindingTrace) {
val entryTypes: MutableSet<JetType> = hashSetOf() val entryTypes: MutableSet<JetType> = hashSetOf()
for (entry in entries) { for (entry in entries) {
checkAnnotationEntry(entry, actualTargets, trace) checkAnnotationEntry(entry, actualTargets, trace)
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue
val classDescriptor = TypeUtils.getClassDescriptor(descriptor.type) ?: continue val classDescriptor = TypeUtils.getClassDescriptor(descriptor.type) ?: continue
if (!entryTypes.add(descriptor.type) && !isRepeatable(classDescriptor)) { if (!entryTypes.add(descriptor.type) && !classDescriptor.isRepeatableAnnotation()) {
trace.report(Errors.REPEATED_ANNOTATION.on(entry)); trace.report(Errors.REPEATED_ANNOTATION.on(entry));
} }
} }
additionalChecker?.checkEntries(entries, actualTargets, trace)
} }
public fun possibleTargetSet(classDescriptor: ClassDescriptor): Set<KotlinTarget>? { public fun possibleTargetSet(classDescriptor: ClassDescriptor): Set<KotlinTarget>? {
@@ -136,3 +131,7 @@ public object AnnotationChecker {
return listOf() return listOf()
} }
} }
public interface AdditionalAnnotationChecker {
public fun checkEntries(entries: List<JetAnnotationEntry>, actualTargets: List<KotlinTarget>, trace: BindingTrace)
}
@@ -48,7 +48,8 @@ public open class PlatformConfigurator(
additionalDeclarationCheckers: List<DeclarationChecker>, additionalDeclarationCheckers: List<DeclarationChecker>,
additionalCallCheckers: List<CallChecker>, additionalCallCheckers: List<CallChecker>,
additionalTypeCheckers: List<AdditionalTypeChecker>, additionalTypeCheckers: List<AdditionalTypeChecker>,
additionalSymbolUsageValidators: List<SymbolUsageValidator> additionalSymbolUsageValidators: List<SymbolUsageValidator>,
private val additionalAnnotationChecker: AdditionalAnnotationChecker? = null
) { ) {
private val declarationCheckers: List<DeclarationChecker> = DEFAULT_DECLARATION_CHECKERS + additionalDeclarationCheckers private val declarationCheckers: List<DeclarationChecker> = DEFAULT_DECLARATION_CHECKERS + additionalDeclarationCheckers
@@ -64,5 +65,6 @@ public open class PlatformConfigurator(
typeCheckers.forEach { useInstance(it) } typeCheckers.forEach { useInstance(it) }
useInstance(symbolUsageValidator) useInstance(symbolUsageValidator)
} }
AnnotationChecker.additionalChecker = additionalAnnotationChecker
} }
} }
@@ -1,5 +1,5 @@
target(AnnotationTarget.EXPRESSION) target(AnnotationTarget.EXPRESSION)
annotation(repeatable = true) class Ann(val x: Int = 1) annotation(repeatable = true, retention = AnnotationRetention.SOURCE) class Ann(val x: Int = 1)
inline fun bar(block: () -> Int): Int = block() inline fun bar(block: () -> Int): Int = block()
@@ -3,7 +3,7 @@ package
kotlin.inline() internal fun bar(/*0*/ block: () -> kotlin.Int): kotlin.Int kotlin.inline() internal fun bar(/*0*/ block: () -> kotlin.Int): kotlin.Int
internal fun foo(): kotlin.Unit internal fun foo(): kotlin.Unit
kotlin.annotation.target(allowedTargets = {AnnotationTarget.EXPRESSION}) kotlin.annotation.annotation(repeatable = true) internal final class Ann : kotlin.Annotation { kotlin.annotation.target(allowedTargets = {AnnotationTarget.EXPRESSION}) kotlin.annotation.annotation(repeatable = true, retention = AnnotationRetention.SOURCE) internal final class Ann : kotlin.Annotation {
public constructor Ann(/*0*/ x: kotlin.Int = ...) public constructor Ann(/*0*/ x: kotlin.Int = ...)
internal final val x: kotlin.Int internal final val x: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -2,7 +2,7 @@
target(AnnotationTarget.TYPE, AnnotationTarget.CLASSIFIER, target(AnnotationTarget.TYPE, AnnotationTarget.CLASSIFIER,
AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION,
AnnotationTarget.EXPRESSION, AnnotationTarget.PROPERTY) AnnotationTarget.EXPRESSION, AnnotationTarget.PROPERTY)
annotation(repeatable = true) class Ann(val x: Int = 6) annotation(repeatable = true, retention = AnnotationRetention.SOURCE) class Ann(val x: Int = 6)
@Ann(1) @Ann(2) @Ann(3) @private class A @Ann constructor() { @Ann(1) @Ann(2) @Ann(3) @private class A @Ann constructor() {
@Ann(x = 5) fun foo() { @Ann(x = 5) fun foo() {
@@ -10,7 +10,7 @@ Ann(x = 1) Ann(x = 2) Ann(x = 3) private final class A {
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
kotlin.annotation.target(allowedTargets = {AnnotationTarget.TYPE, AnnotationTarget.CLASSIFIER, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION, AnnotationTarget.EXPRESSION, AnnotationTarget.PROPERTY}) kotlin.annotation.annotation(repeatable = true) internal final class Ann : kotlin.Annotation { kotlin.annotation.target(allowedTargets = {AnnotationTarget.TYPE, AnnotationTarget.CLASSIFIER, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION, AnnotationTarget.EXPRESSION, AnnotationTarget.PROPERTY}) kotlin.annotation.annotation(repeatable = true, retention = AnnotationRetention.SOURCE) internal final class Ann : kotlin.Annotation {
public constructor Ann(/*0*/ x: kotlin.Int = ...) public constructor Ann(/*0*/ x: kotlin.Int = ...)
internal final val x: kotlin.Int internal final val x: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -4,14 +4,18 @@ annotation(retention = AnnotationRetention.SOURCE, repeatable = true) class repa
annotation(repeatable = true, retention = AnnotationRetention.SOURCE) class repann2(val f: Boolean) annotation(repeatable = true, retention = AnnotationRetention.SOURCE) class repann2(val f: Boolean)
annotation(repeatable = true, retention = AnnotationRetention.BINARY) class binrepann
target(AnnotationTarget.EXPRESSION) annotation(repeatable = true) class repexpr target(AnnotationTarget.EXPRESSION) annotation(repeatable = true) class repexpr
repann repann class DoubleAnnotated repann <!NON_SOURCE_REPEATED_ANNOTATION!>repann<!> class DoubleAnnotated
repann1(1) repann1(2) repann1(3) class TripleAnnotated repann1(1) repann1(2) repann1(3) class TripleAnnotated
repann2(true) repann2(false) repann2(false) repann2(true) class FourTimesAnnotated repann2(true) repann2(false) repann2(false) repann2(true) class FourTimesAnnotated
@repann @repann fun foo(@repann @repann x: Int): Int { binrepann <!NON_SOURCE_REPEATED_ANNOTATION!>binrepann<!> class BinaryAnnotated
@repexpr @repexpr return x
@repann <!NON_SOURCE_REPEATED_ANNOTATION!>@repann<!> fun foo(@repann <!NON_SOURCE_REPEATED_ANNOTATION!>@repann<!> x: Int): Int {
@repexpr <!NON_SOURCE_REPEATED_ANNOTATION!>@repexpr<!> return x
} }
@@ -2,6 +2,13 @@ package
repann() repann() internal fun foo(/*0*/ repann() repann() x: kotlin.Int): kotlin.Int repann() repann() internal fun foo(/*0*/ repann() repann() x: kotlin.Int): kotlin.Int
binrepann() binrepann() internal final class BinaryAnnotated {
public constructor BinaryAnnotated()
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
}
repann() repann() internal final class DoubleAnnotated { repann() repann() internal final class DoubleAnnotated {
public constructor DoubleAnnotated() public constructor DoubleAnnotated()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -23,6 +30,13 @@ repann1(x = 1) repann1(x = 2) repann1(x = 3) internal final class TripleAnnotate
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
kotlin.annotation.annotation(repeatable = true, retention = AnnotationRetention.BINARY) internal final class binrepann : kotlin.Annotation {
public constructor binrepann()
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(repeatable = true) internal final class repann : kotlin.Annotation { kotlin.annotation.annotation(repeatable = true) internal final class repann : kotlin.Annotation {
public constructor repann() public constructor repann()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -1,6 +1,6 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
target(AnnotationTarget.EXPRESSION) target(AnnotationTarget.EXPRESSION)
annotation(repeatable = true) class Ann annotation(repeatable = true, retention = AnnotationRetention.SOURCE) class Ann
fun <T> bar(block: (T) -> Int) {} fun <T> bar(block: (T) -> Int) {}
@@ -3,7 +3,7 @@ package
internal fun </*0*/ T> bar(/*0*/ block: (T) -> kotlin.Int): kotlin.Unit internal fun </*0*/ T> bar(/*0*/ block: (T) -> kotlin.Int): kotlin.Unit
internal fun foo(): kotlin.Unit internal fun foo(): kotlin.Unit
kotlin.annotation.target(allowedTargets = {AnnotationTarget.EXPRESSION}) kotlin.annotation.annotation(repeatable = true) internal final class Ann : kotlin.Annotation { kotlin.annotation.target(allowedTargets = {AnnotationTarget.EXPRESSION}) kotlin.annotation.annotation(repeatable = true, retention = AnnotationRetention.SOURCE) internal final class Ann : kotlin.Annotation {
public constructor Ann() public constructor Ann()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean 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 hashCode(): kotlin.Int
@@ -15,5 +15,6 @@ public @interface RepeatableAnnotations {
// FILE: RepeatableUse.kt // FILE: RepeatableUse.kt
RepeatableAnnotation RepeatableAnnotation class My // Error should be gone when Java 8 Target will be available
RepeatableAnnotation <!NON_SOURCE_REPEATED_ANNOTATION!>RepeatableAnnotation<!> class My
@@ -16,6 +16,7 @@ public @interface RepeatableAnnotations {
// FILE: RepeatableUse.kt // FILE: RepeatableUse.kt
RepeatableAnnotation RepeatableAnnotation class My // Error should be gone when Java 8 Target will be available
RepeatableAnnotation <!NON_SOURCE_REPEATED_ANNOTATION!>RepeatableAnnotation<!> class My
@@ -1,4 +1,4 @@
annotation(repeatable = true) class Ann(val i: IntArray) annotation(repeatable = true, retention = AnnotationRetention.SOURCE) class Ann(val i: IntArray)
Ann(intArrayOf(<!ANNOTATION_PARAMETER_MUST_BE_CONST!>i<!>)) Ann(intArrayOf(<!ANNOTATION_PARAMETER_MUST_BE_CONST!>i<!>))
Ann(intArrayOf(i2)) Ann(intArrayOf(i2))
@@ -13,7 +13,7 @@ val i3 = foo()
fun foo(): Int = 1 fun foo(): Int = 1
annotation(repeatable = true) class AnnAnn(val i: Array<Ann>) annotation(repeatable = true, retention = AnnotationRetention.SOURCE) class AnnAnn(val i: Array<Ann>)
AnnAnn(arrayOf(Ann(intArrayOf(1)))) AnnAnn(arrayOf(Ann(intArrayOf(1))))
AnnAnn(arrayOf(<!ANNOTATION_PARAMETER_MUST_BE_CONST!>iAnn<!>)) AnnAnn(arrayOf(<!ANNOTATION_PARAMETER_MUST_BE_CONST!>iAnn<!>))
class TestAnn class TestAnn
@@ -6,7 +6,7 @@ internal val i3: kotlin.Int
internal val iAnn: Ann internal val iAnn: Ann
internal fun foo(): kotlin.Int internal fun foo(): kotlin.Int
kotlin.annotation.annotation(repeatable = true) internal final class Ann : kotlin.Annotation { kotlin.annotation.annotation(repeatable = true, retention = AnnotationRetention.SOURCE) internal final class Ann : kotlin.Annotation {
public constructor Ann(/*0*/ i: kotlin.IntArray) public constructor Ann(/*0*/ i: kotlin.IntArray)
internal final val i: kotlin.IntArray internal final val i: kotlin.IntArray
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -14,7 +14,7 @@ kotlin.annotation.annotation(repeatable = true) internal final class Ann : kotli
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
kotlin.annotation.annotation(repeatable = true) internal final class AnnAnn : kotlin.Annotation { kotlin.annotation.annotation(repeatable = true, retention = AnnotationRetention.SOURCE) internal final class AnnAnn : kotlin.Annotation {
public constructor AnnAnn(/*0*/ i: kotlin.Array<Ann>) public constructor AnnAnn(/*0*/ i: kotlin.Array<Ann>)
internal final val i: kotlin.Array<Ann> internal final val i: kotlin.Array<Ann>
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -1,4 +1,4 @@
annotation(repeatable = true) class Ann(val i: Int) annotation(repeatable = true, retention = AnnotationRetention.SOURCE) class Ann(val i: Int)
annotation class AnnIA(val ia: IntArray) annotation class AnnIA(val ia: IntArray)
annotation class AnnSA(val sa: Array<String>) annotation class AnnSA(val sa: Array<String>)
@@ -6,7 +6,7 @@ internal val ia: kotlin.IntArray
internal val sa: kotlin.Array<kotlin.String> internal val sa: kotlin.Array<kotlin.String>
internal fun foo(): kotlin.Int internal fun foo(): kotlin.Int
kotlin.annotation.annotation(repeatable = true) internal final class Ann : kotlin.Annotation { kotlin.annotation.annotation(repeatable = true, retention = AnnotationRetention.SOURCE) internal final class Ann : kotlin.Annotation {
public constructor Ann(/*0*/ i: kotlin.Int) public constructor Ann(/*0*/ i: kotlin.Int)
internal final val i: kotlin.Int internal final val i: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -1,4 +1,4 @@
annotation(repeatable = true) class Ann(vararg val i: Int) annotation(repeatable = true, retention = AnnotationRetention.SOURCE) class Ann(vararg val i: Int)
Ann(<!ANNOTATION_PARAMETER_MUST_BE_CONST!>i<!>) Ann(<!ANNOTATION_PARAMETER_MUST_BE_CONST!>i<!>)
Ann(i2) Ann(i2)
@@ -16,7 +16,7 @@ val i3 = foo()
fun foo(): Int = 1 fun foo(): Int = 1
annotation(repeatable = true) class AnnAnn(vararg val i: Ann) annotation(repeatable = true, retention = AnnotationRetention.SOURCE) class AnnAnn(vararg val i: Ann)
AnnAnn(*arrayOf(Ann(1))) AnnAnn(*arrayOf(Ann(1)))
AnnAnn(*arrayOf(<!ANNOTATION_PARAMETER_MUST_BE_CONST!>iAnn<!>)) AnnAnn(*arrayOf(<!ANNOTATION_PARAMETER_MUST_BE_CONST!>iAnn<!>))
class TestAnn class TestAnn
@@ -6,7 +6,7 @@ internal val i3: kotlin.Int
internal val iAnn: Ann internal val iAnn: Ann
internal fun foo(): kotlin.Int internal fun foo(): kotlin.Int
kotlin.annotation.annotation(repeatable = true) internal final class Ann : kotlin.Annotation { kotlin.annotation.annotation(repeatable = true, retention = AnnotationRetention.SOURCE) internal final class Ann : kotlin.Annotation {
public constructor Ann(/*0*/ vararg i: kotlin.Int /*kotlin.IntArray*/) public constructor Ann(/*0*/ vararg i: kotlin.Int /*kotlin.IntArray*/)
internal final val i: kotlin.IntArray internal final val i: kotlin.IntArray
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -14,7 +14,7 @@ kotlin.annotation.annotation(repeatable = true) internal final class Ann : kotli
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
kotlin.annotation.annotation(repeatable = true) internal final class AnnAnn : kotlin.Annotation { kotlin.annotation.annotation(repeatable = true, retention = AnnotationRetention.SOURCE) internal final class AnnAnn : kotlin.Annotation {
public constructor AnnAnn(/*0*/ vararg i: Ann /*kotlin.Array<out Ann>*/) public constructor AnnAnn(/*0*/ vararg i: Ann /*kotlin.Array<out Ann>*/)
internal final val i: kotlin.Array<out Ann> internal final val i: kotlin.Array<out Ann>
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -21,10 +21,14 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ClassKind.ENUM_CLASS import org.jetbrains.kotlin.descriptors.ClassKind.ENUM_CLASS
import org.jetbrains.kotlin.descriptors.ClassKind.ENUM_ENTRY import org.jetbrains.kotlin.descriptors.ClassKind.ENUM_ENTRY
import org.jetbrains.kotlin.descriptors.ClassKind.OBJECT import org.jetbrains.kotlin.descriptors.ClassKind.OBJECT
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.constants.BooleanValue
import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.types.JetType import org.jetbrains.kotlin.types.JetType
public fun ClassDescriptor.getClassObjectReferenceTarget(): ClassDescriptor = getCompanionObjectDescriptor() ?: this public fun ClassDescriptor.getClassObjectReferenceTarget(): ClassDescriptor = getCompanionObjectDescriptor() ?: this
@@ -140,3 +144,19 @@ public fun CallableDescriptor.getOwnerForEffectiveDispatchReceiverParameter(): D
} }
return getDispatchReceiverParameter()?.getContainingDeclaration() return getDispatchReceiverParameter()?.getContainingDeclaration()
} }
public fun Annotated.isRepeatableAnnotation(): Boolean {
val annotationEntryDescriptor = annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.annotation) ?: return false
val repeatableArgumentValue = annotationEntryDescriptor.allValueArguments.entrySet().firstOrNull {
"repeatable" == it.key.name.asString()
}?.getValue() as? BooleanValue ?: return false // not repeatable by default
return repeatableArgumentValue.value
}
public fun Annotated.getAnnotationRetention(): KotlinRetention? {
val annotationEntryDescriptor = annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.annotation) ?: return null
val retentionArgumentValue = annotationEntryDescriptor.allValueArguments.entrySet().firstOrNull {
"retention" == it.key.name.asString()
}?.getValue() as? EnumValue ?: return null
return KotlinRetention.valueOf(retentionArgumentValue.value.name.asString())
}
+1 -1
View File
@@ -20,4 +20,4 @@ val BAZ = "baz"
val N = 0 val N = 0
target(AnnotationTarget.FILE) target(AnnotationTarget.FILE)
annotation(repeatable = true) class myAnnotation(val i: Int, val s: String) annotation(repeatable = true, retention = AnnotationRetention.SOURCE) class myAnnotation(val i: Int, val s: String)
@@ -32,6 +32,6 @@ annotation class a
target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASSIFIER, target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASSIFIER,
AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE)
annotation(repeatable = true) class b(val e: E) annotation(repeatable = true, retention = AnnotationRetention.SOURCE) class b(val e: E)
enum class E { E1 E2 } enum class E { E1 E2 }
@@ -44,19 +44,9 @@ PsiJetFileStubImpl[package=]
CLASS_BODY: CLASS_BODY:
OBJECT_DECLARATION:[fqName=Annotations.Companion, isCompanion=true, isLocal=false, isObjectLiteral=false, isTopLevel=false, name=Companion, superNames=[]] OBJECT_DECLARATION:[fqName=Annotations.Companion, isCompanion=true, isLocal=false, isObjectLiteral=false, isTopLevel=false, name=Companion, superNames=[]]
MODIFIER_LIST:[private companion] MODIFIER_LIST:[private companion]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=b]
CONSTRUCTOR_CALLEE:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=b]
CLASS_BODY: CLASS_BODY:
PROPERTY:[fqName=Annotations.c, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=c] PROPERTY:[fqName=Annotations.c, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=c]
MODIFIER_LIST:[private final] MODIFIER_LIST:[private final]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=b]
CONSTRUCTOR_CALLEE:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=b]
TYPE_REFERENCE: TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false] USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false] USER_TYPE:[isAbsoluteInRootPackage=false]
@@ -133,11 +123,6 @@ PsiJetFileStubImpl[package=]
TYPE_REFERENCE: TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false] USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=a] REFERENCE_EXPRESSION:[referencedName=a]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=b]
CONSTRUCTOR_CALLEE:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=b]
VALUE_PARAMETER_LIST: VALUE_PARAMETER_LIST:
VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=p1] VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=p1]
MODIFIER_LIST:[] MODIFIER_LIST:[]
@@ -200,15 +185,5 @@ PsiJetFileStubImpl[package=]
TYPE_REFERENCE: TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false] USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=a] REFERENCE_EXPRESSION:[referencedName=a]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=b]
CONSTRUCTOR_CALLEE:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=b]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=b]
CONSTRUCTOR_CALLEE:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=b]
VALUE_PARAMETER_LIST: VALUE_PARAMETER_LIST:
CLASS_BODY: CLASS_BODY: