Test for inline dangerous expressions.

Better FindPreviousVisitor#hasDangerous implementation.
This commit is contained in:
Pavel V. Talanov
2012-03-28 20:51:21 +04:00
parent 31ceb1e7df
commit 87381a06a7
5 changed files with 76 additions and 31 deletions
@@ -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");
}
}
@@ -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;
}
@@ -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<DangerousData> {
@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<DangerousData> {
@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<DangerousData> {
}
}
@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;
}
@@ -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<DangerousData> {
@NotNull
private final Map<JetElement, Void> 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<DangerousData> {
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<DangerousData> {
}
}
@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<DangerousData> {
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<DangerousData> {
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);
}
}
@@ -0,0 +1,9 @@
package foo
var i = 0
inline fun f() = i * 2
fun box() : Boolean {
return (++i + f()) == 3
}