LiveVariablesAnalyzer: use EscapeInstruction instead of visiting the closure

GitOrigin-RevId: 0856d5b5e4c15d9ce6fd83eefab92fb4a5373aac
This commit is contained in:
Tagir Valeev
2019-11-29 15:29:19 +07:00
committed by intellij-monorepo-bot
parent e3704df1e9
commit f88bb8439b
2 changed files with 13 additions and 30 deletions

View File

@@ -748,15 +748,15 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
}
private void handleClosure(PsiElement closure) {
Set<PsiLocalVariable> variables = new HashSet<>();
Set<PsiVariable> variables = new HashSet<>();
Set<DfaVariableValue> escapedVars = new HashSet<>();
closure.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
final PsiElement target = expression.resolve();
if (target instanceof PsiLocalVariable) {
variables.add((PsiLocalVariable)target);
if (target instanceof PsiLocalVariable || target instanceof PsiParameter) {
variables.add((PsiVariable)target);
}
if (target instanceof PsiMember && !((PsiMember)target).hasModifierProperty(PsiModifier.STATIC)) {
DfaVariableValue qualifier = getFactory().getExpressionFactory().getQualifierOrThisVariable(expression);
@@ -778,7 +778,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
for (DfaValue value : getFactory().getValues()) {
if(value instanceof DfaVariableValue) {
PsiModifierListOwner var = ((DfaVariableValue)value).getPsiVariable();
if (var instanceof PsiLocalVariable && variables.contains(var)) {
if (var instanceof PsiVariable && variables.contains(var)) {
escapedVars.add((DfaVariableValue)value);
}
}

View File

@@ -8,19 +8,17 @@ import com.intellij.codeInspection.dataFlow.value.DfaValueFactory;
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
import com.intellij.psi.PsiReferenceExpression;
import com.intellij.util.PairFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FilteringIterator;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.containers.Queue;
import com.intellij.util.containers.*;
import gnu.trove.TIntHashSet;
import one.util.streamex.IntStreamEx;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.*;
/**
@@ -31,23 +29,6 @@ public class LiveVariablesAnalyzer {
private final Instruction[] myInstructions;
private final MultiMap<Instruction, Instruction> myForwardMap;
private final MultiMap<Instruction, Instruction> myBackwardMap;
private final Map<PsiElement, List<DfaVariableValue>> myClosureReads =
FactoryMap.create(closure -> {
final Set<DfaVariableValue> result = new LinkedHashSet<>();
closure.accept(new PsiRecursiveElementWalkingVisitor() {
@Override
public void visitElement(PsiElement element) {
if (element instanceof PsiReferenceExpression) {
DfaValue value = myFactory.createValue((PsiReferenceExpression)element);
if (value instanceof DfaVariableValue) {
result.add((DfaVariableValue)value);
}
}
super.visitElement(element);
}
});
return new ArrayList<>(result);
});
public LiveVariablesAnalyzer(ControlFlow flow, DfaValueFactory factory) {
myFactory = factory;
@@ -102,15 +83,17 @@ public class LiveVariablesAnalyzer {
}
@NotNull
private List<DfaVariableValue> getReadVariables(Instruction instruction) {
private static List<DfaVariableValue> getReadVariables(Instruction instruction) {
if (instruction instanceof PushInstruction && !((PushInstruction)instruction).isReferenceWrite()) {
DfaValue value = ((PushInstruction)instruction).getValue();
if (value instanceof DfaVariableValue) {
return Collections.singletonList((DfaVariableValue)value);
}
}
else if (instruction instanceof ClosureInstruction) {
return myClosureReads.get(((ClosureInstruction)instruction).getClosureElement());
else if (instruction instanceof EscapeInstruction) {
return StreamEx.of(((EscapeInstruction)instruction).getEscapedVars())
.flatMap(v -> StreamEx.of(v.getDependentVariables()).prepend(v))
.distinct().toList();
}
return Collections.emptyList();
}