From f9cc443e4fbc8ea70ea2289e55f225706007e2bd Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 3 Oct 2019 09:17:42 +0200 Subject: [PATCH] Support common metadata in kotlinx-metadata KotlinCommonMetadata can be used to inspect .kotlin_builtins and .kotlin_metadata files. It's in an internal package for now, but might be published once the API is finalized. --- .../builtins/BuiltInsPackageFragmentImpl.kt | 23 ++++------ .../metadata/builtins/readPackageFragment.kt | 22 ++++++++++ .../jvm/impl/JvmMetadataExtensions.kt | 7 ++- .../internal/common/KotlinCommonMetadata.kt | 44 +++++++++++++++++++ 4 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 core/metadata/src/org/jetbrains/kotlin/metadata/builtins/readPackageFragment.kt create mode 100644 libraries/kotlinx-metadata/src/kotlinx/metadata/internal/common/KotlinCommonMetadata.kt diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/builtins/BuiltInsPackageFragmentImpl.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/builtins/BuiltInsPackageFragmentImpl.kt index 20157c2821e..021747c0dbe 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/builtins/BuiltInsPackageFragmentImpl.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/builtins/BuiltInsPackageFragmentImpl.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion +import org.jetbrains.kotlin.metadata.builtins.readBuiltinsPackageFragment import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.serialization.deserialization.DeserializedPackageFragmentImpl @@ -33,21 +34,15 @@ class BuiltInsPackageFragmentImpl private constructor( inputStream: InputStream, isFallback: Boolean ): BuiltInsPackageFragmentImpl { - lateinit var version: BuiltInsBinaryVersion + val (proto, version) = inputStream.readBuiltinsPackageFragment() - val proto = inputStream.use { stream -> - version = BuiltInsBinaryVersion.readFrom(stream) - - if (!version.isCompatible()) { - // TODO: report a proper diagnostic - throw UnsupportedOperationException( - "Kotlin built-in definition format version is not supported: " + - "expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " + - "Please update Kotlin" - ) - } - - ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry) + if (proto == null) { + // TODO: report a proper diagnostic + throw UnsupportedOperationException( + "Kotlin built-in definition format version is not supported: " + + "expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " + + "Please update Kotlin" + ) } return BuiltInsPackageFragmentImpl(fqName, storageManager, module, proto, version, isFallback) diff --git a/core/metadata/src/org/jetbrains/kotlin/metadata/builtins/readPackageFragment.kt b/core/metadata/src/org/jetbrains/kotlin/metadata/builtins/readPackageFragment.kt new file mode 100644 index 00000000000..4a43d024fff --- /dev/null +++ b/core/metadata/src/org/jetbrains/kotlin/metadata/builtins/readPackageFragment.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2020 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 org.jetbrains.kotlin.metadata.builtins + +import org.jetbrains.kotlin.metadata.ProtoBuf +import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite +import java.io.InputStream + +fun InputStream.readBuiltinsPackageFragment(): Pair = + use { stream -> + val version = BuiltInsBinaryVersion.readFrom(stream) + val proto = + if (version.isCompatible()) ProtoBuf.PackageFragment.parseFrom( + stream, + ExtensionRegistryLite.newInstance().apply(BuiltInsProtoBuf::registerAllExtensions) + ) + else null + proto to version + } 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 8e63e1f31ae..cbaf9e9aa25 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 @@ -298,7 +298,12 @@ internal class JvmMetadataExtensions : MetadataExtensions { override fun createPackageExtension(): KmPackageExtension = JvmPackageExtension() override fun createModuleFragmentExtensions(): KmModuleFragmentExtension = - error("metadata-jvm doesn't have any extensions for module fragment!") + object : KmModuleFragmentExtension { + override val type: KmExtensionType = KmExtensionType(KmModuleFragmentExtension::class) + + override fun accept(visitor: KmModuleFragmentExtensionVisitor) { + } + } override fun createFunctionExtension(): KmFunctionExtension = JvmFunctionExtension() diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/common/KotlinCommonMetadata.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/common/KotlinCommonMetadata.kt new file mode 100644 index 00000000000..bde301ce7db --- /dev/null +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/common/KotlinCommonMetadata.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2022 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.internal.common + +import kotlinx.metadata.KmModuleFragment +import kotlinx.metadata.KmModuleFragmentVisitor +import kotlinx.metadata.impl.accept +import org.jetbrains.kotlin.metadata.ProtoBuf +import org.jetbrains.kotlin.metadata.builtins.readBuiltinsPackageFragment +import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl +import java.io.ByteArrayInputStream + +class KotlinCommonMetadata private constructor(private val proto: ProtoBuf.PackageFragment) { + fun toKmModuleFragment(): KmModuleFragment = + KmModuleFragment().apply(this::accept) + + class Writer : KmModuleFragmentVisitor() { + // TODO + } + + fun accept(v: KmModuleFragmentVisitor) { + val strings = NameResolverImpl(proto.strings, proto.qualifiedNames) + if (proto.hasPackage()) { + v.visitPackage()?.let { proto.`package`.accept(it, strings) } + } + for (klass in proto.class_List) { + v.visitClass()?.let { klass.accept(it, strings) } + } + v.visitEnd() + } + + companion object { + @JvmStatic + fun read(bytes: ByteArray): KotlinCommonMetadata? { + val (proto, _) = ByteArrayInputStream(bytes).readBuiltinsPackageFragment() + if (proto == null) return null + + return KotlinCommonMetadata(proto) + } + } +}