DataFlowRunner: disable inlining when inner lambda is requested to analyze

Fixes SimplifyStreamApiCallChainsInspectionTest#BooleanIdentity test (when outer method is analyzed, inner lambda was inlined and we cannot get its initial state)
This commit is contained in:
Tagir Valeev
2017-07-27 16:27:26 +07:00
parent c043811795
commit dddf47d466
2 changed files with 20 additions and 8 deletions
@@ -49,7 +49,8 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
public static final String ORG_JETBRAINS_ANNOTATIONS_CONTRACT = Contract.class.getName();
static final String METHOD_REFERENCE_QUALIFIER_SYNTHETIC_FIELD = "Method reference qualifier";
private final PsiElement myCodeFragment;
private boolean myIgnoreAssertions;
private final boolean myIgnoreAssertions;
private final boolean myInlining;
private final Project myProject;
private static class CannotAnalyzeException extends RuntimeException { }
@@ -62,7 +63,8 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
private final PsiType myAssertionError;
private PsiLambdaExpression myLambdaExpression = null;
ControlFlowAnalyzer(final DfaValueFactory valueFactory, @NotNull PsiElement codeFragment, boolean ignoreAssertions) {
ControlFlowAnalyzer(final DfaValueFactory valueFactory, @NotNull PsiElement codeFragment, boolean ignoreAssertions, boolean inlining) {
myInlining = inlining;
myFactory = valueFactory;
myCodeFragment = codeFragment;
myProject = codeFragment.getProject();
@@ -1364,10 +1366,12 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
@Override public void visitMethodCallExpression(PsiMethodCallExpression expression) {
startElement(expression);
for (CallInliner inliner : INLINERS) {
if (inliner.tryInlineCall(new CFGBuilder(this), expression)) {
finishElement(expression);
return;
if (myInlining) {
for (CallInliner inliner : INLINERS) {
if (inliner.tryInlineCall(new CFGBuilder(this), expression)) {
finishElement(expression);
return;
}
}
}
@@ -46,6 +46,7 @@ public class DataFlowRunner {
private final Map<DfaMemoryState, PsiElement> myStackTopClosures = new HashMap<>();
@NotNull
private final DfaValueFactory myValueFactory;
private boolean myInlining = true;
// Maximum allowed attempts to process instruction. Fail as too complex to process if certain instruction
// is executed more than this limit times.
static final int MAX_STATES_PER_BRANCH = 300;
@@ -69,7 +70,14 @@ public class DataFlowRunner {
if (container != null && (!(container instanceof PsiClass) || PsiUtil.isLocalOrAnonymousClass((PsiClass)container))) {
PsiElement block = DfaPsiUtil.getTopmostBlockInSameClass(container.getParent());
if (block != null) {
final RunnerResult result = analyzeMethod(block, visitor);
final RunnerResult result;
try {
myInlining = false;
result = analyzeMethod(block, visitor);
}
finally {
myInlining = true;
}
if (result == RunnerResult.OK) {
final Collection<DfaMemoryState> closureStates = myNestedClosures.get(DfaPsiUtil.getTopmostBlockInSameClass(psiBlock));
if (!closureStates.isEmpty()) {
@@ -103,7 +111,7 @@ public class DataFlowRunner {
boolean ignoreAssertions,
@NotNull Collection<DfaMemoryState> initialStates) {
try {
final ControlFlow flow = new ControlFlowAnalyzer(myValueFactory, psiBlock, ignoreAssertions).buildControlFlow();
final ControlFlow flow = new ControlFlowAnalyzer(myValueFactory, psiBlock, ignoreAssertions, myInlining).buildControlFlow();
if (flow == null) return RunnerResult.NOT_APPLICABLE;
int[] loopNumber = LoopAnalyzer.calcInLoop(flow);