Control-Flow Analysis: Compute STATEMENT slice using control-flow information

This commit is contained in:
Alexey Sedunov
2014-07-11 19:30:25 +04:00
parent ffd4af872c
commit 00dd1dbb0b
19 changed files with 99 additions and 70 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.bindingContextUtil.BindingContextUtilPackage;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.constants.NullValue;
import org.jetbrains.jet.lang.types.JetType;
@@ -42,7 +43,6 @@ import org.jetbrains.k2js.translate.reference.AccessTranslationUtils;
import org.jetbrains.k2js.translate.reference.CallExpressionTranslator;
import org.jetbrains.k2js.translate.reference.QualifiedExpressionTranslator;
import org.jetbrains.k2js.translate.reference.ReferenceTranslator;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
import org.jetbrains.k2js.translate.utils.mutator.AssignToExpressionMutator;
@@ -185,7 +185,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
JsNode thenNode = thenExpression.accept(this, context);
JsNode elseNode = elseExpression == null ? null : elseExpression.accept(this, context);
boolean isKotlinStatement = BindingUtils.isStatement(context.bindingContext(), expression);
boolean isKotlinStatement = BindingContextUtilPackage.isUsedAsStatement(expression, context.bindingContext());
boolean canBeJsExpression = thenNode instanceof JsExpression && elseNode instanceof JsExpression;
if (!isKotlinStatement && canBeJsExpression) {
return new JsConditional(testExpression, convertToExpression(thenNode), convertToExpression(elseNode)).source(expression);
@@ -21,10 +21,10 @@ import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.bindingContextUtil.BindingContextUtilPackage;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
import org.jetbrains.k2js.translate.utils.mutator.AssignToExpressionMutator;
import org.jetbrains.k2js.translate.utils.mutator.LastExpressionMutator;
@@ -39,7 +39,7 @@ public final class WhenTranslator extends AbstractTranslator {
public static JsNode translate(@NotNull JetWhenExpression expression, @NotNull TranslationContext context) {
WhenTranslator translator = new WhenTranslator(expression, context);
if (BindingUtils.isStatement(context.bindingContext(), expression)) {
if (BindingContextUtilPackage.isUsedAsStatement(expression, context.bindingContext())) {
JsBlock jsBlock = new JsBlock();
translator.translateAsStatement(jsBlock.getStatements());
return jsBlock;
@@ -83,25 +83,25 @@ public final class WhenTranslator extends AbstractTranslator {
JsIf prevIf = null;
for (JetWhenEntry entry : whenExpression.getEntries()) {
JsStatement statement = withReturnValueCaptured(translateEntryExpression(entry));
if (entry.isElse()) {
if (prevIf == null) {
statements.add(statement);
}
else {
prevIf.setElseStatement(statement);
}
break;
JsBlock entryBody = new JsBlock();
JsStatement statement = withReturnValueCaptured(translateEntryExpression(entry, context().innerBlock(entryBody)));
if (!entryBody.isEmpty()) {
entryBody.getStatements().add(statement);
statement = entryBody;
}
JsIf ifStatement = new JsIf(translateConditions(entry), statement);
JsStatement statementToAdd = entry.isElse() ? statement : new JsIf(translateConditions(entry), statement);
if (prevIf == null) {
statements.add(ifStatement);
statements.add(statementToAdd);
}
else {
prevIf.setElseStatement(ifStatement);
prevIf.setElseStatement(statementToAdd);
}
prevIf = ifStatement;
if (entry.isElse()) break;
assert statementToAdd instanceof JsIf : "Non-else entry expected: " + entry.getText();
prevIf = (JsIf) statementToAdd;
}
}
@@ -127,10 +127,10 @@ public final class WhenTranslator extends AbstractTranslator {
}
@NotNull
private JsNode translateEntryExpression(@NotNull JetWhenEntry entry) {
private JsNode translateEntryExpression(@NotNull JetWhenEntry entry, @NotNull TranslationContext context) {
JetExpression expressionToExecute = entry.getExpression();
assert expressionToExecute != null : "WhenEntry should have whenExpression to execute.";
return Translation.translateExpression(expressionToExecute, context());
return Translation.translateExpression(expressionToExecute, context);
}
@NotNull
@@ -95,10 +95,6 @@ public final class BindingUtils {
return (JsDescriptorUtils.findAncestorClass(superclassDescriptors) != null);
}
public static boolean isStatement(@NotNull BindingContext context, @NotNull JetExpression expression) {
return BindingContextUtils.getNotNull(context, BindingContext.STATEMENT, expression);
}
@NotNull
public static JetType getTypeByReference(@NotNull BindingContext context,
@NotNull JetTypeReference typeReference) {
@@ -18,11 +18,10 @@ package org.jetbrains.k2js.translate.utils.dangerous;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.bindingContextUtil.BindingContextUtilPackage;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.reference.InlinedCallExpressionTranslator;
import static org.jetbrains.k2js.translate.utils.BindingUtils.isStatement;
public final class FindDangerousVisitor extends JetTreeVisitor<DangerousData> {
@NotNull
@@ -63,12 +62,9 @@ public final class FindDangerousVisitor extends JetTreeVisitor<DangerousData> {
@Override
public Void visitBlockExpression(@NotNull JetBlockExpression expression, DangerousData data) {
if (isStatement(context.bindingContext(), expression)) {
return null;
}
else {
return super.visitBlockExpression(expression, data);
}
return BindingContextUtilPackage.isUsedAsStatement(expression, context.bindingContext())
? null
: super.visitBlockExpression(expression, data);
}
@Override
@@ -85,7 +81,7 @@ public final class FindDangerousVisitor extends JetTreeVisitor<DangerousData> {
if (data.exists()) {
return true;
}
if (!isStatement(context.bindingContext(), expression)) {
if (!BindingContextUtilPackage.isUsedAsStatement(expression, context.bindingContext())) {
data.setDangerousNode(expression);
return true;
}