From 1032e3a17ca63f31fcdbe4cfd7afeea80b35eba1 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Wed, 8 Jan 2020 08:30:29 +0100 Subject: [PATCH] Support field type annotations #KT-35843 Fixed --- .../kotlin/codegen/AnnotationCodegen.java | 65 ++++++---- .../DefaultParameterValueSubstitutor.kt | 6 +- .../kotlin/codegen/FunctionCodegen.java | 10 +- .../codegen/ImplementationBodyCodegen.java | 6 +- .../kotlin/codegen/MemberCodegen.java | 2 +- .../kotlin/codegen/PackagePartCodegen.java | 2 +- .../kotlin/codegen/PropertyCodegen.java | 5 +- .../jetbrains/kotlin/codegen/ScriptCodegen.kt | 5 +- .../asmLike/typeAnnotations/defaultArgs.txt | 2 +- .../asmLike/typeAnnotations/jvmOverload.txt | 6 +- .../asmLike/typeAnnotations/jvmStatic.txt | 6 +- .../asmLike/typeAnnotations/property.kt | 9 ++ .../asmLike/typeAnnotations/property.txt | 121 ++++++++++++++++++ .../AbstractAsmLikeInstructionListingTest.kt | 19 ++- ...smLikeInstructionListingTestGenerated.java | 5 + 15 files changed, 221 insertions(+), 48 deletions(-) create mode 100644 compiler/testData/codegen/asmLike/typeAnnotations/property.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index 1eea550db0d..802c931326a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -88,17 +88,23 @@ public abstract class AnnotationCodegen { private final InnerClassConsumer innerClassConsumer; private final KotlinTypeMapper typeMapper; private final ModuleDescriptor module; + private final GenerationState state; private AnnotationCodegen(@NotNull InnerClassConsumer innerClassConsumer, @NotNull GenerationState state) { this.innerClassConsumer = innerClassConsumer; this.typeMapper = state.getTypeMapper(); this.module = state.getModule(); + this.state = state; } /** * @param returnType can be null if not applicable (e.g. {@code annotated} is a class) */ - public void genAnnotations(@Nullable Annotated annotated, @Nullable Type returnType) { + public void genAnnotations( + @Nullable Annotated annotated, + @Nullable Type returnType, + @Nullable KotlinType typeForTypeAnnotations + ) { if (annotated == null) return; Set annotationDescriptorsAlreadyPresent = new HashSet<>(); @@ -126,13 +132,14 @@ public abstract class AnnotationCodegen { } } - String descriptor = genAnnotation(annotation); + String descriptor = genAnnotation(annotation, null, false); if (descriptor != null) { annotationDescriptorsAlreadyPresent.add(descriptor); } } generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent); + generateTypeAnnotations(typeForTypeAnnotations); } private void generateAdditionalAnnotations( @@ -322,7 +329,11 @@ public abstract class AnnotationCodegen { } @Nullable - private String genAnnotation(@NotNull AnnotationDescriptor annotationDescriptor) { + private String genAnnotation( + @NotNull AnnotationDescriptor annotationDescriptor, + @Nullable TypePath path, + boolean isTypeAnnotation + ) { ClassDescriptor classDescriptor = getAnnotationClass(annotationDescriptor); assert classDescriptor != null : "Annotation descriptor has no class: " + annotationDescriptor; RetentionPolicy rp = getRetentionPolicy(classDescriptor); @@ -340,7 +351,9 @@ public abstract class AnnotationCodegen { innerClassConsumer.addInnerClassInfoFromAnnotation(classDescriptor); String asmTypeDescriptor = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor(); - AnnotationVisitor annotationVisitor = visitAnnotation(asmTypeDescriptor, rp == RetentionPolicy.RUNTIME); + AnnotationVisitor annotationVisitor = isTypeAnnotation + ? visitTypeAnnotation(asmTypeDescriptor, path, rp == RetentionPolicy.RUNTIME) + : visitAnnotation(asmTypeDescriptor, rp == RetentionPolicy.RUNTIME); genAnnotationArguments(annotationDescriptor, annotationVisitor); annotationVisitor.visitEnd(); @@ -553,6 +566,11 @@ public abstract class AnnotationCodegen { @NotNull abstract AnnotationVisitor visitAnnotation(String descr, boolean visible); + @NotNull + AnnotationVisitor visitTypeAnnotation(String descr, TypePath path, boolean visible) { + throw new RuntimeException("Not implemented"); + } + public static AnnotationCodegen forClass( @NotNull ClassVisitor cv, @NotNull InnerClassConsumer innerClassConsumer, @@ -578,6 +596,12 @@ public abstract class AnnotationCodegen { AnnotationVisitor visitAnnotation(String descr, boolean visible) { return safe(mv.visitAnnotation(descr, visible)); } + + @NotNull + @Override + AnnotationVisitor visitTypeAnnotation(String descr, TypePath path, boolean visible) { + return safe(mv.visitTypeAnnotation(TypeReference.newTypeReference(TypeReference.METHOD_RETURN).getValue(), path, descr, visible)); + } }; } @@ -592,6 +616,12 @@ public abstract class AnnotationCodegen { AnnotationVisitor visitAnnotation(String descr, boolean visible) { return safe(fv.visitAnnotation(descr, visible)); } + + @NotNull + @Override + AnnotationVisitor visitTypeAnnotation(String descr, TypePath path, boolean visible) { + return safe(fv.visitTypeAnnotation(TypeReference.newTypeReference(TypeReference.FIELD).getValue(), path, descr, visible)); + } }; } @@ -607,6 +637,12 @@ public abstract class AnnotationCodegen { AnnotationVisitor visitAnnotation(String descr, boolean visible) { return safe(mv.visitParameterAnnotation(parameter, descr, visible)); } + + @NotNull + @Override + AnnotationVisitor visitTypeAnnotation(String descr, TypePath path, boolean visible) { + return safe(mv.visitTypeAnnotation(TypeReference.newFormalParameterReference(parameter).getValue(), path, descr, visible)); + } }; } @@ -629,13 +665,7 @@ public abstract class AnnotationCodegen { return av == null ? NO_ANNOTATION_VISITOR : av; } - public static void writeTypeAnnotations( - @NotNull MethodVisitor mv, - @NotNull GenerationState state, - int parameterIndex, - @Nullable KotlinType type, - @NotNull InnerClassConsumer innerClassConsumer - ) { + private void generateTypeAnnotations(@Nullable KotlinType type) { if (type == null || state.getTarget() == JvmTarget.JVM_1_6 || !state.getConfiguration().getBoolean(JVMConfigurationKeys.EMIT_JVM_TYPE_ANNOTATIONS)) { @@ -646,18 +676,7 @@ public abstract class AnnotationCodegen { new TypeAnnotationCollector().collectTypeAnnotations(type, TypeReference.METHOD_FORMAL_PARAMETER); for (TypePathInfo info : infos) { for (AnnotationDescriptor annotationDescriptor : info.getAnnotations()) { - TypeReference typeReference = parameterIndex != -1 ? - TypeReference.newFormalParameterReference(parameterIndex) - : TypeReference.newTypeReference(TypeReference.METHOD_RETURN); - - AnnotationCodegen codegen = new AnnotationCodegen(innerClassConsumer, state) { - @NotNull - @Override - AnnotationVisitor visitAnnotation(String descr, boolean visible) { - return safe(mv.visitTypeAnnotation(typeReference.getValue(), info.getPath(), descr, visible)); - } - }; - codegen.genAnnotation(annotationDescriptor); + genAnnotation(annotationDescriptor, info.getPath(), true); } } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt index d05dc98b780..7b61696136f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt @@ -150,7 +150,11 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) { FunctionCodegen.getThrownExceptions(functionDescriptor, typeMapper) ) - AnnotationCodegen.forMethod(mv, memberCodegen, state).genAnnotations(functionDescriptor, signature.returnType) + AnnotationCodegen.forMethod(mv, memberCodegen, state).genAnnotations( + functionDescriptor, + signature.returnType, + functionDescriptor.returnType + ) if (state.classBuilderMode == ClassBuilderMode.KAPT3) { mv.visitAnnotation(ANNOTATION_TYPE_DESCRIPTOR_FOR_JVM_OVERLOADS_GENERATED_METHODS, false) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 145aa264a9e..cb91fe62edf 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -303,7 +303,9 @@ public class FunctionCodegen { annotationsOwner = functionDescriptor; } - AnnotationCodegen.forMethod(mv, memberCodegen, state).genAnnotations(annotationsOwner, asmMethod.getReturnType()); + AnnotationCodegen.forMethod(mv, memberCodegen, state) + .genAnnotations(annotationsOwner, asmMethod.getReturnType(), functionDescriptor.getReturnType()); + generateParameterAnnotations(annotationsOwner, mv, jvmSignature, memberCodegen, state); } @@ -544,13 +546,9 @@ public class FunctionCodegen { //noinspection ConstantConditions int parameterIndex = i - syntheticParameterCount; AnnotationCodegen.forParameter(parameterIndex, mv, innerClassConsumer, state) - .genAnnotations(annotated, parameterSignature.getAsmType()); - - AnnotationCodegen.writeTypeAnnotations(mv, state, parameterIndex, annotated.getType(), innerClassConsumer); + .genAnnotations(annotated, parameterSignature.getAsmType(), annotated.getReturnType()); } } - - AnnotationCodegen.writeTypeAnnotations(mv, state, -1, functionDescriptor.getReturnType(), innerClassConsumer); } @Nullable diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 9cb02093d06..85de25c16aa 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -232,7 +232,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { writeEnclosingMethod(); - AnnotationCodegen.forClass(v.getVisitor(), this, state).genAnnotations(descriptor, null); + AnnotationCodegen.forClass(v.getVisitor(), this, state).genAnnotations(descriptor, null, null); generateEnumEntries(); } @@ -905,7 +905,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { type.getDescriptor(), typeMapper.mapFieldSignature(property.getType(), property), info.defaultValue); - AnnotationCodegen.forField(fv, this, state).genAnnotations(property, type); + AnnotationCodegen.forField(fv, this, state).genAnnotations(property, type, null); //This field are always static and final so if it has constant initializer don't do anything in clinit, //field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4 @@ -1087,7 +1087,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { int isDeprecated = KotlinBuiltIns.isDeprecated(descriptor) ? ACC_DEPRECATED : 0; FieldVisitor fv = v.newField(JvmDeclarationOriginKt.OtherOrigin(enumEntry, descriptor), ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL | isDeprecated, descriptor.getName().asString(), classAsmType.getDescriptor(), null, null); - AnnotationCodegen.forField(fv, this, state).genAnnotations(descriptor, null); + AnnotationCodegen.forField(fv, this, state).genAnnotations(descriptor, null, null); } initializeEnumConstants(enumEntries); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 37dbce6f074..b6d6e71c0cb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -261,7 +261,7 @@ public abstract class MemberCodegen { } } Annotated annotatedFile = new AnnotatedImpl(Annotations.Companion.create(fileAnnotationDescriptors)); - AnnotationCodegen.forClass(v.getVisitor(), this, state).genAnnotations(annotatedFile, null); + AnnotationCodegen.forClass(v.getVisitor(), this, state).genAnnotations(annotatedFile, null, null); } @Override diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java index ed916230a59..1c89ab3d71e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java @@ -270,7 +270,7 @@ public class PropertyCodegen { PropertyGetterDescriptor getter = descriptor.getGetter(); assert getter != null : "Annotation property should have a getter: " + descriptor; v.getSerializationBindings().put(METHOD_FOR_FUNCTION, getter, asmMethod); - AnnotationCodegen.forMethod(mv, memberCodegen, state).genAnnotations(getter, asmMethod.getReturnType()); + AnnotationCodegen.forMethod(mv, memberCodegen, state).genAnnotations(getter, asmMethod.getReturnType(), null); KtExpression defaultValue = loadAnnotationArgumentDefaultValue(parameter, descriptor, expectedAnnotationConstructor); if (defaultValue != null) { @@ -417,7 +417,8 @@ public class PropertyCodegen { ); if (annotatedField != null) { - AnnotationCodegen.forField(fv, memberCodegen, state).genAnnotations(annotatedField, type); + AnnotationCodegen.forField(fv, memberCodegen, state) + .genAnnotations(annotatedField, type, propertyDescriptor.getType()); } } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.kt index 5c8cf9e3a4b..06f31e72b3f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.kt @@ -51,7 +51,7 @@ class ScriptCodegen private constructor( typeMapper.mapSupertype(it.defaultType, null).internalName }.toTypedArray() ) - AnnotationCodegen.forClass(v.visitor, this, state).genAnnotations(scriptDescriptor, null) + AnnotationCodegen.forClass(v.visitor, this, state).genAnnotations(scriptDescriptor, null, null) } override fun generateBody() { @@ -99,7 +99,8 @@ class ScriptCodegen private constructor( OtherOrigin(scriptDeclaration, scriptDescriptor.unsubstitutedPrimaryConstructor), ACC_PUBLIC, jvmSignature.asmMethod.name, jvmSignature.asmMethod.descriptor, null, null) - AnnotationCodegen.forMethod(mv, this, state).genAnnotations(scriptDescriptor.unsubstitutedPrimaryConstructor, asmMethod.returnType) + AnnotationCodegen.forMethod(mv, this, state) + .genAnnotations(scriptDescriptor.unsubstitutedPrimaryConstructor, asmMethod.returnType, null) if (state.classBuilderMode.generateBodies) { mv.visitCode() diff --git a/compiler/testData/codegen/asmLike/typeAnnotations/defaultArgs.txt b/compiler/testData/codegen/asmLike/typeAnnotations/defaultArgs.txt index de5c3890fe7..e61dade1cc9 100644 --- a/compiler/testData/codegen/asmLike/typeAnnotations/defaultArgs.txt +++ b/compiler/testData/codegen/asmLike/typeAnnotations/defaultArgs.txt @@ -2,9 +2,9 @@ public final class foo/Kotlin : java/lang/Object { public void () public final java.lang.Object foo(java.lang.String s, int x) + @Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null @Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null @Lfoo/TypeAnn;([name="2"]) : METHOD_FORMAL_PARAMETER 1, null - @Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null public static java.lang.Object foo$default(foo.Kotlin p0, java.lang.String p1, int p2, int p3, java.lang.Object p4) } diff --git a/compiler/testData/codegen/asmLike/typeAnnotations/jvmOverload.txt b/compiler/testData/codegen/asmLike/typeAnnotations/jvmOverload.txt index bc8ab3762bd..60b02033845 100644 --- a/compiler/testData/codegen/asmLike/typeAnnotations/jvmOverload.txt +++ b/compiler/testData/codegen/asmLike/typeAnnotations/jvmOverload.txt @@ -2,13 +2,13 @@ public final class foo/FooClass : java/lang/Object { public void () public final java.lang.Object foo(java.lang.String s, int x) + @Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null @Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null @Lfoo/TypeAnn;([name="2"]) : METHOD_FORMAL_PARAMETER 1, null - @Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null public final java.lang.Object foo(java.lang.String s) - @Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null @Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null + @Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null public final java.lang.Object foo() @Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null @@ -18,4 +18,4 @@ public final class foo/FooClass : java/lang/Object { public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation { public abstract java.lang.String name() -} +} \ No newline at end of file diff --git a/compiler/testData/codegen/asmLike/typeAnnotations/jvmStatic.txt b/compiler/testData/codegen/asmLike/typeAnnotations/jvmStatic.txt index 6c0a6384c30..bcd7bfea7b8 100644 --- a/compiler/testData/codegen/asmLike/typeAnnotations/jvmStatic.txt +++ b/compiler/testData/codegen/asmLike/typeAnnotations/jvmStatic.txt @@ -6,9 +6,9 @@ public final class foo/Foo : java/lang/Object { private void () public final static java.lang.Object foo(java.lang.String s, int x) + @Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null @Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null @Lfoo/TypeAnn;([name="2"]) : METHOD_FORMAL_PARAMETER 1, null - @Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null } public final class foo/FooClass$Companion : java/lang/Object { @@ -17,9 +17,9 @@ public final class foo/FooClass$Companion : java/lang/Object { public void (kotlin.jvm.internal.DefaultConstructorMarker $constructor_marker) public final java.lang.Object foo(java.lang.String s, int x) + @Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null @Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null @Lfoo/TypeAnn;([name="2"]) : METHOD_FORMAL_PARAMETER 1, null - @Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null } public final class foo/FooClass : java/lang/Object { @@ -30,9 +30,9 @@ public final class foo/FooClass : java/lang/Object { public void () public final static java.lang.Object foo(java.lang.String s, int x) + @Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null @Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null @Lfoo/TypeAnn;([name="2"]) : METHOD_FORMAL_PARAMETER 1, null - @Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null } public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation { diff --git a/compiler/testData/codegen/asmLike/typeAnnotations/property.kt b/compiler/testData/codegen/asmLike/typeAnnotations/property.kt index ee5cd906102..d13f62aca03 100644 --- a/compiler/testData/codegen/asmLike/typeAnnotations/property.kt +++ b/compiler/testData/codegen/asmLike/typeAnnotations/property.kt @@ -37,7 +37,16 @@ class Kotlin { lateinit var lateinitProp: @TypeAnn("1") @TypeAnnBinary @TypeAnnSource String + val annotatedGetter: Int + get(): @TypeAnn("1") @TypeAnnBinary @TypeAnnSource Int = 123 + + val unannotatedGetter: @TypeAnn("1") @TypeAnnBinary @TypeAnnSource Int + get(): Int = 123 + companion object { var companionVarProperty: @TypeAnn("1") @TypeAnnBinary @TypeAnnSource String = "123" + + @JvmStatic + var jvmStatic: @TypeAnn("1") @TypeAnnBinary @TypeAnnSource String = "123" } } diff --git a/compiler/testData/codegen/asmLike/typeAnnotations/property.txt b/compiler/testData/codegen/asmLike/typeAnnotations/property.txt new file mode 100644 index 00000000000..427aab1193b --- /dev/null +++ b/compiler/testData/codegen/asmLike/typeAnnotations/property.txt @@ -0,0 +1,121 @@ +public final class foo/Kotlin$Companion : java/lang/Object { + private void () + + public void (kotlin.jvm.internal.DefaultConstructorMarker $constructor_marker) + + public final java.lang.String getCompanionVarProperty() + @Lfoo/TypeAnn;([name="1"]) : METHOD_RETURN, null + @Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible + + public final java.lang.String getJvmStatic() + @Lfoo/TypeAnn;([name="1"]) : METHOD_RETURN, null + @Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible + + public static void jvmStatic$annotations() + + public final void setCompanionVarProperty(java.lang.String ) + @Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null + @Lfoo/TypeAnnBinary;([]) : METHOD_FORMAL_PARAMETER 0, null // invisible + + public final void setJvmStatic(java.lang.String ) + @Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null + @Lfoo/TypeAnnBinary;([]) : METHOD_FORMAL_PARAMETER 0, null // invisible +} + +public final class foo/Kotlin : java/lang/Object { + public final static foo.Kotlin$Companion Companion + + private static java.lang.String companionVarProperty + @Lfoo/TypeAnn;([name="1"]) : FIELD, null + @Lfoo/TypeAnnBinary;([]) : FIELD, null // invisible + + private java.lang.String customSetter + @Lfoo/TypeAnn;([name="1"]) : FIELD, null + @Lfoo/TypeAnnBinary;([]) : FIELD, null // invisible + + public java.lang.String jvmField + @Lfoo/TypeAnn;([name="1"]) : FIELD, null + @Lfoo/TypeAnnBinary;([]) : FIELD, null // invisible + + private static java.lang.String jvmStatic + @Lfoo/TypeAnn;([name="1"]) : FIELD, null + @Lfoo/TypeAnnBinary;([]) : FIELD, null // invisible + + public java.lang.String lateinitProp + @Lfoo/TypeAnn;([name="1"]) : FIELD, null + @Lfoo/TypeAnnBinary;([]) : FIELD, null // invisible + + private final java.lang.String valProp + @Lfoo/TypeAnn;([name="1"]) : FIELD, null + @Lfoo/TypeAnnBinary;([]) : FIELD, null // invisible + + private java.lang.String varProp + @Lfoo/TypeAnn;([name="1"]) : FIELD, null + @Lfoo/TypeAnnBinary;([]) : FIELD, null // invisible + + static void () + + public void () + + public final static java.lang.String access$getCompanionVarProperty$cp() + @Lfoo/TypeAnn;([name="1"]) : METHOD_RETURN, null + @Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible + + public final static java.lang.String access$getJvmStatic$cp() + + public final static void access$setCompanionVarProperty$cp(java.lang.String ) + + public final static void access$setJvmStatic$cp(java.lang.String ) + + public final int getAnnotatedGetter() + @Lfoo/TypeAnn;([name="1"]) : METHOD_RETURN, null + @Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible + + public final java.lang.String getCustomSetter() + @Lfoo/TypeAnn;([name="1"]) : METHOD_RETURN, null + @Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible + + public final static java.lang.String getJvmStatic() + @Lfoo/TypeAnn;([name="1"]) : METHOD_RETURN, null + @Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible + + public final java.lang.String getLateinitProp() + @Lfoo/TypeAnn;([name="1"]) : METHOD_RETURN, null + @Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible + + public final int getUnannotatedGetter() + + public final java.lang.String getValProp() + @Lfoo/TypeAnn;([name="1"]) : METHOD_RETURN, null + @Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible + + public final java.lang.String getVarProp() + @Lfoo/TypeAnn;([name="1"]) : METHOD_RETURN, null + @Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible + + public final void setCustomSetter(java.lang.String field) + + public final static void setJvmStatic(java.lang.String ) + @Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null + @Lfoo/TypeAnnBinary;([]) : METHOD_FORMAL_PARAMETER 0, null // invisible + + public final void setLateinitProp(java.lang.String ) + @Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null + @Lfoo/TypeAnnBinary;([]) : METHOD_FORMAL_PARAMETER 0, null // invisible + + public final void setVarProp(java.lang.String ) + @Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null + @Lfoo/TypeAnnBinary;([]) : METHOD_FORMAL_PARAMETER 0, null // invisible +} + +public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation { + public abstract java.lang.String name() +} + +public abstract interface foo/TypeAnnBinary : java/lang/Object, java/lang/annotation/Annotation { + +} + +public abstract interface foo/TypeAnnSource : java/lang/Object, java/lang/annotation/Annotation { + +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractAsmLikeInstructionListingTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractAsmLikeInstructionListingTest.kt index 0cf734703e7..073bb6b346e 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractAsmLikeInstructionListingTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractAsmLikeInstructionListingTest.kt @@ -14,6 +14,7 @@ import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.tree.* import org.jetbrains.org.objectweb.asm.util.Printer import org.jetbrains.org.objectweb.asm.util.Textifier +import org.jetbrains.org.objectweb.asm.util.TraceFieldVisitor import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor import java.io.File @@ -75,7 +76,7 @@ abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() { appendln(" {") - fields.joinTo(this, LINE_SEPARATOR.repeat(2)) { renderField(it).withMargin() } + fields.joinTo(this, LINE_SEPARATOR.repeat(2)) { renderField(it, showTypeAnnotations).withMargin() } if (fields.isNotEmpty()) { appendln().appendln() @@ -90,11 +91,25 @@ abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() { } } - private fun renderField(field: FieldNode) = buildString { + private fun renderField(field: FieldNode, showTypeAnnotations: Boolean) = buildString { renderVisibilityModifiers(field.access) renderModalityModifiers(field.access) append(Type.getType(field.desc).className).append(' ') append(field.name) + + if (showTypeAnnotations) { + val textifier = Textifier() + val visitor = TraceFieldVisitor(textifier) + field.visibleTypeAnnotations?.forEach { + it.accept(visitor.visitTypeAnnotation(it.typeRef, it.typePath, it.desc, true)) + } + field.invisibleTypeAnnotations?.forEach { + it.accept(visitor.visitTypeAnnotation(it.typeRef, it.typePath, it.desc, false)) + } + textifier.getText().takeIf { it.isNotEmpty() }?.let { + append("\n${textifier.getText().joinToString("").trimEnd()}") + } + } } private fun renderMethod( diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/AsmLikeInstructionListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/AsmLikeInstructionListingTestGenerated.java index 4aa7e0c5ddb..1f8c8d975d5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/AsmLikeInstructionListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/AsmLikeInstructionListingTestGenerated.java @@ -174,6 +174,11 @@ public class AsmLikeInstructionListingTestGenerated extends AbstractAsmLikeInstr runTest("compiler/testData/codegen/asmLike/typeAnnotations/notYetSupported.kt"); } + @TestMetadata("property.kt") + public void testProperty() throws Exception { + runTest("compiler/testData/codegen/asmLike/typeAnnotations/property.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("compiler/testData/codegen/asmLike/typeAnnotations/simple.kt");