Restructure KotlinClass(Module)Metadata.write/read:
- Write now returns result (Metadata or ByteArray) directly without re-wrapping it; - annotationData/bytes is private to avoid unsoundness if external client corrupts it; - .toXxx() do not throw exceptions anymore and deprecated. Exceptions are thrown only from read/write; - Instead of toXxx(), properties like .kmClass should be used instead. They're initialized eagerly and return a view without copying. - KotlinClassMetadata.Unknown is now a data object, as no useful information is exposed #KT-59365 Fixed
This commit is contained in:
committed by
Space Team
parent
5bb4f469ef
commit
b919a12274
@@ -11,7 +11,7 @@ import kotlinx.metadata.jvm.UnstableMetadataApi
|
||||
import java.io.File
|
||||
|
||||
class Kotlinp(private val settings: KotlinpSettings) {
|
||||
internal fun renderClassFile(classFile: KotlinClassMetadata?): String =
|
||||
internal fun renderClassFile(classFile: KotlinClassMetadata): String =
|
||||
when (classFile) {
|
||||
is KotlinClassMetadata.Class -> ClassPrinter(settings).print(classFile)
|
||||
is KotlinClassMetadata.FileFacade -> FileFacadePrinter(settings).print(classFile)
|
||||
@@ -21,14 +21,17 @@ class Kotlinp(private val settings: KotlinpSettings) {
|
||||
}
|
||||
is KotlinClassMetadata.MultiFileClassFacade -> MultiFileClassFacadePrinter().print(classFile)
|
||||
is KotlinClassMetadata.MultiFileClassPart -> MultiFileClassPartPrinter(settings).print(classFile)
|
||||
is KotlinClassMetadata.Unknown -> buildString { appendLine("unknown file (k=${classFile.annotationData.kind})") }
|
||||
null -> buildString { appendLine("unsupported file") }
|
||||
is KotlinClassMetadata.Unknown -> buildString { appendLine("unknown file") }
|
||||
}
|
||||
|
||||
internal fun readClassFile(file: File): KotlinClassMetadata? {
|
||||
val header = file.readKotlinClassHeader() ?: throw KotlinpException("file is not a Kotlin class file: $file")
|
||||
|
||||
internal fun readClassFile(file: File): Metadata {
|
||||
return file.readKotlinClassHeader() ?: throw KotlinpException("file is not a Kotlin class file: $file")
|
||||
}
|
||||
|
||||
internal fun readMetadata(metadata: Metadata): KotlinClassMetadata {
|
||||
return try {
|
||||
KotlinClassMetadata.read(header)
|
||||
KotlinClassMetadata.read(metadata)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
throw KotlinpException("inconsistent Kotlin metadata: ${e.message}")
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ object Main {
|
||||
|
||||
val text = try {
|
||||
when (file.extension) {
|
||||
"class" -> kotlinp.renderClassFile(kotlinp.readClassFile(file))
|
||||
"class" -> kotlinp.renderClassFile(kotlinp.readMetadata(kotlinp.readClassFile(file)))
|
||||
"kotlin_module" -> @OptIn(UnstableMetadataApi::class) kotlinp.renderModuleFile(kotlinp.readModuleFile(file))
|
||||
else -> throw KotlinpException("only .class and .kotlin_module files are supported")
|
||||
}
|
||||
|
||||
@@ -567,7 +567,7 @@ class ClassPrinter(private val settings: KotlinpSettings) : AbstractPrinter<Kotl
|
||||
}
|
||||
}
|
||||
|
||||
override fun print(klass: KotlinClassMetadata.Class): String = print(klass.toKmClass())
|
||||
override fun print(klass: KotlinClassMetadata.Class): String = print(klass.kmClass)
|
||||
|
||||
@OptIn(ExperimentalContextReceivers::class)
|
||||
fun print(kmClass: KmClass): String {
|
||||
@@ -625,7 +625,7 @@ abstract class PackagePrinter(private val settings: KotlinpSettings) {
|
||||
|
||||
class FileFacadePrinter(settings: KotlinpSettings) : PackagePrinter(settings), AbstractPrinter<KotlinClassMetadata.FileFacade> {
|
||||
override fun print(klass: KotlinClassMetadata.FileFacade): String {
|
||||
print(klass.toKmPackage())
|
||||
print(klass.kmPackage)
|
||||
return sb.toString()
|
||||
}
|
||||
}
|
||||
@@ -635,7 +635,7 @@ class LambdaPrinter(private val settings: KotlinpSettings) : AbstractPrinter<Kot
|
||||
val sb = StringBuilder().apply {
|
||||
appendLine("lambda {")
|
||||
}
|
||||
val kLambda = klass.toKmLambda() ?: throw KotlinpException("Synthetic class $klass is not a lambda")
|
||||
val kLambda = klass.kmLambda ?: throw KotlinpException("Synthetic class $klass is not a lambda")
|
||||
visitFunction(kLambda.function, settings, sb)
|
||||
sb.appendLine("}")
|
||||
return sb.toString()
|
||||
@@ -647,7 +647,7 @@ class MultiFileClassPartPrinter(
|
||||
) : PackagePrinter(settings), AbstractPrinter<KotlinClassMetadata.MultiFileClassPart> {
|
||||
override fun print(klass: KotlinClassMetadata.MultiFileClassPart): String {
|
||||
sb.appendLine(" // facade: ${klass.facadeClassName}")
|
||||
print(klass.toKmPackage())
|
||||
print(klass.kmPackage)
|
||||
return sb.toString()
|
||||
}
|
||||
}
|
||||
@@ -696,7 +696,7 @@ class ModuleFilePrinter(private val settings: KotlinpSettings) {
|
||||
|
||||
@UnstableMetadataApi
|
||||
fun print(metadata: KotlinModuleMetadata): String {
|
||||
val kmModule = metadata.toKmModule()
|
||||
val kmModule = metadata.kmModule
|
||||
kmModule.packageParts.forEach { (fqName, kmPackageParts) ->
|
||||
visitPackageParts(fqName, kmPackageParts.fileFacades, kmPackageParts.multiFileClassParts)
|
||||
}
|
||||
|
||||
+15
-13
@@ -49,8 +49,8 @@ fun compileAndPrintAllFiles(
|
||||
when (outputFile.extension) {
|
||||
"kotlin_module" -> {
|
||||
val moduleFile = kotlinp.readModuleFile(outputFile)!!
|
||||
val transformedWithVisitors = transformModuleFileWithReadWriteVisitors(moduleFile)
|
||||
val transformedWithNodes = transformModuleFileWithNodes(moduleFile)
|
||||
val transformedWithVisitors = KotlinModuleMetadata.read(transformModuleFileWithReadWriteVisitors(moduleFile))
|
||||
val transformedWithNodes = KotlinModuleMetadata.read(transformModuleFileWithNodes(moduleFile))
|
||||
|
||||
for ((sb, moduleFileToRender) in listOf(
|
||||
main to moduleFile, afterVisitors to transformedWithVisitors, afterNodes to transformedWithNodes
|
||||
@@ -60,9 +60,10 @@ fun compileAndPrintAllFiles(
|
||||
}
|
||||
}
|
||||
"class" -> {
|
||||
val classFile = kotlinp.readClassFile(outputFile)!!
|
||||
val metadata = kotlinp.readClassFile(outputFile)
|
||||
val classFile = kotlinp.readMetadata(metadata)
|
||||
val classFile2 = transformClassFileWithReadWriteVisitors(classFile)
|
||||
val classFile3 = transformClassFileWithNodes(classFile)
|
||||
val classFile3 = KotlinClassMetadata.read(transformClassFileWithNodes(metadata, classFile))
|
||||
|
||||
for ((sb, classFileToRender) in listOf(
|
||||
main to classFile, afterVisitors to classFile2, afterNodes to classFile3
|
||||
@@ -130,24 +131,25 @@ private fun transformClassFileWithReadWriteVisitors(classFile: KotlinClassMetada
|
||||
}
|
||||
|
||||
// Reads the class file and writes it back with KmClass/KmFunction/... elements.
|
||||
private fun transformClassFileWithNodes(classFile: KotlinClassMetadata): KotlinClassMetadata =
|
||||
private fun transformClassFileWithNodes(metadata: Metadata, classFile: KotlinClassMetadata): Metadata =
|
||||
when (classFile) {
|
||||
is KotlinClassMetadata.Class ->
|
||||
KotlinClassMetadata.writeClass(classFile.toKmClass())
|
||||
KotlinClassMetadata.writeClass(classFile.kmClass)
|
||||
is KotlinClassMetadata.FileFacade ->
|
||||
KotlinClassMetadata.writeFileFacade(classFile.toKmPackage())
|
||||
KotlinClassMetadata.writeFileFacade(classFile.kmPackage)
|
||||
is KotlinClassMetadata.SyntheticClass ->
|
||||
classFile.toKmLambda()?.let { KotlinClassMetadata.writeLambda(it) } ?: KotlinClassMetadata.writeSyntheticClass()
|
||||
classFile.kmLambda?.let { KotlinClassMetadata.writeLambda(it) } ?: KotlinClassMetadata.writeSyntheticClass()
|
||||
is KotlinClassMetadata.MultiFileClassPart ->
|
||||
KotlinClassMetadata.writeMultiFileClassPart(classFile.toKmPackage(), classFile.facadeClassName)
|
||||
else -> classFile
|
||||
KotlinClassMetadata.writeMultiFileClassPart(classFile.kmPackage, classFile.facadeClassName)
|
||||
is KotlinClassMetadata.MultiFileClassFacade -> KotlinClassMetadata.writeMultiFileClassFacade(classFile.partClassNames)
|
||||
is KotlinClassMetadata.Unknown -> metadata
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION") // We're testing that reading/writing with KmNodes is identical to direct
|
||||
@OptIn(UnstableMetadataApi::class)
|
||||
private fun transformModuleFileWithReadWriteVisitors(moduleFile: KotlinModuleMetadata): KotlinModuleMetadata =
|
||||
private fun transformModuleFileWithReadWriteVisitors(moduleFile: KotlinModuleMetadata): ByteArray =
|
||||
KotlinModuleMetadata.Writer().apply(moduleFile::accept).write()
|
||||
|
||||
@OptIn(UnstableMetadataApi::class)
|
||||
private fun transformModuleFileWithNodes(moduleFile: KotlinModuleMetadata): KotlinModuleMetadata =
|
||||
KotlinModuleMetadata.write(moduleFile.toKmModule())
|
||||
private fun transformModuleFileWithNodes(moduleFile: KotlinModuleMetadata): ByteArray =
|
||||
KotlinModuleMetadata.write(moduleFile.kmModule)
|
||||
|
||||
Reference in New Issue
Block a user