From a23c64012b39316cea28af90d1acc51d7be47f08 Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Thu, 8 Jun 2017 13:25:43 +0300 Subject: [PATCH] A bit of infrastructure for the klib pretty printer. --- LIBRARIES.md | 8 ++-- .../backend/konan/library/KonanLibrary.kt | 6 +-- .../konan/library/KtBcMetadataGenerator.kt | 4 +- .../serialization/KonanSerializationUtil.kt | 19 +++++---- .../kotlin/cli/klib/PrettyPrinter.kt | 41 +++++++++++++++++++ .../org/jetbrains/kotlin/cli/klib/main.kt | 29 +++++++------ 6 files changed, 77 insertions(+), 30 deletions(-) create mode 100644 klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/PrettyPrinter.kt diff --git a/LIBRARIES.md b/LIBRARIES.md index 4d5ee5b3b42..4ad4d3d29d4 100644 --- a/LIBRARIES.md +++ b/LIBRARIES.md @@ -47,13 +47,13 @@ The **klib** library management utility allows one to inspect and install the li The following commands are available. -To ask the details of the library +To list library contents: - $ klib info foo + $ klib contents foo -To list library contents: +To ask the details of the library - $ klib list foo + $ klib info foo To install the library to the default location use diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibrary.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibrary.kt index 55bc04994e1..0620a06ae6b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibrary.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibrary.kt @@ -50,15 +50,15 @@ abstract open class FileBasedLibraryReader( override val moduleName: String get() = namedModuleData.name - protected val tableOfContentsAsString : String + val tableOfContents : Base64 get() = namedModuleData.base64 - protected fun packageMetadata(fqName: String): Base64 = + fun packageMetadata(fqName: String): Base64 = reader.loadSerializedPackageFragment(fqName) override fun moduleDescriptor(specifics: LanguageVersionSettings) = deserializeModule(specifics, {packageMetadata(it)}, - tableOfContentsAsString, moduleName) + tableOfContents, moduleName) } // This scheme describes the Konan Library (klib) layout. diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KtBcMetadataGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KtBcMetadataGenerator.kt index 15da0486007..4dc7403aea7 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KtBcMetadataGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KtBcMetadataGenerator.kt @@ -45,8 +45,8 @@ override fun loadSerializedModule(currentAbiVersion: Int): NamedModuleData { throw Error("Expected ABI version ${currentAbiVersion}, but the binary is ${abiVersion}") } val moduleName = string(nameNode) - val tableOfContentsAsString = string(dataNode) - return NamedModuleData(moduleName, tableOfContentsAsString) + val tableOfContents = string(dataNode) + return NamedModuleData(moduleName, tableOfContents) } override fun loadSerializedPackageFragment(fqName: String): String { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt index 5ddcf647194..2a0a6b3516d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt @@ -41,6 +41,7 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer import org.jetbrains.kotlin.serialization.KonanLinkData +import org.jetbrains.kotlin.serialization.KonanLinkData.* import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.storage.LockBasedStorageManager @@ -123,11 +124,13 @@ fun createKonanPackageFragmentProvider( return provider } -internal fun deserializePackageFragment(base64: Base64): KonanLinkData.PackageFragment { - return KonanLinkData.PackageFragment - .parseFrom(base64ToStream(base64), - KonanSerializerProtocol.extensionRegistry) -} +public fun parsePackageFragment(base64: Base64): PackageFragment = + PackageFragment.parseFrom(base64ToStream(base64), + KonanSerializerProtocol.extensionRegistry) + +public fun parseModuleHeader(base64: Base64): Library = + Library.parseFrom(base64ToStream(base64), + KonanSerializerProtocol.extensionRegistry) internal fun deserializeModule(languageVersionSettings: LanguageVersionSettings, packageLoader:(String)->Base64, library: Base64, moduleName: String): ModuleDescriptorImpl { @@ -139,13 +142,11 @@ internal fun deserializeModule(languageVersionSettings: LanguageVersionSettings, builtIns.builtInsModule = moduleDescriptor val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings) - val libraryProto = KonanLinkData.Library - .parseFrom(base64ToStream(library), - KonanSerializerProtocol.extensionRegistry) + val libraryProto = parseModuleHeader(library) val provider = createKonanPackageFragmentProvider( libraryProto.packageFragmentNameList, - {it -> deserializePackageFragment(packageLoader(it))}, + {it -> parsePackageFragment(packageLoader(it))}, storageManager, moduleDescriptor, deserializationConfiguration) diff --git a/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/PrettyPrinter.kt b/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/PrettyPrinter.kt new file mode 100644 index 00000000000..eff9ead9023 --- /dev/null +++ b/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/PrettyPrinter.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.cli.klib + +import org.jetbrains.kotlin.serialization.KonanLinkData +import org.jetbrains.kotlin.backend.konan.serialization.Base64 +import org.jetbrains.kotlin.backend.konan.serialization.parseModuleHeader +import org.jetbrains.kotlin.backend.konan.serialization.parsePackageFragment + +class PrettyPrinter(val library: Base64, val packageLoader: (String) -> Base64) { + + private val moduleHeader: KonanLinkData.Library + get() = parseModuleHeader(library) + + fun packageFragment(fqname: String): KonanLinkData.PackageFragment + = parsePackageFragment(packageLoader(fqname)) + + val packageFragmentNameList: List + get() = moduleHeader.packageFragmentNameList + + fun printPackageFragment(fqname: String) { + if (fqname.isNotEmpty()) println("package $fqname" ) + println("\tHere goes the \"$fqname\" package body.\n\tIt is not implemented yet.\n") + // TODO: implement deserialized package protobuf print out. + } +} + diff --git a/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt b/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt index d93b0e1da9b..29003d092fa 100644 --- a/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt +++ b/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt @@ -13,7 +13,7 @@ fun printUsage() { println("where the commands are:") println("\tinfo\tgeneral information about the library") println("\tinstall\tinstall the library to the local repository") - println("\tlist\tcontents of the library") + println("\tcontents\tlist contents of the library") println("\tremove\tremove the library from the local repository") println("and the options are:") println("\t-repository \twork with the specified repository") @@ -66,8 +66,8 @@ class Library(val name: String, val repository: String, val target: String) { // TODO: need to do something here. val currentAbiVersion = 1 - val splitLibrary = SplitLibraryReader(file, currentAbiVersion, target) - val manifestFile = splitLibrary.manifestFile + val library = SplitLibraryReader(file, currentAbiVersion, target) + val manifestFile = library.manifestFile fun info() { val header = Properties() @@ -78,29 +78,34 @@ class Library(val name: String, val repository: String, val target: String) { val moduleName = header.getProperty("module_name")!! println("Module name: $moduleName") println("ABI version: $headerAbiVersion") - val targets = splitLibrary.targetsDir.listFiles.map{it.name}.joinToString(", ") + val targets = library.targetsDir.listFiles.map{it.name}.joinToString(", ") print("Available targets: $targets\n") } fun install() { remove() - val baseName = splitLibrary.klibFile.name + val baseName = library.klibFile.name val newKlibName = File(repositoryFile, baseName) - splitLibrary.klibFile.copyTo(newKlibName) + library.klibFile.copyTo(newKlibName) } fun remove() { repositoryFile.mkdirs() - val baseName = splitLibrary.klibFile.name - val newDirName = File(repositoryFile, splitLibrary.libDir.name) + val baseName = library.klibFile.name + val newDirName = File(repositoryFile, library.libDir.name) val newKlibName = File(repositoryFile, baseName) newKlibName.deleteRecursively() newDirName.deleteRecursively() } - fun list() { - // TODO: implement printing deserialized module protobuf. - println("Module listing not implemented yet.") + fun contents() { + val moduleName = library.moduleName + val printer = PrettyPrinter( + library.tableOfContents, {name -> library.packageMetadata(name)}) + + printer.packageFragmentNameList.forEach{ + printer.printPackageFragment(it) + } } } @@ -122,9 +127,9 @@ fun main(args: Array) { warn("IMPORTANT: the library format is unstable now. It can change with any new git commit without warning!") when (command.verb) { + "contents" -> library.contents() "info" -> library.info() "install" -> library.install() - "list" -> library.list() "remove" -> library.remove() else -> error("Unknown command ${command.verb}.") }