mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-dfa] Rework unknowns are nullables mode: now tracked by visitor instead of factory
GitOrigin-RevId: e9af3d831999536f83f58fc431a1a7a819d9e785
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d8e57214a9
commit
0b0c0b1bd5
+4
-3
@@ -12,6 +12,7 @@ import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.siyeh.ig.psiutils.BoolUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -78,9 +79,9 @@ class DebuggerInstructionVisitor extends StandardInstructionVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkNotNullable(DfaMemoryState state,
|
||||
@NotNull DfaValue value,
|
||||
@Nullable NullabilityProblemKind.NullabilityProblem<?> problem) {
|
||||
protected ThreeState checkNotNullable(DfaMemoryState state,
|
||||
@NotNull DfaValue value,
|
||||
@Nullable NullabilityProblemKind.NullabilityProblem<?> problem) {
|
||||
if (problem != null) {
|
||||
PsiExpression expression = problem.getDereferencedExpression();
|
||||
if (expression != null && problem.thrownException() != null) {
|
||||
|
||||
+1
-1
@@ -205,7 +205,7 @@ public final class CommonDataflow {
|
||||
@NotNull
|
||||
private static DataflowResult runDFA(@Nullable PsiElement block) {
|
||||
if (block == null) return new DataflowResult(RunnerResult.NOT_APPLICABLE);
|
||||
DataFlowRunner runner = new DataFlowRunner(block.getProject(), block, false, ThreeState.UNSURE);
|
||||
DataFlowRunner runner = new DataFlowRunner(block.getProject(), block, ThreeState.UNSURE);
|
||||
CommonDataflowVisitor visitor = new CommonDataflowVisitor();
|
||||
RunnerResult result = runner.analyzeMethodRecursively(block, visitor);
|
||||
if (result != RunnerResult.OK) return new DataflowResult(result);
|
||||
|
||||
+3
-4
@@ -91,8 +91,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(holder.getProject(), aClass, TREAT_UNKNOWN_MEMBERS_AS_NULLABLE,
|
||||
ThreeState.fromBoolean(IGNORE_ASSERT_STATEMENTS));
|
||||
final DataFlowRunner runner = new DataFlowRunner(holder.getProject(), aClass, ThreeState.fromBoolean(IGNORE_ASSERT_STATEMENTS));
|
||||
DataFlowInstructionVisitor visitor =
|
||||
analyzeDfaWithNestedClosures(aClass, holder, runner, Collections.singletonList(runner.createMemoryState()));
|
||||
List<DfaMemoryState> states = visitor.getEndOfInitializerStates();
|
||||
@@ -117,7 +116,7 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
|
||||
public void visitMethod(PsiMethod method) {
|
||||
if (method.isConstructor()) return;
|
||||
final DataFlowRunner runner = new DataFlowRunner(
|
||||
holder.getProject(), method.getBody(), TREAT_UNKNOWN_MEMBERS_AS_NULLABLE, ThreeState.fromBoolean(IGNORE_ASSERT_STATEMENTS));
|
||||
holder.getProject(), method.getBody(), ThreeState.fromBoolean(IGNORE_ASSERT_STATEMENTS));
|
||||
analyzeMethod(method, runner, Collections.singletonList(runner.createMemoryState()));
|
||||
}
|
||||
|
||||
@@ -201,7 +200,7 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
|
||||
ProblemsHolder holder,
|
||||
DataFlowRunner dfaRunner,
|
||||
Collection<? extends DfaMemoryState> initialStates) {
|
||||
final DataFlowInstructionVisitor visitor = new DataFlowInstructionVisitor();
|
||||
final DataFlowInstructionVisitor visitor = new DataFlowInstructionVisitor(TREAT_UNKNOWN_MEMBERS_AS_NULLABLE);
|
||||
final RunnerResult rc = dfaRunner.analyzeMethod(scope, visitor, initialStates);
|
||||
if (rc == RunnerResult.OK) {
|
||||
if (dfaRunner.wasForciblyMerged() &&
|
||||
|
||||
+20
-7
@@ -50,6 +50,7 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
||||
private final Map<PsiExpression, ThreeState> mySwitchLabelsReachability = new HashMap<>();
|
||||
private boolean myAlwaysReturnsNotNull = true;
|
||||
private final List<DfaMemoryState> myEndOfInitializerStates = new ArrayList<>();
|
||||
private final boolean myStrictMode;
|
||||
|
||||
private static final CallMatcher USELESS_SAME_ARGUMENTS = CallMatcher.anyOf(
|
||||
CallMatcher.staticCall(CommonClassNames.JAVA_LANG_MATH, "min", "max").parameterCount(2),
|
||||
@@ -60,6 +61,10 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "replace").parameterCount(2)
|
||||
);
|
||||
|
||||
DataFlowInstructionVisitor(boolean strictMode) {
|
||||
myStrictMode = strictMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DfaInstructionState[] visitAssign(AssignInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
|
||||
PsiExpression left = instruction.getLExpression();
|
||||
@@ -144,7 +149,7 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
||||
|
||||
@Override
|
||||
protected void onTypeCast(PsiTypeCastExpression castExpression, DfaMemoryState state, boolean castPossible) {
|
||||
myClassCastProblems.computeIfAbsent(castExpression, e -> new StateInfo()).update(state, castPossible);
|
||||
myClassCastProblems.computeIfAbsent(castExpression, e -> new StateInfo()).update(state, ThreeState.fromBoolean(castPossible));
|
||||
}
|
||||
|
||||
StreamEx<NullabilityProblemKind.NullabilityProblem<?>> problems() {
|
||||
@@ -316,12 +321,15 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkNotNullable(DfaMemoryState state, @NotNull DfaValue value, @Nullable NullabilityProblemKind.NullabilityProblem<?> problem) {
|
||||
protected ThreeState checkNotNullable(DfaMemoryState state, @NotNull DfaValue value, @Nullable NullabilityProblemKind.NullabilityProblem<?> problem) {
|
||||
if (problem != null && problem.getKind() == NullabilityProblemKind.nullableReturn && !state.isNotNull(value)) {
|
||||
myAlwaysReturnsNotNull = false;
|
||||
}
|
||||
|
||||
boolean ok = super.checkNotNullable(state, value, problem);
|
||||
ThreeState ok = super.checkNotNullable(state, value, problem);
|
||||
if (!myStrictMode && ok == ThreeState.UNSURE) {
|
||||
ok = ThreeState.YES;
|
||||
}
|
||||
if (problem == null) return ok;
|
||||
StateInfo info = myStateInfos.computeIfAbsent(problem, k -> new StateInfo());
|
||||
info.update(state, ok);
|
||||
@@ -349,14 +357,19 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
||||
boolean ephemeralException;
|
||||
boolean normalException;
|
||||
boolean normalOk;
|
||||
boolean unknown = true;
|
||||
|
||||
void update(DfaMemoryState state, boolean ok) {
|
||||
void update(DfaMemoryState state, ThreeState ok) {
|
||||
if (state.isEphemeral()) {
|
||||
if (!ok) ephemeralException = true;
|
||||
if (ok != ThreeState.YES) ephemeralException = true;
|
||||
if (ok != ThreeState.UNSURE) unknown = false;
|
||||
}
|
||||
else {
|
||||
if (ok) normalOk = true;
|
||||
else normalException = true;
|
||||
if (ok == ThreeState.YES) normalOk = true;
|
||||
else {
|
||||
normalException = true;
|
||||
if (ok != ThreeState.UNSURE) unknown = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -61,21 +61,19 @@ public class DataFlowRunner {
|
||||
}
|
||||
|
||||
public DataFlowRunner(@NotNull Project project, @Nullable PsiElement context) {
|
||||
this(project, context, false, ThreeState.NO);
|
||||
this(project, context, ThreeState.NO);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param project current project
|
||||
* @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(@NotNull Project project,
|
||||
@Nullable PsiElement context,
|
||||
boolean unknownMembersAreNullable,
|
||||
@NotNull ThreeState ignoreAssertions) {
|
||||
myValueFactory = new DfaValueFactory(project, context, unknownMembersAreNullable);
|
||||
myValueFactory = new DfaValueFactory(project, context);
|
||||
myIgnoreAssertions = ignoreAssertions;
|
||||
}
|
||||
|
||||
|
||||
@@ -293,8 +293,9 @@ public final class DfaUtil {
|
||||
return Integer.MAX_VALUE; // accessed after initialization or at unknown moment
|
||||
}
|
||||
|
||||
public static boolean hasInitializationHacks(@NotNull PsiField field) {
|
||||
PsiClass containingClass = field.getContainingClass();
|
||||
public static boolean hasInitializationHacks(@NotNull PsiVariable var) {
|
||||
if (!(var instanceof PsiField)) return false;
|
||||
PsiClass containingClass = ((PsiField)var).getContainingClass();
|
||||
return containingClass != null && System.class.getName().equals(containingClass.getQualifiedName());
|
||||
}
|
||||
|
||||
|
||||
+8
-7
@@ -39,14 +39,15 @@ public final class NullabilityUtil {
|
||||
if (value.getType() instanceof PsiPrimitiveType) {
|
||||
return DfaNullability.UNKNOWN;
|
||||
}
|
||||
if (var instanceof PsiField && DfaUtil.hasInitializationHacks((PsiField)var)) {
|
||||
return DfaNullability.FLUSHED;
|
||||
}
|
||||
Nullability nullability = DfaPsiUtil.getElementNullabilityIgnoringParameterInference(value.getType(), var);
|
||||
if (nullability != Nullability.UNKNOWN) {
|
||||
return DfaNullability.fromNullability(nullability);
|
||||
}
|
||||
if (var == null) return DfaNullability.UNKNOWN;
|
||||
|
||||
Nullability defaultNullability = value.getFactory().suggestNullabilityForNonAnnotatedMember(var);
|
||||
|
||||
if (var instanceof PsiParameter && var.getParent() instanceof PsiForeachStatement) {
|
||||
PsiExpression iteratedValue = ((PsiForeachStatement)var.getParent()).getIteratedValue();
|
||||
if (iteratedValue != null) {
|
||||
@@ -58,13 +59,13 @@ public final class NullabilityUtil {
|
||||
}
|
||||
|
||||
if (var instanceof PsiField && value.getFactory().canTrustFieldInitializer((PsiField)var)) {
|
||||
return DfaNullability.fromNullability(getNullabilityFromFieldInitializers((PsiField)var, defaultNullability).second);
|
||||
return DfaNullability.fromNullability(getNullabilityFromFieldInitializers((PsiField)var).second);
|
||||
}
|
||||
|
||||
return DfaNullability.fromNullability(defaultNullability);
|
||||
return DfaNullability.fromNullability(Nullability.UNKNOWN);
|
||||
}
|
||||
|
||||
static Pair<PsiExpression, Nullability> getNullabilityFromFieldInitializers(PsiField field, Nullability defaultNullability) {
|
||||
static Pair<PsiExpression, Nullability> getNullabilityFromFieldInitializers(PsiField field) {
|
||||
if (DfaPsiUtil.isFinalField(field)) {
|
||||
PsiExpression initializer = field.getInitializer();
|
||||
if (initializer != null) {
|
||||
@@ -73,7 +74,7 @@ public final class NullabilityUtil {
|
||||
|
||||
List<PsiExpression> initializers = DfaPsiUtil.findAllConstructorInitializers(field);
|
||||
if (initializers.isEmpty()) {
|
||||
return Pair.create(null, defaultNullability);
|
||||
return Pair.create(null, Nullability.UNKNOWN);
|
||||
}
|
||||
|
||||
for (PsiExpression expression : initializers) {
|
||||
@@ -90,7 +91,7 @@ public final class NullabilityUtil {
|
||||
else if (isOnlyImplicitlyInitialized(field)) {
|
||||
return Pair.create(null, Nullability.NOT_NULL);
|
||||
}
|
||||
return Pair.create(null, defaultNullability);
|
||||
return Pair.create(null, Nullability.UNKNOWN);
|
||||
}
|
||||
|
||||
private static boolean isOnlyImplicitlyInitialized(PsiField field) {
|
||||
|
||||
+5
-7
@@ -618,12 +618,12 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
private <T extends PsiElement> DfaValue dereference(DfaMemoryState memState,
|
||||
DfaValue value,
|
||||
@Nullable NullabilityProblemKind.NullabilityProblem<T> problem) {
|
||||
boolean ok = checkNotNullable(memState, value, problem);
|
||||
ThreeState ok = checkNotNullable(memState, value, problem);
|
||||
if (value instanceof DfaTypeValue) {
|
||||
DfType dfType = value.getDfType().meet(NOT_NULL_OBJECT);
|
||||
return value.getFactory().fromDfType(dfType == BOTTOM ? NOT_NULL_OBJECT : dfType);
|
||||
}
|
||||
if (ok) return value;
|
||||
if (ok != ThreeState.NO) return value;
|
||||
if (memState.isNull(value) && problem != null && problem.getKind() == NullabilityProblemKind.nullableFunctionReturn) {
|
||||
return value.getFactory().fromDfType(NOT_NULL_OBJECT);
|
||||
}
|
||||
@@ -700,9 +700,6 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
mutable = Mutability.getMutability(realMethod);
|
||||
}
|
||||
type = narrowReturnType(type, qualifierType, realMethod);
|
||||
if (nullability == Nullability.UNKNOWN) {
|
||||
nullability = factory.suggestNullabilityForNonAnnotatedMember(targetMethod);
|
||||
}
|
||||
}
|
||||
DfType dfType = instruction.getContext() instanceof PsiNewExpression ?
|
||||
TypeConstraints.exact(type).asDfType().meet(NOT_NULL_OBJECT) :
|
||||
@@ -768,13 +765,14 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
return precalculated;
|
||||
}
|
||||
|
||||
protected boolean checkNotNullable(DfaMemoryState state, @NotNull DfaValue value, @Nullable NullabilityProblemKind.NullabilityProblem<?> problem) {
|
||||
protected ThreeState checkNotNullable(DfaMemoryState state, @NotNull DfaValue value, @Nullable NullabilityProblemKind.NullabilityProblem<?> problem) {
|
||||
DfaNullability nullability = DfaNullability.fromDfType(state.getDfType(value));
|
||||
boolean notNullable = nullability != DfaNullability.NULL && nullability != DfaNullability.NULLABLE;
|
||||
if (notNullable && problem != null && problem.thrownException() != null) {
|
||||
state.applyCondition(value.cond(RelationType.NE, value.getFactory().getNull()));
|
||||
}
|
||||
return notNullable;
|
||||
boolean unknown = nullability == DfaNullability.UNKNOWN;
|
||||
return notNullable ? unknown ? ThreeState.UNSURE : ThreeState.YES : ThreeState.NO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-6
@@ -60,9 +60,8 @@ public final class TrackingRunner extends DataFlowRunner {
|
||||
|
||||
private TrackingRunner(@NotNull PsiElement context,
|
||||
PsiExpression expression,
|
||||
boolean unknownMembersAreNullable,
|
||||
boolean ignoreAssertions) {
|
||||
super(context.getProject(), context, unknownMembersAreNullable, ThreeState.fromBoolean(ignoreAssertions));
|
||||
super(context.getProject(), context, ThreeState.fromBoolean(ignoreAssertions));
|
||||
myExpression = expression;
|
||||
}
|
||||
|
||||
@@ -121,13 +120,12 @@ public final class TrackingRunner extends DataFlowRunner {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CauseItem findProblemCause(boolean unknownAreNullables,
|
||||
boolean ignoreAssertions,
|
||||
public static CauseItem findProblemCause(boolean ignoreAssertions,
|
||||
PsiExpression expression,
|
||||
DfaProblemType type) {
|
||||
PsiElement body = DfaUtil.getDataflowContext(expression);
|
||||
if (body == null) return null;
|
||||
TrackingRunner runner = new TrackingRunner(body, expression, unknownAreNullables, ignoreAssertions);
|
||||
TrackingRunner runner = new TrackingRunner(body, expression, ignoreAssertions);
|
||||
if (!runner.analyze(expression, body)) return null;
|
||||
return runner.findProblemCause(expression, type);
|
||||
}
|
||||
@@ -1230,7 +1228,7 @@ public final class TrackingRunner extends DataFlowRunner {
|
||||
}
|
||||
if (owner instanceof PsiField && getFactory().canTrustFieldInitializer((PsiField)owner)) {
|
||||
Pair<PsiExpression, Nullability> fieldNullability =
|
||||
NullabilityUtil.getNullabilityFromFieldInitializers((PsiField)owner, Nullability.UNKNOWN);
|
||||
NullabilityUtil.getNullabilityFromFieldInitializers((PsiField)owner);
|
||||
if (fieldNullability.second == DfaNullability.toNullability(nullability)) {
|
||||
PsiExpression initializer = fieldNullability.first;
|
||||
if (initializer != null) {
|
||||
|
||||
+3
-3
@@ -368,7 +368,8 @@ public class DfaExpressionFactory {
|
||||
|
||||
@Override
|
||||
public boolean isStable() {
|
||||
return PsiUtil.isJvmLocalVariable(myVariable) || myVariable.hasModifierProperty(PsiModifier.FINAL);
|
||||
return PsiUtil.isJvmLocalVariable(myVariable) ||
|
||||
(myVariable.hasModifierProperty(PsiModifier.FINAL) && !DfaUtil.hasInitializationHacks(myVariable));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -379,8 +380,7 @@ public class DfaExpressionFactory {
|
||||
return factory.getObjectType(type, DfaPsiUtil.getElementNullability(type, myVariable));
|
||||
}
|
||||
if (PsiUtil.isJvmLocalVariable(myVariable) ||
|
||||
(myVariable instanceof PsiField && myVariable.hasModifierProperty(PsiModifier.STATIC) &&
|
||||
(!myVariable.hasModifierProperty(PsiModifier.FINAL) || !DfaUtil.hasInitializationHacks((PsiField)myVariable)))) {
|
||||
(myVariable instanceof PsiField && myVariable.hasModifierProperty(PsiModifier.STATIC))) {
|
||||
return factory.getVarFactory().createVariableValue(this);
|
||||
}
|
||||
return VariableDescriptor.super.createValue(factory, qualifier, forAccessor);
|
||||
|
||||
+1
-25
@@ -2,7 +2,6 @@
|
||||
|
||||
package com.intellij.codeInspection.dataFlow.value;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.Nullability;
|
||||
import com.intellij.codeInspection.dataFlow.*;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfType;
|
||||
@@ -10,7 +9,6 @@ import com.intellij.codeInspection.dataFlow.types.DfTypes;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.PsiFieldImpl;
|
||||
import com.intellij.psi.util.*;
|
||||
@@ -25,13 +23,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.patterns.PsiJavaPatterns.psiMember;
|
||||
import static com.intellij.patterns.PsiJavaPatterns.psiParameter;
|
||||
import static com.intellij.patterns.StandardPatterns.or;
|
||||
|
||||
public class DfaValueFactory {
|
||||
private final @NotNull List<DfaValue> myValues = new ArrayList<>();
|
||||
private final boolean myUnknownMembersAreNullable;
|
||||
private final @NotNull FieldChecker myFieldChecker;
|
||||
private final @NotNull Project myProject;
|
||||
private @Nullable DfaVariableValue myAssertionDisabled;
|
||||
@@ -39,12 +32,10 @@ public class DfaValueFactory {
|
||||
/**
|
||||
* @param project a project in which context the analysis is performed
|
||||
* @param context an item to analyze (code-block, expression, class)
|
||||
* @param unknownMembersAreNullable if true, unknown (non-annotated members) are assumed to be nullable
|
||||
*/
|
||||
public DfaValueFactory(@NotNull Project project, @Nullable PsiElement context, boolean unknownMembersAreNullable) {
|
||||
public DfaValueFactory(@NotNull Project project, @Nullable PsiElement context) {
|
||||
myProject = project;
|
||||
myFieldChecker = new FieldChecker(context);
|
||||
myUnknownMembersAreNullable = unknownMembersAreNullable;
|
||||
myValues.add(null);
|
||||
myVarFactory = new DfaVariableValue.Factory(this);
|
||||
myBoxedFactory = new DfaBoxedValue.Factory(this);
|
||||
@@ -57,21 +48,6 @@ public class DfaValueFactory {
|
||||
return myFieldChecker.canTrustFieldInitializer(field);
|
||||
}
|
||||
|
||||
private static final ElementPattern<? extends PsiModifierListOwner> MEMBER_OR_METHOD_PARAMETER =
|
||||
or(psiMember(), psiParameter().withSuperParent(2, psiMember()));
|
||||
|
||||
|
||||
@NotNull
|
||||
public Nullability suggestNullabilityForNonAnnotatedMember(@NotNull PsiModifierListOwner member) {
|
||||
if (myUnknownMembersAreNullable &&
|
||||
MEMBER_OR_METHOD_PARAMETER.accepts(member) &&
|
||||
AnnotationUtil.getSuperAnnotationOwners(member).isEmpty()) {
|
||||
return Nullability.NULLABLE;
|
||||
}
|
||||
|
||||
return Nullability.UNKNOWN;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DfaTypeValue getObjectType(@Nullable PsiType type, @NotNull Nullability nullability) {
|
||||
return fromDfType(DfTypes.typedObject(type, nullability));
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ public final class FindDfaProblemCauseFix implements OnTheFlyLocalFix, LowPriori
|
||||
ThrowableComputable<TrackingRunner.CauseItem, RuntimeException> causeFinder = () -> {
|
||||
PsiExpression element = myAnchor.getElement();
|
||||
if (element == null) return null;
|
||||
return TrackingRunner.findProblemCause(myUnknownMembersAsNullable, myIgnoreAssertStatements, element, myProblemType);
|
||||
return TrackingRunner.findProblemCause(myIgnoreAssertStatements, element, myProblemType);
|
||||
};
|
||||
TrackingRunner.CauseItem item = ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
() -> ReadAction.compute(causeFinder), JavaBundle.message("progress.title.finding.cause"), true, project);
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ public class DataFlowInspectionTrackerTest extends LightJavaCodeInsightFixtureTe
|
||||
assertTrue("Selected element is not an expression: " + selectedText, element instanceof PsiExpression);
|
||||
PsiExpression expression = (PsiExpression)element;
|
||||
TrackingRunner.DfaProblemType problemType = getProblemType(selectedText, expression);
|
||||
TrackingRunner.CauseItem item = TrackingRunner.findProblemCause(true, false, expression, problemType);
|
||||
TrackingRunner.CauseItem item = TrackingRunner.findProblemCause(false, expression, problemType);
|
||||
assertNotNull(item);
|
||||
String dump = item.dump(getEditor().getDocument());
|
||||
PsiComment firstComment = PsiTreeUtil.findChildOfType(file, PsiComment.class);
|
||||
|
||||
+1
-1
@@ -337,7 +337,7 @@ public final class ReorderingUtils {
|
||||
List<? extends MethodContract> contracts = DfaUtil.addRangeContracts(method, JavaMethodContractUtil.getMethodCallContracts(call));
|
||||
contracts = ContainerUtil.filter(contracts, c -> c.getReturnValue().isFail() && c.getConditions().size() == 1);
|
||||
if (contracts.isEmpty()) return null;
|
||||
DfaValueFactory factory = new DfaValueFactory(expression.getProject(), null, false);
|
||||
DfaValueFactory factory = new DfaValueFactory(expression.getProject(), null);
|
||||
List<DfaRelation> conditions = new ArrayList<>();
|
||||
for (MethodContract contract : contracts) {
|
||||
ContractValue condition = contract.getConditions().get(0);
|
||||
|
||||
+2
-2
@@ -166,7 +166,7 @@ public class ConditionCoveredByFurtherConditionInspection extends AbstractBaseJa
|
||||
Map<PsiExpression, ThreeState> values = new HashMap<>();
|
||||
StandardInstructionVisitor visitor = new StandardInstructionVisitor() {
|
||||
@Override
|
||||
protected boolean checkNotNullable(DfaMemoryState state,
|
||||
protected ThreeState checkNotNullable(DfaMemoryState state,
|
||||
@NotNull DfaValue value,
|
||||
@Nullable NullabilityProblemKind.NullabilityProblem<?> problem) {
|
||||
if (value instanceof DfaVariableValue) {
|
||||
@@ -175,7 +175,7 @@ public class ConditionCoveredByFurtherConditionInspection extends AbstractBaseJa
|
||||
state.setDfType(value, ((DfReferenceType)dfType).dropNullability().meet(DfaNullability.NULLABLE.asDfType()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return ThreeState.YES;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user