diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 017f4ac7eb4..cf4bac8a9c3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -2005,12 +2005,12 @@ public class ExpressionCodegen extends KtVisitor impleme DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); - boolean isBackingFieldInClassCompanion = JvmAbi.isPropertyWithBackingFieldInOuterClass(propertyDescriptor); + boolean isBackingFieldMovedFromCompanion = JvmAbi.isPropertyWithBackingFieldInOuterClass(propertyDescriptor); AccessorKind fieldAccessorKind; if (skipLateinitAssertion) { fieldAccessorKind = AccessorKind.LATEINIT_INTRINSIC; } - else if (isBackingFieldInClassCompanion && + else if (isBackingFieldMovedFromCompanion && (forceField || (Visibilities.isPrivate(propertyDescriptor.getVisibility()) && isDefaultAccessor(propertyDescriptor.getGetter()) && isDefaultAccessor(propertyDescriptor.getSetter())))) { @@ -2076,7 +2076,7 @@ public class ExpressionCodegen extends KtVisitor impleme } else { skipPropertyAccessors = forceField; - ownerDescriptor = isBackingFieldInClassCompanion ? containingDeclaration : propertyDescriptor; + ownerDescriptor = isBackingFieldMovedFromCompanion ? containingDeclaration : propertyDescriptor; } if (!skipPropertyAccessors) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 5d4fa4e9b76..c33adaeb952 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -929,7 +929,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { boolean isNonCompanionObject = isNonCompanionObject(descriptor); boolean isInterfaceCompanion = isCompanionObjectInInterfaceNotIntrinsic(descriptor); boolean isMappedIntrinsicCompanionObject = isMappedIntrinsicCompanionObject(descriptor); - if (isNonCompanionObject || isInterfaceCompanion || isMappedIntrinsicCompanionObject) { + boolean objectWithBackingFieldsInOuter = isCompanionObjectWithBackingFieldsInOuter(descriptor); + if (isNonCompanionObject || (isInterfaceCompanion && !objectWithBackingFieldsInOuter) || isMappedIntrinsicCompanionObject) { ExpressionCodegen clInitCodegen = createOrGetClInitCodegen(); InstructionAdapter v = clInitCodegen.v; markLineNumberForElement(element.getPsiOrParent(), v); @@ -957,7 +958,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { ); } } - else if (isCompanionObjectWithBackingFieldsInOuter(descriptor)) { + else if (objectWithBackingFieldsInOuter) { ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen(); ExpressionCodegen parentClInitCodegen = parentCodegen.createOrGetClInitCodegen(); InstructionAdapter parentVisitor = parentClInitCodegen.v; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java index a1041001318..6288b33446a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java @@ -57,9 +57,9 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAn import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface; import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.DELEGATED_PROPERTIES; import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.DELEGATED_PROPERTY_METADATA_OWNER; -import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.FIELD_FOR_PROPERTY; -import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.SYNTHETIC_METHOD_FOR_PROPERTY; +import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.*; import static org.jetbrains.kotlin.diagnostics.Errors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND; +import static org.jetbrains.kotlin.load.java.JvmAbi.isInterfaceCompanionWithBackingFieldsInOuter; import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject; import static org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface; import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.K_PROPERTY_TYPE; @@ -420,6 +420,10 @@ public class PropertyCodegen { String name = backingFieldContext.getFieldName(propertyDescriptor, isDelegate); v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, Pair.create(type, name)); + if (hasJvmFieldAnnotation(propertyDescriptor) && + isInterfaceCompanionWithBackingFieldsInOuter(propertyDescriptor.getContainingDeclaration())) { + v.getSerializationBindings().put(FIELD_MOVED_FROM_INTERFACE_COMPANION, propertyDescriptor, true); + } FieldVisitor fv = builder.newField( JvmDeclarationOriginKt.OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(), diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializationBindings.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializationBindings.java index a058069be0c..a8759e7fe81 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializationBindings.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializationBindings.java @@ -35,6 +35,8 @@ public final class JvmSerializationBindings { SerializationMappingSlice.create(); public static final SerializationMappingSlice SYNTHETIC_METHOD_FOR_PROPERTY = SerializationMappingSlice.create(); + public static final SerializationMappingSlice FIELD_MOVED_FROM_INTERFACE_COMPANION = + SerializationMappingSlice.create(); private static final class SerializationMappingSlice extends BasicWritableSlice { public SerializationMappingSlice() { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.java index 2a59ca57913..d657b640abc 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.java @@ -189,6 +189,11 @@ public class JvmSerializerExtension extends SerializerExtension { ); proto.setExtension(JvmProtoBuf.propertySignature, signature); + Boolean fieldMovedFromInterfaceCompanion = bindings.get(FIELD_MOVED_FROM_INTERFACE_COMPANION, descriptor); + if (fieldMovedFromInterfaceCompanion != null && fieldMovedFromInterfaceCompanion) { + proto.setExtension(JvmProtoBuf.isMovedFromInterfaceCompanion, 1); + } + } @Override diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmFieldApplicabilityChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmFieldApplicabilityChecker.kt index 278f4f8a543..44ff6058b41 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmFieldApplicabilityChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmFieldApplicabilityChecker.kt @@ -16,9 +16,11 @@ package org.jetbrains.kotlin.resolve.jvm.checkers +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.isInsideJvmMultifileClassFile +import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.resolve.BindingContext @@ -40,6 +42,7 @@ class JvmFieldApplicabilityChecker : DeclarationChecker { LATEINIT("JvmField cannot be applied to lateinit property"), CONST("JvmField cannot be applied to const property"), INSIDE_COMPANION_OF_INTERFACE("JvmField cannot be applied to a property defined in companion object of interface"), + NOT_PUBLIC_VAL_WITH_JVMFIELD("JvmField could be applied only if all interface companion properties are 'public final val' with '@JvmField' annotation"), TOP_LEVEL_PROPERTY_OF_MULTIFILE_FACADE("JvmField cannot be applied to top level property of a file annotated with ${JvmFileClassUtil.JVM_MULTIFILE_CLASS_SHORT}"), DELEGATE("JvmField cannot be applied to delegated property") } @@ -57,7 +60,14 @@ class JvmFieldApplicabilityChecker : DeclarationChecker { descriptor.overriddenDescriptors.isNotEmpty() -> OVERRIDES descriptor.isLateInit -> LATEINIT descriptor.isConst -> CONST - descriptor.isInsideCompanionObjectOfInterface() -> INSIDE_COMPANION_OF_INTERFACE + descriptor.isInsideCompanionObjectOfInterface() -> + if (!context.languageVersionSettings.supportsFeature(LanguageFeature.JvmFieldInInterface)) + INSIDE_COMPANION_OF_INTERFACE + else { + if (!JvmAbi.isInterfaceCompanionWithBackingFieldsInOuter(descriptor.containingDeclaration)) { + NOT_PUBLIC_VAL_WITH_JVMFIELD + } else return + } DescriptorUtils.isTopLevelDeclaration(descriptor) && declaration.isInsideJvmMultifileClassFile() -> TOP_LEVEL_PROPERTY_OF_MULTIFILE_FACADE else -> return @@ -79,4 +89,5 @@ class JvmFieldApplicabilityChecker : DeclarationChecker { val outerClassKind = (containingClass.containingDeclaration as? ClassDescriptor)?.kind return outerClassKind == ClassKind.INTERFACE || outerClassKind == ClassKind.ANNOTATION_CLASS } + } diff --git a/compiler/testData/codegen/box/callableReference/bound/boundJvmFieldInInterfaceCompanion.kt b/compiler/testData/codegen/box/callableReference/bound/boundJvmFieldInInterfaceCompanion.kt new file mode 100644 index 00000000000..173a9fc2865 --- /dev/null +++ b/compiler/testData/codegen/box/callableReference/bound/boundJvmFieldInInterfaceCompanion.kt @@ -0,0 +1,20 @@ +// !LANGUAGE: +JvmFieldInInterface +// TARGET_BACKEND: JVM +// WITH_RUNTIME +import kotlin.reflect.full.memberProperties + +class Bar(val value: String) + +interface Foo { + + companion object { + @JvmField + val z = Bar("OK") + } +} + + +fun box(): String { + val field = Foo.Companion::z + return field.get().value +} diff --git a/compiler/testData/codegen/box/jvmField/annotationCompanion.kt b/compiler/testData/codegen/box/jvmField/annotationCompanion.kt new file mode 100644 index 00000000000..26741f1dda1 --- /dev/null +++ b/compiler/testData/codegen/box/jvmField/annotationCompanion.kt @@ -0,0 +1,21 @@ +// !LANGUAGE: +JvmFieldInInterface +NestedClassesInAnnotations +// TARGET_BACKEND: JVM + +// WITH_RUNTIME +// FILE: Foo.kt + +public class Bar(public val value: String) + +annotation class Foo { + companion object { + @JvmField + val FOO = Bar("OK") + } +} + + +// FILE: bar.kt + +fun box(): String { + return Foo.FOO.value +} diff --git a/compiler/testData/codegen/box/jvmField/annotationCompanionWithJava.kt b/compiler/testData/codegen/box/jvmField/annotationCompanionWithJava.kt new file mode 100644 index 00000000000..1b8002ff7da --- /dev/null +++ b/compiler/testData/codegen/box/jvmField/annotationCompanionWithJava.kt @@ -0,0 +1,29 @@ +// !LANGUAGE: +JvmFieldInInterface +NestedClassesInAnnotations +// TARGET_BACKEND: JVM + +// WITH_RUNTIME +// FILE: Test.java + +public class Test { + public static String publicField() { + return Foo.z.getS(); + } +} + +// FILE: simple.kt + + +public class Bar(public val s: String) + +annotation class Foo { + + companion object { + @JvmField + val z = Bar("OK") + } +} + + +fun box(): String { + return Test.publicField() +} diff --git a/compiler/testData/codegen/box/jvmField/classFieldReference.kt b/compiler/testData/codegen/box/jvmField/classFieldReference.kt index 3707e8cd3c6..14dc9449c54 100644 --- a/compiler/testData/codegen/box/jvmField/classFieldReference.kt +++ b/compiler/testData/codegen/box/jvmField/classFieldReference.kt @@ -8,6 +8,7 @@ package zzz import java.lang.reflect.Field import kotlin.reflect.KProperty1 +import kotlin.reflect.KProperty0 import kotlin.test.assertEquals class A(val s1: String, val s2: String) { @@ -21,27 +22,28 @@ class A(val s1: String, val s2: String) { } -/* -// TODO: uncomment when callable references to object members are supported class AWithCompanion { companion object { @JvmField public val publicField = "1"; @JvmField internal val internalField = "2"; fun testAccessors() { - checkAccessor(AWithCompanion.Companion::publicField, "1", AWithCompanion.Companion) - checkAccessor(AWithCompanion.Companion::internalField, "2", AWithCompanion.Companion) + checkAccessor(AWithCompanion.Companion::publicField, "1") + checkAccessor(AWithCompanion.Companion::internalField, "2") } } } -*/ fun box(): String { A("1", "2").testAccessors() - // AWithCompanion.testAccessors() + AWithCompanion.testAccessors() return "OK" } public fun checkAccessor(prop: KProperty1, value: R, receiver: T) { assertEquals(prop.get(receiver), value, "Property ${prop} has wrong value") } + +public fun checkAccessor(prop: KProperty0, value: R) { + assertEquals(prop.get(), value, "Property ${prop} has wrong value") +} diff --git a/compiler/testData/codegen/box/jvmField/interfaceCompanion.kt b/compiler/testData/codegen/box/jvmField/interfaceCompanion.kt new file mode 100644 index 00000000000..f99d3fec96a --- /dev/null +++ b/compiler/testData/codegen/box/jvmField/interfaceCompanion.kt @@ -0,0 +1,21 @@ +// !LANGUAGE: +JvmFieldInInterface +// TARGET_BACKEND: JVM + +// WITH_RUNTIME +// FILE: Foo.kt + +public class Bar(public val value: String) + +interface Foo { + companion object { + @JvmField + val FOO = Bar("OK") + } +} + + +// FILE: bar.kt + +fun box(): String { + return Foo.FOO.value +} diff --git a/compiler/testData/codegen/box/jvmField/interfaceCompanionWithJava.kt b/compiler/testData/codegen/box/jvmField/interfaceCompanionWithJava.kt new file mode 100644 index 00000000000..76f63e669c4 --- /dev/null +++ b/compiler/testData/codegen/box/jvmField/interfaceCompanionWithJava.kt @@ -0,0 +1,32 @@ +// !LANGUAGE: +JvmFieldInInterface +// TARGET_BACKEND: JVM + +// WITH_RUNTIME +// FILE: Test.java + +public class Test { + public static String publicField() { + return Foo.o.getS() + Foo.k.getS(); + } +} + +// FILE: simple.kt + + +public class Bar(public val s: String) + +interface Foo { + + companion object { + @JvmField + val o = Bar("O") + + @JvmField + val k = Bar("K") + } +} + + +fun box(): String { + return Test.publicField() +} diff --git a/compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt b/compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt new file mode 100644 index 00000000000..7f696a82d9f --- /dev/null +++ b/compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt @@ -0,0 +1,18 @@ +// !LANGUAGE: +JvmFieldInInterface +// TARGET_BACKEND: JVM +// WITH_REFLECT + +import kotlin.reflect.jvm.* +import kotlin.test.assertEquals + +interface Foo { + companion object { + @JvmField + val value = "OK" + } +} + +fun box(): String { + val field = Foo.Companion::value.javaField!! + return field.get(null) as String +} diff --git a/compiler/testData/codegen/box/reflection/properties/jvmFieldInAnnotationCompanionWithAnnotation.kt b/compiler/testData/codegen/box/reflection/properties/jvmFieldInAnnotationCompanionWithAnnotation.kt new file mode 100644 index 00000000000..a360948af4f --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/jvmFieldInAnnotationCompanionWithAnnotation.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +JvmFieldInInterface +NestedClassesInAnnotations +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// WITH_REFLECT + +import kotlin.reflect.full.declaredMemberProperties + +annotation class Ann(val value: String) + +public class Bar(public val value: String) + +annotation class Foo { + companion object { + @JvmField @Ann("O") + val FOO = Bar("K") + } +} + +fun box(): String { + val field = Foo.Companion::class.declaredMemberProperties.single() + return (field.annotations.single() as Ann).value + (field.get(Foo.Companion) as Bar).value +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanion.kt b/compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanion.kt new file mode 100644 index 00000000000..10ff05104b3 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanion.kt @@ -0,0 +1,23 @@ +// !LANGUAGE: +JvmFieldInInterface +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// WITH_REFLECT +import kotlin.reflect.KProperty1 +import kotlin.reflect.full.memberProperties +import kotlin.reflect.full.companionObject + +class Bar(val value: String) + +interface Foo { + + companion object { + @JvmField + val z = Bar("OK") + } +} + + +fun box(): String { + val field = Foo::class.companionObject!!.memberProperties.single() as KProperty1 + return field.get(Foo.Companion).value +} diff --git a/compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanionWithAnnotation.kt b/compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanionWithAnnotation.kt new file mode 100644 index 00000000000..200093d27ee --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanionWithAnnotation.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +JvmFieldInInterface +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// WITH_REFLECT + +import kotlin.reflect.full.declaredMemberProperties + +annotation class Ann(val value: String) + +public class Bar(public val value: String) + +interface Foo { + companion object { + @JvmField @Ann("O") + val FOO = Bar("K") + } +} + +fun box(): String { + val field = Foo.Companion::class.declaredMemberProperties.single() + return (field.annotations.single() as Ann).value + (field.get(Foo.Companion) as Bar).value +} \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstKotlin/jvmFieldInAnnotationCompanion.kt b/compiler/testData/compileKotlinAgainstKotlin/jvmFieldInAnnotationCompanion.kt new file mode 100644 index 00000000000..8b6d0c6a540 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/jvmFieldInAnnotationCompanion.kt @@ -0,0 +1,21 @@ +// !LANGUAGE: +JvmFieldInInterface +NestedClassesInAnnotations +// TARGER_BACKEND: JVM + +// WITH_RUNTIME +// FILE: Foo.kt + +public class Bar(public val value: String) + +annotation class Foo { + companion object { + @JvmField + val FOO = Bar("OK") + } +} + + +// FILE: bar.kt + +fun box(): String { + return Foo.FOO.value +} diff --git a/compiler/testData/compileKotlinAgainstKotlin/jvmFieldInInterfaceCompanion.kt b/compiler/testData/compileKotlinAgainstKotlin/jvmFieldInInterfaceCompanion.kt new file mode 100644 index 00000000000..9f73d92c947 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/jvmFieldInInterfaceCompanion.kt @@ -0,0 +1,21 @@ +// !LANGUAGE: +JvmFieldInInterface +// TARGER_BACKEND: JVM + +// WITH_RUNTIME +// FILE: Foo.kt + +public class Bar(public val value: String) + +interface Foo { + companion object { + @JvmField + val FOO = Bar("OK") + } +} + + +// FILE: bar.kt + +fun box(): String { + return Foo.FOO.value +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.kt new file mode 100644 index 00000000000..2cf5fc7f17b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.kt @@ -0,0 +1,59 @@ +// !LANGUAGE: +JvmFieldInInterface + +interface A { + + companion object { + @JvmField + val c = 3 + } +} + + +interface B { + + companion object { + @JvmField + val c = 3 + + @JvmField + val a = 3 + } +} + +interface C { + companion object { + @JvmField + val c = 3 + + val a = 3 + } +} + +interface D { + companion object { + @JvmField + var c = 3 + } +} + + +interface E { + companion object { + @JvmField + private val a = 3 + + @JvmField + internal val b = 3 + + @JvmField + protected val c = 3 + } +} + + +interface F { + companion object { + @JvmField + open val a = 3 + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.txt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.txt new file mode 100644 index 00000000000..97809385109 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.txt @@ -0,0 +1,75 @@ +package + +public interface A { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public companion object Companion { + private constructor Companion() + @kotlin.jvm.JvmField public final val c: kotlin.Int = 3 + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public interface B { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public companion object Companion { + private constructor Companion() + @kotlin.jvm.JvmField public final val a: kotlin.Int = 3 + @kotlin.jvm.JvmField public final val c: kotlin.Int = 3 + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public interface C { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public companion object Companion { + private constructor Companion() + public final val a: kotlin.Int = 3 + @kotlin.jvm.JvmField public final val c: kotlin.Int = 3 + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public interface D { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public companion object Companion { + private constructor Companion() + @kotlin.jvm.JvmField public final var c: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public interface E { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public companion object Companion { + private constructor Companion() + @kotlin.jvm.JvmField private final val a: kotlin.Int = 3 + @kotlin.jvm.JvmField internal final val b: kotlin.Int = 3 + @kotlin.jvm.JvmField protected final val c: kotlin.Int = 3 + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.kt index 8bad5a18b3e..4b19aad3d3d 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.kt @@ -95,6 +95,8 @@ interface K { companion object { @JvmField var c = 3 + + var x = 3 } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.txt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.txt index 369df04519e..7a971bf5f0e 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.txt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.txt @@ -75,6 +75,7 @@ public interface K { public companion object Companion { private constructor Companion() @kotlin.jvm.JvmField public final var c: kotlin.Int + public final var x: kotlin.Int public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 175e3097956..36de29baf2b 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -1637,6 +1637,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/callableReference/bound/array.kt"); } + @TestMetadata("boundJvmFieldInInterfaceCompanion.kt") + public void testBoundJvmFieldInInterfaceCompanion() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/bound/boundJvmFieldInInterfaceCompanion.kt"); + } + @TestMetadata("companionObjectReceiver.kt") public void testCompanionObjectReceiver() throws Exception { runTest("compiler/testData/codegen/box/callableReference/bound/companionObjectReceiver.kt"); @@ -11943,6 +11948,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/jvmField"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); } + @TestMetadata("annotationCompanion.kt") + public void testAnnotationCompanion() throws Exception { + runTest("compiler/testData/codegen/box/jvmField/annotationCompanion.kt"); + } + + @TestMetadata("annotationCompanionWithJava.kt") + public void testAnnotationCompanionWithJava() throws Exception { + runTest("compiler/testData/codegen/box/jvmField/annotationCompanionWithJava.kt"); + } + @TestMetadata("captureClassFields.kt") public void testCaptureClassFields() throws Exception { runTest("compiler/testData/codegen/box/jvmField/captureClassFields.kt"); @@ -11973,6 +11988,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/jvmField/constructorProperty.kt"); } + @TestMetadata("interfaceCompanion.kt") + public void testInterfaceCompanion() throws Exception { + runTest("compiler/testData/codegen/box/jvmField/interfaceCompanion.kt"); + } + + @TestMetadata("interfaceCompanionWithJava.kt") + public void testInterfaceCompanionWithJava() throws Exception { + runTest("compiler/testData/codegen/box/jvmField/interfaceCompanionWithJava.kt"); + } + @TestMetadata("publicField.kt") public void testPublicField() throws Exception { runTest("compiler/testData/codegen/box/jvmField/publicField.kt"); @@ -17691,6 +17716,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/reflection/mapping/inlineReifiedFun.kt"); } + @TestMetadata("interfaceCompanionPropertyWithJvmField.kt") + public void testInterfaceCompanionPropertyWithJvmField() throws Exception { + runTest("compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt"); + } + @TestMetadata("mappedClassIsEqualToClassLiteral.kt") public void testMappedClassIsEqualToClassLiteral() throws Exception { runTest("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt"); @@ -18286,6 +18316,21 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/reflection/properties/javaStaticField.kt"); } + @TestMetadata("jvmFieldInAnnotationCompanionWithAnnotation.kt") + public void testJvmFieldInAnnotationCompanionWithAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/jvmFieldInAnnotationCompanionWithAnnotation.kt"); + } + + @TestMetadata("jvmFieldInInterfaceCompanion.kt") + public void testJvmFieldInInterfaceCompanion() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanion.kt"); + } + + @TestMetadata("jvmFieldInInterfaceCompanionWithAnnotation.kt") + public void testJvmFieldInInterfaceCompanionWithAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanionWithAnnotation.kt"); + } + @TestMetadata("kotlinPropertyInheritedInJava.kt") public void testKotlinPropertyInheritedInJava() throws Exception { runTest("compiler/testData/codegen/box/reflection/properties/kotlinPropertyInheritedInJava.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 53f87c5f7a6..9609c59e79d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -556,6 +556,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/inSingleFileFacade.kt"); } + @TestMetadata("interface13.kt") + public void testInterface13() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.kt"); + } + @TestMetadata("jvmFieldApplicability.kt") public void testJvmFieldApplicability() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index b5d62d1fde0..eda6eab37d2 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -556,6 +556,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/inSingleFileFacade.kt"); } + @TestMetadata("interface13.kt") + public void testInterface13() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.kt"); + } + @TestMetadata("jvmFieldApplicability.kt") public void testJvmFieldApplicability() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 0be7535fc31..8145c14c536 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -1637,6 +1637,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/callableReference/bound/array.kt"); } + @TestMetadata("boundJvmFieldInInterfaceCompanion.kt") + public void testBoundJvmFieldInInterfaceCompanion() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/bound/boundJvmFieldInInterfaceCompanion.kt"); + } + @TestMetadata("companionObjectReceiver.kt") public void testCompanionObjectReceiver() throws Exception { runTest("compiler/testData/codegen/box/callableReference/bound/companionObjectReceiver.kt"); @@ -11943,6 +11948,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/jvmField"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("annotationCompanion.kt") + public void testAnnotationCompanion() throws Exception { + runTest("compiler/testData/codegen/box/jvmField/annotationCompanion.kt"); + } + + @TestMetadata("annotationCompanionWithJava.kt") + public void testAnnotationCompanionWithJava() throws Exception { + runTest("compiler/testData/codegen/box/jvmField/annotationCompanionWithJava.kt"); + } + @TestMetadata("captureClassFields.kt") public void testCaptureClassFields() throws Exception { runTest("compiler/testData/codegen/box/jvmField/captureClassFields.kt"); @@ -11973,6 +11988,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/jvmField/constructorProperty.kt"); } + @TestMetadata("interfaceCompanion.kt") + public void testInterfaceCompanion() throws Exception { + runTest("compiler/testData/codegen/box/jvmField/interfaceCompanion.kt"); + } + + @TestMetadata("interfaceCompanionWithJava.kt") + public void testInterfaceCompanionWithJava() throws Exception { + runTest("compiler/testData/codegen/box/jvmField/interfaceCompanionWithJava.kt"); + } + @TestMetadata("publicField.kt") public void testPublicField() throws Exception { runTest("compiler/testData/codegen/box/jvmField/publicField.kt"); @@ -17691,6 +17716,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/reflection/mapping/inlineReifiedFun.kt"); } + @TestMetadata("interfaceCompanionPropertyWithJvmField.kt") + public void testInterfaceCompanionPropertyWithJvmField() throws Exception { + runTest("compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt"); + } + @TestMetadata("mappedClassIsEqualToClassLiteral.kt") public void testMappedClassIsEqualToClassLiteral() throws Exception { runTest("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt"); @@ -18286,6 +18316,21 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/reflection/properties/javaStaticField.kt"); } + @TestMetadata("jvmFieldInAnnotationCompanionWithAnnotation.kt") + public void testJvmFieldInAnnotationCompanionWithAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/jvmFieldInAnnotationCompanionWithAnnotation.kt"); + } + + @TestMetadata("jvmFieldInInterfaceCompanion.kt") + public void testJvmFieldInInterfaceCompanion() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanion.kt"); + } + + @TestMetadata("jvmFieldInInterfaceCompanionWithAnnotation.kt") + public void testJvmFieldInInterfaceCompanionWithAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanionWithAnnotation.kt"); + } + @TestMetadata("kotlinPropertyInheritedInJava.kt") public void testKotlinPropertyInheritedInJava() throws Exception { runTest("compiler/testData/codegen/box/reflection/properties/kotlinPropertyInheritedInJava.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java index ce23000b247..8a927e363b7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java @@ -143,11 +143,21 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl runTest("compiler/testData/compileKotlinAgainstKotlin/jvmField.kt"); } + @TestMetadata("jvmFieldInAnnotationCompanion.kt") + public void testJvmFieldInAnnotationCompanion() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/jvmFieldInAnnotationCompanion.kt"); + } + @TestMetadata("jvmFieldInConstructor.kt") public void testJvmFieldInConstructor() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/jvmFieldInConstructor.kt"); } + @TestMetadata("jvmFieldInInterfaceCompanion.kt") + public void testJvmFieldInInterfaceCompanion() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/jvmFieldInInterfaceCompanion.kt"); + } + @TestMetadata("jvmNames.kt") public void testJvmNames() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/jvmNames.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index ddfc21db359..7f258e81dd8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -1637,6 +1637,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/callableReference/bound/array.kt"); } + @TestMetadata("boundJvmFieldInInterfaceCompanion.kt") + public void testBoundJvmFieldInInterfaceCompanion() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/bound/boundJvmFieldInInterfaceCompanion.kt"); + } + @TestMetadata("companionObjectReceiver.kt") public void testCompanionObjectReceiver() throws Exception { runTest("compiler/testData/codegen/box/callableReference/bound/companionObjectReceiver.kt"); @@ -11943,6 +11948,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/jvmField"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("annotationCompanion.kt") + public void testAnnotationCompanion() throws Exception { + runTest("compiler/testData/codegen/box/jvmField/annotationCompanion.kt"); + } + + @TestMetadata("annotationCompanionWithJava.kt") + public void testAnnotationCompanionWithJava() throws Exception { + runTest("compiler/testData/codegen/box/jvmField/annotationCompanionWithJava.kt"); + } + @TestMetadata("captureClassFields.kt") public void testCaptureClassFields() throws Exception { runTest("compiler/testData/codegen/box/jvmField/captureClassFields.kt"); @@ -11973,6 +11988,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/jvmField/constructorProperty.kt"); } + @TestMetadata("interfaceCompanion.kt") + public void testInterfaceCompanion() throws Exception { + runTest("compiler/testData/codegen/box/jvmField/interfaceCompanion.kt"); + } + + @TestMetadata("interfaceCompanionWithJava.kt") + public void testInterfaceCompanionWithJava() throws Exception { + runTest("compiler/testData/codegen/box/jvmField/interfaceCompanionWithJava.kt"); + } + @TestMetadata("publicField.kt") public void testPublicField() throws Exception { runTest("compiler/testData/codegen/box/jvmField/publicField.kt"); @@ -17691,6 +17716,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/reflection/mapping/inlineReifiedFun.kt"); } + @TestMetadata("interfaceCompanionPropertyWithJvmField.kt") + public void testInterfaceCompanionPropertyWithJvmField() throws Exception { + runTest("compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt"); + } + @TestMetadata("mappedClassIsEqualToClassLiteral.kt") public void testMappedClassIsEqualToClassLiteral() throws Exception { runTest("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt"); @@ -18286,6 +18316,21 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/reflection/properties/javaStaticField.kt"); } + @TestMetadata("jvmFieldInAnnotationCompanionWithAnnotation.kt") + public void testJvmFieldInAnnotationCompanionWithAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/jvmFieldInAnnotationCompanionWithAnnotation.kt"); + } + + @TestMetadata("jvmFieldInInterfaceCompanion.kt") + public void testJvmFieldInInterfaceCompanion() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanion.kt"); + } + + @TestMetadata("jvmFieldInInterfaceCompanionWithAnnotation.kt") + public void testJvmFieldInInterfaceCompanionWithAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanionWithAnnotation.kt"); + } + @TestMetadata("kotlinPropertyInheritedInJava.kt") public void testKotlinPropertyInheritedInJava() throws Exception { runTest("compiler/testData/codegen/box/reflection/properties/kotlinPropertyInheritedInJava.kt"); diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 566060bf35f..1cc6823206e 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -67,6 +67,7 @@ enum class LanguageFeature( ProperForInArrayLoopRangeVariableAssignmentSemantic(KOTLIN_1_3, kind = BUG_FIX), NestedClassesInAnnotations(KOTLIN_1_3), JvmStaticInInterface(KOTLIN_1_3, kind = UNSTABLE_FEATURE), + JvmFieldInInterface(KOTLIN_1_3, kind = UNSTABLE_FEATURE), ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion(KOTLIN_1_3, kind = BUG_FIX), ProhibitNonConstValuesAsVarargsInAnnotations(KOTLIN_1_3, kind = BUG_FIX), ReleaseCoroutines(KOTLIN_1_3, kind = UNSTABLE_FEATURE), diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/JvmAbi.java b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/JvmAbi.java index c1f0847b766..a00f6f914c2 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/JvmAbi.java +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/JvmAbi.java @@ -7,21 +7,26 @@ package org.jetbrains.kotlin.load.java; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.builtins.CompanionObjectMapping; -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor; -import org.jetbrains.kotlin.descriptors.ClassDescriptor; -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; -import org.jetbrains.kotlin.descriptors.PropertyDescriptor; +import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget; +import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget; import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter; +import org.jetbrains.kotlin.resolve.scopes.MemberScope; import org.jetbrains.kotlin.util.capitalizeDecapitalize.CapitalizeDecapitalizeKt; -import static org.jetbrains.kotlin.resolve.DescriptorUtils.isClassOrEnumClass; -import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; public final class JvmAbi { public static final String DEFAULT_IMPLS_CLASS_NAME = "DefaultImpls"; public static final String ERASED_INLINE_CLASS_NAME = "Erased"; + public static final FqName JVM_FIELD_ANNOTATION_FQ_NAME = new FqName("kotlin.jvm.JvmField"); /** * Warning: use DEFAULT_IMPLS_CLASS_NAME and TypeMappingConfiguration.innerClassNameFactory when possible. @@ -97,16 +102,54 @@ public final class JvmAbi { public static boolean isPropertyWithBackingFieldInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) { return propertyDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && - isCompanionObjectWithBackingFieldsInOuter(propertyDescriptor.getContainingDeclaration()); + (isCompanionObjectWithBackingFieldsInOuter(propertyDescriptor.getContainingDeclaration()) + || + (isCompanionObject(propertyDescriptor.getContainingDeclaration()) && + hasJvmFieldAnnotation(propertyDescriptor))); } public static boolean isCompanionObjectWithBackingFieldsInOuter(@NotNull DeclarationDescriptor companionObject) { return isCompanionObject(companionObject) && - isClassOrEnumClass(companionObject.getContainingDeclaration()) && + (isClassOrEnumClass(companionObject.getContainingDeclaration()) || + isInterfaceCompanionWithBackingFieldsInOuter(companionObject)) && !isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject); + + } + + public static boolean isInterfaceCompanionWithBackingFieldsInOuter(@NotNull DeclarationDescriptor companionObject) { + DeclarationDescriptor interfaceClass = companionObject.getContainingDeclaration(); + if (!isInterface(interfaceClass) && !isAnnotationClass(interfaceClass)) return false; + Collection descriptors = ((ClassDescriptor) companionObject).getUnsubstitutedMemberScope() + .getContributedDescriptors(DescriptorKindFilter.ALL, MemberScope.Companion.getALL_NAME_FILTER()); + boolean hasJvmFieldAnnotation = false; + for (DeclarationDescriptor next : descriptors) { + if (!(next instanceof PropertyDescriptor)) continue; + PropertyDescriptor propertyDescriptor = (PropertyDescriptor) next; + + if (propertyDescriptor.getVisibility() != Visibilities.PUBLIC || + propertyDescriptor.isVar() || + propertyDescriptor.getModality() != Modality.FINAL) { + return false; + } + + if (!hasJvmFieldAnnotation(propertyDescriptor)) return false; + hasJvmFieldAnnotation = true; + } + return hasJvmFieldAnnotation; } public static boolean isMappedIntrinsicCompanionObject(@NotNull ClassDescriptor companionObject) { return CompanionObjectMapping.INSTANCE.isMappedIntrinsicCompanionObject(companionObject); } + + private static boolean hasJvmFieldAnnotation(@NotNull CallableMemberDescriptor memberDescriptor) { + List annotations = memberDescriptor.getAnnotations().getUseSiteTargetedAnnotations(); + for (AnnotationWithTarget annotationWithTarget : annotations) { + if (AnnotationUseSiteTarget.FIELD.equals(annotationWithTarget.getTarget()) && + JVM_FIELD_ANNOTATION_FQ_NAME.equals(annotationWithTarget.getAnnotation().getFqName())) { + return true; + } + } + return memberDescriptor.getAnnotations().hasAnnotation(JVM_FIELD_ANNOTATION_FQ_NAME); + } } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt index 5d9e631d0ab..2560ce99c61 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt @@ -99,13 +99,26 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader - findClassAndLoadMemberAnnotations(container, sig, property = true, isConst = isConst) + findClassAndLoadMemberAnnotations( + container, + sig, + property = true, + isConst = isConst, + isMovedFromInterfaceCompanion = isMovedFromInterfaceCompanion + ) }.orEmpty() val fieldAnnotations = fieldSignature?.let { sig -> - findClassAndLoadMemberAnnotations(container, sig, property = true, field = true, isConst = isConst) + findClassAndLoadMemberAnnotations( + container, + sig, + property = true, + field = true, + isConst = isConst, + isMovedFromInterfaceCompanion = isMovedFromInterfaceCompanion + ) }.orEmpty() // TODO: check delegate presence in some other way @@ -136,11 +149,24 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader): List private fun findClassAndLoadMemberAnnotations( - container: ProtoContainer, signature: MemberSignature, - property: Boolean = false, field: Boolean = false, isConst: Boolean? = null + container: ProtoContainer, + signature: MemberSignature, + property: Boolean = false, + field: Boolean = false, + isConst: Boolean? = null, + isMovedFromInterfaceCompanion: Boolean = false ): List { val kotlinClass = - findClassWithAnnotationsAndInitializers(container, getSpecialCaseContainerClass(container, property, field, isConst)) + findClassWithAnnotationsAndInitializers( + container, + getSpecialCaseContainerClass( + container, + property, + field, + isConst, + isMovedFromInterfaceCompanion + ) + ) ?: return listOf() return storage(kotlinClass).memberAnnotations[signature] ?: listOf() @@ -202,7 +228,13 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader private constructor( is KotlinProperty -> { val descriptor = jvmSignature.descriptor JvmProtoBufUtil.getJvmFieldSignature(jvmSignature.proto, jvmSignature.nameResolver, jvmSignature.typeTable)?.let { - val owner = if (JvmAbi.isCompanionObjectWithBackingFieldsInOuter(descriptor.containingDeclaration)) { + val owner = if (JvmAbi.isPropertyWithBackingFieldInOuterClass(descriptor) || + JvmProtoBufUtil.isMovedFromInterfaceCompanion(jvmSignature.proto) + ) { container.jClass.enclosingClass } else descriptor.containingDeclaration.let { containingDeclaration -> if (containingDeclaration is ClassDescriptor) containingDeclaration.toJavaClass() @@ -188,6 +192,11 @@ private fun KPropertyImpl.Accessor<*, *>.computeCallerForAccessor(isGetter: Bool !DescriptorUtils.isInterface(possibleCompanionObject.containingDeclaration) } + fun isInsideInterfaceCompanionObjectWithJvmField(): Boolean { + val possibleCompanionObject = property.descriptor.containingDeclaration + return JvmAbi.isInterfaceCompanionWithBackingFieldsInOuter(possibleCompanionObject) + } + fun isJvmStaticProperty() = property.descriptor.annotations.findAnnotation(JVM_STATIC) != null @@ -195,7 +204,7 @@ private fun KPropertyImpl.Accessor<*, *>.computeCallerForAccessor(isGetter: Bool !TypeUtils.isNullableType(property.descriptor.type) fun computeFieldCaller(field: Field): FunctionCaller = when { - isInsideClassCompanionObject() -> { + isInsideClassCompanionObject() || isInsideInterfaceCompanionObjectWithJvmField() -> { val klass = (descriptor.containingDeclaration as ClassDescriptor).toJavaClass()!! if (isGetter) if (isBound) FunctionCaller.BoundClassCompanionFieldGetter(field, klass) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java index 993537a5da1..9bf10f06ae8 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java @@ -1562,6 +1562,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/callableReference/bound/array.kt"); } + @TestMetadata("boundJvmFieldInInterfaceCompanion.kt") + public void testBoundJvmFieldInInterfaceCompanion() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/bound/boundJvmFieldInInterfaceCompanion.kt"); + } + @TestMetadata("companionObjectReceiver.kt") public void testCompanionObjectReceiver() throws Exception { runTest("compiler/testData/codegen/box/callableReference/bound/companionObjectReceiver.kt"); @@ -16551,6 +16556,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/reflection/properties/javaStaticField.kt"); } + @TestMetadata("jvmFieldInInterfaceCompanion.kt") + public void testJvmFieldInInterfaceCompanion() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanion.kt"); + } + @TestMetadata("kotlinPropertyInheritedInJava.kt") public void testKotlinPropertyInheritedInJava() throws Exception { runTest("compiler/testData/codegen/box/reflection/properties/kotlinPropertyInheritedInJava.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 21e948c9799..8ff049bc849 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -1582,6 +1582,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/callableReference/bound/array.kt"); } + @TestMetadata("boundJvmFieldInInterfaceCompanion.kt") + public void testBoundJvmFieldInInterfaceCompanion() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/bound/boundJvmFieldInInterfaceCompanion.kt"); + } + @TestMetadata("companionObjectReceiver.kt") public void testCompanionObjectReceiver() throws Exception { runTest("compiler/testData/codegen/box/callableReference/bound/companionObjectReceiver.kt"); @@ -17546,6 +17551,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/reflection/properties/javaStaticField.kt"); } + @TestMetadata("jvmFieldInInterfaceCompanion.kt") + public void testJvmFieldInInterfaceCompanion() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanion.kt"); + } + @TestMetadata("kotlinPropertyInheritedInJava.kt") public void testKotlinPropertyInheritedInJava() throws Exception { runTest("compiler/testData/codegen/box/reflection/properties/kotlinPropertyInheritedInJava.kt"); diff --git a/libraries/stdlib/jvm/runtime/kotlin/jvm/annotations/JvmPlatformAnnotations.kt b/libraries/stdlib/jvm/runtime/kotlin/jvm/annotations/JvmPlatformAnnotations.kt index 692246db1d1..8def18df7ba 100644 --- a/libraries/stdlib/jvm/runtime/kotlin/jvm/annotations/JvmPlatformAnnotations.kt +++ b/libraries/stdlib/jvm/runtime/kotlin/jvm/annotations/JvmPlatformAnnotations.kt @@ -125,4 +125,4 @@ public annotation class JvmSuppressWildcards(val suppress: Boolean = true) @Target(AnnotationTarget.TYPE) @Retention(AnnotationRetention.BINARY) @MustBeDocumented -public annotation class JvmWildcard \ No newline at end of file +public annotation class JvmWildcard