From 2a3786e3f86c9f84f329da0604b2aa00a4a90f59 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 7 May 2019 12:32:33 +0200 Subject: [PATCH] Retain "is moved from interface companion" property flag in kotlinx-metadata-jvm #KT-31338 Fixed --- .../JvmFieldInInterfaceCompanion.kt | 11 ++++++ .../JvmFieldInInterfaceCompanion.txt | 12 +++++++ .../jvm/compiler/LoadJavaTestGenerated.java | 5 +++ .../LoadJavaUsingJavacTestGenerated.java | 5 +++ libraries/kotlinx-metadata/jvm/ChangeLog.md | 2 ++ .../jvm/src/kotlinx/metadata/jvm/JvmFlag.kt | 36 +++++++++++++++++++ .../jvm/impl/JvmMetadataExtensions.kt | 12 ++++++- .../src/kotlinx/metadata/jvm/jvmExtensions.kt | 27 ++++++++++++-- .../src/kotlinx/metadata/Flag.kt | 6 +--- .../kotlinMetadataVisibilities.kt | 5 ++- .../org/jetbrains/kotlin/kotlinp/printers.kt | 10 +++++- 11 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/JvmFieldInInterfaceCompanion.kt create mode 100644 compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/JvmFieldInInterfaceCompanion.txt create mode 100644 libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmFlag.kt diff --git a/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/JvmFieldInInterfaceCompanion.kt b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/JvmFieldInInterfaceCompanion.kt new file mode 100644 index 00000000000..eba803f9ae6 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/JvmFieldInInterfaceCompanion.kt @@ -0,0 +1,11 @@ +package test + +interface I { + companion object { + @JvmField + val x = "x" + + @JvmField + val y = "y" + } +} diff --git a/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/JvmFieldInInterfaceCompanion.txt b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/JvmFieldInInterfaceCompanion.txt new file mode 100644 index 00000000000..c8084b8b284 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/JvmFieldInInterfaceCompanion.txt @@ -0,0 +1,12 @@ +package test + +public interface I { + + public companion object Companion { + /*primary*/ private constructor Companion() + @field:kotlin.jvm.JvmField public final val x: kotlin.String = "x" + public final fun (): kotlin.String + @field:kotlin.jvm.JvmField public final val y: kotlin.String = "y" + public final fun (): kotlin.String + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java index 2bd510e8ccf..43d083d8374 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java @@ -4618,6 +4618,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/ConstValInMultifileClass.kt"); } + @TestMetadata("JvmFieldInInterfaceCompanion.kt") + public void testJvmFieldInInterfaceCompanion() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/JvmFieldInInterfaceCompanion.kt"); + } + @TestMetadata("WithUnsignedTypeParameters.kt") public void testWithUnsignedTypeParameters() throws Exception { runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/WithUnsignedTypeParameters.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java index 3ee3a9cc7a0..d3b9e5c7474 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java @@ -4618,6 +4618,11 @@ public class LoadJavaUsingJavacTestGenerated extends AbstractLoadJavaUsingJavacT runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/ConstValInMultifileClass.kt"); } + @TestMetadata("JvmFieldInInterfaceCompanion.kt") + public void testJvmFieldInInterfaceCompanion() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/JvmFieldInInterfaceCompanion.kt"); + } + @TestMetadata("WithUnsignedTypeParameters.kt") public void testWithUnsignedTypeParameters() throws Exception { runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/WithUnsignedTypeParameters.kt"); diff --git a/libraries/kotlinx-metadata/jvm/ChangeLog.md b/libraries/kotlinx-metadata/jvm/ChangeLog.md index 2cec6da8bfe..f3d9fe38972 100644 --- a/libraries/kotlinx-metadata/jvm/ChangeLog.md +++ b/libraries/kotlinx-metadata/jvm/ChangeLog.md @@ -3,6 +3,8 @@ ## 0.0.6 - [`KT-31308`](https://youtrack.jetbrains.com/issue/KT-31308) Add module name extensions to kotlinx-metadata-jvm +- [`KT-31338`](https://youtrack.jetbrains.com/issue/KT-31338) Retain "is moved from interface companion" property flag in kotlinx-metadata-jvm + - Breaking change: JvmPropertyExtensionVisitor.visit has a new parameter `jvmFlags: Flags` - Rename `desc` parameters to `signature` in JvmFunctionExtensionVisitor, JvmPropertyExtensionVisitor, JvmConstructorExtensionVisitor ## 0.0.5 diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmFlag.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmFlag.kt new file mode 100644 index 00000000000..2ab38a36565 --- /dev/null +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmFlag.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlinx.metadata.jvm + +import kotlinx.metadata.Flag +import kotlinx.metadata.Flags +import org.jetbrains.kotlin.metadata.deserialization.Flags as F +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmFlags as JF + +/** + * JVM-specific flags in addition to common flags declared in [Flag]. + * + * @see Flag + * @see Flags + */ +object JvmFlag { + /** + * JVM-specific property flags in addition to common property flags declared in [Flag.Property]. + */ + object Property { + /** + * Applied to a property declared in an interface's companion object, signifies that its backing field is declared as a static + * field in the interface. In Kotlin code, this usually happens if the property is annotated with [JvmField]. + * + * Has no effect if the property is not declared in a companion object of some interface. + */ + @JvmField + val IS_MOVED_FROM_INTERFACE_COMPANION = booleanFlag(JF.IS_MOVED_FROM_INTERFACE_COMPANION) + } + + private fun booleanFlag(f: F.BooleanFlagField): Flag = + Flag(f.offset, f.bitWidth, 1) +} diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/impl/JvmMetadataExtensions.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/impl/JvmMetadataExtensions.kt index 327762db476..2a39fcd08af 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/impl/JvmMetadataExtensions.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/impl/JvmMetadataExtensions.kt @@ -69,6 +69,7 @@ internal class JvmMetadataExtensions : MetadataExtensions { val setterSignature = if (propertySignature != null && propertySignature.hasSetter()) propertySignature.setter else null ext.visit( + proto.getExtension(JvmProtoBuf.flags), fieldSignature?.wrapAsPublic(), getterSignature?.run { JvmMethodSignature(c[name], c[desc]) }, setterSignature?.run { JvmMethodSignature(c[name], c[desc]) } @@ -165,11 +166,17 @@ internal class JvmMetadataExtensions : MetadataExtensions { ): KmPropertyExtensionVisitor? { if (type != JvmPropertyExtensionVisitor.TYPE) return null return object : JvmPropertyExtensionVisitor() { + var jvmFlags: Flags = ProtoBuf.Property.getDefaultInstance().getExtension(JvmProtoBuf.flags) var signature: JvmProtoBuf.JvmPropertySignature.Builder? = null override fun visit( - fieldSignature: JvmFieldSignature?, getterSignature: JvmMethodSignature?, setterSignature: JvmMethodSignature? + jvmFlags: Flags, + fieldSignature: JvmFieldSignature?, + getterSignature: JvmMethodSignature?, + setterSignature: JvmMethodSignature? ) { + this.jvmFlags = jvmFlags + if (fieldSignature == null && getterSignature == null && setterSignature == null) return if (signature == null) { @@ -202,6 +209,9 @@ internal class JvmMetadataExtensions : MetadataExtensions { } override fun visitEnd() { + if (jvmFlags != ProtoBuf.Property.getDefaultInstance().getExtension(JvmProtoBuf.flags)) { + proto.setExtension(JvmProtoBuf.flags, jvmFlags) + } if (signature != null) { proto.setExtension(JvmProtoBuf.propertySignature, signature!!.build()) } diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/jvmExtensions.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/jvmExtensions.kt index 525794c6115..272b539f1b2 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/jvmExtensions.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/jvmExtensions.kt @@ -156,16 +156,37 @@ open class JvmPropertyExtensionVisitor @JvmOverloads constructor( /** * Visits JVM signatures of field and accessors generated for the property. * + * @param jvmFlags JVM-specific flags of the property, consisting of [JvmFlag.Property] flags * @param fieldSignature the signature of the field, or `null` if this property has no field. * Example: `JvmFieldSignature("X", "Ljava/lang/Object;")` - * * @param getterSignature the signature of the property getter, or `null` if this property has no getter or its signature is unknown. * Example: `JvmMethodSignature("getX()", "Ljava/lang/Object;")` - * * @param setterSignature the signature of the property setter, or `null` if this property has no setter or its signature is unknown. * Example: `JvmMethodSignature("setX", "(Ljava/lang/Object;)V")` */ - open fun visit(fieldSignature: JvmFieldSignature?, getterSignature: JvmMethodSignature?, setterSignature: JvmMethodSignature?) { + open fun visit( + jvmFlags: Flags, + fieldSignature: JvmFieldSignature?, + getterSignature: JvmMethodSignature?, + setterSignature: JvmMethodSignature? + ) { + delegate?.visit(jvmFlags, fieldSignature, getterSignature, setterSignature) + + @Suppress("DEPRECATION_ERROR") + visit(fieldSignature, getterSignature, setterSignature) + } + + @Deprecated( + "Use visit(Flags, JvmFieldSignature?, JvmMethodSignature?, JvmMethodSignature?) instead.", + level = DeprecationLevel.ERROR, + replaceWith = ReplaceWith("visit(flagsOf(), fieldSignature, getterSignature, setterSignature)", "kotlinx.metadata.flagsOf") + ) + open fun visit( + fieldSignature: JvmFieldSignature?, + getterSignature: JvmMethodSignature?, + setterSignature: JvmMethodSignature? + ) { + @Suppress("DEPRECATION_ERROR") delegate?.visit(fieldSignature, getterSignature, setterSignature) } diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/Flag.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/Flag.kt index 09375205f07..5cdd6b31860 100644 --- a/libraries/kotlinx-metadata/src/kotlinx/metadata/Flag.kt +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/Flag.kt @@ -37,11 +37,7 @@ import org.jetbrains.kotlin.metadata.ProtoBuf.Class.Kind as ClassKind * @see Flags * @see flagsOf */ -class Flag internal constructor( - private val offset: Int, - private val bitWidth: Int, - private val value: Int -) { +class Flag(private val offset: Int, private val bitWidth: Int, private val value: Int) { internal constructor(field: F.FlagField<*>, value: Int) : this(field.offset, field.bitWidth, value) internal constructor(field: F.BooleanFlagField) : this(field, 1) diff --git a/libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools/kotlinMetadataVisibilities.kt b/libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools/kotlinMetadataVisibilities.kt index 0506ce0a1f5..50e9b9d8a42 100644 --- a/libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools/kotlinMetadataVisibilities.kt +++ b/libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools/kotlinMetadataVisibilities.kt @@ -96,7 +96,10 @@ private fun visitProperty(flags: Flags, name: String, getterFlags: Flags, setter if (type != JvmPropertyExtensionVisitor.TYPE) return null return object : JvmPropertyExtensionVisitor() { override fun visit( - fieldSignature: JvmFieldSignature?, getterSignature: JvmMethodSignature?, setterSignature: JvmMethodSignature? + jvmFlags: Flags, + fieldSignature: JvmFieldSignature?, + getterSignature: JvmMethodSignature?, + setterSignature: JvmMethodSignature? ) { fieldDesc = fieldSignature getterDesc = getterSignature diff --git a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt index 7383703a394..c892b4da619 100644 --- a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt +++ b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt @@ -95,6 +95,7 @@ private fun visitProperty( var jvmGetterSignature: JvmMemberSignature? = null var jvmSetterSignature: JvmMemberSignature? = null var jvmSyntheticMethodForAnnotationsSignature: JvmMemberSignature? = null + var isMovedFromInterfaceCompanion: Boolean = false override fun visitReceiverParameterType(flags: Flags): KmTypeVisitor? = printType(flags) { receiverParameterType = it } @@ -115,8 +116,12 @@ private fun visitProperty( if (type != JvmPropertyExtensionVisitor.TYPE) return null return object : JvmPropertyExtensionVisitor() { override fun visit( - fieldSignature: JvmFieldSignature?, getterSignature: JvmMethodSignature?, setterSignature: JvmMethodSignature? + jvmFlags: Flags, + fieldSignature: JvmFieldSignature?, + getterSignature: JvmMethodSignature?, + setterSignature: JvmMethodSignature? ) { + isMovedFromInterfaceCompanion = JvmFlag.Property.IS_MOVED_FROM_INTERFACE_COMPANION(jvmFlags) jvmFieldSignature = fieldSignature jvmGetterSignature = getterSignature jvmSetterSignature = setterSignature @@ -145,6 +150,9 @@ private fun visitProperty( if (jvmSyntheticMethodForAnnotationsSignature != null) { sb.appendln(" // synthetic method for annotations: $jvmSyntheticMethodForAnnotationsSignature") } + if (isMovedFromInterfaceCompanion) { + sb.appendln(" // is moved from interface companion") + } sb.append(" ") sb.appendFlags(flags, PROPERTY_FLAGS_MAP) sb.append(if (Flag.Property.IS_VAR(flags)) "var " else "val ")