mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
DFA instruction visitor refactoring wave#4
DataFlowInstructionVisitor#visitPush -> visitReferenceExpression
This commit is contained in:
+9
-15
@@ -503,24 +503,19 @@ public class DataFlowInspectionBase extends AbstractBaseJavaLocalInspectionTool
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void reportConstantReferenceValues(ProblemsHolder holder, DataFlowInstructionVisitor visitor, Set<PsiElement> reportedAnchors) {
|
private void reportConstantReferenceValues(ProblemsHolder holder, DataFlowInstructionVisitor visitor, Set<PsiElement> reportedAnchors) {
|
||||||
for (Pair<PsiReferenceExpression, DfaConstValue> pair : visitor.getConstantReferenceValues()) {
|
visitor.getConstantReferenceValues().forEach((ref, dfaConst) -> {
|
||||||
PsiReferenceExpression ref = pair.first;
|
if (ref.getParent() instanceof PsiReferenceExpression || DfaConstValue.isSentinel(dfaConst)) return;
|
||||||
if (ref.getParent() instanceof PsiReferenceExpression || !reportedAnchors.add(ref)) {
|
if (!reportedAnchors.add(ref)) return;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Object value = pair.second.getValue();
|
final Object value = dfaConst.getValue();
|
||||||
PsiVariable constant = pair.second.getConstant();
|
PsiVariable constant = dfaConst.getConstant();
|
||||||
final String presentableName = constant != null ? constant.getName() : String.valueOf(value);
|
|
||||||
final String exprText = String.valueOf(value);
|
final String exprText = String.valueOf(value);
|
||||||
if (presentableName == null || exprText == null) {
|
final String presentableName = constant != null ? constant.getName() : exprText;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<LocalQuickFix> fixes = new SmartList<>();
|
List<LocalQuickFix> fixes = new SmartList<>();
|
||||||
fixes.add(new ReplaceWithConstantValueFix(presentableName, exprText));
|
fixes.add(new ReplaceWithConstantValueFix(presentableName, exprText));
|
||||||
boolean isAssertion = value instanceof Boolean && isAssertionEffectively(ref, (Boolean)value);
|
boolean isAssertion = value instanceof Boolean && isAssertionEffectively(ref, (Boolean)value);
|
||||||
if (isAssertion && DONT_REPORT_TRUE_ASSERT_STATEMENTS) continue;
|
if (isAssertion && DONT_REPORT_TRUE_ASSERT_STATEMENTS) return;
|
||||||
if (holder.isOnTheFly()) {
|
if (holder.isOnTheFly()) {
|
||||||
fixes.add(new SetInspectionOptionFix(this, "REPORT_CONSTANT_REFERENCE_VALUES",
|
fixes.add(new SetInspectionOptionFix(this, "REPORT_CONSTANT_REFERENCE_VALUES",
|
||||||
InspectionsBundle.message("inspection.data.flow.turn.off.constant.references.quickfix"),
|
InspectionsBundle.message("inspection.data.flow.turn.off.constant.references.quickfix"),
|
||||||
@@ -532,9 +527,8 @@ public class DataFlowInspectionBase extends AbstractBaseJavaLocalInspectionTool
|
|||||||
}
|
}
|
||||||
|
|
||||||
holder.registerProblem(ref, "Value <code>#ref</code> #loc is always '" + presentableName + "'",
|
holder.registerProblem(ref, "Value <code>#ref</code> #loc is always '" + presentableName + "'",
|
||||||
ProblemHighlightType.WEAK_WARNING,
|
ProblemHighlightType.WEAK_WARNING, fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
|
||||||
fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportNullableArgumentsPassedToNonAnnotated(DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors) {
|
private void reportNullableArgumentsPassedToNonAnnotated(DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors) {
|
||||||
|
|||||||
+21
-30
@@ -9,10 +9,8 @@ import com.intellij.openapi.util.TextRange;
|
|||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import com.intellij.psi.util.PsiTypesUtil;
|
import com.intellij.psi.util.PsiTypesUtil;
|
||||||
import com.intellij.util.ObjectUtils;
|
|
||||||
import com.intellij.util.ThreeState;
|
import com.intellij.util.ThreeState;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import com.intellij.util.containers.MultiMap;
|
|
||||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||||
import one.util.streamex.StreamEx;
|
import one.util.streamex.StreamEx;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -25,7 +23,6 @@ import static com.intellij.util.ObjectUtils.tryCast;
|
|||||||
|
|
||||||
final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
||||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.DataFlowInstructionVisitor");
|
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.DataFlowInstructionVisitor");
|
||||||
private static final Object ANY_VALUE = ObjectUtils.sentinel("ANY_VALUE");
|
|
||||||
private final Map<NullabilityProblemKind.NullabilityProblem<?>, StateInfo> myStateInfos = new LinkedHashMap<>();
|
private final Map<NullabilityProblemKind.NullabilityProblem<?>, StateInfo> myStateInfos = new LinkedHashMap<>();
|
||||||
private final Set<Instruction> myCCEInstructions = ContainerUtil.newHashSet();
|
private final Set<Instruction> myCCEInstructions = ContainerUtil.newHashSet();
|
||||||
private final Map<PsiCallExpression, Boolean> myFailingCalls = new HashMap<>();
|
private final Map<PsiCallExpression, Boolean> myFailingCalls = new HashMap<>();
|
||||||
@@ -34,7 +31,7 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
|||||||
private final Map<PsiAssignmentExpression, Pair<PsiType, PsiType>> myArrayStoreProblems = new HashMap<>();
|
private final Map<PsiAssignmentExpression, Pair<PsiType, PsiType>> myArrayStoreProblems = new HashMap<>();
|
||||||
private final Map<PsiMethodReferenceExpression, DfaValue> myMethodReferenceResults = new HashMap<>();
|
private final Map<PsiMethodReferenceExpression, DfaValue> myMethodReferenceResults = new HashMap<>();
|
||||||
private final Map<PsiArrayAccessExpression, ThreeState> myOutOfBoundsArrayAccesses = new HashMap<>();
|
private final Map<PsiArrayAccessExpression, ThreeState> myOutOfBoundsArrayAccesses = new HashMap<>();
|
||||||
private final MultiMap<PushInstruction, Object> myPossibleVariableValues = MultiMap.createSet();
|
private final Map<PsiReferenceExpression, DfaConstValue> myValues = new HashMap<>();
|
||||||
private final Set<PsiElement> myReceiverMutabilityViolation = new HashSet<>();
|
private final Set<PsiElement> myReceiverMutabilityViolation = new HashSet<>();
|
||||||
private final Set<PsiElement> myArgumentMutabilityViolation = new HashSet<>();
|
private final Set<PsiElement> myArgumentMutabilityViolation = new HashSet<>();
|
||||||
private final Map<PsiExpression, Boolean> mySameValueAssigned = new HashMap<>();
|
private final Map<PsiExpression, Boolean> mySameValueAssigned = new HashMap<>();
|
||||||
@@ -206,20 +203,6 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public DfaInstructionState[] visitPush(PushInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
|
|
||||||
PsiExpression place = instruction.getExpression();
|
|
||||||
if (!instruction.isReferenceWrite() && place instanceof PsiReferenceExpression) {
|
|
||||||
DfaValue dfaValue = instruction.getValue();
|
|
||||||
if (dfaValue instanceof DfaVariableValue) {
|
|
||||||
DfaConstValue constValue = memState.getConstantValue((DfaVariableValue)dfaValue);
|
|
||||||
boolean report = constValue != null && shouldReportConstValue(constValue.getValue());
|
|
||||||
myPossibleVariableValues.putValue(instruction, report ? constValue : ANY_VALUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.visitPush(instruction, runner, memState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DfaInstructionState[] visitEndOfInitializer(EndOfInitializerInstruction instruction, DataFlowRunner runner, DfaMemoryState state) {
|
public DfaInstructionState[] visitEndOfInitializer(EndOfInitializerInstruction instruction, DataFlowRunner runner, DfaMemoryState state) {
|
||||||
if (!instruction.isStatic()) {
|
if (!instruction.isStatic()) {
|
||||||
@@ -228,18 +211,8 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
|||||||
return super.visitEndOfInitializer(instruction, runner, state);
|
return super.visitEndOfInitializer(instruction, runner, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Pair<PsiReferenceExpression, DfaConstValue>> getConstantReferenceValues() {
|
public Map<PsiReferenceExpression, DfaConstValue> getConstantReferenceValues() {
|
||||||
List<Pair<PsiReferenceExpression, DfaConstValue>> result = ContainerUtil.newArrayList();
|
return myValues;
|
||||||
for (PushInstruction instruction : myPossibleVariableValues.keySet()) {
|
|
||||||
Collection<Object> values = myPossibleVariableValues.get(instruction);
|
|
||||||
if (values.size() == 1) {
|
|
||||||
Object singleValue = values.iterator().next();
|
|
||||||
if (singleValue != ANY_VALUE) {
|
|
||||||
result.add(Pair.create((PsiReferenceExpression)instruction.getExpression(), (DfaConstValue)singleValue));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasNonTrivialFailingContracts(PsiCallExpression call) {
|
private static boolean hasNonTrivialFailingContracts(PsiCallExpression call) {
|
||||||
@@ -329,6 +302,24 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||||
|
super.visitReferenceExpression(expression);
|
||||||
|
DfaConstValue oldValue = myValues.get(expression);
|
||||||
|
if (DfaConstValue.isSentinel(oldValue)) return;
|
||||||
|
if (myValue instanceof DfaVariableValue) {
|
||||||
|
DfaConstValue constValue = myMemState.getConstantValue((DfaVariableValue)myValue);
|
||||||
|
boolean report = constValue != null && shouldReportConstValue(constValue.getValue());
|
||||||
|
if (!report) {
|
||||||
|
constValue = null;
|
||||||
|
}
|
||||||
|
DfaConstValue newValue = constValue != null && (oldValue == null || oldValue == constValue)
|
||||||
|
? constValue
|
||||||
|
: myValue.getFactory().getConstFactory().getSentinel();
|
||||||
|
myValues.put(expression, newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleBooleanCalls(PsiMethodCallExpression call) {
|
private void handleBooleanCalls(PsiMethodCallExpression call) {
|
||||||
ThreeState curState = myBooleanCalls.get(call);
|
ThreeState curState = myBooleanCalls.get(call);
|
||||||
if (curState == ThreeState.UNSURE) return;
|
if (curState == ThreeState.UNSURE) return;
|
||||||
|
|||||||
+10
@@ -202,4 +202,14 @@ public class DfaConstValue extends DfaValue {
|
|||||||
public static boolean isContractFail(DfaValue value) {
|
public static boolean isContractFail(DfaValue value) {
|
||||||
return value instanceof DfaConstValue && ((DfaConstValue)value).getValue() == ourThrowable;
|
return value instanceof DfaConstValue && ((DfaConstValue)value).getValue() == ourThrowable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether given value is a special internal sentinel value returned by {@link Factory#getSentinel()}.
|
||||||
|
*
|
||||||
|
* @param value value to check
|
||||||
|
* @return true if specified value is a sentinel value
|
||||||
|
*/
|
||||||
|
public static boolean isSentinel(DfaValue value) {
|
||||||
|
return value instanceof DfaConstValue && ((DfaConstValue)value).getValue() == SENTINEL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user