JVM IR: generate kotlin.Metadata.packageName value for JvmPackageName files

Support this for single file facades as well as for multi-file classes,
similar to code in
MultifileClassCodegen.writeKotlinMultifileFacadeAnnotationIfNeeded.
Extend the test on this attribute to also cover multi-file classes.
This commit is contained in:
Alexander Udalov
2019-11-08 20:30:33 +01:00
parent 808000e458
commit 9772de0088
4 changed files with 49 additions and 8 deletions
@@ -214,6 +214,10 @@ open class ClassCodegen protected constructor(
writeKotlinMetadata(visitor, state, KotlinClassHeader.Kind.CLASS, 0) {
AsmUtil.writeAnnotationData(it, serializer, classProto)
}
assert(irClass !in context.classNameOverride) {
"JvmPackageName is not supported for classes: ${irClass.render()}"
}
}
is MetadataSource.File -> {
val packageFqName = irClass.getPackageFragment()!!.fqName
@@ -230,7 +234,9 @@ open class ClassCodegen protected constructor(
av.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME, facadeClassName.internalName)
}
// TODO: JvmPackageName
if (irClass in context.classNameOverride) {
av.visit(JvmAnnotationNames.METADATA_PACKAGE_NAME_FIELD_NAME, irClass.fqNameWhenAvailable!!.parent().asString())
}
}
}
else -> {
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
@@ -112,7 +113,10 @@ private class FileClassLowering(val context: JvmBackendContext) : FileLoweringPa
if (fileClassInfo.withJvmMultifileClass) AsmUtil.asmTypeByFqNameWithoutInnerClasses(fileClassInfo.facadeClassFqName)
else null
context.state.factory.packagePartRegistry.addPart(irFile.fqName, partClassType.internalName, facadeClassType?.internalName)
context.classNameOverride[this] = JvmClassName.byInternalName(partClassType.internalName)
if (fileClassInfo.fileClassFqName != fqNameWhenAvailable) {
context.classNameOverride[this] = JvmClassName.byInternalName(partClassType.internalName)
}
if (facadeClassType != null) {
val jvmClassName = JvmClassName.byInternalName(facadeClassType.internalName)
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -100,14 +101,27 @@ private fun generateMultifileFacades(
functionDelegates: MutableMap<IrFunctionSymbol, IrFunctionSymbol>
): List<IrFile> =
context.multifileFacadesToAdd.map { (jvmClassName, partClasses) ->
val kotlinPackageFqName = partClasses.first().fqNameWhenAvailable!!.parent()
if (!partClasses.all { it.fqNameWhenAvailable!!.parent() == kotlinPackageFqName }) {
throw UnsupportedOperationException(
"Multi-file parts of a facade with JvmPackageName should all lie in the same Kotlin package:\n " +
partClasses.joinToString("\n ") { klass ->
"Class ${klass.fqNameWhenAvailable}, JVM name ${context.classNameOverride[klass]}"
}
)
}
val fileEntry = MultifileFacadeFileEntry(jvmClassName, partClasses.map(IrClass::fileParent))
val file = IrFileImpl(fileEntry, EmptyPackageFragmentDescriptor(module, jvmClassName.packageFqName))
val file = IrFileImpl(fileEntry, EmptyPackageFragmentDescriptor(module, kotlinPackageFqName))
val facadeClass = buildClass {
name = jvmClassName.fqNameForTopLevelClassMaybeWithDollars.shortName()
}.apply {
parent = file
createImplicitParameterDeclarationWithWrappedDescriptor()
if (jvmClassName.packageFqName != kotlinPackageFqName) {
context.classNameOverride[this] = jvmClassName
}
}
file.declarations.add(facadeClass)