All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.library.impl.KotlinLibraryImpl.kt Maven / Gradle / Ivy

/*
 * Copyright 2010-2018 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.library.impl

import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.konan.properties.Properties
import org.jetbrains.kotlin.konan.properties.loadProperties

open class BaseKotlinLibraryImpl(
    val access: BaseLibraryAccess,
    override val isDefault: Boolean
) : BaseKotlinLibrary {
    override val libraryFile get() = access.klib
    override val libraryName: String by lazy { access.inPlace { it.libraryName } }

    override fun toString() = "$libraryName[default=$isDefault]"

    override val manifestProperties: Properties by lazy {
        access.inPlace { it.manifestFile.loadProperties() }
    }

    override val versions: KonanLibraryVersioning by lazy {
        manifestProperties.readKonanLibraryVersioning()
    }
}

open class MetadataLibraryImpl(
    val access: MetadataLibraryAccess
) : MetadataLibrary {

    override val moduleHeaderData: ByteArray by lazy {
        access.inPlace {
            it.moduleHeaderFile.readBytes()
        }
    }

    override fun packageMetadata(fqName: String, partName: String): ByteArray =
        access.inPlace {
            it.packageFragmentFile(fqName, partName).readBytes()
        }

    override fun packageMetadataParts(fqName: String): Set =
        access.inPlace { inPlaceaccess ->
            val fileList =
                inPlaceaccess.packageFragmentsDir(fqName)
                    .listFiles
                    .mapNotNull {
                        it.name
                            .substringBeforeLast(KLIB_METADATA_FILE_EXTENSION_WITH_DOT, missingDelimiterValue = "")
                            .takeIf { it.isNotEmpty() }
                    }

            fileList.toSortedSet().also {
                require(it.size == fileList.size) { "Duplicated names: ${fileList.groupingBy { it }.eachCount().filter { (_, count) -> count > 1 }}" }
            }
        }
}

abstract class IrLibraryImpl(
    val access: IrLibraryAccess
) : IrLibrary {
    override val dataFlowGraph by lazy {
        access.inPlace { it: IrKotlinLibraryLayout ->
            it.dataFlowGraphFile.let { if (it.exists) it.readBytes() else null }
        }
    }
}

class IrMonoliticLibraryImpl(_access: IrLibraryAccess) : IrLibraryImpl(_access) {
    override fun fileCount(): Int = files.entryCount()

    override fun irDeclaration(index: Long, isLocal: Boolean, fileIndex: Int) = loadIrDeclaration(index, isLocal, fileIndex)

    override fun symbol(index: Int, fileIndex: Int) = symbols.tableItemBytes(fileIndex, index)

    override fun type(index: Int, fileIndex: Int) = types.tableItemBytes(fileIndex, index)

    override fun string(index: Int, fileIndex: Int) = strings.tableItemBytes(fileIndex, index)

    override fun body(index: Int, fileIndex: Int) = bodies.tableItemBytes(fileIndex, index)

    override fun file(index: Int) = files.tableItemBytes(index)

    private fun loadIrDeclaration(index: Long, isLocal: Boolean, fileIndex: Int) =
        combinedDeclarations.tableItemBytes(fileIndex, DeclarationId(index, isLocal))

    private val combinedDeclarations: DeclarationIrMultiTableReader by lazy {
        DeclarationIrMultiTableReader(access.realFiles {
            it.irDeclarations
        })
    }

    private val symbols: IrMultiArrayReader by lazy {
        IrMultiArrayReader(access.realFiles {
            it.irSymbols
        })
    }

    private val types: IrMultiArrayReader by lazy {
        IrMultiArrayReader(access.realFiles {
            it.irTypes
        })
    }

    private val strings: IrMultiArrayReader by lazy {
        IrMultiArrayReader(access.realFiles {
            it.irStrings
        })
    }

    private val bodies: IrMultiArrayReader by lazy {
        IrMultiArrayReader(access.realFiles {
            it.irBodies
        })
    }

    private val files: IrArrayReader by lazy {
        IrArrayReader(access.realFiles {
            it.irFiles
        })
    }
}

class IrPerFileLibraryImpl(_access: IrLibraryAccess) : IrLibraryImpl(_access) {

    private val directories by lazy {
        access.realFiles {
            it.irDir.listFiles.filter { f -> f.isDirectory && f.name.endsWith(".file") }
        }
    }

    private val fileToDeclarationMap = mutableMapOf()
    override fun irDeclaration(index: Long, isLocal: Boolean, fileIndex: Int): ByteArray {
        val dataReader = fileToDeclarationMap.getOrPut(fileIndex) {
            val fileDirectory = directories[fileIndex]
            DeclarationIrTableReader(access.realFiles {
                it.irDeclarations(fileDirectory)
            })
        }
        return dataReader.tableItemBytes(DeclarationId(index, isLocal))
    }

    private val fileToSymbolMap = mutableMapOf()
    override fun symbol(index: Int, fileIndex: Int): ByteArray {
        val dataReader = fileToSymbolMap.getOrPut(fileIndex) {
            val fileDirectory = directories[fileIndex]
            IrArrayReader(access.realFiles {
                it.irSymbols(fileDirectory)
            })
        }
        return dataReader.tableItemBytes(index)
    }

    private val fileToTypeMap = mutableMapOf()
    override fun type(index: Int, fileIndex: Int): ByteArray {
        val dataReader = fileToTypeMap.getOrPut(fileIndex) {
            val fileDirectory = directories[fileIndex]
            IrArrayReader(access.realFiles {
                it.irTypes(fileDirectory)
            })
        }
        return dataReader.tableItemBytes(index)
    }

    private val fileToStringMap = mutableMapOf()
    override fun string(index: Int, fileIndex: Int): ByteArray {
        val dataReader = fileToStringMap.getOrPut(fileIndex) {
            val fileDirectory = directories[fileIndex]
            IrArrayReader(access.realFiles {
                it.irStrings(fileDirectory)
            })
        }
        return dataReader.tableItemBytes(index)
    }

    private val fileToBodyMap = mutableMapOf()
    override fun body(index: Int, fileIndex: Int): ByteArray {
        val dataReader = fileToBodyMap.getOrPut(fileIndex) {
            val fileDirectory = directories[fileIndex]
            IrArrayReader(access.realFiles {
                it.irBodies(fileDirectory)
            })
        }
        return dataReader.tableItemBytes(index)
    }

    override fun file(index: Int): ByteArray {
        return access.realFiles {
            it.irFile(directories[index]).readBytes()
        }
    }

    override fun fileCount(): Int {
        return directories.size
    }
}

open class KotlinLibraryImpl(
    val base: BaseKotlinLibraryImpl,
    val metadata: MetadataLibraryImpl,
    val ir: IrLibraryImpl
) : KotlinLibrary,
    BaseKotlinLibrary by base,
    MetadataLibrary by metadata,
    IrLibrary by ir

fun createKotlinLibrary(
    libraryFile: File,
    isDefault: Boolean = false
): KotlinLibrary {
    val baseAccess = BaseLibraryAccess(libraryFile)
    val metadataAccess = MetadataLibraryAccess(libraryFile)
    val irAccess = IrLibraryAccess(libraryFile)

    val base = BaseKotlinLibraryImpl(baseAccess, isDefault)
    val metadata = MetadataLibraryImpl(metadataAccess)
    val ir = IrMonoliticLibraryImpl(irAccess)
//    val ir = IrPerFileLibraryImpl(irAccess)

    return KotlinLibraryImpl(base, metadata, ir)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy