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