JS: move label renaming to new fragment post-processing
Also remove metadata renaming from the global passes
This commit is contained in:
@@ -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.backend.ast.metadata.staticRef
|
||||||
import org.jetbrains.kotlin.js.inline.clean.removeUnusedFunctionDefinitions
|
import org.jetbrains.kotlin.js.inline.clean.removeUnusedFunctionDefinitions
|
||||||
import org.jetbrains.kotlin.js.inline.clean.removeUnusedImports
|
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.clean.simplifyWrappedFunctions
|
||||||
import org.jetbrains.kotlin.js.inline.util.*
|
import org.jetbrains.kotlin.js.inline.util.*
|
||||||
import org.jetbrains.kotlin.js.translate.declaration.transformSpecialFunctionsToCoroutineMetadata
|
import org.jetbrains.kotlin.js.translate.declaration.transformSpecialFunctionsToCoroutineMetadata
|
||||||
@@ -162,6 +163,7 @@ class ProgramFragmentInliningScope(
|
|||||||
simplifyWrappedFunctions(allCode)
|
simplifyWrappedFunctions(allCode)
|
||||||
removeUnusedFunctionDefinitions(allCode, collectNamedFunctions(allCode))
|
removeUnusedFunctionDefinitions(allCode, collectNamedFunctions(allCode))
|
||||||
removeUnusedImports(fragment, allCode)
|
removeUnusedImports(fragment, allCode)
|
||||||
|
renameLabels(allCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hasImport(name: JsName, tag: String): JsName? {
|
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)
|
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
|
return replacements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.google.gwt.dev.js.rhino.CodePosition
|
|||||||
import com.google.gwt.dev.js.rhino.ErrorReporter
|
import com.google.gwt.dev.js.rhino.ErrorReporter
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
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.inline.clean.resolveTemporaryNames
|
||||||
import org.jetbrains.kotlin.js.parser.parse
|
import org.jetbrains.kotlin.js.parser.parse
|
||||||
import org.jetbrains.kotlin.js.test.BasicBoxTest
|
import org.jetbrains.kotlin.js.test.BasicBoxTest
|
||||||
@@ -69,21 +70,21 @@ class NameResolutionTest {
|
|||||||
node.name = node.name?.let { name ->
|
node.name = node.name?.let { name ->
|
||||||
if (name.ident.startsWith("$")) {
|
if (name.ident.startsWith("$")) {
|
||||||
cache.getOrPut(name) { JsScope.declareTemporaryName("x") }
|
cache.getOrPut(name) { JsScope.declareTemporaryName("x") }
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
renameLabels(originalAst)
|
||||||
originalAst.resolveTemporaryNames()
|
originalAst.resolveTemporaryNames()
|
||||||
|
|
||||||
assertEquals(expectedAst.toString(), originalAst.toString())
|
assertEquals(expectedAst.toString(), originalAst.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
private val errorReporter = object : ErrorReporter {
|
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) {
|
override fun error(message: String, startPosition: CodePosition, endPosition: CodePosition) {
|
||||||
fail("Error parsing JS file: $message at $startPosition")
|
fail("Error parsing JS file: $message at $startPosition")
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ class Merger(
|
|||||||
|
|
||||||
// TODO better placing?
|
// TODO better placing?
|
||||||
val additionalFakeOverrides = mutableListOf<JsStatement>()
|
val additionalFakeOverrides = mutableListOf<JsStatement>()
|
||||||
importedFunctionWrappers.values.forEach {block ->
|
importedFunctionWrappers.values.forEach { block ->
|
||||||
block.statements.forEach { s ->
|
block.statements.forEach { s ->
|
||||||
if (s.isFakeOverrideAssignment()) {
|
if (s.isFakeOverrideAssignment()) {
|
||||||
additionalFakeOverrides += s
|
additionalFakeOverrides += s
|
||||||
|
|||||||
Reference in New Issue
Block a user