DataFlowRunner: move ignoreAssertions to the field

GitOrigin-RevId: f43cdfeda78ff6fdb381962d2a2f37a7926fe830
This commit is contained in:
Tagir Valeev
2019-11-18 12:37:04 +07:00
committed by intellij-monorepo-bot
parent 1b98680aa9
commit e90f84e72d
6 changed files with 41 additions and 30 deletions

View File

@@ -244,7 +244,7 @@ public class CommonDataflow {
if (block == null) return new DataflowResult(RunnerResult.NOT_APPLICABLE);
DataFlowRunner runner = new DataFlowRunner(block);
CommonDataflowVisitor visitor = new CommonDataflowVisitor();
RunnerResult result = runner.analyzeMethodRecursively(block, visitor, false);
RunnerResult result = runner.analyzeMethodRecursively(block, visitor);
if (result != RunnerResult.OK) return new DataflowResult(result);
if (!(block instanceof PsiClass)) return visitor.myResult;
DataflowResult dfr = visitor.myResult.copy();
@@ -259,7 +259,7 @@ public class CommonDataflow {
} else {
initialStates = StreamEx.of(states).map(DfaMemoryState::createCopy).toList();
}
if(runner.analyzeBlockRecursively(body, initialStates, visitor, false) == RunnerResult.OK) {
if(runner.analyzeBlockRecursively(body, initialStates, visitor) == RunnerResult.OK) {
dfr = visitor.myResult.copy();
} else {
visitor.myResult = dfr;

View File

@@ -138,7 +138,7 @@ class ContractChecker {
}
ContractCheckerVisitor visitor = new ContractCheckerVisitor(method, contract, ownContract);
runner.analyzeMethod(body, visitor, false, Collections.singletonList(initialState));
runner.analyzeMethod(body, visitor, Collections.singletonList(initialState));
return visitor.getErrors();
}
}

View File

@@ -97,7 +97,7 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
if (aClass instanceof PsiTypeParameter) return;
if (PsiUtil.isLocalOrAnonymousClass(aClass) && !(aClass instanceof PsiEnumConstantInitializer)) return;
final DataFlowRunner runner = new DataFlowRunner(aClass, TREAT_UNKNOWN_MEMBERS_AS_NULLABLE);
final DataFlowRunner runner = new DataFlowRunner(aClass, TREAT_UNKNOWN_MEMBERS_AS_NULLABLE, IGNORE_ASSERT_STATEMENTS);
DataFlowInstructionVisitor visitor =
analyzeDfaWithNestedClosures(aClass, holder, runner, Collections.singletonList(runner.createMemoryState()));
List<DfaMemoryState> states = visitor.getEndOfInitializerStates();
@@ -121,7 +121,7 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
@Override
public void visitMethod(PsiMethod method) {
if (method.isConstructor()) return;
final DataFlowRunner runner = new DataFlowRunner(method.getBody(), TREAT_UNKNOWN_MEMBERS_AS_NULLABLE);
final DataFlowRunner runner = new DataFlowRunner(method.getBody(), TREAT_UNKNOWN_MEMBERS_AS_NULLABLE, IGNORE_ASSERT_STATEMENTS);
analyzeMethod(method, runner, Collections.singletonList(runner.createMemoryState()));
}
@@ -205,7 +205,7 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
DataFlowRunner dfaRunner,
Collection<? extends DfaMemoryState> initialStates) {
final DataFlowInstructionVisitor visitor = new DataFlowInstructionVisitor();
final RunnerResult rc = dfaRunner.analyzeMethod(scope, visitor, IGNORE_ASSERT_STATEMENTS, initialStates);
final RunnerResult rc = dfaRunner.analyzeMethod(scope, visitor, initialStates);
if (rc == RunnerResult.OK) {
if (dfaRunner.wasForciblyMerged() &&
(ApplicationManager.getApplication().isUnitTestMode() || Registry.is("ide.dfa.report.imprecise"))) {

View File

@@ -42,17 +42,18 @@ import java.util.function.Consumer;
public class DataFlowRunner {
private static final Logger LOG = Logger.getInstance(DataFlowRunner.class);
private static final int MERGING_BACK_BRANCHES_THRESHOLD = 50;
static final int MAX_STATES_PER_BRANCH = 300;
private Instruction[] myInstructions;
private final MultiMap<PsiElement, DfaMemoryState> myNestedClosures = new MultiMap<>();
@NotNull
private final DfaValueFactory myValueFactory;
private final boolean myIgnoreAssertions;
private boolean myInlining = true;
private boolean myCancelled = false;
private boolean myWasForciblyMerged = false;
// 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;
private TimeStats myStats;
public DataFlowRunner() {
@@ -60,11 +61,18 @@ public class DataFlowRunner {
}
public DataFlowRunner(@Nullable PsiElement context) {
this(context, false);
this(context, false, false);
}
public DataFlowRunner(@Nullable PsiElement context, boolean unknownMembersAreNullable) {
/**
* @param context analysis context element (code block, class, expression, etc.); used to determine whether we can trust
* field initializers (e.g. we usually cannot if context is a constructor)
* @param unknownMembersAreNullable if true every parameter or method return value without nullity annotation is assumed to be nullable
* @param ignoreAssertions if true, assertion statements will be ignored, as if JVM is started with -da.
*/
public DataFlowRunner(@Nullable PsiElement context, boolean unknownMembersAreNullable, boolean ignoreAssertions) {
myValueFactory = new DfaValueFactory(context, unknownMembersAreNullable);
myIgnoreAssertions = ignoreAssertions;
}
@NotNull
@@ -121,7 +129,7 @@ public class DataFlowRunner {
@NotNull
public final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock, @NotNull InstructionVisitor visitor) {
Collection<DfaMemoryState> initialStates = createInitialStates(psiBlock, visitor, false);
return initialStates == null ? RunnerResult.NOT_APPLICABLE : analyzeMethod(psiBlock, visitor, false, initialStates);
return initialStates == null ? RunnerResult.NOT_APPLICABLE : analyzeMethod(psiBlock, visitor, initialStates);
}
/**
@@ -141,7 +149,7 @@ public class DataFlowRunner {
if (initialStates.isEmpty()) {
return RunnerResult.OK;
}
return analyzeMethod(psiBlock, visitor, false, initialStates);
return analyzeMethod(psiBlock, visitor, initialStates);
}
public final RunnerResult analyzeCodeBlock(@NotNull PsiCodeBlock block,
@@ -149,18 +157,17 @@ public class DataFlowRunner {
Consumer<? super DfaMemoryState> initialStateAdjuster) {
final DfaMemoryState state = createMemoryState();
initialStateAdjuster.accept(state);
return analyzeMethod(block, visitor, false, Collections.singleton(state));
return analyzeMethod(block, visitor, Collections.singleton(state));
}
@NotNull
final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock,
@NotNull InstructionVisitor visitor,
boolean ignoreAssertions,
@NotNull Collection<? extends DfaMemoryState> initialStates) {
ControlFlow flow = null;
try {
myStats = new TimeStats();
flow = new ControlFlowAnalyzer(myValueFactory, psiBlock, ignoreAssertions, myInlining).buildControlFlow();
flow = new ControlFlowAnalyzer(myValueFactory, psiBlock, myIgnoreAssertions, myInlining).buildControlFlow();
myStats.endFlow();
if (flow == null) return RunnerResult.NOT_APPLICABLE;
@@ -395,22 +402,23 @@ public class DataFlowRunner {
LOG.error(new RuntimeExceptionWithAttachments(e, attachments));
}
public RunnerResult analyzeMethodRecursively(@NotNull PsiElement block, StandardInstructionVisitor visitor, boolean ignoreAssertions) {
@NotNull
public RunnerResult analyzeMethodRecursively(@NotNull PsiElement block, @NotNull StandardInstructionVisitor visitor) {
Collection<DfaMemoryState> states = createInitialStates(block, visitor, false);
if (states == null) return RunnerResult.NOT_APPLICABLE;
return analyzeBlockRecursively(block, states, visitor, ignoreAssertions);
return analyzeBlockRecursively(block, states, visitor);
}
@NotNull
public RunnerResult analyzeBlockRecursively(@NotNull PsiElement block,
Collection<? extends DfaMemoryState> states,
StandardInstructionVisitor visitor,
boolean ignoreAssertions) {
RunnerResult result = analyzeMethod(block, visitor, ignoreAssertions, states);
@NotNull Collection<? extends DfaMemoryState> states,
@NotNull StandardInstructionVisitor visitor) {
RunnerResult result = analyzeMethod(block, visitor, states);
if (result != RunnerResult.OK) return result;
Ref<RunnerResult> ref = Ref.create(RunnerResult.OK);
forNestedClosures((closure, nestedStates) -> {
RunnerResult res = analyzeBlockRecursively(closure, nestedStates, visitor, ignoreAssertions);
RunnerResult res = analyzeBlockRecursively(closure, nestedStates, visitor);
if (res != RunnerResult.OK) {
ref.set(res);
}
@@ -420,7 +428,7 @@ public class DataFlowRunner {
private void initializeVariables(@NotNull PsiElement psiBlock,
@NotNull Collection<? extends DfaMemoryState> initialStates,
ControlFlow flow) {
@NotNull ControlFlow flow) {
if (psiBlock instanceof PsiClass) {
DfaVariableValue thisValue = getFactory().getVarFactory().createThisValue((PsiClass)psiBlock);
// In class initializer this variable is local until escaped

View File

@@ -305,7 +305,7 @@ public class DfaUtil {
/**
* Returns a surrounding PSI element which should be analyzed via DFA
* (e.g. passed to {@link DataFlowRunner#analyzeMethodRecursively(PsiElement, StandardInstructionVisitor, boolean)}) to cover
* (e.g. passed to {@link #analyzeMethodRecursively(PsiElement, StandardInstructionVisitor)}) to cover
* given expression.
*
* @param expression expression to cover

View File

@@ -50,8 +50,11 @@ public class TrackingRunner extends DataFlowRunner {
private final List<DfaInstructionState> afterStates = new ArrayList<>();
private final List<TrackingDfaMemoryState> killedStates = new ArrayList<>();
private TrackingRunner(boolean unknownMembersAreNullable, @Nullable PsiElement context, PsiExpression expression) {
super(context, unknownMembersAreNullable);
private TrackingRunner(@Nullable PsiElement context,
PsiExpression expression,
boolean unknownMembersAreNullable,
boolean ignoreAssertions) {
super(context, unknownMembersAreNullable, ignoreAssertions);
myExpression = expression;
}
@@ -117,12 +120,12 @@ public class TrackingRunner extends DataFlowRunner {
DfaProblemType type) {
PsiElement body = DfaUtil.getDataflowContext(expression);
if (body == null) return null;
TrackingRunner runner = new TrackingRunner(unknownAreNullables, body, expression);
if (!runner.analyze(ignoreAssertions, expression, body)) return null;
TrackingRunner runner = new TrackingRunner(body, expression, unknownAreNullables, ignoreAssertions);
if (!runner.analyze(expression, body)) return null;
return runner.findProblemCause(expression, type);
}
private boolean analyze(boolean ignoreAssertions, PsiExpression expression, PsiElement body) {
private boolean analyze(PsiExpression expression, PsiElement body) {
List<DfaMemoryState> endOfInitializerStates = new ArrayList<>();
StandardInstructionVisitor visitor = new StandardInstructionVisitor(true) {
@Override
@@ -135,7 +138,7 @@ public class TrackingRunner extends DataFlowRunner {
return super.visitEndOfInitializer(instruction, runner, state);
}
};
RunnerResult result = analyzeMethodRecursively(body, visitor, ignoreAssertions);
RunnerResult result = analyzeMethodRecursively(body, visitor);
if (result != RunnerResult.OK) return false;
if (body instanceof PsiClass) {
PsiMethod ctor = PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiClass.class, PsiLambdaExpression.class);
@@ -151,7 +154,7 @@ public class TrackingRunner extends DataFlowRunner {
else {
initialStates = StreamEx.of(endOfInitializerStates).map(DfaMemoryState::createCopy).toList();
}
return analyzeBlockRecursively(ctorBody, initialStates, visitor, false) == RunnerResult.OK;
return analyzeBlockRecursively(ctorBody, initialStates, visitor) == RunnerResult.OK;
}
}
}