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

org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.MultiModuleSupport.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * 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.ir.backend.js.transformers.irToJs

import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.utils.IrNamer
import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetField
import org.jetbrains.kotlin.ir.expressions.IrSetField
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.util.constructedClass
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.js.backend.ast.JsName
import org.jetbrains.kotlin.name.Name

interface CrossModuleReferenceInfo {
    fun exports(module: IrModuleFragment): List

    fun withReferenceTracking(namer: IrNamer, excludedModules: Iterable): IrNamerWithImports
}

interface IrNamerWithImports : IrNamer {
    fun imports(): List>>
}

object EmptyCrossModuleReferenceInfo : CrossModuleReferenceInfo {
    override fun exports(module: IrModuleFragment): List = emptyList()

    override fun withReferenceTracking(namer: IrNamer, excludedModules: Iterable): IrNamerWithImports =
        object : IrNamerWithImports, IrNamer by namer {
            override fun imports() = emptyList>>()
        }
}

private class CrossModuleReferenceInfoImpl(val topLevelDeclarationToModule: Map) :
    CrossModuleReferenceInfo {

    private val exportedNames: MutableMap> = mutableMapOf()

    override fun exports(module: IrModuleFragment): List {
        return exportedNames[module]?.toList() ?: emptyList()
    }

    override fun withReferenceTracking(namer: IrNamer, excludedModules: Iterable): IrNamerWithImports {
        val excludedModulesSet = excludedModules.toSet()

        return object : IrNamerWithImports, IrNamer by namer {

            override fun imports(): List>> {
                return importedNames.entries.map { (module, names) -> module to names.toList() }
            }

            private val importedNames: MutableMap> = mutableMapOf()

            private fun JsName.track(d: IrDeclaration): JsName {
                topLevelDeclarationToModule[d]?.let { module ->
                    if (module !in excludedModulesSet) {
                        importedNames.getOrPut(module) { mutableSetOf() } += this.ident
                        exportedNames.getOrPut(module) { mutableSetOf() } += this.ident
                    }
                }

                return this
            }

            override fun getNameForConstructor(constructor: IrConstructor): JsName {
                return namer.getNameForConstructor(constructor).track(constructor.constructedClass)
            }

            override fun getNameForField(field: IrField): JsName {
                return namer.getNameForField(field).track(field)
            }

            override fun getNameForClass(klass: IrClass): JsName {
                return namer.getNameForClass(klass).track(klass)
            }

            override fun getNameForStaticFunction(function: IrSimpleFunction): JsName {
                return namer.getNameForStaticFunction(function).track(function)
            }

            override fun getNameForStaticDeclaration(declaration: IrDeclarationWithName): JsName {
                return namer.getNameForStaticDeclaration(declaration).track(declaration)
            }

            override fun getNameForProperty(property: IrProperty): JsName {
                return namer.getNameForProperty(property).track(property)
            }
        }
    }

}

fun buildCrossModuleReferenceInfo(modules: Iterable): CrossModuleReferenceInfo {
    val map = mutableMapOf()

    modules.forEach { module ->
        module.files.forEach { file ->
            file.declarations.forEach { declaration ->
                map[declaration] = module
            }
        }
    }

    return CrossModuleReferenceInfoImpl(map)
}

val IrModuleFragment.safeName: String
    get() = name.asString().safeModuleName

val String.safeModuleName: String
    get() {
        var result = this

        if (result.startsWith('<')) result = result.substring(1)
        if (result.endsWith('>')) result = result.substring(0, result.length - 1)

        return sanitizeName("kotlin_$result", false)
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy