DataFlowRunner: forNestedClosures; merging nested state is encapsulated within the runner

This commit is contained in:
Tagir Valeev
2017-11-20 16:11:24 +07:00
parent d41ccf66f2
commit d6d7d4b3ab
2 changed files with 20 additions and 23 deletions
@@ -18,7 +18,6 @@ import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.dataFlow.value.DfaConstValue;
import com.intellij.codeInspection.dataFlow.value.DfaUnknownValue;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.codeInspection.nullable.NullableStuffInspectionBase;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -31,7 +30,6 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.siyeh.ig.psiutils.*;
import one.util.streamex.StreamEx;
import org.jdom.Element;
@@ -184,24 +182,7 @@ public class DataFlowInspectionBase extends AbstractBaseJavaLocalInspectionTool
final RunnerResult rc = dfaRunner.analyzeMethod(scope, visitor, IGNORE_ASSERT_STATEMENTS, initialStates);
if (rc == RunnerResult.OK) {
createDescription(dfaRunner, holder, visitor, scope);
MultiMap<PsiElement,DfaMemoryState> nestedClosures = dfaRunner.getNestedClosures();
for (PsiElement closure : nestedClosures.keySet()) {
List<DfaVariableValue> unusedVars = StreamEx.of(dfaRunner.getFactory().getValues())
.select(DfaVariableValue.class)
.filter(var -> var.getQualifier() == null)
.filter(var -> var.getPsiVariable() instanceof PsiVariable &&
!VariableAccessUtils.variableIsUsed((PsiVariable)var.getPsiVariable(), closure))
.toList();
Collection<? extends DfaMemoryState> states = nestedClosures.get(closure);
if (!unusedVars.isEmpty()) {
List<DfaMemoryStateImpl> stateList = StreamEx.of(states)
.peek(state -> unusedVars.forEach(state::flushVariable))
.map(state -> (DfaMemoryStateImpl)state).distinct().toList();
states = StateQueue.mergeGroup(stateList);
}
analyzeDfaWithNestedClosures(closure, holder, dfaRunner, states);
}
dfaRunner.forNestedClosures((closure, states) -> analyzeDfaWithNestedClosures(closure, holder, dfaRunner, states));
}
else if (rc == RunnerResult.TOO_COMPLEX) {
PsiIdentifier name = null;
@@ -30,12 +30,14 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.siyeh.ig.psiutils.VariableAccessUtils;
import gnu.trove.THashSet;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class DataFlowRunner {
@@ -372,9 +374,23 @@ public class DataFlowRunner {
return myInstructions[index];
}
@NotNull
MultiMap<PsiElement, DfaMemoryState> getNestedClosures() {
return new MultiMap<>(myNestedClosures);
public void forNestedClosures(BiConsumer<PsiElement, Collection<? extends DfaMemoryState>> consumer) {
for (PsiElement closure : myNestedClosures.keySet()) {
List<DfaVariableValue> unusedVars = StreamEx.of(getFactory().getValues())
.select(DfaVariableValue.class)
.filter(var -> var.getQualifier() == null)
.filter(var -> var.getPsiVariable() instanceof PsiVariable &&
!VariableAccessUtils.variableIsUsed((PsiVariable)var.getPsiVariable(), closure))
.toList();
Collection<? extends DfaMemoryState> states = myNestedClosures.get(closure);
if (!unusedVars.isEmpty()) {
List<DfaMemoryStateImpl> stateList = StreamEx.of(states)
.peek(state -> unusedVars.forEach(state::flushVariable))
.map(state -> (DfaMemoryStateImpl)state).distinct().toList();
states = StateQueue.mergeGroup(stateList);
}
consumer.accept(closure, states);
}
}
@NotNull