diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ForeachTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ForeachTest.java index 61f95541962..fb11f9e2d9a 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ForeachTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ForeachTest.java @@ -29,4 +29,8 @@ public final class ForeachTest extends AbstractExpressionTest { public void testForOnEmptyArray() throws Exception { fooBoxTest(); } + + public void testLabeledFor() throws Exception { + fooBoxTest(); + } } \ No newline at end of file diff --git a/js/js.translator/lib/dart-ast.jar b/js/js.translator/lib/dart-ast.jar index de3a20e193f..b070d459c80 100644 Binary files a/js/js.translator/lib/dart-ast.jar and b/js/js.translator/lib/dart-ast.jar differ diff --git a/js/js.translator/lib/src/dart-ast-src.jar b/js/js.translator/lib/src/dart-ast-src.jar index 7830e0022c6..1cc9832315e 100644 Binary files a/js/js.translator/lib/src/dart-ast-src.jar and b/js/js.translator/lib/src/dart-ast-src.jar differ diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index 021a1f384df..05a1fa11065 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -17,6 +17,7 @@ package org.jetbrains.k2js.translate.expression; import com.google.dart.compiler.backend.js.ast.*; +import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; @@ -291,9 +292,21 @@ public final class ExpressionVisitor extends TranslatorVisitor { @Override @NotNull - public JsNode visitPrefixExpression(@NotNull JetPrefixExpression expression, - @NotNull TranslationContext context) { - return UnaryOperationTranslator.translate(expression, context); + public JsNode visitPrefixExpression( + @NotNull JetPrefixExpression expression, + @NotNull TranslationContext context + ) { + JetSimpleNameExpression operationReference = expression.getOperationReference(); + IElementType operationToken = operationReference.getReferencedNameElementType(); + if (JetTokens.LABELS.contains(operationToken)) { + JetExpression baseExpression = expression.getBaseExpression(); + assert baseExpression != null; + return source(new JsLabel(context.scope().declareName(getReferencedName(operationReference)), + convertToStatement(baseExpression.accept(this, context))), expression); + } + else { + return UnaryOperationTranslator.translate(expression, context); + } } @Override @@ -343,18 +356,35 @@ public final class ExpressionVisitor extends TranslatorVisitor { return TranslationUtils.sure(jsExpression, context); } + private static String getReferencedName(JetSimpleNameExpression expression) { + String name = expression.getReferencedName(); + return name.charAt(0) == '@' ? name.substring(1) + '$' : name; + } + + private static String getTargetLabel(JetLabelQualifiedExpression expression, TranslationContext context) { + JetSimpleNameExpression labelElement = expression.getTargetLabel(); + if (labelElement == null) { + return null; + } + else { + JsName name = context.scope().findName(getReferencedName(labelElement)); + assert name != null; + return name.getIdent(); + } + } + @Override @NotNull public JsNode visitBreakExpression(@NotNull JetBreakExpression expression, @NotNull TranslationContext context) { - return new JsBreak(); + return new JsBreak(getTargetLabel(expression, context)); } @Override @NotNull public JsNode visitContinueExpression(@NotNull JetContinueExpression expression, @NotNull TranslationContext context) { - return new JsContinue(); + return new JsContinue(getTargetLabel(expression, context)); } @Override diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java b/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java index f91b894306d..d32e2c90c21 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java @@ -46,7 +46,6 @@ import org.jetbrains.k2js.translate.utils.dangerous.DangerousData; import org.jetbrains.k2js.translate.utils.dangerous.DangerousTranslator; import java.util.Collection; -import java.util.Collections; import java.util.List; import static org.jetbrains.jet.plugin.JetMainDetector.getMainFunction; @@ -175,23 +174,10 @@ public final class Translation { if (mainFunction == null) { return null; } - JsInvocation translatedCall = generateInvocation(context, mainFunction); - setArguments(context, arguments, translatedCall); - return translatedCall.makeStmt(); - } - - - @NotNull - private static JsInvocation generateInvocation(@NotNull TranslationContext context, @NotNull JetNamedFunction mainFunction) { FunctionDescriptor functionDescriptor = getFunctionDescriptor(context.bindingContext(), mainFunction); - JsExpression translatedCall = CallBuilder.build(context).descriptor(functionDescriptor).translate(); - assert translatedCall instanceof JsInvocation; - return (JsInvocation) translatedCall; - } - - private static void setArguments(@NotNull TranslationContext context, @NotNull List arguments, - @NotNull JsInvocation translatedCall) { - JsArrayLiteral arrayLiteral = new JsArrayLiteral(toStringLiteralList(arguments, context.program())); - JsAstUtils.setArguments(translatedCall, Collections.singletonList(arrayLiteral)); + return CallBuilder.build(context) + .args(new JsArrayLiteral(toStringLiteralList(arguments, context.program()))) + .descriptor(functionDescriptor) + .translate().makeStmt(); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/operation/IncrementTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/operation/IncrementTranslator.java index 40acca0f0d7..68dd07727b0 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/operation/IncrementTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/operation/IncrementTranslator.java @@ -21,6 +21,7 @@ import com.google.dart.compiler.backend.js.ast.JsBinaryOperation; import com.google.dart.compiler.backend.js.ast.JsBinaryOperator; import com.google.dart.compiler.backend.js.ast.JsExpression; import com.google.dart.compiler.util.AstUtil; +import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetUnaryExpression; @@ -41,8 +42,9 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.hasCorrespondi // TODO: provide better increment translator logic public abstract class IncrementTranslator extends AbstractTranslator { - public static boolean isIncrement(@NotNull JetUnaryExpression expression) { - return OperatorConventions.INCREMENT_OPERATIONS.contains(getOperationToken(expression)); + public static boolean isIncrement(IElementType operationToken) { + //noinspection SuspiciousMethodCalls + return OperatorConventions.INCREMENT_OPERATIONS.contains(operationToken); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java index e4e2f86ac3f..31351538da0 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java @@ -18,16 +18,14 @@ package org.jetbrains.k2js.translate.operation; import com.google.dart.compiler.backend.js.ast.JsBinaryOperation; import com.google.dart.compiler.backend.js.ast.JsExpression; +import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetUnaryExpression; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.reference.CallBuilder; -import org.jetbrains.k2js.translate.reference.CallType; import org.jetbrains.k2js.translate.utils.TranslationUtils; -import java.util.Collections; - import static org.jetbrains.k2js.translate.general.Translation.translateAsExpression; import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall; import static org.jetbrains.k2js.translate.utils.PsiUtils.getBaseExpression; @@ -41,12 +39,15 @@ public final class UnaryOperationTranslator { } @NotNull - public static JsExpression translate(@NotNull JetUnaryExpression expression, - @NotNull TranslationContext context) { - if (isExclExcl(expression)) { - return translateExclExclOperator(expression, context); + public static JsExpression translate( + @NotNull JetUnaryExpression expression, + @NotNull TranslationContext context + ) { + IElementType operationToken = expression.getOperationReference().getReferencedNameElementType(); + if (operationToken == JetTokens.EXCLEXCL) { + return sure(translateAsExpression(getBaseExpression(expression), context), context); } - if (IncrementTranslator.isIncrement(expression)) { + if (IncrementTranslator.isIncrement(operationToken)) { return IncrementTranslator.translate(expression, context); } @@ -54,16 +55,11 @@ public final class UnaryOperationTranslator { if (isExclForBinaryEqualLikeExpr(expression, baseExpression)) { return translateExclForBinaryEqualLikeExpr((JsBinaryOperation) baseExpression); } - return translateAsCall(expression, context, baseExpression); - } - private static boolean isExclExcl(@NotNull JetUnaryExpression expression) { - return getOperationToken(expression).equals(JetTokens.EXCLEXCL); - } - - @NotNull - private static JsExpression translateExclExclOperator(@NotNull JetUnaryExpression expression, @NotNull TranslationContext context) { - return sure(translateAsExpression(getBaseExpression(expression), context), context); + return CallBuilder.build(context) + .receiver(TranslationUtils.translateBaseExpression(context, expression)) + .resolvedCall(getResolvedCall(context.bindingContext(), expression.getOperationReference())) + .translate(); } private static boolean isExclForBinaryEqualLikeExpr(@NotNull JetUnaryExpression expression, @NotNull JsExpression baseExpression) { @@ -74,15 +70,4 @@ public final class UnaryOperationTranslator { } return false; } - - @NotNull - private static JsExpression translateAsCall(@NotNull JetUnaryExpression expression, - @NotNull TranslationContext context, - @NotNull JsExpression baseExpression) { - return CallBuilder.build(context) - .receiver(baseExpression) - .args(Collections.emptyList()) - .resolvedCall(getResolvedCall(context.bindingContext(), expression.getOperationReference())) - .type(CallType.NORMAL).translate(); - } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java index b4637fd3f40..2a4e3cabbab 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java @@ -16,7 +16,6 @@ package org.jetbrains.k2js.translate.reference; -import com.google.common.collect.Lists; import com.google.dart.compiler.backend.js.ast.JsExpression; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,6 +33,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.k2js.translate.context.TranslationContext; import java.util.Arrays; +import java.util.Collections; import java.util.List; public final class CallBuilder { @@ -47,7 +47,7 @@ public final class CallBuilder { @Nullable private /*var*/ JsExpression receiver = null; @NotNull - private final List args = Lists.newArrayList(); + private List args = Collections.emptyList(); @NotNull private /*var*/ CallType callType = CallType.NORMAL; @Nullable @@ -70,8 +70,8 @@ public final class CallBuilder { @NotNull public CallBuilder args(@NotNull List args) { - assert this.args.isEmpty(); - this.args.addAll(args); + assert this.args == Collections.EMPTY_LIST; + this.args = args; return this; } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java index 61e24c1032b..45a9d25419c 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java @@ -165,12 +165,6 @@ public final class JsAstUtils { return new JsVars(new JsVars.JsVar(name, expr)); } - public static void setArguments(@NotNull JsInvocation invocation, @NotNull List newArgs) { - List arguments = invocation.getArguments(); - assert arguments.isEmpty() : "Arguments already set."; - arguments.addAll(newArgs); - } - public static void setArguments(@NotNull HasArguments invocation, @NotNull List newArgs) { List arguments = invocation.getArguments(); assert arguments.isEmpty() : "Arguments already set."; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/PsiUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/PsiUtils.java index dbd0f441ee9..9346339e2fb 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/PsiUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/PsiUtils.java @@ -16,7 +16,6 @@ package org.jetbrains.k2js.translate.utils; -import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -121,14 +120,6 @@ public final class PsiUtils { return Collections.emptyList(); } - @NotNull - public static JetObjectDeclaration getObjectDeclarationForName(@NotNull JetObjectDeclarationName name) { - PsiElement parent = name.getParent(); - assert parent instanceof JetObjectDeclaration : - "ObjectDeclarationName should have a parent of type ObjectDeclaration."; - return (JetObjectDeclaration) parent; - } - @NotNull public static JetObjectDeclarationName getObjectDeclarationName(@NotNull JetObjectDeclaration objectDeclaration) { //TODO: util diff --git a/js/js.translator/testFiles/expression/for/cases/labeledFor.kt b/js/js.translator/testFiles/expression/for/cases/labeledFor.kt new file mode 100644 index 00000000000..1d08104a680 --- /dev/null +++ b/js/js.translator/testFiles/expression/for/cases/labeledFor.kt @@ -0,0 +1,14 @@ +package foo + +val a1 = arrayOfNulls(0) + +fun box(): Boolean { + var bar = 33 + @outer for (a in array(1, 2)) { + for (b in array(1, 4)) { + break @outer + } + bar = 42 + } + return bar == 33; +} \ No newline at end of file