diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java index 1c6f9e50215..ec8609d9fea 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java @@ -34,9 +34,11 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.constants.*; import org.jetbrains.jet.lang.resolve.constants.StringValue; +import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.*; @@ -288,23 +290,19 @@ public abstract class AnnotationCodegen { @NotNull private RetentionPolicy getRetentionPolicy(@NotNull Annotated descriptor) { - for (AnnotationDescriptor annotationDescriptor : descriptor.getAnnotations()) { - String internalName = typeMapper.mapType(annotationDescriptor.getType()).getInternalName(); - if ("java/lang/annotation/Retention".equals(internalName)) { - Collection> valueArguments = annotationDescriptor.getAllValueArguments().values(); - assert valueArguments.size() == 1 : "Retention should have an argument: " + annotationDescriptor; - CompileTimeConstant compileTimeConstant = valueArguments.iterator().next(); - assert compileTimeConstant instanceof EnumValue : "Retention argument should be enum value: " + compileTimeConstant; - ClassDescriptor enumEntry = ((EnumValue) compileTimeConstant).getValue(); - JetType classObjectType = enumEntry.getClassObjectType(); - assert classObjectType != null : "Enum entry should have a class object: " + enumEntry; - assert "java/lang/annotation/RetentionPolicy".equals(typeMapper.mapType(classObjectType).getInternalName()) : - "Retention argument should be of type RetentionPolicy: " + enumEntry; - return RetentionPolicy.valueOf(enumEntry.getName().asString()); - } - } + AnnotationDescriptor retentionAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Retention.class.getName())); + if (retentionAnnotation == null) return RetentionPolicy.CLASS; - return RetentionPolicy.CLASS; + Collection> valueArguments = retentionAnnotation.getAllValueArguments().values(); + assert valueArguments.size() == 1 : "Retention should have an argument: " + retentionAnnotation + " on " + descriptor; + CompileTimeConstant compileTimeConstant = valueArguments.iterator().next(); + assert compileTimeConstant instanceof EnumValue : "Retention argument should be enum value: " + compileTimeConstant; + ClassDescriptor enumEntry = ((EnumValue) compileTimeConstant).getValue(); + JetType classObjectType = enumEntry.getClassObjectType(); + assert classObjectType != null : "Enum entry should have a class object: " + enumEntry; + assert "java/lang/annotation/RetentionPolicy".equals(typeMapper.mapType(classObjectType).getInternalName()) : + "Retention argument should be of type RetentionPolicy: " + enumEntry; + return RetentionPolicy.valueOf(enumEntry.getName().asString()); } @NotNull diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index 0aa9e85cf68..f58015c12cc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -21,9 +21,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.codegen.RangeCodegenUtil; import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; -import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor; -import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.resolve.AnnotationUtils; import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; @@ -228,16 +227,9 @@ public class IntrinsicMethods { } } - for (AnnotationDescriptor annotation : descriptor.getAnnotations()) { - ClassifierDescriptor classifierDescriptor = annotation.getType().getConstructor().getDeclarationDescriptor(); - assert classifierDescriptor != null; - if ("Intrinsic".equals(classifierDescriptor.getName().asString())) { - String value = (String) annotation.getAllValueArguments().values().iterator().next().getValue(); - IntrinsicMethod result = namedMethods.get(value); - if (result != null) return result; - } - } + String value = AnnotationUtils.getIntrinsicAnnotationArgument(descriptor); + if (value == null) return null; - return null; + return namedMethods.get(value); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationUtils.java index 7aef6be000f..8eeb65131de 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationUtils.java @@ -16,20 +16,25 @@ package org.jetbrains.jet.lang.resolve; +import jet.runtime.Intrinsic; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; +import org.jetbrains.jet.lang.descriptors.annotations.Annotated; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.descriptors.annotations.Annotations; import org.jetbrains.jet.lang.psi.JetParameter; import org.jetbrains.jet.lang.psi.JetTypeReference; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import java.util.Collection; import java.util.List; import static org.jetbrains.jet.lang.diagnostics.Errors.INVALID_TYPE_OF_ANNOTATION_MEMBER; @@ -91,26 +96,24 @@ public class AnnotationUtils { return false; } + @Nullable + public static String getIntrinsicAnnotationArgument(@NotNull Annotated annotatedDescriptor) { + AnnotationDescriptor intrinsicAnnotation = annotatedDescriptor.getAnnotations().findAnnotation(new FqName(Intrinsic.class.getName())); + if (intrinsicAnnotation == null) return null; + + Collection> values = intrinsicAnnotation.getAllValueArguments().values(); + if (values.isEmpty()) return null; + + Object value = values.iterator().next().getValue(); + return value instanceof String ? (String) value : null; + } + public static boolean isArrayMethodCall(@NotNull ResolvedCall resolvedCall) { - Annotations annotations = resolvedCall.getResultingDescriptor().getOriginal().getAnnotations(); - for (AnnotationDescriptor annotation : annotations) { - //noinspection ConstantConditions - if ("Intrinsic".equals(annotation.getType().getConstructor().getDeclarationDescriptor().getName().asString())) { - return "kotlin.arrays.array".equals(annotation.getAllValueArguments().values().iterator().next().getValue()); - } - } - return false; + return "kotlin.arrays.array".equals(getIntrinsicAnnotationArgument(resolvedCall.getResultingDescriptor().getOriginal())); } public static boolean isJavaClassMethodCall(@NotNull ResolvedCall resolvedCall) { - Annotations annotations = resolvedCall.getResultingDescriptor().getOriginal().getAnnotations(); - for (AnnotationDescriptor annotation : annotations) { - //noinspection ConstantConditions - if ("Intrinsic".equals(annotation.getType().getConstructor().getDeclarationDescriptor().getName().asString())) { - return "kotlin.javaClass.function".equals(annotation.getAllValueArguments().values().iterator().next().getValue()); - } - } - return false; + return "kotlin.javaClass.function".equals(getIntrinsicAnnotationArgument(resolvedCall.getResultingDescriptor().getOriginal())); } public static boolean isPropertyCompileTimeConstant(@NotNull PropertyDescriptor descriptor) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index c31adf87bb3..83cacc19f4b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -618,14 +618,13 @@ public class OverrideResolver { @NotNull private JetAnnotationEntry findDataAnnotationForDataClass(@NotNull DeclarationDescriptor dataClass) { ClassDescriptor stdDataClassAnnotation = KotlinBuiltIns.getInstance().getDataClassAnnotation(); - for (AnnotationDescriptor annotation : dataClass.getAnnotations()) { - if (stdDataClassAnnotation.equals(annotation.getType().getConstructor().getDeclarationDescriptor())) { - return BindingContextUtils.getNotNull(trace.getBindingContext(), - BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT, - annotation); - } + AnnotationDescriptor annotation = dataClass.getAnnotations().findAnnotation(DescriptorUtils.getFqNameSafe(stdDataClassAnnotation)); + if (annotation == null) { + throw new IllegalStateException("No data annotation is found for data class " + dataClass); } - throw new IllegalStateException("No data annotation is found for data class"); + return BindingContextUtils.getNotNull(trace.getBindingContext(), + BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT, + annotation); } private CallableMemberDescriptor findInvisibleOverriddenDescriptor(CallableMemberDescriptor declared, ClassDescriptor declaringClass) { diff --git a/compiler/tests/org/jetbrains/jet/asJava/NullabilityAnnotationsTest.java b/compiler/tests/org/jetbrains/jet/asJava/NullabilityAnnotationsTest.java index cf7392e3275..fb9e8ed0afb 100644 --- a/compiler/tests/org/jetbrains/jet/asJava/NullabilityAnnotationsTest.java +++ b/compiler/tests/org/jetbrains/jet/asJava/NullabilityAnnotationsTest.java @@ -39,6 +39,7 @@ public class NullabilityAnnotationsTest extends KotlinAsJavaTestBase { @Override protected void extraConfiguration(@NotNull CompilerConfiguration configuration) { configuration.add(JVMConfigurationKeys.CLASSPATH_KEY, JetTestUtils.getAnnotationsJar()); + configuration.add(JVMConfigurationKeys.CLASSPATH_KEY, JetTestUtils.findMockJdkRtJar()); } public void test_DefaultPackage() throws Exception { diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/ExpectedLoadErrorsUtil.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/ExpectedLoadErrorsUtil.java index f8dcf18fec3..fce31e8c017 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/ExpectedLoadErrorsUtil.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/ExpectedLoadErrorsUtil.java @@ -23,9 +23,9 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.java.JavaBindingContext; +import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.renderer.DescriptorRenderer; @@ -81,21 +81,16 @@ public class ExpectedLoadErrorsUtil { } private Void visitDeclaration(@NotNull DeclarationDescriptor descriptor) { - for (AnnotationDescriptor annotation : descriptor.getAnnotations()) { - ClassDescriptor annotationClass = (ClassDescriptor) annotation.getType().getConstructor().getDeclarationDescriptor(); - assert annotationClass != null; + AnnotationDescriptor annotation = descriptor.getAnnotations().findAnnotation(new FqName(ANNOTATION_CLASS_NAME)); + if (annotation == null) return null; - if (DescriptorUtils.getFqName(annotationClass).asString().equals(ANNOTATION_CLASS_NAME)) { + // we expect exactly one annotation argument + CompileTimeConstant argument = annotation.getAllValueArguments().values().iterator().next(); - // we expect exactly one annotation argument - CompileTimeConstant argument = annotation.getAllValueArguments().values().iterator().next(); + String error = (String) argument.getValue(); + List errors = Arrays.asList(error.split("\\|")); - String error = (String) argument.getValue(); - List errors = Arrays.asList(error.split("\\|")); - - map.put(descriptor, errors); - } - } + map.put(descriptor, errors); return null; } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java index 91d53cbe373..355ecc75460 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java @@ -22,7 +22,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.PlatformToKotlinClassMap; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.Annotations; import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl; import org.jetbrains.jet.lang.resolve.DescriptorUtils; @@ -932,13 +931,8 @@ public class KotlinBuiltIns { } static boolean containsAnnotation(DeclarationDescriptor descriptor, ClassDescriptor annotationClass) { - Annotations annotations = descriptor.getOriginal().getAnnotations(); - for (AnnotationDescriptor annotation : annotations) { - if (annotationClass.equals(annotation.getType().getConstructor().getDeclarationDescriptor())) { - return true; - } - } - return false; + FqName fqName = DescriptorUtils.getFqName(annotationClass).toSafe(); + return descriptor.getOriginal().getAnnotations().findAnnotation(fqName) != null; } public boolean isVolatile(@NotNull PropertyDescriptor descriptor) { diff --git a/idea/src/org/jetbrains/jet/plugin/highlighter/DeprecatedAnnotationVisitor.java b/idea/src/org/jetbrains/jet/plugin/highlighter/DeprecatedAnnotationVisitor.java index 2dba4a48ec8..4e663ac0c71 100644 --- a/idea/src/org/jetbrains/jet/plugin/highlighter/DeprecatedAnnotationVisitor.java +++ b/idea/src/org/jetbrains/jet/plugin/highlighter/DeprecatedAnnotationVisitor.java @@ -220,14 +220,8 @@ public class DeprecatedAnnotationVisitor extends AfterAnalysisHighlightingVisito @Nullable private static AnnotationDescriptor getDeprecated(DeclarationDescriptor descriptor) { - for (AnnotationDescriptor annotation : descriptor.getAnnotations()) { - ClassDescriptor jetDeprecated = KotlinBuiltIns.getInstance().getDeprecatedAnnotation(); - ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(annotation.getType()); - if (jetDeprecated.equals(classDescriptor)) { - return annotation; - } - } - return null; + ClassDescriptor jetDeprecated = KotlinBuiltIns.getInstance().getDeprecatedAnnotation(); + return descriptor.getAnnotations().findAnnotation(DescriptorUtils.getFqNameSafe(jetDeprecated)); } private static String composeTooltipString(@NotNull DeclarationDescriptor declarationDescriptor, @NotNull AnnotationDescriptor descriptor) { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/AnnotationsUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/AnnotationsUtils.java index 8b459e61f04..fcf87056279 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/AnnotationsUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/AnnotationsUtils.java @@ -21,8 +21,8 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.name.FqName; import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getContainingClass; @@ -85,20 +85,7 @@ public final class AnnotationsUtils { @Nullable private static AnnotationDescriptor getAnnotationByName(@NotNull DeclarationDescriptor descriptor, @NotNull String fqn) { - for (AnnotationDescriptor annotationDescriptor : descriptor.getAnnotations()) { - if (getAnnotationClassFQName(annotationDescriptor).equals(fqn)) { - return annotationDescriptor; - } - } - return null; - } - - @NotNull - private static String getAnnotationClassFQName(@NotNull AnnotationDescriptor annotationDescriptor) { - DeclarationDescriptor annotationDeclaration = - annotationDescriptor.getType().getConstructor().getDeclarationDescriptor(); - assert annotationDeclaration != null : "Annotation supposed to have a declaration"; - return DescriptorUtils.getFqName(annotationDeclaration).asString(); + return descriptor.getAnnotations().findAnnotation(new FqName(fqn)); } public static boolean isNativeObject(@NotNull DeclarationDescriptor descriptor) {