[JS IR BE] Support nested external classes
This commit is contained in:
@@ -57,6 +57,7 @@ class JsIrBackendContext(
|
||||
val phaseConfig = PhaseConfig(jsPhases, configuration)
|
||||
override var inVerbosePhase: Boolean = false
|
||||
|
||||
val externalNestedClasses = mutableListOf<IrClass>()
|
||||
val packageLevelJsModules = mutableListOf<IrFile>()
|
||||
val declarationLevelJsModules = mutableListOf<IrDeclaration>()
|
||||
|
||||
|
||||
+14
@@ -58,8 +58,22 @@ fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, module:
|
||||
}
|
||||
}, FqName.ROOT)
|
||||
|
||||
fun collectExternalClasses(container: IrDeclarationContainer, includeCurrentLevel: Boolean): List<IrClass> {
|
||||
val externalClasses =
|
||||
container.declarations.filterIsInstance<IrClass>().filter { it.isEffectivelyExternal() }
|
||||
|
||||
val nestedExternalClasses =
|
||||
externalClasses.flatMap { collectExternalClasses(it, true) }
|
||||
|
||||
return if (includeCurrentLevel)
|
||||
externalClasses + nestedExternalClasses
|
||||
else
|
||||
nestedExternalClasses
|
||||
}
|
||||
|
||||
fun lowerFile(irFile: IrFile): IrFile? {
|
||||
context.externalNestedClasses += collectExternalClasses(irFile, includeCurrentLevel = false)
|
||||
|
||||
if (irFile.getJsModule() != null || irFile.getJsQualifier() != null) {
|
||||
context.packageLevelJsModules.add(irFile)
|
||||
return null
|
||||
|
||||
+16
-5
@@ -9,14 +9,12 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.ModuleType
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsModule
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithVisibility
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
|
||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
@@ -106,7 +104,7 @@ class IrModuleToJsTransformer(private val backendContext: JsIrBackendContext) :
|
||||
val qualifiedReference: JsNameRef
|
||||
|
||||
if (jsModule != null) {
|
||||
val internalName = rootFunction.scope.declareFreshName("moduleImport")
|
||||
val internalName = rootFunction.scope.declareFreshName(sanitizeName("\$module\$$jsModule"))
|
||||
packageLevelJsModules += JsImportedModule(jsModule, internalName, null)
|
||||
|
||||
qualifiedReference =
|
||||
@@ -131,6 +129,19 @@ class IrModuleToJsTransformer(private val backendContext: JsIrBackendContext) :
|
||||
}
|
||||
}
|
||||
|
||||
for (externalClass in backendContext.externalNestedClasses) {
|
||||
val declName = rootContext.getNameForDeclaration(externalClass)
|
||||
val parentName = rootContext.getNameForDeclaration(externalClass.parentAsClass)
|
||||
importStatements.add(
|
||||
JsExpressionStatement(
|
||||
jsAssignment(
|
||||
declName.makeRef(),
|
||||
JsNameRef(externalClass.name.identifier, parentName.makeRef())
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val importedJsModules = declarationLevelJsModules + packageLevelJsModules
|
||||
rootFunction.parameters += importedJsModules.map { JsParameter(it.internalName) }
|
||||
|
||||
|
||||
+17
-9
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.util.isDynamic
|
||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.ir.util.isInlined
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsName
|
||||
import org.jetbrains.kotlin.js.naming.isES5IdentifierPart
|
||||
import org.jetbrains.kotlin.js.naming.isES5IdentifierStart
|
||||
@@ -107,12 +108,19 @@ class SimpleNameGenerator : NameGenerator {
|
||||
|
||||
if (declaration.isEffectivelyExternal()) {
|
||||
// TODO: descriptors are still used here due to the corresponding declaration doesn't have enough information yet
|
||||
val descriptorForName = when (descriptor) {
|
||||
val descriptorName = when (descriptor) {
|
||||
is ConstructorDescriptor -> descriptor.constructedClass
|
||||
is PropertyAccessorDescriptor -> descriptor.correspondingProperty
|
||||
else -> descriptor
|
||||
}.name
|
||||
|
||||
if (declaration is IrConstructor) return@getOrPut getNameForDeclaration(declaration.parentAsClass, context)
|
||||
|
||||
if (declaration is IrClass && declaration.parent is IrClass) {
|
||||
val parentName = getNameForDeclaration(declaration.parentAsClass, context).ident
|
||||
return@getOrPut context.currentScope.declareFreshName(parentName + "$" + descriptorName.identifier)
|
||||
}
|
||||
return@getOrPut context.staticContext.rootScope.declareName(descriptorForName.name.asString())
|
||||
return@getOrPut context.staticContext.rootScope.declareName(descriptorName.identifier)
|
||||
}
|
||||
|
||||
when (declaration) {
|
||||
@@ -224,11 +232,11 @@ class SimpleNameGenerator : NameGenerator {
|
||||
|
||||
nameDeclarator(sanitizeName(nameBuilder.toString()))
|
||||
}
|
||||
|
||||
private fun sanitizeName(name: String): String {
|
||||
if (name.isEmpty()) return "_"
|
||||
|
||||
val first = name.first().let { if (it.isES5IdentifierStart()) it else '_' }
|
||||
return first.toString() + name.drop(1).map { if (it.isES5IdentifierPart()) it else '_' }.joinToString("")
|
||||
}
|
||||
}
|
||||
|
||||
fun sanitizeName(name: String): String {
|
||||
if (name.isEmpty()) return "_"
|
||||
|
||||
val first = name.first().let { if (it.isES5IdentifierStart()) it else '_' }
|
||||
return first.toString() + name.drop(1).map { if (it.isES5IdentifierPart()) it else '_' }.joinToString("")
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1288
|
||||
// FILE: foo.kt
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1290
|
||||
// FILE: a.kt
|
||||
// MODULE_KIND: AMD
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1289
|
||||
// FILE: a.kt
|
||||
@file:JsModule("lib")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1288
|
||||
// FILE: main.kt
|
||||
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1288
|
||||
// MODULE: module1
|
||||
// FILE: module1.kt
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1282
|
||||
// MODULE: lib
|
||||
// FILE: lib.kt
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1282
|
||||
// FILE: main.kt
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1281
|
||||
package foo
|
||||
|
||||
|
||||
Reference in New Issue
Block a user