diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index b740a133e7c..980d9ba1c47 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -50,6 +50,9 @@ import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getA public abstract class AnnotationCodegen { + private static final String ORG_JETBRAINS_ANNOTATIONS_NOTNULL = Type.getType(NotNull.class).getDescriptor(); + private static final String ORG_JETBRAINS_ANNOTATIONS_NULLABLE = Type.getType(Nullable.class).getDescriptor(); + public static final class JvmFlagAnnotation { private final FqName fqName; private final int jvmFlag; @@ -120,7 +123,7 @@ public abstract class AnnotationCodegen { @Nullable Type returnType, @Nullable KotlinType typeForTypeAnnotations, @Nullable DeclarationDescriptorWithVisibility parameterContainer, - @NotNull List> additionalAnnotations + @NotNull List additionalVisibleAnnotations ) { if (annotated == null) return; @@ -155,9 +158,9 @@ public abstract class AnnotationCodegen { } } - for (Class annotation : additionalAnnotations) { - String descriptor = generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotation); - annotationDescriptorsAlreadyPresent.add(descriptor); + for (String annotation : additionalVisibleAnnotations) { + generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotation, true); + annotationDescriptorsAlreadyPresent.add(annotation); } generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent, parameterContainer); @@ -248,17 +251,15 @@ public abstract class AnnotationCodegen { if (!TypeUtils.isNullableType(flexibleType.getLowerBound()) && TypeUtils.isNullableType(flexibleType.getUpperBound())) { AnnotationDescriptor notNull = type.getAnnotations().findAnnotation(JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION); if (notNull != null) { - generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, NotNull.class); + generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, ORG_JETBRAINS_ANNOTATIONS_NOTNULL, false); } return; } } - boolean isNullableType = TypeUtils.isNullableType(type); - - Class annotationClass = isNullableType ? Nullable.class : NotNull.class; - - generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotationClass); + String annotationDescriptor = + TypeUtils.isNullableType(type) ? ORG_JETBRAINS_ANNOTATIONS_NULLABLE : ORG_JETBRAINS_ANNOTATIONS_NOTNULL; + generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotationDescriptor, false); } private static final Map> annotationTargetMaps = new EnumMap<>(JvmTarget.class); @@ -338,13 +339,14 @@ public abstract class AnnotationCodegen { visitor.visitEnd(); } - @NotNull - private String generateAnnotationIfNotPresent(Set annotationDescriptorsAlreadyPresent, Class annotationClass) { - String descriptor = Type.getType(annotationClass).getDescriptor(); - if (!annotationDescriptorsAlreadyPresent.contains(descriptor)) { - visitAnnotation(descriptor, false).visitEnd(); + private void generateAnnotationIfNotPresent( + Set annotationDescriptorsAlreadyPresent, + String annotationDescriptor, + boolean visible + ) { + if (!annotationDescriptorsAlreadyPresent.contains(annotationDescriptor)) { + visitAnnotation(annotationDescriptor, visible).visitEnd(); } - return descriptor; } private static boolean isBareTypeParameterWithNullableUpperBound(@NotNull KotlinType type) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 399c10ab7af..4409f5fe9e6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -83,6 +83,8 @@ import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*; import static org.jetbrains.org.objectweb.asm.Opcodes.*; public class FunctionCodegen { + private static final String JAVA_LANG_DEPRECATED = Type.getType(Deprecated.class).getDescriptor(); + public final GenerationState state; private final KotlinTypeMapper typeMapper; private final BindingContext bindingContext; @@ -221,7 +223,7 @@ public class FunctionCodegen { InlineClassDescriptorResolver.isSpecializedEqualsMethod(functionDescriptor); generateMethodAnnotationsIfRequired( functionDescriptor, asmMethod, jvmSignature, mv, - isCompatibilityStubInDefaultImpls ? Collections.singletonList(Deprecated.class) : Collections.emptyList(), + isCompatibilityStubInDefaultImpls ? Collections.singletonList(JAVA_LANG_DEPRECATED) : Collections.emptyList(), skipNullabilityAnnotations ); GenerateJava8ParameterNamesKt.generateParameterNames(functionDescriptor, mv, jvmSignature, state, (flags & ACC_SYNTHETIC) != 0); @@ -285,7 +287,7 @@ public class FunctionCodegen { @NotNull Method asmMethod, @NotNull JvmMethodGenericSignature jvmSignature, @NotNull MethodVisitor mv, - @NotNull List> additionalNoArgAnnotations, + @NotNull List additionalVisibleAnnotations, boolean skipNullabilityAnnotations ) { FunctionDescriptor annotationsOwner; @@ -302,7 +304,7 @@ public class FunctionCodegen { } AnnotationCodegen.forMethod(mv, memberCodegen, state, skipNullabilityAnnotations) - .genAnnotations(annotationsOwner, asmMethod.getReturnType(), functionDescriptor.getReturnType(), null, additionalNoArgAnnotations); + .genAnnotations(annotationsOwner, asmMethod.getReturnType(), functionDescriptor.getReturnType(), null, additionalVisibleAnnotations); generateParameterAnnotations( annotationsOwner, mv, jvmSignature, diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 52ad4b9e01a..e118a1d2068 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -15640,6 +15640,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/defaultArgsViaAnonymousObject.kt"); } + @TestMetadata("deprecatedAnnotation.kt") + public void testDeprecatedAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/deprecatedAnnotation.kt"); + } + @TestMetadata("inheritedFunctionWithDefaultParameters.kt") public void testInheritedFunctionWithDefaultParameters() throws Exception { runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedFunctionWithDefaultParameters.kt"); diff --git a/compiler/testData/codegen/box/jvm8/defaults/compatibility/deprecatedAnnotation.kt b/compiler/testData/codegen/box/jvm8/defaults/compatibility/deprecatedAnnotation.kt new file mode 100644 index 00000000000..59051a6bafc --- /dev/null +++ b/compiler/testData/codegen/box/jvm8/defaults/compatibility/deprecatedAnnotation.kt @@ -0,0 +1,20 @@ +// !JVM_DEFAULT_MODE: compatibility +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// FULL_JDK +// WITH_RUNTIME + +interface IFoo { + @JvmDefault + fun foo() {} +} + +fun box(): String { + val iFoo = IFoo::class.java + val iFooDefaultImpls = Class.forName("${iFoo.name}\$DefaultImpls") + val fooMethod = iFooDefaultImpls.declaredMethods.find { it.name == "foo" } + ?: throw AssertionError("No method 'foo' in class ${iFooDefaultImpls.name}") + fooMethod.getAnnotation(java.lang.Deprecated::class.java) + ?: throw AssertionError("No java.lang.Deprecated annotation on method 'foo'") + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 4b677f600ab..8df5d378b01 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -16865,6 +16865,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/defaultArgsViaAnonymousObject.kt"); } + @TestMetadata("deprecatedAnnotation.kt") + public void testDeprecatedAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/deprecatedAnnotation.kt"); + } + @TestMetadata("inheritedFunctionWithDefaultParameters.kt") public void testInheritedFunctionWithDefaultParameters() throws Exception { runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedFunctionWithDefaultParameters.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 319f5485ca3..e7dc61889c7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -16865,6 +16865,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/defaultArgsViaAnonymousObject.kt"); } + @TestMetadata("deprecatedAnnotation.kt") + public void testDeprecatedAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/deprecatedAnnotation.kt"); + } + @TestMetadata("inheritedFunctionWithDefaultParameters.kt") public void testInheritedFunctionWithDefaultParameters() throws Exception { runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedFunctionWithDefaultParameters.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index b0b0c3e05bc..30146ace1d6 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -15640,6 +15640,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/defaultArgsViaAnonymousObject.kt"); } + @TestMetadata("deprecatedAnnotation.kt") + public void testDeprecatedAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/deprecatedAnnotation.kt"); + } + @TestMetadata("inheritedFunctionWithDefaultParameters.kt") public void testInheritedFunctionWithDefaultParameters() throws Exception { runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedFunctionWithDefaultParameters.kt");