Add anonymousObjectOriginName/lambdaClassOriginName to kotlinx-metadata

#KT-21320
 #KT-23198
This commit is contained in:
Alexander Udalov
2018-05-16 15:23:25 +02:00
parent b97379b39b
commit e1a4bd01f5
10 changed files with 117 additions and 3 deletions
@@ -5,6 +5,11 @@ inline fun a() {}
inline fun b() {}
inline fun c() {}
inline fun c(crossinline f: () -> Unit) {
object { init { f() }}
{ f() }
}
inline fun d() {}
inline fun d() {
c {}
}
@@ -2,5 +2,5 @@ package test
public inline fun a(): kotlin.Unit
public inline fun b(): kotlin.Unit
public inline fun c(): kotlin.Unit
public inline fun c(/*0*/ crossinline f: () -> kotlin.Unit): kotlin.Unit
public inline fun d(): kotlin.Unit
@@ -19,9 +19,23 @@ import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.metadata.serialization.StringTable
internal class JvmMetadataExtensions : MetadataExtensions {
override fun readClassExtensions(v: KmClassVisitor, proto: ProtoBuf.Class, strings: NameResolver, types: TypeTable) {
val ext = v.visitExtensions(JvmClassExtensionVisitor.TYPE) as? JvmClassExtensionVisitor ?: return
val anonymousObjectOriginName = proto.getExtensionOrNull(JvmProtoBuf.anonymousObjectOriginName)
if (anonymousObjectOriginName != null) {
ext.visitAnonymousObjectOriginName(strings.getString(anonymousObjectOriginName))
}
}
override fun readFunctionExtensions(v: KmFunctionVisitor, proto: ProtoBuf.Function, strings: NameResolver, types: TypeTable) {
val ext = v.visitExtensions(JvmFunctionExtensionVisitor.TYPE) as? JvmFunctionExtensionVisitor ?: return
ext.visit(JvmProtoBufUtil.getJvmMethodSignature(proto, strings, types))
val lambdaClassOriginName = proto.getExtensionOrNull(JvmProtoBuf.lambdaClassOriginName)
if (lambdaClassOriginName != null) {
ext.visitLambdaClassOriginName(strings.getString(lambdaClassOriginName))
}
}
override fun readPropertyExtensions(v: KmPropertyVisitor, proto: ProtoBuf.Property, strings: NameResolver, types: TypeTable) {
@@ -68,6 +82,17 @@ internal class JvmMetadataExtensions : MetadataExtensions {
ext.visitEnd()
}
override fun writeClassExtensions(
type: KmExtensionType, proto: ProtoBuf.Class.Builder, strings: StringTable
): KmClassExtensionVisitor? {
if (type != JvmClassExtensionVisitor.TYPE) return null
return object : JvmClassExtensionVisitor() {
override fun visitAnonymousObjectOriginName(internalName: String) {
proto.setExtension(JvmProtoBuf.anonymousObjectOriginName, strings.getStringIndex(internalName))
}
}
}
override fun writeFunctionExtensions(
type: KmExtensionType, proto: ProtoBuf.Function.Builder, strings: StringTable
): KmFunctionExtensionVisitor? {
@@ -78,6 +103,10 @@ internal class JvmMetadataExtensions : MetadataExtensions {
proto.setExtension(JvmProtoBuf.methodSignature, desc.toJvmMethodSignature(strings))
}
}
override fun visitLambdaClassOriginName(internalName: String) {
proto.setExtension(JvmProtoBuf.lambdaClassOriginName, strings.getStringIndex(internalName))
}
}
}
@@ -8,6 +8,31 @@ package kotlinx.metadata.jvm
import kotlinx.metadata.*
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
/**
* A visitor to visit JVM extensions for a function.
*/
open class JvmClassExtensionVisitor @JvmOverloads constructor(
private val delegate: JvmClassExtensionVisitor? = null
) : KmClassExtensionVisitor {
/**
* Visits the JVM internal name of the original class this anonymous object is copied from. This method is called for
* anonymous objects copied from bodies of inline functions to the use site by the Kotlin compiler.
*/
open fun visitAnonymousObjectOriginName(internalName: String) {
delegate?.visitAnonymousObjectOriginName(internalName)
}
companion object {
/**
* The type of this extension visitor.
*
* @see KmExtensionType
*/
@JvmField
val TYPE: KmExtensionType = KmExtensionType(JvmClassExtensionVisitor::class)
}
}
/**
* A visitor to visit JVM extensions for a function.
*/
@@ -24,6 +49,14 @@ open class JvmFunctionExtensionVisitor @JvmOverloads constructor(
delegate?.visit(desc)
}
/**
* Visits the JVM internal name of the original class the lambda class for this function is copied from.
* This information is present for lambdas copied from bodies of inline functions to the use site by the Kotlin compiler.
*/
open fun visitLambdaClassOriginName(internalName: String) {
delegate?.visitLambdaClassOriginName(internalName)
}
companion object {
/**
* The type of this extension visitor.
@@ -35,6 +35,11 @@ data class KmExtensionType(val klass: KClass<out KmExtensionVisitor>)
*/
interface KmExtensionVisitor
/**
* A visitor to visit platform-specific extensions for a class.
*/
interface KmClassExtensionVisitor : KmExtensionVisitor
/**
* A visitor to visit platform-specific extensions for a function.
*/
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.metadata.serialization.StringTable
import java.util.*
interface MetadataExtensions {
fun readClassExtensions(v: KmClassVisitor, proto: ProtoBuf.Class, strings: NameResolver, types: TypeTable)
fun readFunctionExtensions(v: KmFunctionVisitor, proto: ProtoBuf.Function, strings: NameResolver, types: TypeTable)
fun readPropertyExtensions(v: KmPropertyVisitor, proto: ProtoBuf.Property, strings: NameResolver, types: TypeTable)
@@ -23,6 +25,8 @@ interface MetadataExtensions {
fun readTypeExtensions(v: KmTypeVisitor, proto: ProtoBuf.Type, strings: NameResolver)
fun writeClassExtensions(type: KmExtensionType, proto: ProtoBuf.Class.Builder, strings: StringTable): KmClassExtensionVisitor?
fun writeFunctionExtensions(type: KmExtensionType, proto: ProtoBuf.Function.Builder, strings: StringTable): KmFunctionExtensionVisitor?
fun writePropertyExtensions(type: KmExtensionType, proto: ProtoBuf.Property.Builder, strings: StringTable): KmPropertyExtensionVisitor?
@@ -81,6 +81,10 @@ fun ProtoBuf.Class.accept(v: KmClassVisitor, strings: NameResolver) {
v.visitVersionRequirement()?.let { acceptVersionRequirementVisitor(it, c) }
}
for (extension in c.extensions) {
extension.readClassExtensions(v, this, c.strings, c.types)
}
v.visitEnd()
}
@@ -455,6 +455,11 @@ open class ClassWriter(stringTable: StringTable) : KmClassVisitor() {
override fun visitVersionRequirement(): KmVersionRequirementVisitor? =
writeVersionRequirement(c) { t.versionRequirement = it }
override fun visitExtensions(type: KmExtensionType): KmClassExtensionVisitor? =
c.applySingleExtension(type) {
writeClassExtensions(type, t, c.strings)
}
override fun visitEnd() {
c.versionRequirements.serialize()?.let {
t.versionRequirementTable = it
@@ -131,6 +131,14 @@ abstract class KmClassVisitor @JvmOverloads constructor(delegate: KmClassVisitor
open fun visitVersionRequirement(): KmVersionRequirementVisitor? =
delegate?.visitVersionRequirement()
/**
* Visits the extensions of the given type on the class.
*
* @param type the type of extension visitor to be returned
*/
open fun visitExtensions(type: KmExtensionType): KmClassExtensionVisitor? =
delegate?.visitExtensions(type)
/**
* Visits the end of the class.
*/
@@ -20,6 +20,7 @@ private fun visitFunction(settings: KotlinpSettings, sb: StringBuilder, flags: F
var returnType: String? = null
var versionRequirement: String? = null
var jvmDesc: String? = null
var lambdaClassOriginName: String? = null
override fun visitReceiverParameterType(flags: Flags): KmTypeVisitor? =
printType(flags) { receiverParameterType = it }
@@ -44,11 +45,18 @@ private fun visitFunction(settings: KotlinpSettings, sb: StringBuilder, flags: F
override fun visit(desc: String?) {
jvmDesc = desc
}
override fun visitLambdaClassOriginName(internalName: String) {
lambdaClassOriginName = internalName
}
}
}
override fun visitEnd() {
sb.appendln()
if (lambdaClassOriginName != null) {
sb.appendln(" // lambda class origin: $lambdaClassOriginName")
}
if (versionRequirement != null) {
sb.appendln(" // $versionRequirement")
}
@@ -520,6 +528,7 @@ class ClassPrinter(private val settings: KotlinpSettings) : KmClassVisitor(), Ab
private val typeParams = mutableListOf<String>()
private val supertypes = mutableListOf<String>()
private var versionRequirement: String? = null
private var anonymousObjectOriginName: String? = null
override fun visit(flags: Flags, name: ClassName) {
this.flags = flags
@@ -527,6 +536,9 @@ class ClassPrinter(private val settings: KotlinpSettings) : KmClassVisitor(), Ab
}
override fun visitEnd() {
if (anonymousObjectOriginName != null) {
result.appendln("// anonymous object origin: $anonymousObjectOriginName")
}
if (versionRequirement != null) {
result.appendln(" // $versionRequirement")
}
@@ -585,6 +597,15 @@ class ClassPrinter(private val settings: KotlinpSettings) : KmClassVisitor(), Ab
override fun visitVersionRequirement(): KmVersionRequirementVisitor? =
printVersionRequirement { versionRequirement = it }
override fun visitExtensions(type: KmExtensionType): KmClassExtensionVisitor? {
if (type != JvmClassExtensionVisitor.TYPE) return null
return object : JvmClassExtensionVisitor() {
override fun visitAnonymousObjectOriginName(internalName: String) {
anonymousObjectOriginName = internalName
}
}
}
override fun print(klass: KotlinClassMetadata.Class): String {
klass.accept(this)
return result.toString()