diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmSerializerExtension.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmSerializerExtension.java index 566e5b9426b..5599c16be1e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmSerializerExtension.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmSerializerExtension.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen; import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; @@ -52,6 +53,14 @@ public class JvmSerializerExtension extends SerializerExtension { this.typeMapper = typeMapper; } + @Override + public void serializeClass(@NotNull ClassDescriptor descriptor, @NotNull ProtoBuf.Class.Builder proto, @NotNull StringTable stringTable) { + AnnotationDescriptor annotation = descriptor.getAnnotations().findAnnotation(KotlinBuiltIns.FQ_NAMES.annotation); + if (annotation != null) { + proto.addExtension(JvmProtoBuf.classAnnotation, annotationSerializer.serializeAnnotation(annotation, stringTable)); + } + } + @Override public void serializeCallable( @NotNull CallableMemberDescriptor callable, diff --git a/compiler/tests/org/jetbrains/kotlin/serialization/jvm/DebugJvmProtoBuf.java b/compiler/tests/org/jetbrains/kotlin/serialization/jvm/DebugJvmProtoBuf.java index 032991632be..89fa31ea8fc 100644 --- a/compiler/tests/org/jetbrains/kotlin/serialization/jvm/DebugJvmProtoBuf.java +++ b/compiler/tests/org/jetbrains/kotlin/serialization/jvm/DebugJvmProtoBuf.java @@ -12,6 +12,7 @@ public final class DebugJvmProtoBuf { registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.implClassName); registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.typeAnnotation); registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.index); + registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.classAnnotation); } public interface JvmTypeOrBuilder extends com.google.protobuf.MessageOrBuilder { @@ -3785,6 +3786,17 @@ public final class DebugJvmProtoBuf { .newFileScopedGeneratedExtension( java.lang.Integer.class, null); + public static final int CLASS_ANNOTATION_FIELD_NUMBER = 100; + /** + * extend .org.jetbrains.kotlin.serialization.Class { ... } + */ + public static final + com.google.protobuf.GeneratedMessage.GeneratedExtension< + org.jetbrains.kotlin.serialization.DebugProtoBuf.Class, + java.util.List> classAnnotation = com.google.protobuf.GeneratedMessage + .newFileScopedGeneratedExtension( + org.jetbrains.kotlin.serialization.DebugProtoBuf.Annotation.class, + org.jetbrains.kotlin.serialization.DebugProtoBuf.Annotation.getDefaultInstance()); private static com.google.protobuf.Descriptors.Descriptor internal_static_org_jetbrains_kotlin_serialization_jvm_JvmType_descriptor; private static @@ -3853,8 +3865,11 @@ public final class DebugJvmProtoBuf { "s.kotlin.serialization.Type\030d \003(\0132..org." + "jetbrains.kotlin.serialization.Annotatio" + "n:J\n\005index\022;.org.jetbrains.kotlin.serial" + - "ization.Callable.ValueParameter\030d \001(\005B\022B", - "\020DebugJvmProtoBuf" + "ization.Callable.ValueParameter\030d \001(\005:s\n", + "\020class_annotation\022).org.jetbrains.kotlin" + + ".serialization.Class\030d \003(\0132..org.jetbrai" + + "ns.kotlin.serialization.AnnotationB\022B\020De" + + "bugJvmProtoBuf" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -3890,6 +3905,7 @@ public final class DebugJvmProtoBuf { implClassName.internalInit(descriptor.getExtensions().get(2)); typeAnnotation.internalInit(descriptor.getExtensions().get(3)); index.internalInit(descriptor.getExtensions().get(4)); + classAnnotation.internalInit(descriptor.getExtensions().get(5)); return null; } }; diff --git a/core/builtins/src/kotlin/annotation/Annotations.kt b/core/builtins/src/kotlin/annotation/Annotations.kt index c23799585bc..8732725225d 100644 --- a/core/builtins/src/kotlin/annotation/Annotations.kt +++ b/core/builtins/src/kotlin/annotation/Annotations.kt @@ -85,7 +85,7 @@ public annotation class target(vararg val allowedTargets: AnnotationTarget) * @property repeatable true if annotation is repeatable (applicable twice or more on a single code element), otherwise false (default) */ target(AnnotationTarget.ANNOTATION_CLASS) -public annotation class annotation ( +public annotation(retention = AnnotationRetention.SOURCE) class annotation ( val retention: AnnotationRetention = AnnotationRetention.RUNTIME, val repeatable: Boolean = false ) diff --git a/core/descriptor.loader.java/src/jvm_descriptors.proto b/core/descriptor.loader.java/src/jvm_descriptors.proto index 44dc9ccfe3b..5e1b3fea4d0 100644 --- a/core/descriptor.loader.java/src/jvm_descriptors.proto +++ b/core/descriptor.loader.java/src/jvm_descriptors.proto @@ -93,3 +93,7 @@ extend org.jetbrains.kotlin.serialization.Callable.ValueParameter { // Index of the corresponding parameter of this method in JVM (counting receiver parameters, enum constructor synthetic parameters, etc.) optional int32 index = 100; } + +extend org.jetbrains.kotlin.serialization.Class { + repeated Annotation class_annotation = 100; +} diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt index a867de852c4..53470c8bac8 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.serialization.deserialization.AnnotationDeserializer import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter import org.jetbrains.kotlin.serialization.deserialization.NameResolver import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies +import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.types.ErrorUtils import java.util.ArrayList @@ -50,6 +51,18 @@ public class BinaryClassAnnotationAndConstantLoaderImpl( private val annotationDeserializer = AnnotationDeserializer(module) private val factory = ConstantValueFactory(module.builtIns) + override fun loadClassAnnotations( + classProto: ProtoBuf.Class, + nameResolver: NameResolver + ): List { + val binaryAnnotationDescriptors = super.loadClassAnnotations(classProto, nameResolver) + val serializedAnnotations = classProto.getExtension(JvmProtoBuf.classAnnotation).orEmpty() + val serializedAnnotationDescriptors = serializedAnnotations.map { + annotationDeserializer.deserializeAnnotation(it, nameResolver) + } + return binaryAnnotationDescriptors + serializedAnnotationDescriptors + } + override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationDescriptor = annotationDeserializer.deserializeAnnotation(proto, nameResolver) diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/JvmProtoBuf.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/JvmProtoBuf.java index b5305d7af5c..2c790c1f6dc 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/JvmProtoBuf.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/JvmProtoBuf.java @@ -12,6 +12,7 @@ public final class JvmProtoBuf { registry.add(org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.implClassName); registry.add(org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.typeAnnotation); registry.add(org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.index); + registry.add(org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.classAnnotation); } public interface JvmTypeOrBuilder extends com.google.protobuf.MessageLiteOrBuilder { @@ -2880,6 +2881,21 @@ public final class JvmProtoBuf { null, 100, com.google.protobuf.WireFormat.FieldType.INT32); + public static final int CLASS_ANNOTATION_FIELD_NUMBER = 100; + /** + * extend .org.jetbrains.kotlin.serialization.Class { ... } + */ + public static final + com.google.protobuf.GeneratedMessageLite.GeneratedExtension< + org.jetbrains.kotlin.serialization.ProtoBuf.Class, + java.util.List> classAnnotation = com.google.protobuf.GeneratedMessageLite + .newRepeatedGeneratedExtension( + org.jetbrains.kotlin.serialization.ProtoBuf.Class.getDefaultInstance(), + org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.getDefaultInstance(), + null, + 100, + com.google.protobuf.WireFormat.FieldType.MESSAGE, + false); static { } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt index 1d19cf14dce..cd5f547e377 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.serialization.deserialization.AnnotationAndConstantL import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter import org.jetbrains.kotlin.serialization.deserialization.NameResolver +import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf import org.jetbrains.kotlin.storage.LockBasedStorageManager class ClsStubBuilderComponents( @@ -92,6 +93,17 @@ class AnnotationLoaderForStubBuilder( errorReporter: ErrorReporter ) : AbstractBinaryClassAnnotationAndConstantLoader( LockBasedStorageManager.NO_LOCKS, kotlinClassFinder, errorReporter) { + + override fun loadClassAnnotations( + classProto: ProtoBuf.Class, + nameResolver: NameResolver + ): List { + val binaryAnnotationDescriptors = super.loadClassAnnotations(classProto, nameResolver) + val serializedAnnotations = classProto.getExtension(JvmProtoBuf.classAnnotation).orEmpty() + val serializedAnnotationDescriptors = serializedAnnotations.map { nameResolver.getClassId(it.id) } + return binaryAnnotationDescriptors + serializedAnnotationDescriptors + } + override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): ClassId = nameResolver.getClassId(proto.getId()) diff --git a/idea/testData/decompiler/stubBuilder/AnnotationClass/AnnotationClass.txt b/idea/testData/decompiler/stubBuilder/AnnotationClass/AnnotationClass.txt index f9f3011a981..77b1fcb9c83 100644 --- a/idea/testData/decompiler/stubBuilder/AnnotationClass/AnnotationClass.txt +++ b/idea/testData/decompiler/stubBuilder/AnnotationClass/AnnotationClass.txt @@ -15,17 +15,6 @@ PsiJetFileStubImpl[package=test.a] REFERENCE_EXPRESSION:[referencedName=kotlin] REFERENCE_EXPRESSION:[referencedName=annotation] REFERENCE_EXPRESSION:[referencedName=annotation] - ANNOTATION_ENTRY:[hasValueArguments=false, shortName=Retention] - CONSTRUCTOR_CALLEE: - TYPE_REFERENCE: - USER_TYPE:[isAbsoluteInRootPackage=false] - USER_TYPE:[isAbsoluteInRootPackage=false] - USER_TYPE:[isAbsoluteInRootPackage=false] - USER_TYPE:[isAbsoluteInRootPackage=false] - REFERENCE_EXPRESSION:[referencedName=java] - REFERENCE_EXPRESSION:[referencedName=lang] - REFERENCE_EXPRESSION:[referencedName=annotation] - REFERENCE_EXPRESSION:[referencedName=Retention] PRIMARY_CONSTRUCTOR: MODIFIER_LIST:[public] VALUE_PARAMETER_LIST: diff --git a/idea/testData/decompiler/stubBuilder/ClassObject/ClassObject.txt b/idea/testData/decompiler/stubBuilder/ClassObject/ClassObject.txt index d9f5b894866..536cba0ec46 100644 --- a/idea/testData/decompiler/stubBuilder/ClassObject/ClassObject.txt +++ b/idea/testData/decompiler/stubBuilder/ClassObject/ClassObject.txt @@ -123,17 +123,6 @@ PsiJetFileStubImpl[package=test.class_object] REFERENCE_EXPRESSION:[referencedName=kotlin] REFERENCE_EXPRESSION:[referencedName=annotation] REFERENCE_EXPRESSION:[referencedName=annotation] - ANNOTATION_ENTRY:[hasValueArguments=false, shortName=Retention] - CONSTRUCTOR_CALLEE: - TYPE_REFERENCE: - USER_TYPE:[isAbsoluteInRootPackage=false] - USER_TYPE:[isAbsoluteInRootPackage=false] - USER_TYPE:[isAbsoluteInRootPackage=false] - USER_TYPE:[isAbsoluteInRootPackage=false] - REFERENCE_EXPRESSION:[referencedName=java] - REFERENCE_EXPRESSION:[referencedName=lang] - REFERENCE_EXPRESSION:[referencedName=annotation] - REFERENCE_EXPRESSION:[referencedName=Retention] PRIMARY_CONSTRUCTOR: MODIFIER_LIST:[public] VALUE_PARAMETER_LIST: diff --git a/plugins/annotation-collector/testData/collectToFile/annotationInSameFile/annotations.txt b/plugins/annotation-collector/testData/collectToFile/annotationInSameFile/annotations.txt index 45399e7808f..6e5a0ae00c6 100644 --- a/plugins/annotation-collector/testData/collectToFile/annotationInSameFile/annotations.txt +++ b/plugins/annotation-collector/testData/collectToFile/annotationInSameFile/annotations.txt @@ -1,8 +1,6 @@ -a kotlin.annotation.annotation 0 +a java.lang.annotation.Retention 0 p org.test 0 c 0 0/SomeAnnotation -a java.lang.annotation.Retention 1 -c 1 0/SomeAnnotation -a org.test.SomeAnnotation 2 -c 2 0/SomeClass -m 2 0/SomeClass annotatedFunction +a org.test.SomeAnnotation 1 +c 1 0/SomeClass +m 1 0/SomeClass annotatedFunction