From 87381a06a7998b2c6eefb982dfc99758bd30d4cf Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Wed, 28 Mar 2012 20:51:21 +0400 Subject: [PATCH] Test for inline dangerous expressions. Better FindPreviousVisitor#hasDangerous implementation. --- .../k2js/test/semantics/DangerousTest.java | 4 ++ .../utils/dangerous/DangerousData.java | 4 +- .../utils/dangerous/FindDangerousVisitor.java | 23 +++++-- .../utils/dangerous/FindPreviousVisitor.java | 67 ++++++++++++------- .../dangerous/cases/dangerousInline.kt | 9 +++ 5 files changed, 76 insertions(+), 31 deletions(-) create mode 100644 js/js.translator/testFiles/dangerous/cases/dangerousInline.kt diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/DangerousTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/DangerousTest.java index 19204854554..9867eb335aa 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/DangerousTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/DangerousTest.java @@ -50,4 +50,8 @@ public final class DangerousTest extends SingleFileTranslationTest { public void test2dangerousInExpression() throws Exception { checkFooBoxIsTrue("2dangerousInExpression.kt"); } + + public void testDangerousInline() throws Exception { + checkFooBoxIsTrue("dangerousInline.kt"); + } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/dangerous/DangerousData.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/dangerous/DangerousData.java index 80b21fc9f1e..baa064c14fb 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/dangerous/DangerousData.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/dangerous/DangerousData.java @@ -58,13 +58,13 @@ public class DangerousData { private static DangerousData doCollectData(@NotNull JetExpression expression, @NotNull TranslationContext context) { DangerousData data = new DangerousData(); - FindDangerousVisitor visitor = new FindDangerousVisitor(context.bindingContext()); + FindDangerousVisitor visitor = new FindDangerousVisitor(context); expression.accept(visitor, data); if (!data.exists()) { return emptyData(); } data.setRootNode(expression); - FindPreviousVisitor findPreviousVisitor = new FindPreviousVisitor(); + FindPreviousVisitor findPreviousVisitor = new FindPreviousVisitor(data); expression.accept(findPreviousVisitor, data); return data; } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/dangerous/FindDangerousVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/dangerous/FindDangerousVisitor.java index bf033c552f2..c3726840942 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/dangerous/FindDangerousVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/dangerous/FindDangerousVisitor.java @@ -18,7 +18,8 @@ package org.jetbrains.k2js.translate.utils.dangerous; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.k2js.translate.context.TranslationContext; +import org.jetbrains.k2js.translate.reference.InlinedCallExpressionTranslator; import static org.jetbrains.k2js.translate.utils.BindingUtils.isStatement; @@ -28,10 +29,10 @@ import static org.jetbrains.k2js.translate.utils.BindingUtils.isStatement; public final class FindDangerousVisitor extends JetTreeVisitor { @NotNull - private final BindingContext bindingContext; + private final TranslationContext context; - public FindDangerousVisitor(@NotNull BindingContext context) { - bindingContext = context; + public FindDangerousVisitor(@NotNull TranslationContext context) { + this.context = context; } @Override @@ -65,7 +66,7 @@ public final class FindDangerousVisitor extends JetTreeVisitor { @Override public Void visitBlockExpression(JetBlockExpression expression, DangerousData data) { - if (isStatement(bindingContext, expression)) { + if (isStatement(context.bindingContext(), expression)) { return null; } else { @@ -73,11 +74,21 @@ public final class FindDangerousVisitor extends JetTreeVisitor { } } + @Override + public Void visitCallExpression(JetCallExpression expression, DangerousData data) { + if (InlinedCallExpressionTranslator.shouldBeInlined(expression, context)) { + if (expressionFound(expression, data)) { + return null; + } + } + return super.visitCallExpression(expression, data); + } + private boolean expressionFound(@NotNull JetExpression expression, @NotNull DangerousData data) { if (data.exists()) { return true; } - if (!isStatement(bindingContext, expression)) { + if (!isStatement(context.bindingContext(), expression)) { data.setDangerousNode(expression); return true; } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/dangerous/FindPreviousVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/dangerous/FindPreviousVisitor.java index 8410c194fe9..602df9dff5c 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/dangerous/FindPreviousVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/dangerous/FindPreviousVisitor.java @@ -16,21 +16,39 @@ package org.jetbrains.k2js.translate.utils.dangerous; +import com.google.common.collect.Maps; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.*; +import java.util.Map; + /** * @author Pavel Talanov */ +//TODO: refactor public final class FindPreviousVisitor extends JetTreeVisitor { + @NotNull + private final Map hasDangerous = Maps.newHashMap(); + + public FindPreviousVisitor(@NotNull DangerousData data) { + JetElement node = data.getDangerousNode(); + PsiElement last = data.getRootNode().getParent(); + while (node != last) { + hasDangerous.put(node, null); + PsiElement parent = node.getParent(); + assert parent instanceof JetElement; + node = (JetElement)parent; + } + } + @Override public Void visitJetElement(JetElement element, DangerousData data) { if (data.getDangerousNode() == element) { return null; } - if (!hasDangerous(element, data)) { + if (!hasDangerous(element)) { addElement(element, data); } else { @@ -52,7 +70,7 @@ public final class FindPreviousVisitor extends JetTreeVisitor { while (current != null) { if (current instanceof JetElement) { ((JetElement)current).accept(this, data); - if (hasDangerous(element, data)) { + if (hasDangerous(element)) { break; } } @@ -60,12 +78,32 @@ public final class FindPreviousVisitor extends JetTreeVisitor { } } + @Override + public Void visitPrefixExpression(@NotNull JetPrefixExpression expression, @NotNull DangerousData data) { + if (data.getDangerousNode() == expression) { + return null; + } + if (!hasDangerous(expression)) { + addElement(expression, data); + return null; + } + else { + if (hasDangerous(expression.getBaseExpression())) { + return null; + } + else { + //TODO: + throw new IllegalStateException(); + } + } + } + @Override public Void visitCallExpression(@NotNull JetCallExpression expression, @NotNull DangerousData data) { if (data.getDangerousNode() == expression) { return null; } - if (!hasDangerous(expression, data)) { + if (!hasDangerous(expression)) { data.getNodesToBeGeneratedBefore().add(expression); } else { @@ -79,30 +117,13 @@ public final class FindPreviousVisitor extends JetTreeVisitor { JetExpression argumentExpression = argument.getArgumentExpression(); assert argumentExpression != null; argumentExpression.accept(this, data); - if (hasDangerous(argumentExpression, data)) { + if (hasDangerous(argumentExpression)) { break; } } } - private static boolean hasDangerous(@NotNull JetElement element, @NotNull DangerousData data) { - HasDangerousVisitor visitor = new HasDangerousVisitor(); - element.accept(visitor, data); - return visitor.hasDangerous; - } - - private static final class HasDangerousVisitor extends JetTreeVisitor { - - private boolean hasDangerous = false; - - @Override - public Void visitJetElement(JetElement element, DangerousData data) { - if (element == data.getDangerousNode()) { - hasDangerous = true; - return null; - } - element.acceptChildren(this, data); - return null; - } + private boolean hasDangerous(@NotNull JetElement element) { + return hasDangerous.containsKey(element); } } diff --git a/js/js.translator/testFiles/dangerous/cases/dangerousInline.kt b/js/js.translator/testFiles/dangerous/cases/dangerousInline.kt new file mode 100644 index 00000000000..d031a85ec4e --- /dev/null +++ b/js/js.translator/testFiles/dangerous/cases/dangerousInline.kt @@ -0,0 +1,9 @@ +package foo + +var i = 0 + +inline fun f() = i * 2 + +fun box() : Boolean { + return (++i + f()) == 3 +} \ No newline at end of file