mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-08-26 15:27:45 +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) {
|
||||
for (Pair<PsiReferenceExpression, DfaConstValue> pair : visitor.getConstantReferenceValues()) {
|
||||
PsiReferenceExpression ref = pair.first;
|
||||
if (ref.getParent() instanceof PsiReferenceExpression || !reportedAnchors.add(ref)) {
|
||||
continue;
|
||||
}
|
||||
visitor.getConstantReferenceValues().forEach((ref, dfaConst) -> {
|
||||
if (ref.getParent() instanceof PsiReferenceExpression || DfaConstValue.isSentinel(dfaConst)) return;
|
||||
if (!reportedAnchors.add(ref)) return;
|
||||
|
||||
final Object value = pair.second.getValue();
|
||||
PsiVariable constant = pair.second.getConstant();
|
||||
final String presentableName = constant != null ? constant.getName() : String.valueOf(value);
|
||||
final Object value = dfaConst.getValue();
|
||||
PsiVariable constant = dfaConst.getConstant();
|
||||
final String exprText = String.valueOf(value);
|
||||
if (presentableName == null || exprText == null) {
|
||||
continue;
|
||||
}
|
||||
final String presentableName = constant != null ? constant.getName() : exprText;
|
||||
|
||||
List<LocalQuickFix> fixes = new SmartList<>();
|
||||
fixes.add(new ReplaceWithConstantValueFix(presentableName, exprText));
|
||||
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()) {
|
||||
fixes.add(new SetInspectionOptionFix(this, "REPORT_CONSTANT_REFERENCE_VALUES",
|
||||
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 + "'",
|
||||
ProblemHighlightType.WEAK_WARNING,
|
||||
fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
|
||||
}
|
||||
ProblemHighlightType.WEAK_WARNING, fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
|
||||
});
|
||||
}
|
||||
|
||||
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.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiTypesUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -25,7 +23,6 @@ import static com.intellij.util.ObjectUtils.tryCast;
|
||||
|
||||
final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
||||
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 Set<Instruction> myCCEInstructions = ContainerUtil.newHashSet();
|
||||
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<PsiMethodReferenceExpression, DfaValue> myMethodReferenceResults = 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> myArgumentMutabilityViolation = new HashSet<>();
|
||||
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
|
||||
public DfaInstructionState[] visitEndOfInitializer(EndOfInitializerInstruction instruction, DataFlowRunner runner, DfaMemoryState state) {
|
||||
if (!instruction.isStatic()) {
|
||||
@@ -228,18 +211,8 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
||||
return super.visitEndOfInitializer(instruction, runner, state);
|
||||
}
|
||||
|
||||
public List<Pair<PsiReferenceExpression, DfaConstValue>> getConstantReferenceValues() {
|
||||
List<Pair<PsiReferenceExpression, DfaConstValue>> result = ContainerUtil.newArrayList();
|
||||
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;
|
||||
public Map<PsiReferenceExpression, DfaConstValue> getConstantReferenceValues() {
|
||||
return myValues;
|
||||
}
|
||||
|
||||
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) {
|
||||
ThreeState curState = myBooleanCalls.get(call);
|
||||
if (curState == ThreeState.UNSURE) return;
|
||||
|
||||
+10
@@ -202,4 +202,14 @@ public class DfaConstValue extends DfaValue {
|
||||
public static boolean isContractFail(DfaValue value) {
|
||||
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