[JS IR] fix name clashes for imported external declarations

This commit is contained in:
Anton Bannykh
2020-09-29 14:00:38 +03:00
committed by TeamCityServer
parent 6e40c814c8
commit 0182c09318
6 changed files with 130 additions and 3 deletions
@@ -9,6 +9,10 @@ import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.backend.common.ir.isTopLevel
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrLoop
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.js.backend.ast.JsName
class IrNamerImpl(
@@ -28,4 +32,52 @@ class IrNamerImpl(
require(!field.isStatic)
return newNameTables.getNameForMemberField(field).toJsName()
}
override fun getNameForField(field: IrField): JsName {
return if (field.isStatic || field.parent is IrScript) {
getNameForStaticDeclaration(field)
} else {
getNameForMemberField(field)
}
}
override fun getNameForValueDeclaration(declaration: IrValueDeclaration): JsName =
getNameForStaticDeclaration(declaration)
override fun getNameForClass(klass: IrClass): JsName =
getNameForStaticDeclaration(klass)
override fun getNameForStaticFunction(function: IrSimpleFunction): JsName =
getNameForStaticDeclaration(function)
override fun getNameForProperty(property: IrProperty): JsName =
if (property.isTopLevel) getNameForStaticDeclaration(property) else property.getJsNameOrKotlinName().asString().toJsName()
override fun getRefForExternalClass(klass: IrClass): JsNameRef {
val parent = klass.parent
if (klass.isCompanion)
return getRefForExternalClass(parent as IrClass)
val currentClassName = if (klass.isTopLevel) getNameForStaticDeclaration(klass).ident else klass.getJsNameOrKotlinName().identifier
return when (parent) {
is IrClass ->
JsNameRef(currentClassName, getRefForExternalClass(parent))
is IrPackageFragment ->
JsNameRef(currentClassName)
else ->
error("Unsupported external class parent $parent")
}
}
private val associatedObjectKeyMap = mutableMapOf<IrClass, Int>()
override fun getAssociatedObjectKey(irClass: IrClass): Int? {
if (irClass.isAssociatedObjectAnnotatedAnnotation) {
return associatedObjectKeyMap.getOrPut(irClass) { associatedObjectKeyMap.size }
}
return null
}
}
@@ -286,7 +286,7 @@ class NameTables(
return
// TODO: Handle JsQualifier
declaration.isEffectivelyExternal() && (declaration.getJsModule() == null || declaration.isJsNonModule()) -> {
declaration.isEffectivelyExternal() && !declaration.isImportedFromModuleOnly() -> {
if (declaration.file.getJsModule() != null) {
globalNames.declareFreshName(declaration, declaration.name.asString())
} else {
@@ -73,8 +73,7 @@ class StableNamesCollector : IrElementVisitorVoid {
return null
}
val importedFromModuleOnly =
declaration.getJsModule() != null && !declaration.isJsNonModule()
val importedFromModuleOnly = declaration.isImportedFromModuleOnly()
val jsName = declaration.getJsName()
val jsQualifier = declaration.getJsQualifier()
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.utils
import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
import org.jetbrains.kotlin.backend.common.ir.isTopLevel
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
@@ -18,6 +19,8 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isNullableAny
import org.jetbrains.kotlin.ir.types.isUnit
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.ir.util.isTopLevelDeclaration
import org.jetbrains.kotlin.name.Name
@@ -111,4 +114,8 @@ fun IrBody.prependFunctionCall(
)
}
}
}
fun IrDeclaration.isImportedFromModuleOnly(): Boolean {
return isTopLevel && isEffectivelyExternal() && (getJsModule() != null && !isJsNonModule() || (parent as? IrAnnotationContainer)?.getJsModule() != null)
}
@@ -0,0 +1,29 @@
define("a", [], function() {
function A() {}
A.prototype.foo = function () {
return "O";
};
return {
A: A,
bar: function() { return 1; },
prop: 10
};
});
define("b", [], function() {
function A() {}
A.prototype.foo = function () {
return "K";
};
return {
A: A,
bar: function() { return 2; },
prop: 20
};
});
@@ -0,0 +1,40 @@
// EXPECTED_REACHABLE_NODES: 1284
// FILE: a.kt
// MODULE_KIND: AMD
@file:JsModule("a")
package a
external class A {
fun foo(): String
}
external fun bar(): Int
external val prop: Int
// FILE: b.kt
// MODULE_KIND: AMD
@file:JsModule("b")
package b
external class A {
fun foo(): String
}
external fun bar(): Int
external var prop: Int
// FILE: main.kt
import a.A as O
import b.A as K
fun box(): String {
if (a.bar() != 1) return "fail 1"
if (a.prop != 10) return "fail 2"
if (b.bar() != 2) return "fail 3"
if (b.prop != 20) return "fail 4"
return O().foo() + K().foo()
}