Add underlying property name & type for inline class to kotlinx-metadata

#KT-45635 Fixed
This commit is contained in:
Alexander Udalov
2021-03-23 11:23:51 +01:00
parent 9b5bbb95e7
commit c4b2b7e0da
8 changed files with 84 additions and 0 deletions
@@ -23,6 +23,12 @@ import org.jetbrains.kotlin.metadata.ProtoBuf
fun ProtoBuf.Class.supertypes(typeTable: TypeTable): List<ProtoBuf.Type> =
supertypeList.takeIf(Collection<*>::isNotEmpty) ?: supertypeIdList.map { typeTable[it] }
fun ProtoBuf.Class.inlineClassUnderlyingType(typeTable: TypeTable): ProtoBuf.Type? = when {
hasInlineClassUnderlyingType() -> inlineClassUnderlyingType
hasInlineClassUnderlyingTypeId() -> typeTable[inlineClassUnderlyingTypeId]
else -> null
}
fun ProtoBuf.Type.Argument.type(typeTable: TypeTable): ProtoBuf.Type? = when {
hasType() -> type
hasTypeId() -> typeTable[typeId]
@@ -17,6 +17,7 @@
- Breaking change: deprecate `KotlinClassHeader.bytecodeVersion` and `KotlinClassHeader`'s constructor that takes a bytecode version array.
Related to ['KT-41758`](https://youtrack.jetbrains.com/issue/KT-41758).
- [`KT-45594`](https://youtrack.jetbrains.com/issue/KT-45594) KClass annotation argument containing array of classes is not read/written correctly
- [`KT-45635`](https://youtrack.jetbrains.com/issue/KT-45635) Add underlying property name & type for inline classes
## 0.2.0
@@ -93,6 +93,13 @@ fun ProtoBuf.Class.accept(
v.visitSealedSubclass(c.className(sealedSubclassFqName))
}
if (hasInlineClassUnderlyingPropertyName()) {
v.visitInlineClassUnderlyingPropertyName(c[inlineClassUnderlyingPropertyName])
}
loadInlineClassUnderlyingType(c)?.let { underlyingType ->
v.visitInlineClassUnderlyingType(underlyingType.flags)?.let { underlyingType.accept(it, c) }
}
for (versionRequirement in versionRequirementList) {
v.visitVersionRequirement()?.let { acceptVersionRequirementVisitor(versionRequirement, it, c) }
}
@@ -104,6 +111,18 @@ fun ProtoBuf.Class.accept(
v.visitEnd()
}
private fun ProtoBuf.Class.loadInlineClassUnderlyingType(c: ReadContext): ProtoBuf.Type? {
val type = inlineClassUnderlyingType(c.types)
if (type != null) return type
if (!hasInlineClassUnderlyingPropertyName()) return null
// Kotlin compiler doesn't write underlying type to metadata in case it can be loaded from the underlying property.
return propertyList
.singleOrNull { it.receiverType(c.types) == null && c[it.name] == c[inlineClassUnderlyingPropertyName] }
?.returnType(c.types)
}
fun ProtoBuf.Package.accept(
v: KmPackageVisitor,
strings: NameResolver,
@@ -457,6 +457,13 @@ open class ClassWriter(stringTable: StringTable, contextExtensions: List<WriteCo
t.addSealedSubclassFqName(c.getClassName(name))
}
override fun visitInlineClassUnderlyingPropertyName(name: String) {
t.inlineClassUnderlyingPropertyName = c[name]
}
override fun visitInlineClassUnderlyingType(flags: Flags): KmTypeVisitor? =
writeType(c, flags) { t.inlineClassUnderlyingType = it.build() }
override fun visitVersionRequirement(): KmVersionRequirementVisitor? =
writeVersionRequirement(c) { t.addVersionRequirement(it) }
@@ -93,6 +93,16 @@ class KmClass : KmClassVisitor(), KmDeclarationContainer {
*/
val sealedSubclasses: MutableList<ClassName> = ArrayList(0)
/**
* Name of the underlying property, if this class is `inline`.
*/
var inlineClassUnderlyingPropertyName: String? = null
/**
* Type of the underlying property, if this class is `inline`.
*/
var inlineClassUnderlyingType: KmType? = null
/**
* Version requirements on this class.
*/
@@ -140,6 +150,13 @@ class KmClass : KmClassVisitor(), KmDeclarationContainer {
sealedSubclasses.add(name)
}
override fun visitInlineClassUnderlyingPropertyName(name: String) {
inlineClassUnderlyingPropertyName = name
}
override fun visitInlineClassUnderlyingType(flags: Flags): KmTypeVisitor =
KmType(flags).also { inlineClassUnderlyingType = it }
override fun visitVersionRequirement(): KmVersionRequirementVisitor =
KmVersionRequirement().addTo(versionRequirements)
@@ -163,6 +180,8 @@ class KmClass : KmClassVisitor(), KmDeclarationContainer {
nestedClasses.forEach(visitor::visitNestedClass)
enumEntries.forEach(visitor::visitEnumEntry)
sealedSubclasses.forEach(visitor::visitSealedSubclass)
inlineClassUnderlyingPropertyName?.let(visitor::visitInlineClassUnderlyingPropertyName)
inlineClassUnderlyingType?.let { visitor.visitInlineClassUnderlyingType(it.flags)?.let(it::accept) }
versionRequirements.forEach { visitor.visitVersionRequirement()?.let(it::accept) }
extensions.forEach { visitor.visitExtensions(it.type)?.let(it::accept) }
visitor.visitEnd()
@@ -132,6 +132,23 @@ abstract class KmClassVisitor @JvmOverloads constructor(delegate: KmClassVisitor
delegate?.visitSealedSubclass(name)
}
/**
* Visits the name of the underlying property, if this class is `inline`.
*
* @param name the name of the underlying property.
*/
open fun visitInlineClassUnderlyingPropertyName(name: String) {
delegate?.visitInlineClassUnderlyingPropertyName(name)
}
/**
* Visits the type of the underlying property, if this class is `inline`.
*
* @param flags type flags, consisting of [Flag.Type] flags
*/
open fun visitInlineClassUnderlyingType(flags: Flags): KmTypeVisitor? =
delegate?.visitInlineClassUnderlyingType(flags)
/**
* Visits the version requirement on this class.
*/
@@ -767,6 +767,17 @@ class ClassPrinter(private val settings: KotlinpSettings) : KmClassVisitor(), Ab
sb.appendLine(" // sealed subclass: $name")
}
override fun visitInlineClassUnderlyingPropertyName(name: String) {
sb.appendLine()
sb.appendLine(" // underlying property: $name")
}
override fun visitInlineClassUnderlyingType(flags: Flags): KmTypeVisitor? =
printType(flags) {
sb.appendLine()
sb.appendLine(" // underlying type: $it")
}
override fun visitVersionRequirement(): KmVersionRequirementVisitor? =
printVersionRequirement { versionRequirements.add(it) }
+4
View File
@@ -21,6 +21,10 @@ public final value class Z : kotlin/Any {
public final val s: kotlin/String
public final get
// underlying property: s
// underlying type: kotlin/String
// module name: test-module
}
// META-INF/test-module.kotlin_module