[JS IR] Fix creating of classes extended from nested one

[JS IR] Extract getClassRef method

 ^KT-44950 fixed
This commit is contained in:
Ilya Goncharov
2021-03-15 18:00:28 +03:00
committed by TeamCityServer
parent a61312120b
commit 88abb3d6c9
12 changed files with 76 additions and 33 deletions
@@ -19512,6 +19512,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/innerNested/createdNestedInOuterMember.kt");
}
@Test
@TestMetadata("extenderNestedClass.kt")
public void testExtenderNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/extenderNestedClass.kt");
}
@Test
@TestMetadata("extensionFun.kt")
public void testExtensionFun() throws Exception {
@@ -25,10 +25,8 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
private val classNameRef = className.makeRef()
private val baseClass: IrType? = irClass.superTypes.firstOrNull { !it.classifierOrFail.isInterface }
private val baseClassName by lazy { // Lazy in case was not collected by namer during JsClassGenerator construction
baseClass?.let {
context.getNameForClass(baseClass.classifierOrFail.owner as IrClass)
}
private val baseClassRef by lazy { // Lazy in case was not collected by namer during JsClassGenerator construction
baseClass?.getClassRef(context)
}
private val classPrototypeRef = prototypeOf(classNameRef)
private val classBlock = JsGlobalBlock()
@@ -49,7 +47,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
val jsClass = JsClass(name = className)
if (baseClass != null && !baseClass.isAny()) {
jsClass.baseClass = baseClassName?.makeRef()
jsClass.baseClass = baseClassRef
}
if (es6mode) classModel.preDeclarationBlock.statements += jsClass.makeStmt()
@@ -197,7 +195,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
}
val createCall = jsAssignment(
classPrototypeRef, JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototypeOf(baseClassName!!.makeRef()))
classPrototypeRef, JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototypeOf(baseClassRef!!))
).makeStmt()
val ctorAssign = jsAssignment(JsNameRef(Namer.CONSTRUCTOR_NAME, classPrototypeRef), classNameRef).makeStmt()
@@ -8,19 +8,16 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
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.getClassRef
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.getInlineClassBackingField
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.js.backend.ast.*
@@ -92,18 +89,8 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
add(intrinsics.jsClass) { call, context ->
val typeArgument = call.getTypeArgument(0)
val classSymbol = typeArgument?.classOrNull
typeArgument?.getClassRef(context)
?: error("Type argument of jsClass must be statically known class, but " + typeArgument?.render())
val klass = classSymbol.owner
when {
klass.isEffectivelyExternal() ->
context.getRefForExternalClass(klass)
else ->
context.getNameForStaticDeclaration(klass as IrDeclarationWithName).makeRef()
}
}
add(intrinsics.jsNewTarget) { _, _ ->
@@ -124,16 +111,8 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
}
add(intrinsics.es6DefaultType) { call, context ->
val classifier: IrClassifierSymbol = call.getTypeArgument(0)!!.classifierOrFail
val owner = classifier.owner
when {
owner is IrClass && owner.isEffectivelyExternal() ->
context.getRefForExternalClass(owner)
else ->
context.getNameForStaticDeclaration(owner as IrDeclarationWithName).makeRef()
}
val typeArgument = call.getTypeArgument(0)!!
typeArgument.getClassRef(context)
}
addIfNotNull(intrinsics.jsCode) { _, _ -> error("Should not be called") }
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.utils
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
@@ -13,10 +14,12 @@ import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.getInlineClassUnderlyingType
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.js.backend.ast.JsNameRef
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
fun IrType.asString(): String = when(this) {
fun IrType.asString(): String = when (this) {
// TODO: should each IrErrorType have own string representation?
is IrErrorType -> "\$ErrorType\$"
// TODO: should we prohibit user classes called dynamic?
@@ -30,7 +33,7 @@ fun IrType.asString(): String = when(this) {
else -> error("Unexpected kind of IrType: " + javaClass.typeName)
}
private fun IrTypeArgument.asString(): String = when(this) {
private fun IrTypeArgument.asString(): String = when (this) {
is IrStarProjection -> "*"
is IrTypeProjection -> variance.label + (if (variance != Variance.INVARIANT) " " else "") + type.asString()
else -> error("Unexpected kind of IrTypeArgument: " + javaClass.simpleName)
@@ -78,3 +81,14 @@ tailrec fun erase(type: IrType): IrClass? {
else -> error(classifier)
}
}
fun IrType.getClassRef(context: JsGenerationContext): JsNameRef =
when (val klass = classifierOrFail.owner) {
is IrClass ->
if (klass.isEffectivelyExternal())
context.getRefForExternalClass(klass)
else
context.getNameForClass(klass).makeRef()
else -> context.getNameForStaticDeclaration(klass as IrDeclarationWithName).makeRef()
}
@@ -0,0 +1,9 @@
object Foo {
open class Bar(val bar: String)
}
class Baz: Foo.Bar("OK")
fun box(): String {
return Baz().bar
}
@@ -19512,6 +19512,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/innerNested/createdNestedInOuterMember.kt");
}
@Test
@TestMetadata("extenderNestedClass.kt")
public void testExtenderNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/extenderNestedClass.kt");
}
@Test
@TestMetadata("extensionFun.kt")
public void testExtensionFun() throws Exception {
@@ -19512,6 +19512,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/innerNested/createdNestedInOuterMember.kt");
}
@Test
@TestMetadata("extenderNestedClass.kt")
public void testExtenderNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/extenderNestedClass.kt");
}
@Test
@TestMetadata("extensionFun.kt")
public void testExtensionFun() throws Exception {
@@ -16306,6 +16306,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/innerNested/createdNestedInOuterMember.kt");
}
@TestMetadata("extenderNestedClass.kt")
public void testExtenderNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/extenderNestedClass.kt");
}
@TestMetadata("extensionFun.kt")
public void testExtensionFun() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/extensionFun.kt");
@@ -14349,6 +14349,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/innerNested/createdNestedInOuterMember.kt");
}
@TestMetadata("extenderNestedClass.kt")
public void testExtenderNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/extenderNestedClass.kt");
}
@TestMetadata("extensionFun.kt")
public void testExtensionFun() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/extensionFun.kt");
@@ -13806,6 +13806,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/innerNested/createdNestedInOuterMember.kt");
}
@TestMetadata("extenderNestedClass.kt")
public void testExtenderNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/extenderNestedClass.kt");
}
@TestMetadata("extensionFun.kt")
public void testExtensionFun() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/extensionFun.kt");
@@ -13871,6 +13871,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/innerNested/createdNestedInOuterMember.kt");
}
@TestMetadata("extenderNestedClass.kt")
public void testExtenderNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/extenderNestedClass.kt");
}
@TestMetadata("extensionFun.kt")
public void testExtensionFun() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/extensionFun.kt");
@@ -7927,6 +7927,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/innerNested/createdNestedInOuterMember.kt");
}
@TestMetadata("extenderNestedClass.kt")
public void testExtenderNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/extenderNestedClass.kt");
}
@TestMetadata("extensionFun.kt")
public void testExtensionFun() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/extensionFun.kt");