[JS IR BE] Fix codegen for nested external objects
This commit is contained in:
+1
-2
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.isClass
|
|
||||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -68,7 +67,7 @@ fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, module:
|
|||||||
externalClasses.flatMap { collectExternalClasses(it, true) }
|
externalClasses.flatMap { collectExternalClasses(it, true) }
|
||||||
|
|
||||||
return if (includeCurrentLevel)
|
return if (includeCurrentLevel)
|
||||||
externalClasses.filter { it.isClass } + nestedExternalClasses
|
externalClasses + nestedExternalClasses
|
||||||
else
|
else
|
||||||
nestedExternalClasses
|
nestedExternalClasses
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -143,13 +143,18 @@ class IrModuleToJsTransformer(private val backendContext: JsIrBackendContext) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (externalClass in backendContext.externalNestedClasses) {
|
for (externalClass in backendContext.externalNestedClasses) {
|
||||||
|
|
||||||
|
// External companions are not "nested". Instead they use parent class name.
|
||||||
|
if (externalClass.isCompanion)
|
||||||
|
continue
|
||||||
|
|
||||||
val declName = rootContext.getNameForDeclaration(externalClass)
|
val declName = rootContext.getNameForDeclaration(externalClass)
|
||||||
val parentName = rootContext.getNameForDeclaration(externalClass.parentAsClass)
|
val parentName = rootContext.getNameForDeclaration(externalClass.parentAsClass)
|
||||||
importStatements.add(
|
importStatements.add(
|
||||||
JsExpressionStatement(
|
JsExpressionStatement(
|
||||||
jsAssignment(
|
jsAssignment(
|
||||||
declName.makeRef(),
|
declName.makeRef(),
|
||||||
JsNameRef(externalClass.name.identifier, parentName.makeRef())
|
JsNameRef(externalClass.getJsNameOrKotlinName().identifier, parentName.makeRef())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,11 +6,13 @@
|
|||||||
package org.jetbrains.kotlin.ir.backend.js.utils
|
package org.jetbrains.kotlin.ir.backend.js.utils
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
|
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||||
import org.jetbrains.kotlin.ir.util.getAnnotation
|
import org.jetbrains.kotlin.ir.util.getAnnotation
|
||||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
object JsAnnotations {
|
object JsAnnotations {
|
||||||
val jsModuleFqn = FqName("kotlin.js.JsModule")
|
val jsModuleFqn = FqName("kotlin.js.JsModule")
|
||||||
@@ -33,3 +35,10 @@ fun IrAnnotationContainer.getJsQualifier(): String? =
|
|||||||
|
|
||||||
fun IrAnnotationContainer.getJsName(): String? =
|
fun IrAnnotationContainer.getJsName(): String? =
|
||||||
getAnnotation(JsAnnotations.jsNameFqn)?.getSingleConstStringArgument()
|
getAnnotation(JsAnnotations.jsNameFqn)?.getSingleConstStringArgument()
|
||||||
|
|
||||||
|
|
||||||
|
fun IrDeclarationWithName.getJsNameOrKotlinName(): Name =
|
||||||
|
when (val jsName = getJsName()) {
|
||||||
|
null -> name
|
||||||
|
else -> Name.identifier(jsName)
|
||||||
|
}
|
||||||
+22
-28
@@ -32,7 +32,7 @@ class SimpleNameGenerator : NameGenerator {
|
|||||||
private val loopCache = mutableMapOf<IrLoop, JsName>()
|
private val loopCache = mutableMapOf<IrLoop, JsName>()
|
||||||
|
|
||||||
override fun getNameForSymbol(symbol: IrSymbol, context: JsGenerationContext): JsName =
|
override fun getNameForSymbol(symbol: IrSymbol, context: JsGenerationContext): JsName =
|
||||||
if (symbol.isBound) getNameForDeclaration(symbol.owner as IrDeclaration, context) else
|
if (symbol.isBound) getNameForDeclaration(symbol.owner as IrDeclarationWithName, context) else
|
||||||
declareDynamic(symbol.descriptor, context)
|
declareDynamic(symbol.descriptor, context)
|
||||||
|
|
||||||
override fun getNameForLoop(loop: IrLoop, context: JsGenerationContext): JsName? = loop.label?.let {
|
override fun getNameForLoop(loop: IrLoop, context: JsGenerationContext): JsName? = loop.label?.let {
|
||||||
@@ -40,7 +40,7 @@ class SimpleNameGenerator : NameGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getNameForType(type: IrType, context: JsGenerationContext) =
|
override fun getNameForType(type: IrType, context: JsGenerationContext) =
|
||||||
getNameForDeclaration(type.classifierOrFail.owner as IrDeclaration, context)
|
getNameForDeclaration(type.classifierOrFail.owner as IrDeclarationWithName, context)
|
||||||
|
|
||||||
@Deprecated("Descriptors-based code is deprecated")
|
@Deprecated("Descriptors-based code is deprecated")
|
||||||
private fun declareDynamic(descriptor: DeclarationDescriptor, context: JsGenerationContext): JsName {
|
private fun declareDynamic(descriptor: DeclarationDescriptor, context: JsGenerationContext): JsName {
|
||||||
@@ -91,35 +91,24 @@ class SimpleNameGenerator : NameGenerator {
|
|||||||
"Kotlin"
|
"Kotlin"
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun getNameForDeclaration(declaration: IrDeclaration, context: JsGenerationContext): JsName =
|
private fun getNameForDeclaration(declaration: IrDeclarationWithName, context: JsGenerationContext): JsName =
|
||||||
nameCache.getOrPut(declaration) {
|
nameCache.getOrPut(declaration) {
|
||||||
var nameDeclarator: (String) -> JsName = context.currentScope::declareName
|
var nameDeclarator: (String) -> JsName = context.currentScope::declareName
|
||||||
val nameBuilder = StringBuilder()
|
val nameBuilder = StringBuilder()
|
||||||
|
|
||||||
val descriptor = declaration.descriptor
|
|
||||||
|
|
||||||
if (declaration.isDynamic()) {
|
if (declaration.isDynamic()) {
|
||||||
return@getOrPut nameDeclarator(declaration.descriptor.name.asString())
|
return@getOrPut nameDeclarator(declaration.descriptor.name.asString())
|
||||||
}
|
}
|
||||||
|
|
||||||
val jsName = declaration.getJsName()
|
val declarationName = declaration.getJsNameOrKotlinName().asString()
|
||||||
if (jsName != null) {
|
|
||||||
return@getOrPut context.currentScope.declareName(jsName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (declaration is IrSimpleFunction && declaration.origin == JsLoweredDeclarationOrigin.BRIDGE_TO_EXTERNAL_FUNCTION) {
|
if (declaration is IrSimpleFunction && declaration.origin == JsLoweredDeclarationOrigin.BRIDGE_TO_EXTERNAL_FUNCTION) {
|
||||||
return@getOrPut context.staticContext.rootScope.declareName(declaration.name.identifier)
|
return@getOrPut nameDeclarator(declarationName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declaration.isEffectivelyExternal()) {
|
if (declaration.isEffectivelyExternal()) {
|
||||||
// TODO: descriptors are still used here due to the corresponding declaration doesn't have enough information yet
|
if (declaration is IrConstructor)
|
||||||
val descriptorName = when (descriptor) {
|
return@getOrPut getNameForDeclaration(declaration.parentAsClass, context)
|
||||||
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) {
|
if (declaration is IrClass && declaration.parent is IrClass) {
|
||||||
val parentName = getNameForDeclaration(declaration.parentAsClass, context)
|
val parentName = getNameForDeclaration(declaration.parentAsClass, context)
|
||||||
@@ -127,9 +116,14 @@ class SimpleNameGenerator : NameGenerator {
|
|||||||
// External companions are class references
|
// External companions are class references
|
||||||
return@getOrPut parentName
|
return@getOrPut parentName
|
||||||
}
|
}
|
||||||
return@getOrPut context.currentScope.declareFreshName(parentName.ident + "$" + descriptorName.identifier)
|
return@getOrPut context.currentScope.declareFreshName(parentName.ident + "$" + declarationName)
|
||||||
}
|
}
|
||||||
return@getOrPut context.staticContext.rootScope.declareName(descriptorName.identifier)
|
return@getOrPut nameDeclarator(declarationName)
|
||||||
|
}
|
||||||
|
|
||||||
|
val jsName = declaration.getJsName()
|
||||||
|
if (jsName != null) {
|
||||||
|
return@getOrPut context.currentScope.declareName(jsName)
|
||||||
}
|
}
|
||||||
|
|
||||||
when (declaration) {
|
when (declaration) {
|
||||||
@@ -141,7 +135,7 @@ class SimpleNameGenerator : NameGenerator {
|
|||||||
else if (declaration == context.currentFunction?.extensionReceiverParameter) {
|
else if (declaration == context.currentFunction?.extensionReceiverParameter) {
|
||||||
nameBuilder.append(Namer.EXTENSION_RECEIVER_NAME)
|
nameBuilder.append(Namer.EXTENSION_RECEIVER_NAME)
|
||||||
} else {
|
} else {
|
||||||
val declaredName = declaration.name.asString()
|
val declaredName = declarationName
|
||||||
nameBuilder.append(declaredName)
|
nameBuilder.append(declaredName)
|
||||||
if (declaredName.startsWith("\$")) {
|
if (declaredName.startsWith("\$")) {
|
||||||
nameBuilder.append('.')
|
nameBuilder.append('.')
|
||||||
@@ -151,22 +145,22 @@ class SimpleNameGenerator : NameGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is IrField -> {
|
is IrField -> {
|
||||||
nameBuilder.append(declaration.name.asString())
|
nameBuilder.append(declarationName)
|
||||||
if (declaration.isTopLevel) {
|
if (declaration.isTopLevel) {
|
||||||
nameDeclarator = context.staticContext.rootScope::declareFreshName
|
nameDeclarator = context.staticContext.rootScope::declareFreshName
|
||||||
} else {
|
} else {
|
||||||
nameBuilder.append('.')
|
nameBuilder.append('.')
|
||||||
nameBuilder.append(getNameForDeclaration(declaration.parent as IrDeclaration, context))
|
nameBuilder.append(getNameForDeclaration(declaration.parent as IrDeclarationWithName, context))
|
||||||
if (declaration.visibility == Visibilities.PRIVATE) nameDeclarator = context.currentScope::declareFreshName
|
if (declaration.visibility == Visibilities.PRIVATE) nameDeclarator = context.currentScope::declareFreshName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is IrClass -> {
|
is IrClass -> {
|
||||||
if (declaration.isCompanion) {
|
if (declaration.isCompanion) {
|
||||||
nameBuilder.append(getNameForDeclaration(declaration.parent as IrDeclaration, context))
|
nameBuilder.append(getNameForDeclaration(declaration.parent as IrDeclarationWithName, context))
|
||||||
nameBuilder.append('.')
|
nameBuilder.append('.')
|
||||||
}
|
}
|
||||||
|
|
||||||
nameBuilder.append(declaration.name.asString())
|
nameBuilder.append(declarationName)
|
||||||
|
|
||||||
(declaration.parent as? IrClass)?.let {
|
(declaration.parent as? IrClass)?.let {
|
||||||
nameBuilder.append("$")
|
nameBuilder.append("$")
|
||||||
@@ -181,7 +175,7 @@ class SimpleNameGenerator : NameGenerator {
|
|||||||
}
|
}
|
||||||
val parent = declaration.parent
|
val parent = declaration.parent
|
||||||
when (parent) {
|
when (parent) {
|
||||||
is IrDeclaration -> nameBuilder.append(getNameForDeclaration(parent, context))
|
is IrDeclarationWithName -> nameBuilder.append(getNameForDeclaration(parent, context))
|
||||||
is IrPackageFragment -> nameBuilder.append(parent.fqName.asString())
|
is IrPackageFragment -> nameBuilder.append(parent.fqName.asString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,14 +198,14 @@ class SimpleNameGenerator : NameGenerator {
|
|||||||
is IrSimpleFunction -> {
|
is IrSimpleFunction -> {
|
||||||
|
|
||||||
if (declaration.isStaticMethodOfClass) {
|
if (declaration.isStaticMethodOfClass) {
|
||||||
nameBuilder.append(getNameForDeclaration(declaration.parent as IrDeclaration, context))
|
nameBuilder.append(getNameForDeclaration(declaration.parent as IrClass, context))
|
||||||
nameBuilder.append('.')
|
nameBuilder.append('.')
|
||||||
}
|
}
|
||||||
if (declaration.dispatchReceiverParameter == null) {
|
if (declaration.dispatchReceiverParameter == null) {
|
||||||
nameDeclarator = context.staticContext.rootScope::declareFreshName
|
nameDeclarator = context.staticContext.rootScope::declareFreshName
|
||||||
}
|
}
|
||||||
|
|
||||||
nameBuilder.append(declaration.name.asString())
|
nameBuilder.append(declarationName)
|
||||||
// TODO should we skip type parameters and use upper bound of type parameter when print type of value parameters?
|
// TODO should we skip type parameters and use upper bound of type parameter when print type of value parameters?
|
||||||
declaration.typeParameters.ifNotEmpty {
|
declaration.typeParameters.ifNotEmpty {
|
||||||
nameBuilder.append("_\$t")
|
nameBuilder.append("_\$t")
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JS_IR
|
|
||||||
// EXPECTED_REACHABLE_NODES: 1310
|
// EXPECTED_REACHABLE_NODES: 1310
|
||||||
package foo
|
package foo
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user