[JS IR] Generate context dependent names for anonymous objects and classes.
This commit is contained in:
committed by
Space
parent
b1643075f2
commit
a34c97ebd5
@@ -67,6 +67,7 @@ class JsIrBackendContext(
|
|||||||
val fileToInitializerPureness: MutableMap<IrFile, Boolean> = mutableMapOf()
|
val fileToInitializerPureness: MutableMap<IrFile, Boolean> = mutableMapOf()
|
||||||
val fieldToInitializer: MutableMap<IrField, IrExpression> = mutableMapOf()
|
val fieldToInitializer: MutableMap<IrField, IrExpression> = mutableMapOf()
|
||||||
|
|
||||||
|
val localClassNames: MutableMap<IrClass, String> = mutableMapOf()
|
||||||
val extractedLocalClasses: MutableSet<IrClass> = hashSetOf()
|
val extractedLocalClasses: MutableSet<IrClass> = hashSetOf()
|
||||||
|
|
||||||
override val builtIns = module.builtIns
|
override val builtIns = module.builtIns
|
||||||
|
|||||||
@@ -149,6 +149,12 @@ val createScriptFunctionsPhase = makeJsModulePhase(
|
|||||||
description = "Create functions for initialize and evaluate script"
|
description = "Create functions for initialize and evaluate script"
|
||||||
).toModuleLowering()
|
).toModuleLowering()
|
||||||
|
|
||||||
|
private val inventNamesForLocalClassesPhase = makeJsModulePhase(
|
||||||
|
::JsInventNamesForLocalClasses,
|
||||||
|
name = "InventNamesForLocalClasses",
|
||||||
|
description = "Invent names for local classes and anonymous objects",
|
||||||
|
).toModuleLowering()
|
||||||
|
|
||||||
private val annotationInstantiationLowering = makeDeclarationTransformerPhase(
|
private val annotationInstantiationLowering = makeDeclarationTransformerPhase(
|
||||||
::JsAnnotationImplementationTransformer,
|
::JsAnnotationImplementationTransformer,
|
||||||
name = "AnnotationImplementation",
|
name = "AnnotationImplementation",
|
||||||
@@ -220,13 +226,15 @@ private val sharedVariablesLoweringPhase = makeBodyLoweringPhase(
|
|||||||
private val localClassesInInlineLambdasPhase = makeBodyLoweringPhase(
|
private val localClassesInInlineLambdasPhase = makeBodyLoweringPhase(
|
||||||
::LocalClassesInInlineLambdasLowering,
|
::LocalClassesInInlineLambdasLowering,
|
||||||
name = "LocalClassesInInlineLambdasPhase",
|
name = "LocalClassesInInlineLambdasPhase",
|
||||||
description = "Extract local classes from inline lambdas"
|
description = "Extract local classes from inline lambdas",
|
||||||
|
prerequisite = setOf(inventNamesForLocalClassesPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val localClassesInInlineFunctionsPhase = makeBodyLoweringPhase(
|
private val localClassesInInlineFunctionsPhase = makeBodyLoweringPhase(
|
||||||
::LocalClassesInInlineFunctionsLowering,
|
::LocalClassesInInlineFunctionsLowering,
|
||||||
name = "LocalClassesInInlineFunctionsPhase",
|
name = "LocalClassesInInlineFunctionsPhase",
|
||||||
description = "Extract local classes from inline functions"
|
description = "Extract local classes from inline functions",
|
||||||
|
prerequisite = setOf(inventNamesForLocalClassesPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val localClassesExtractionFromInlineFunctionsPhase = makeBodyLoweringPhase(
|
private val localClassesExtractionFromInlineFunctionsPhase = makeBodyLoweringPhase(
|
||||||
@@ -807,6 +815,7 @@ private val jsSuspendArityStorePhase = makeDeclarationTransformerPhase(
|
|||||||
val loweringList = listOf<Lowering>(
|
val loweringList = listOf<Lowering>(
|
||||||
scriptRemoveReceiverLowering,
|
scriptRemoveReceiverLowering,
|
||||||
validateIrBeforeLowering,
|
validateIrBeforeLowering,
|
||||||
|
inventNamesForLocalClassesPhase,
|
||||||
annotationInstantiationLowering,
|
annotationInstantiationLowering,
|
||||||
expectDeclarationsRemovingPhase,
|
expectDeclarationsRemovingPhase,
|
||||||
stripTypeAliasDeclarationsPhase,
|
stripTypeAliasDeclarationsPhase,
|
||||||
|
|||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.InventNamesForLocalClasses
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
|
||||||
|
class JsInventNamesForLocalClasses(private val context: JsIrBackendContext) : InventNamesForLocalClasses(allowTopLevelCallables = true) {
|
||||||
|
override fun computeTopLevelClassName(clazz: IrClass): String = clazz.name.toString()
|
||||||
|
|
||||||
|
override fun sanitizeNameIfNeeded(name: String): String = sanitizeName(name, withHash = false)
|
||||||
|
|
||||||
|
override fun putLocalClassName(declaration: IrAttributeContainer, localClassName: String) {
|
||||||
|
if (declaration is IrClass) {
|
||||||
|
context.localClassNames[declaration] = localClassName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-1
@@ -21,7 +21,10 @@ class JsNameLinkingNamer(private val context: JsIrBackendContext) : IrNamerBase(
|
|||||||
val nameMap = mutableMapOf<IrDeclaration, JsName>()
|
val nameMap = mutableMapOf<IrDeclaration, JsName>()
|
||||||
|
|
||||||
private fun IrDeclarationWithName.getName(prefix: String = ""): JsName {
|
private fun IrDeclarationWithName.getName(prefix: String = ""): JsName {
|
||||||
return nameMap.getOrPut(this) { JsName(sanitizeName(prefix + getJsNameOrKotlinName().asString()), true) }
|
return nameMap.getOrPut(this) {
|
||||||
|
val name = (this as? IrClass)?.let { context.localClassNames[this] } ?: getJsNameOrKotlinName().asString()
|
||||||
|
JsName(sanitizeName(prefix + name), true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val importedModules = mutableListOf<JsImportedModule>()
|
val importedModules = mutableListOf<JsImportedModule>()
|
||||||
|
|||||||
@@ -280,6 +280,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/classObject"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/classObject"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("contextDependentClassObjectName.kt")
|
||||||
|
public void testContextDependentClassObjectName() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/classObject/contextDependentClassObjectName.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("defaultObjectSameNamesAsInOuter.kt")
|
@TestMetadata("defaultObjectSameNamesAsInOuter.kt")
|
||||||
public void testDefaultObjectSameNamesAsInOuter() throws Exception {
|
public void testDefaultObjectSameNamesAsInOuter() throws Exception {
|
||||||
@@ -524,6 +530,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/closure/closureVarToScopeWithSameNameDeclaration.kt");
|
runTest("js/js.translator/testData/box/closure/closureVarToScopeWithSameNameDeclaration.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("contextDependentClosureName.kt")
|
||||||
|
public void testContextDependentClosureName() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/closure/contextDependentClosureName.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("deepInnerClassInLocalClass.kt")
|
@TestMetadata("deepInnerClassInLocalClass.kt")
|
||||||
public void testDeepInnerClassInLocalClass() throws Exception {
|
public void testDeepInnerClassInLocalClass() throws Exception {
|
||||||
@@ -6691,6 +6703,22 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("js/js.translator/testData/box/local")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class Local {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInLocal() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/local"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("contextDependentLocalClassName.kt")
|
||||||
|
public void testContextDependentLocalClassName() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/local/contextDependentLocalClassName.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("js/js.translator/testData/box/main")
|
@TestMetadata("js/js.translator/testData/box/main")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@@ -7788,6 +7816,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/objectDeclaration"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/objectDeclaration"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("contextDependentObjectName.kt")
|
||||||
|
public void testContextDependentObjectName() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/objectDeclaration/contextDependentObjectName.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("dontPolluteObject.kt")
|
@TestMetadata("dontPolluteObject.kt")
|
||||||
public void testDontPolluteObject() throws Exception {
|
public void testDontPolluteObject() throws Exception {
|
||||||
|
|||||||
+34
@@ -280,6 +280,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/classObject"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/classObject"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("contextDependentClassObjectName.kt")
|
||||||
|
public void testContextDependentClassObjectName() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/classObject/contextDependentClassObjectName.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("defaultObjectSameNamesAsInOuter.kt")
|
@TestMetadata("defaultObjectSameNamesAsInOuter.kt")
|
||||||
public void testDefaultObjectSameNamesAsInOuter() throws Exception {
|
public void testDefaultObjectSameNamesAsInOuter() throws Exception {
|
||||||
@@ -524,6 +530,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/closure/closureVarToScopeWithSameNameDeclaration.kt");
|
runTest("js/js.translator/testData/box/closure/closureVarToScopeWithSameNameDeclaration.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("contextDependentClosureName.kt")
|
||||||
|
public void testContextDependentClosureName() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/closure/contextDependentClosureName.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("deepInnerClassInLocalClass.kt")
|
@TestMetadata("deepInnerClassInLocalClass.kt")
|
||||||
public void testDeepInnerClassInLocalClass() throws Exception {
|
public void testDeepInnerClassInLocalClass() throws Exception {
|
||||||
@@ -7075,6 +7087,22 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("js/js.translator/testData/box/local")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class Local {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInLocal() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/local"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("contextDependentLocalClassName.kt")
|
||||||
|
public void testContextDependentLocalClassName() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/local/contextDependentLocalClassName.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("js/js.translator/testData/box/main")
|
@TestMetadata("js/js.translator/testData/box/main")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@@ -8172,6 +8200,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/objectDeclaration"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/objectDeclaration"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("contextDependentObjectName.kt")
|
||||||
|
public void testContextDependentObjectName() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/objectDeclaration/contextDependentObjectName.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("dontPolluteObject.kt")
|
@TestMetadata("dontPolluteObject.kt")
|
||||||
public void testDontPolluteObject() throws Exception {
|
public void testDontPolluteObject() throws Exception {
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
class MyClass {
|
||||||
|
companion object {
|
||||||
|
fun ok(): String {
|
||||||
|
val okMaker = object {
|
||||||
|
fun getOk(): String = "OK"
|
||||||
|
}
|
||||||
|
return okMaker.getOk()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK_FUNCTION_EXISTS: MyClass$Companion$ok$okMaker$1 TARGET_BACKENDS=JS_IR
|
||||||
|
fun box(): String {
|
||||||
|
return MyClass.ok()
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fun foo(a: () -> Unit) = a()
|
||||||
|
|
||||||
|
// CHECK_CALLED_IN_SCOPE: scope=box function=box$lambda
|
||||||
|
fun box(): String {
|
||||||
|
var result = "FAILURE"
|
||||||
|
foo { result = "OK" }
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// CHECK_FUNCTION_EXISTS: box$MyClass TARGET_BACKENDS=JS_IR
|
||||||
|
// CHECK_FUNCTION_EXISTS: box$MyClass$ok$InternalClass TARGET_BACKENDS=JS_IR
|
||||||
|
fun box(): String {
|
||||||
|
class MyClass {
|
||||||
|
fun ok(): String {
|
||||||
|
class InternalClass {
|
||||||
|
fun getOk(): String = "OK"
|
||||||
|
}
|
||||||
|
return InternalClass().getOk()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MyClass().ok()
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
interface A {
|
||||||
|
fun run()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK_FUNCTION_EXISTS: box$a$1 TARGET_BACKENDS=JS_IR
|
||||||
|
// CHECK_FUNCTION_EXISTS: box$a$1$run$b$1 TARGET_BACKENDS=JS_IR
|
||||||
|
fun box(): String {
|
||||||
|
var result = "FAILURE"
|
||||||
|
|
||||||
|
val a: A = object : A {
|
||||||
|
override fun run() {
|
||||||
|
val b = object {
|
||||||
|
fun foo() {
|
||||||
|
result = "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.foo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.run()
|
||||||
|
return result
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user