JS: move label renaming to new fragment post-processing

Also remove metadata renaming from the global passes
This commit is contained in:
Anton Bannykh
2018-12-24 16:13:29 +03:00
parent 6921d4d128
commit 36fd4d24fb
5 changed files with 59 additions and 34 deletions
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.js.backend.ast.metadata.localAlias
import org.jetbrains.kotlin.js.backend.ast.metadata.staticRef
import org.jetbrains.kotlin.js.inline.clean.removeUnusedFunctionDefinitions
import org.jetbrains.kotlin.js.inline.clean.removeUnusedImports
import org.jetbrains.kotlin.js.inline.clean.renameLabels
import org.jetbrains.kotlin.js.inline.clean.simplifyWrappedFunctions
import org.jetbrains.kotlin.js.inline.util.*
import org.jetbrains.kotlin.js.translate.declaration.transformSpecialFunctionsToCoroutineMetadata
@@ -162,6 +163,7 @@ class ProgramFragmentInliningScope(
simplifyWrappedFunctions(allCode)
removeUnusedFunctionDefinitions(allCode, collectNamedFunctions(allCode))
removeUnusedImports(fragment, allCode)
renameLabels(allCode)
}
override fun hasImport(name: JsName, tag: String): JsName? {
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.js.inline.clean
import org.jetbrains.kotlin.js.backend.ast.*
fun renameLabels(root: JsNode) {
// Labels in JS are in separate scope from local variables. It's only important that nested labels don't clash.
// Adjacent labels in one function is OK
root.accept(object : RecursiveJsVisitor() {
val replacements = mutableMapOf<JsName, JsName>()
var labels = mutableSetOf<String>()
override fun visitElement(node: JsNode) {
super.visitElement(node)
if (node is HasName) {
val name = node.name
if (name != null) {
replacements[name]?.let { node.name = it }
}
}
}
override fun visitLabel(x: JsLabel) {
var addedName: String? = null
if (x.name.isTemporary) {
var resolvedName = x.name.ident
var suffix = 0
while (!labels.add(resolvedName)) {
resolvedName = "${x.name.ident}_${suffix++}"
}
replacements[x.name] = JsDynamicScope.declareName(resolvedName)
addedName = resolvedName
}
super.visitLabel(x)
addedName?.let {
labels.remove(it)
}
}
override fun visitFunction(x: JsFunction) {
val oldLabels = labels
labels = mutableSetOf()
super.visitFunction(x)
labels = oldLabels
}
})
}
@@ -62,36 +62,6 @@ private fun JsNode.resolveNames(): Map<JsName, JsName> {
traverse(rootScope)
// Labels in JS are in separate scope from local variables. It's only important that nested labels don't clash.
// Adjacent labels in one function is OK
accept(object : RecursiveJsVisitor() {
var labels = mutableSetOf<String>()
override fun visitLabel(x: JsLabel) {
var addedName: String? = null
if (x.name.isTemporary) {
var resolvedName = x.name.ident
var suffix = 0
while (!labels.add(resolvedName)) {
resolvedName = "${x.name.ident}_${suffix++}"
}
replacements[x.name] = JsDynamicScope.declareName(resolvedName)
addedName = resolvedName
}
super.visitLabel(x)
addedName?.let {
labels.remove(it)
}
}
override fun visitFunction(x: JsFunction) {
val oldLabels = labels
labels = mutableSetOf()
super.visitFunction(x)
labels = oldLabels
}
})
return replacements
}
@@ -20,6 +20,7 @@ import com.google.gwt.dev.js.rhino.CodePosition
import com.google.gwt.dev.js.rhino.ErrorReporter
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.inline.clean.renameLabels
import org.jetbrains.kotlin.js.inline.clean.resolveTemporaryNames
import org.jetbrains.kotlin.js.parser.parse
import org.jetbrains.kotlin.js.test.BasicBoxTest
@@ -69,21 +70,21 @@ class NameResolutionTest {
node.name = node.name?.let { name ->
if (name.ident.startsWith("$")) {
cache.getOrPut(name) { JsScope.declareTemporaryName("x") }
}
else {
} else {
name
}
}
}
}
})
renameLabels(originalAst)
originalAst.resolveTemporaryNames()
assertEquals(expectedAst.toString(), originalAst.toString())
}
private val errorReporter = object : ErrorReporter {
override fun warning(message: String, startPosition: CodePosition, endPosition: CodePosition) { }
override fun warning(message: String, startPosition: CodePosition, endPosition: CodePosition) {}
override fun error(message: String, startPosition: CodePosition, endPosition: CodePosition) {
fail("Error parsing JS file: $message at $startPosition")
@@ -241,7 +241,7 @@ class Merger(
// TODO better placing?
val additionalFakeOverrides = mutableListOf<JsStatement>()
importedFunctionWrappers.values.forEach {block ->
importedFunctionWrappers.values.forEach { block ->
block.statements.forEach { s ->
if (s.isFakeOverrideAssignment()) {
additionalFakeOverrides += s