[K/JS] Import @JsModule declarations without asterisk
This commit is contained in:
+3
-3
@@ -223,7 +223,7 @@ class IrModuleToJsTransformer(
|
||||
private val optimizeGeneratedJs = backendContext.configuration.get(JSConfigurationKeys.OPTIMIZE_GENERATED_JS, true)
|
||||
|
||||
private fun generateProgramFragment(fileExports: IrFileExports, minimizedMemberNames: Boolean): JsIrProgramFragment {
|
||||
val nameGenerator = JsNameLinkingNamer(backendContext, minimizedMemberNames)
|
||||
val nameGenerator = JsNameLinkingNamer(backendContext, minimizedMemberNames, isEsModules)
|
||||
|
||||
val globalNameScope = NameTable<IrDeclaration>()
|
||||
|
||||
@@ -329,9 +329,9 @@ class IrModuleToJsTransformer(
|
||||
}
|
||||
}
|
||||
|
||||
nameGenerator.imports.entries.forEach { (declaration, importExpression) ->
|
||||
nameGenerator.imports.entries.forEach { (declaration, importStatement) ->
|
||||
val tag = computeTag(declaration) ?: error("No tag for imported declaration ${declaration.render()}")
|
||||
result.imports[tag] = importExpression
|
||||
result.imports[tag] = importStatement
|
||||
result.optionalCrossModuleImports += tag
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ class JsIrProgramFragment(val packageFqn: String) {
|
||||
val declarations = JsCompositeBlock()
|
||||
val exports = JsCompositeBlock()
|
||||
val importedModules = mutableListOf<JsImportedModule>()
|
||||
val imports = mutableMapOf<String, JsExpression>()
|
||||
val imports = mutableMapOf<String, JsStatement>()
|
||||
var dts: TypeScriptFragment? = null
|
||||
val classes = mutableMapOf<JsName, JsIrIcClassModel>()
|
||||
val initializers = JsCompositeBlock()
|
||||
|
||||
+74
-37
@@ -19,7 +19,11 @@ import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class JsNameLinkingNamer(private val context: JsIrBackendContext, private val minimizedMemberNames: Boolean) : IrNamerBase() {
|
||||
class JsNameLinkingNamer(
|
||||
private val context: JsIrBackendContext,
|
||||
private val minimizedMemberNames: Boolean,
|
||||
private val isEsModules: Boolean
|
||||
) : IrNamerBase() {
|
||||
|
||||
val nameMap = mutableMapOf<IrDeclaration, JsName>()
|
||||
|
||||
@@ -33,50 +37,19 @@ class JsNameLinkingNamer(private val context: JsIrBackendContext, private val mi
|
||||
}
|
||||
|
||||
val importedModules = mutableListOf<JsImportedModule>()
|
||||
val imports = mutableMapOf<IrDeclaration, JsExpression>()
|
||||
val imports = mutableMapOf<IrDeclaration, JsStatement>()
|
||||
|
||||
override fun getNameForStaticDeclaration(declaration: IrDeclarationWithName): JsName {
|
||||
|
||||
if (declaration.isEffectivelyExternal()) {
|
||||
val jsModule: String? = declaration.getJsModule()
|
||||
val maybeParentFile: IrFile? = declaration.parent as? IrFile
|
||||
val fileJsModule: String? = maybeParentFile?.getJsModule()
|
||||
val jsQualifier: List<JsName>? = maybeParentFile?.getJsQualifier()?.split('.')?.map { JsName(it, false) }
|
||||
|
||||
when {
|
||||
jsModule != null -> {
|
||||
val nameString = if (declaration.isJsNonModule()) {
|
||||
declaration.getJsNameOrKotlinName().asString()
|
||||
} else {
|
||||
val parent = declaration.fqNameWhenAvailable!!.parent()
|
||||
parent.child(declaration.getJsNameOrKotlinName()).asString()
|
||||
}
|
||||
val name = JsName(sanitizeName(nameString), false)
|
||||
importedModules += JsImportedModule(jsModule, name, name.makeRef())
|
||||
return name
|
||||
}
|
||||
|
||||
fileJsModule != null -> {
|
||||
if (declaration !in nameMap) {
|
||||
val moduleName = JsName(sanitizeName("\$module\$$fileJsModule"), true)
|
||||
importedModules += JsImportedModule(fileJsModule, moduleName, null)
|
||||
val qualifiedReference =
|
||||
if (jsQualifier == null) moduleName.makeRef() else (listOf(moduleName) + jsQualifier).makeRef()
|
||||
imports[declaration] = jsElementAccess(declaration.getJsNameOrKotlinName().identifier, qualifiedReference)
|
||||
return declaration.getName()
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
val name = declaration.getJsNameOrKotlinName().identifier
|
||||
|
||||
if (jsQualifier != null) {
|
||||
imports[declaration] = jsElementAccess(name, jsQualifier.makeRef())
|
||||
return declaration.getName()
|
||||
}
|
||||
|
||||
return name.toJsName(temporary = false)
|
||||
}
|
||||
return when {
|
||||
jsModule != null -> declaration.generateImportForDeclarationWithJsModule(jsModule)
|
||||
fileJsModule != null -> declaration.generateImportForDeclarationInFileWithJsModule(fileJsModule, jsQualifier)
|
||||
else -> declaration.generateRegularQualifiedImport(jsQualifier)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +77,70 @@ class JsNameLinkingNamer(private val context: JsIrBackendContext, private val mi
|
||||
return JsName(field.parentAsClass.fieldData()[field]!!, false)
|
||||
}
|
||||
|
||||
private fun IrDeclarationWithName.generateImportForDeclarationWithJsModule(jsModule: String): JsName {
|
||||
val nameString = if (isJsNonModule()) {
|
||||
getJsNameOrKotlinName().asString()
|
||||
} else {
|
||||
val parent = fqNameWhenAvailable!!.parent()
|
||||
parent.child(getJsNameOrKotlinName()).asString()
|
||||
}
|
||||
val name = JsName(sanitizeName(nameString), true)
|
||||
|
||||
if (isEsModules) {
|
||||
imports[this] = JsImport(jsModule, JsImport.Target.Default(name.makeRef()))
|
||||
} else {
|
||||
importedModules += JsImportedModule(jsModule, name, name.makeRef())
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
private fun IrDeclarationWithName.generateImportForDeclarationInFileWithJsModule(
|
||||
fileJsModule: String,
|
||||
jsQualifier: List<JsName>?
|
||||
): JsName {
|
||||
if (this in nameMap) return getName()
|
||||
|
||||
val declarationStableName = getJsNameOrKotlinName().identifier
|
||||
|
||||
if (isEsModules) {
|
||||
val importedName = jsQualifier?.firstOrNull() ?: declarationStableName.toJsName(temporary = false)
|
||||
val importStatement = JsImport(fileJsModule, JsImport.Element(importedName))
|
||||
imports[this] = when (val qualifiedReference = jsQualifier?.makeRef()) {
|
||||
null -> importStatement
|
||||
else -> JsCompositeBlock(
|
||||
listOf(
|
||||
importStatement,
|
||||
jsElementAccess(declarationStableName, qualifiedReference).putIntoVariableWitName(
|
||||
declarationStableName.toJsName()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
} else {
|
||||
val moduleName = JsName(sanitizeName("\$module\$$fileJsModule"), true)
|
||||
importedModules += JsImportedModule(fileJsModule, moduleName, null)
|
||||
val qualifiedReference =
|
||||
if (jsQualifier == null) moduleName.makeRef() else (listOf(moduleName) + jsQualifier).makeRef()
|
||||
imports[this] =
|
||||
jsElementAccess(declarationStableName, qualifiedReference).putIntoVariableWitName(declarationStableName.toJsName())
|
||||
}
|
||||
|
||||
return getName()
|
||||
}
|
||||
|
||||
private fun IrDeclarationWithName.generateRegularQualifiedImport(jsQualifier: List<JsName>?): JsName {
|
||||
val name = getJsNameOrKotlinName().identifier
|
||||
|
||||
if (jsQualifier != null) {
|
||||
imports[this] = jsElementAccess(name, jsQualifier.makeRef()).putIntoVariableWitName(name.toJsName())
|
||||
return getName()
|
||||
}
|
||||
|
||||
return name.toJsName(temporary = false)
|
||||
}
|
||||
|
||||
|
||||
private fun IrClass.fieldData(): Map<IrField, String> {
|
||||
return context.fieldDataCache.getOrPut(this) {
|
||||
val nameCnt = hashMapOf<String, Int>()
|
||||
|
||||
+33
-4
@@ -34,9 +34,14 @@ class Merger(
|
||||
rename(f.declarations)
|
||||
rename(f.exports)
|
||||
|
||||
f.imports.entries.forEach { (declaration, importExpression) ->
|
||||
val importName = nameMap[declaration] ?: error("Missing name for declaration '${declaration}'")
|
||||
importStatements.putIfAbsent(declaration, JsVars(JsVars.JsVar(importName, rename(importExpression))))
|
||||
f.imports.entries.forEach { (declaration, importStatement) ->
|
||||
val importName = nameMap[declaration]
|
||||
|
||||
if (importName == null && !isEsModules) {
|
||||
error("Missing name for declaration '${declaration}'")
|
||||
}
|
||||
|
||||
importStatements.putIfAbsent(declaration, rename(importStatement).importStatementWithName(importName))
|
||||
}
|
||||
|
||||
val classModels = (mutableMapOf<JsName, JsIrIcClassModel>() + f.classes)
|
||||
@@ -60,7 +65,6 @@ class Merger(
|
||||
|
||||
for ((tag, crossModuleJsImport) in crossModuleReferences.jsImports) {
|
||||
val importName = nameMap[tag] ?: error("Missing name for declaration '$tag'")
|
||||
|
||||
importStatements.putIfAbsent(tag, crossModuleJsImport.renameImportedSymbolInternalName(importName))
|
||||
}
|
||||
|
||||
@@ -330,4 +334,29 @@ class Merger(
|
||||
this += statements
|
||||
endRegion()
|
||||
}
|
||||
|
||||
private fun JsStatement.importStatementWithName(name: JsName?): JsStatement {
|
||||
if (name == null) return this
|
||||
|
||||
return when (this) {
|
||||
is JsVars -> JsVars(JsVars.JsVar(name, vars.single().initExpression))
|
||||
is JsImport -> JsImport(
|
||||
module,
|
||||
when (target) {
|
||||
is JsImport.Target.All -> JsImport.Target.All(alias = name.makeRef())
|
||||
is JsImport.Target.Default -> JsImport.Target.Default(name = name.makeRef())
|
||||
is JsImport.Target.Elements -> JsImport.Target.Elements(
|
||||
mutableListOf(
|
||||
JsImport.Element(
|
||||
elements.single().name,
|
||||
name.makeRef()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
is JsCompositeBlock -> JsCompositeBlock(statements.dropLast(1) + statements.last().importStatementWithName(name))
|
||||
else -> error("Unexpected import statement ${this::class.qualifiedName}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-17
@@ -53,7 +53,7 @@ object ModuleWrapperTranslation {
|
||||
ModuleKind.COMMON_JS -> wrapCommonJs(function, importedModules, program)
|
||||
ModuleKind.UMD -> wrapUmd(moduleId, function, importedModules, program)
|
||||
ModuleKind.PLAIN -> wrapPlain(moduleId, function, importedModules, program)
|
||||
ModuleKind.ES -> wrapEsModule(function, importedModules)
|
||||
ModuleKind.ES -> wrapEsModule(function)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,27 +128,19 @@ object ModuleWrapperTranslation {
|
||||
return listOf(invocation.makeStmt())
|
||||
}
|
||||
|
||||
private fun wrapEsModule(function: JsFunction, importedModules: List<JsImportedModule>): List<JsStatement> {
|
||||
val (alreadyPresentedImportStatements, restStatements) = function.body.statements.partitionIsInstance<JsStatement, JsImport>()
|
||||
private fun wrapEsModule(function: JsFunction): List<JsStatement> {
|
||||
val (alreadyPresentedImportStatements, restStatements) = function.body.statements
|
||||
.flatMap { if (it is JsCompositeBlock) it.statements else listOf(it) }
|
||||
.partitionIsInstance<JsStatement, JsImport>()
|
||||
val (multipleElementsImport, defaultImports) = alreadyPresentedImportStatements.partition { it.target is JsImport.Target.Elements }
|
||||
|
||||
val importStatements = importedModules.zip(function.parameters.drop(1)).map {
|
||||
JsImport(
|
||||
it.first.getRequireName(true),
|
||||
if (it.first.plainReference == null) {
|
||||
JsImport.Target.All(alias = it.second.name.makeRef())
|
||||
} else {
|
||||
JsImport.Target.Default(name = it.second.name.makeRef())
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
val alreadyPresentedImportStatementsWithoutDuplicates = alreadyPresentedImportStatements
|
||||
val mergedImports = multipleElementsImport
|
||||
.groupBy { it.module }
|
||||
.map { (module, import) ->
|
||||
JsImport(module, *import.flatMap { it.elements }.toTypedArray())
|
||||
JsImport(module, *import.flatMap { it.elements }.distinctBy { it.name.ident }.toTypedArray())
|
||||
}
|
||||
|
||||
return importStatements + alreadyPresentedImportStatementsWithoutDuplicates + restStatements.dropLast(1)
|
||||
return mergedImports + defaultImports + restStatements.dropLast(1)
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
@@ -63,6 +63,10 @@ fun <T : JsNode> IrWhen.toJsNode(
|
||||
fun jsElementAccess(name: String, receiver: JsExpression?): JsExpression =
|
||||
jsElementAccess(JsName(name, false), receiver)
|
||||
|
||||
fun JsExpression.putIntoVariableWitName(name: JsName): JsVars {
|
||||
return JsVars(JsVars.JsVar(name, this))
|
||||
}
|
||||
|
||||
fun jsElementAccess(name: JsName, receiver: JsExpression?): JsExpression =
|
||||
if (receiver == null || name.ident.isValidES5Identifier()) {
|
||||
JsNameRef(name, receiver)
|
||||
|
||||
+2
-6
@@ -120,12 +120,8 @@ private fun JsNode.computeScopes(): Scope {
|
||||
when (val target = import.target) {
|
||||
is JsImport.Target.All -> target.alias.name?.let { currentScope.declaredNames += it }
|
||||
is JsImport.Target.Default -> target.name.name?.let { currentScope.declaredNames += it }
|
||||
is JsImport.Target.Elements -> target.elements.forEach { element ->
|
||||
if (element.alias != null) {
|
||||
element.alias?.name?.let { currentScope.declaredNames += it }
|
||||
} else {
|
||||
currentScope.declaredNames += element.name
|
||||
}
|
||||
is JsImport.Target.Elements -> target.elements.forEach {
|
||||
currentScope.declaredNames += it.alias?.name ?: it.name
|
||||
}
|
||||
}
|
||||
super.visitImport(import)
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ private class JsIrAstDeserializer(private val source: ByteArray) {
|
||||
)
|
||||
}
|
||||
|
||||
readRepeated { imports[stringTable[readInt()]] = readExpression() }
|
||||
readRepeated { imports[stringTable[readInt()]] = readStatement() }
|
||||
|
||||
readRepeated { declarations.statements += readStatement() }
|
||||
readRepeated { initializers.statements += readStatement() }
|
||||
|
||||
+2
-2
@@ -118,9 +118,9 @@ private class JsIrAstSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
writeCollection(fragment.imports.entries) { (signatureId, expression) ->
|
||||
writeCollection(fragment.imports.entries) { (signatureId, statement) ->
|
||||
writeInt(internalizeString(signatureId))
|
||||
writeExpression(expression)
|
||||
writeStatement(statement)
|
||||
}
|
||||
|
||||
writeCompositeBlock(fragment.declarations)
|
||||
|
||||
@@ -27,7 +27,7 @@ class JsImport(
|
||||
|
||||
class Element(
|
||||
val name: JsName,
|
||||
val alias: JsNameRef?
|
||||
val alias: JsNameRef? = null
|
||||
)
|
||||
|
||||
override fun accept(visitor: JsVisitor) {
|
||||
|
||||
Reference in New Issue
Block a user