Fix translation of labels with non-identifier names in JS BE

See KT-18027
This commit is contained in:
Alexey Andreev
2017-05-25 16:20:32 +03:00
parent 9375a1d984
commit 4bb1130f3f
7 changed files with 37 additions and 22 deletions
@@ -37,8 +37,8 @@ open class JsDeclarationScope(parent: JsScope, description: String, useParentSco
private val topLabelScope
get() = if (labelScopes.isNotEmpty()) labelScopes.peek() else null
open fun enterLabel(label: String): JsName {
val scope = LabelScope(topLabelScope, label)
open fun enterLabel(label: String, outputName: String): JsName {
val scope = LabelScope(topLabelScope, label, outputName)
labelScopes.push(scope)
return scope.labelName
}
@@ -51,18 +51,8 @@ open class JsDeclarationScope(parent: JsScope, description: String, useParentSco
open fun findLabel(label: String): JsName? =
topLabelScope?.findName(label)
private inner class LabelScope(parent: LabelScope?, val ident: String) : JsScope(parent, "Label scope for $ident") {
val labelName: JsName
init {
val freshIdent = when {
ident in RESERVED_WORDS -> getFreshIdent(ident)
parent != null -> parent.getFreshIdent(ident)
else -> ident
}
labelName = JsName(freshIdent, false)
}
private inner class LabelScope(parent: LabelScope?, val ident: String, outputIdent: String) : JsScope(parent, "Label scope for $ident") {
val labelName: JsName = JsName(outputIdent, true)
override fun findOwnName(name: String): JsName? =
if (name == ident) labelName else null
@@ -130,8 +120,8 @@ class DelegatingJsFunctionScopeWithTemporaryParent(
override fun declareFreshName(suggestedName: String): JsName =
delegatingScope.declareFreshName(suggestedName)
override fun enterLabel(label: String): JsName =
delegatingScope.enterLabel(label)
override fun enterLabel(label: String, outputName: String): JsName =
delegatingScope.enterLabel(label, outputName)
override fun exitLabel() =
delegatingScope.exitLabel()
@@ -42,7 +42,7 @@ class LabelNameRefreshingVisitor(val functionScope: JsFunctionScope) : JsVisitor
override fun visit(x: JsLabel, ctx: JsContext<JsNode>): Boolean {
val labelName = x.name
val freshName = functionScope.enterLabel(labelName.ident)
val freshName = functionScope.enterLabel(labelName.ident, labelName.ident)
substitutions.getOrPut(labelName) { ArrayDeque() }.push(freshName)
return super.visit(x, ctx)
@@ -57,5 +57,5 @@ class LabelNameRefreshingVisitor(val functionScope: JsFunctionScope) : JsVisitor
super.endVisit(x, ctx)
}
private fun getSubstitution(name: JsName) = substitutions[name]?.let { it.peek() } ?: name
private fun getSubstitution(name: JsName) = substitutions[name]?.peek() ?: name
}
@@ -665,7 +665,7 @@ public class JsAstMapper {
private JsLabel mapLabel(Node labelNode) throws JsParserException {
String fromName = labelNode.getFirstChild().getString();
JsName toName = scopeContext.enterLabel(fromName);
JsName toName = scopeContext.enterLabel(fromName, fromName);
Node fromStmt = labelNode.getFirstChild().getNext();
JsLabel toLabel = new JsLabel(toName);
@@ -49,8 +49,8 @@ class ScopeContext(scope: JsScope) {
exitScope()
}
fun enterLabel(ident: String): JsName =
(currentScope as JsDeclarationScope).enterLabel(ident)
fun enterLabel(ident: String, outputName: String): JsName =
(currentScope as JsDeclarationScope).enterLabel(ident, outputName)
fun exitLabel() =
(currentScope as JsDeclarationScope).exitLabel()
@@ -5450,6 +5450,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
doTest(fileName);
}
@TestMetadata("peculiarNames.kt")
public void testPeculiarNames() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/labels/peculiarNames.kt");
doTest(fileName);
}
@TestMetadata("siblingLabels.kt")
public void testSiblingLabels() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/labels/siblingLabels.kt");
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention;
import org.jetbrains.kotlin.js.backend.ast.*;
import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties;
import org.jetbrains.kotlin.js.naming.NameSuggestion;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.declaration.ClassTranslator;
import org.jetbrains.kotlin.js.translate.declaration.PropertyTranslatorKt;
@@ -363,7 +364,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
String labelIdent = getReferencedName(expression.getTargetLabel());
JsName labelName = functionScope.enterLabel(labelIdent);
JsName labelName = functionScope.enterLabel(labelIdent, NameSuggestion.sanitizeName(labelIdent));
JsStatement baseStatement = Translation.translateAsStatement(baseExpression, context);
functionScope.exitLabel();
+18
View File
@@ -0,0 +1,18 @@
// EXPECTED_REACHABLE_NODES: 487
fun box(): String {
var log = ""
var i = 0
`!`@while (true) {
log += "i=$i;"
for (j in 1..3) {
log += "j=$j;"
if (i++ + j > 5) break@`!`
log += "!"
}
}
if (log != "i=0;j=1;!j=2;!j=3;!i=3;j=1;!j=2;") return "fail: $log"
return "OK"
}