[JS IR BE] Fix codegen for nested external objects

This commit is contained in:
Svyatoslav Kuzmich
2019-02-21 16:16:20 +03:00
parent 41f3316981
commit d323dce2b6
5 changed files with 38 additions and 32 deletions
@@ -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.impl.IrExternalPackageFragmentImpl
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.transformFlat
import org.jetbrains.kotlin.name.FqName
@@ -68,7 +67,7 @@ fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, module:
externalClasses.flatMap { collectExternalClasses(it, true) }
return if (includeCurrentLevel)
externalClasses.filter { it.isClass } + nestedExternalClasses
externalClasses + nestedExternalClasses
else
nestedExternalClasses
}
@@ -143,13 +143,18 @@ class IrModuleToJsTransformer(private val backendContext: JsIrBackendContext) :
}
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 parentName = rootContext.getNameForDeclaration(externalClass.parentAsClass)
importStatements.add(
JsExpressionStatement(
jsAssignment(
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
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.IrConst
import org.jetbrains.kotlin.ir.util.getAnnotation
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
object JsAnnotations {
val jsModuleFqn = FqName("kotlin.js.JsModule")
@@ -33,3 +35,10 @@ fun IrAnnotationContainer.getJsQualifier(): String? =
fun IrAnnotationContainer.getJsName(): String? =
getAnnotation(JsAnnotations.jsNameFqn)?.getSingleConstStringArgument()
fun IrDeclarationWithName.getJsNameOrKotlinName(): Name =
when (val jsName = getJsName()) {
null -> name
else -> Name.identifier(jsName)
}
@@ -32,7 +32,7 @@ class SimpleNameGenerator : NameGenerator {
private val loopCache = mutableMapOf<IrLoop, 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)
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) =
getNameForDeclaration(type.classifierOrFail.owner as IrDeclaration, context)
getNameForDeclaration(type.classifierOrFail.owner as IrDeclarationWithName, context)
@Deprecated("Descriptors-based code is deprecated")
private fun declareDynamic(descriptor: DeclarationDescriptor, context: JsGenerationContext): JsName {
@@ -91,35 +91,24 @@ class SimpleNameGenerator : NameGenerator {
"Kotlin"
)
private fun getNameForDeclaration(declaration: IrDeclaration, context: JsGenerationContext): JsName =
private fun getNameForDeclaration(declaration: IrDeclarationWithName, context: JsGenerationContext): JsName =
nameCache.getOrPut(declaration) {
var nameDeclarator: (String) -> JsName = context.currentScope::declareName
val nameBuilder = StringBuilder()
val descriptor = declaration.descriptor
if (declaration.isDynamic()) {
return@getOrPut nameDeclarator(declaration.descriptor.name.asString())
}
val jsName = declaration.getJsName()
if (jsName != null) {
return@getOrPut context.currentScope.declareName(jsName)
}
val declarationName = declaration.getJsNameOrKotlinName().asString()
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()) {
// TODO: descriptors are still used here due to the corresponding declaration doesn't have enough information yet
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 IrConstructor)
return@getOrPut getNameForDeclaration(declaration.parentAsClass, context)
if (declaration is IrClass && declaration.parent is IrClass) {
val parentName = getNameForDeclaration(declaration.parentAsClass, context)
@@ -127,9 +116,14 @@ class SimpleNameGenerator : NameGenerator {
// External companions are class references
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) {
@@ -141,7 +135,7 @@ class SimpleNameGenerator : NameGenerator {
else if (declaration == context.currentFunction?.extensionReceiverParameter) {
nameBuilder.append(Namer.EXTENSION_RECEIVER_NAME)
} else {
val declaredName = declaration.name.asString()
val declaredName = declarationName
nameBuilder.append(declaredName)
if (declaredName.startsWith("\$")) {
nameBuilder.append('.')
@@ -151,22 +145,22 @@ class SimpleNameGenerator : NameGenerator {
}
}
is IrField -> {
nameBuilder.append(declaration.name.asString())
nameBuilder.append(declarationName)
if (declaration.isTopLevel) {
nameDeclarator = context.staticContext.rootScope::declareFreshName
} else {
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
}
}
is IrClass -> {
if (declaration.isCompanion) {
nameBuilder.append(getNameForDeclaration(declaration.parent as IrDeclaration, context))
nameBuilder.append(getNameForDeclaration(declaration.parent as IrDeclarationWithName, context))
nameBuilder.append('.')
}
nameBuilder.append(declaration.name.asString())
nameBuilder.append(declarationName)
(declaration.parent as? IrClass)?.let {
nameBuilder.append("$")
@@ -181,7 +175,7 @@ class SimpleNameGenerator : NameGenerator {
}
val parent = declaration.parent
when (parent) {
is IrDeclaration -> nameBuilder.append(getNameForDeclaration(parent, context))
is IrDeclarationWithName -> nameBuilder.append(getNameForDeclaration(parent, context))
is IrPackageFragment -> nameBuilder.append(parent.fqName.asString())
}
}
@@ -204,14 +198,14 @@ class SimpleNameGenerator : NameGenerator {
is IrSimpleFunction -> {
if (declaration.isStaticMethodOfClass) {
nameBuilder.append(getNameForDeclaration(declaration.parent as IrDeclaration, context))
nameBuilder.append(getNameForDeclaration(declaration.parent as IrClass, context))
nameBuilder.append('.')
}
if (declaration.dispatchReceiverParameter == null) {
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?
declaration.typeParameters.ifNotEmpty {
nameBuilder.append("_\$t")
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1310
package foo