diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 77328160c9c..e6aa45a4727 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter; import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; +import org.jetbrains.kotlin.config.LanguageFeature; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.incremental.components.NoLookupLocation; import org.jetbrains.kotlin.lexer.KtTokens; @@ -64,10 +65,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver; import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver; import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.kotlin.types.KotlinType; -import org.jetbrains.org.objectweb.asm.FieldVisitor; -import org.jetbrains.org.objectweb.asm.Label; -import org.jetbrains.org.objectweb.asm.MethodVisitor; -import org.jetbrains.org.objectweb.asm.Type; +import org.jetbrains.org.objectweb.asm.*; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import org.jetbrains.org.objectweb.asm.commons.Method; @@ -838,9 +836,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { @Nullable KtObjectDeclaration companionObject = CollectionsKt.firstOrNull(myClass.getCompanionObjects()); + int properFieldVisibilityFlag = getVisibilityAccessFlag(companionObjectDescriptor); + boolean fieldShouldBeDeprecated = + state.getLanguageVersionSettings().supportsFeature(LanguageFeature.DeprecatedFieldForInvisibleCompanionObject) && + (properFieldVisibilityFlag & (ACC_PRIVATE | ACC_PROTECTED)) != 0; + // TODO generate field with proper visibility in language version 1.3 + int fieldAccessFlags = ACC_PUBLIC | ACC_STATIC | ACC_FINAL; + if (fieldShouldBeDeprecated) { + fieldAccessFlags |= ACC_DEPRECATED; + } StackValue.Field field = StackValue.singleton(companionObjectDescriptor, typeMapper); - v.newField(JvmDeclarationOriginKt.OtherOrigin(companionObject == null ? myClass.getPsiOrParent() : companionObject), - ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null); + FieldVisitor fv = v.newField(JvmDeclarationOriginKt.OtherOrigin(companionObject == null ? myClass.getPsiOrParent() : companionObject), + fieldAccessFlags, field.name, field.type.getDescriptor(), null, null); + if (fieldShouldBeDeprecated) { + AnnotationCodegen.forField(fv, this, typeMapper).visitAnnotation("Ljava/lang/Deprecated;", true).visitEnd(); + } } private void generateCompanionObjectBackingFieldCopies() { diff --git a/compiler/testData/codegen/bytecodeListing/invisibleCompanionObject.kt b/compiler/testData/codegen/bytecodeListing/invisibleCompanionObject.kt new file mode 100644 index 00000000000..3f11dd6987c --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/invisibleCompanionObject.kt @@ -0,0 +1,13 @@ +// LANGUAGE_VERSION: 1.2 + +class TestPrivateCompanion { + private companion object Test +} + +open class TestProtectedCompanion { + protected companion object Test +} + +class TestInternalCompanion { + internal companion object Test +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/invisibleCompanionObject.txt b/compiler/testData/codegen/bytecodeListing/invisibleCompanionObject.txt new file mode 100644 index 00000000000..e2b445a099c --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/invisibleCompanionObject.txt @@ -0,0 +1,44 @@ +@kotlin.Metadata +public final class TestInternalCompanion$Test { + inner class TestInternalCompanion$Test + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void +} + +@kotlin.Metadata +public final class TestInternalCompanion { + public final static field Test: TestInternalCompanion$Test + inner class TestInternalCompanion$Test + static method (): void + public method (): void +} + +@kotlin.Metadata +final class TestPrivateCompanion$Test { + inner class TestPrivateCompanion$Test + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void +} + +@kotlin.Metadata +public final class TestPrivateCompanion { + public deprecated final static @java.lang.Deprecated field Test: TestPrivateCompanion$Test + inner class TestPrivateCompanion$Test + static method (): void + public method (): void +} + +@kotlin.Metadata +public final class TestProtectedCompanion$Test { + inner class TestProtectedCompanion$Test + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void +} + +@kotlin.Metadata +public class TestProtectedCompanion { + public deprecated final static @java.lang.Deprecated field Test: TestProtectedCompanion$Test + inner class TestProtectedCompanion$Test + static method (): void + public method (): void +} diff --git a/compiler/testData/codegen/bytecodeListing/invisibleCompanionObject_lv11.kt b/compiler/testData/codegen/bytecodeListing/invisibleCompanionObject_lv11.kt new file mode 100644 index 00000000000..5333a76ceec --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/invisibleCompanionObject_lv11.kt @@ -0,0 +1,13 @@ +// LANGUAGE_VERSION: 1.1 + +class TestPrivateCompanion { + private companion object Test +} + +open class TestProtectedCompanion { + protected companion object Test +} + +class TestInternalCompanion { + internal companion object Test +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/invisibleCompanionObject_lv11.txt b/compiler/testData/codegen/bytecodeListing/invisibleCompanionObject_lv11.txt new file mode 100644 index 00000000000..3558ed77657 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/invisibleCompanionObject_lv11.txt @@ -0,0 +1,44 @@ +@kotlin.Metadata +public final class TestInternalCompanion$Test { + inner class TestInternalCompanion$Test + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void +} + +@kotlin.Metadata +public final class TestInternalCompanion { + public final static field Test: TestInternalCompanion$Test + inner class TestInternalCompanion$Test + static method (): void + public method (): void +} + +@kotlin.Metadata +final class TestPrivateCompanion$Test { + inner class TestPrivateCompanion$Test + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void +} + +@kotlin.Metadata +public final class TestPrivateCompanion { + public final static field Test: TestPrivateCompanion$Test + inner class TestPrivateCompanion$Test + static method (): void + public method (): void +} + +@kotlin.Metadata +public final class TestProtectedCompanion$Test { + inner class TestProtectedCompanion$Test + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void +} + +@kotlin.Metadata +public class TestProtectedCompanion { + public final static field Test: TestProtectedCompanion$Test + inner class TestProtectedCompanion$Test + static method (): void + public method (): void +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index ec3efbc3873..43780afee61 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -90,6 +90,18 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { doTest(fileName); } + @TestMetadata("invisibleCompanionObject.kt") + public void testInvisibleCompanionObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/invisibleCompanionObject.kt"); + doTest(fileName); + } + + @TestMetadata("invisibleCompanionObject_lv11.kt") + public void testInvisibleCompanionObject_lv11() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/invisibleCompanionObject_lv11.kt"); + doTest(fileName); + } + @TestMetadata("jvmOverloadsAndParametersAnnotations.kt") public void testJvmOverloadsAndParametersAnnotations() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/jvmOverloadsAndParametersAnnotations.kt"); diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 59d49036909..d1226aeafeb 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -52,6 +52,7 @@ enum class LanguageFeature( ArrayLiteralsInAnnotations(KOTLIN_1_2), InlineDefaultFunctionalParameters(KOTLIN_1_2), SoundSmartCastsAfterTry(KOTLIN_1_2), + DeprecatedFieldForInvisibleCompanionObject(KOTLIN_1_2), // Experimental features