DataFlowInstructionVisitor: unify method reference results and constant results processing

GitOrigin-RevId: 16b69d9f678f71ab6c9d03a93b96ffe72b5be618
This commit is contained in:
Tagir Valeev
2019-11-29 07:07:42 +00:00
committed by intellij-monorepo-bot
parent ccb7c7addc
commit 19283ee76f
2 changed files with 22 additions and 31 deletions
@@ -12,7 +12,6 @@ import com.intellij.codeInspection.dataFlow.NullabilityProblemKind.NullabilityPr
import com.intellij.codeInspection.dataFlow.fix.*;
import com.intellij.codeInspection.dataFlow.instructions.InstanceofInstruction;
import com.intellij.codeInspection.dataFlow.instructions.Instruction;
import com.intellij.codeInspection.dataFlow.value.DfaConstValue;
import com.intellij.codeInspection.nullable.NullableStuffInspectionBase;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -592,13 +591,11 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
}
private void reportMethodReferenceProblems(ProblemsHolder holder, DataFlowInstructionVisitor visitor) {
visitor.getMethodReferenceResults().forEach((methodRef, dfaValue) -> {
if (dfaValue instanceof DfaConstValue) {
Object value = ((DfaConstValue)dfaValue).getValue();
if(value instanceof Boolean) {
holder.registerProblem(methodRef, InspectionsBundle.message("dataflow.message.constant.method.reference", value),
createReplaceWithTrivialLambdaFix(value));
}
visitor.getMethodReferenceResults().forEach((methodRef, result) -> {
if (result != ConstantResult.UNKNOWN) {
Object value = result.value();
holder.registerProblem(methodRef, InspectionsBundle.message("dataflow.message.constant.method.reference", value),
createReplaceWithTrivialLambdaFix(value));
}
});
}
@@ -39,7 +39,7 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
private final Map<ExpressionChunk, ConstantResult> myConstantExpressions = new HashMap<>();
private final Map<PsiElement, ThreeState> myOfNullableCalls = new HashMap<>();
private final Map<PsiAssignmentExpression, Pair<PsiType, PsiType>> myArrayStoreProblems = new HashMap<>();
private final Map<PsiMethodReferenceExpression, DfaValue> myMethodReferenceResults = new HashMap<>();
private final Map<PsiMethodReferenceExpression, ConstantResult> myMethodReferenceResults = new HashMap<>();
private final Map<PsiArrayAccessExpression, ThreeState> myOutOfBoundsArrayAccesses = new HashMap<>();
private final Set<PsiElement> myReceiverMutabilityViolation = new HashSet<>();
private final Set<PsiElement> myArgumentMutabilityViolation = new HashSet<>();
@@ -166,7 +166,7 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
return myConstantExpressions;
}
Map<PsiMethodReferenceExpression, DfaValue> getMethodReferenceResults() {
Map<PsiMethodReferenceExpression, ConstantResult> getMethodReferenceResults() {
return myMethodReferenceResults;
}
@@ -203,13 +203,9 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
public boolean isInstanceofRedundant(InstanceofInstruction instruction) {
PsiExpression expression = instruction.getExpression();
if (expression == null || myUsefulInstanceofs.contains(instruction) || !myReachable.contains(instruction)) return false;
if (expression instanceof PsiMethodReferenceExpression) {
DfaValue value = myMethodReferenceResults.get(expression);
return !(value instanceof DfaConstValue) || !(((DfaConstValue)value).getValue() instanceof Boolean);
} else {
ConstantResult result = myConstantExpressions.get(new ExpressionChunk(expression, null));
return result != ConstantResult.TRUE && result != ConstantResult.FALSE;
}
ConstantResult result = expression instanceof PsiMethodReferenceExpression ?
myMethodReferenceResults.get(expression) : myConstantExpressions.get(new ExpressionChunk(expression, null));
return result != ConstantResult.TRUE && result != ConstantResult.FALSE;
}
@Override
@@ -252,11 +248,10 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
processOfNullableResult(value, state, methodRef.getReferenceNameElement());
}
PsiMethod method = tryCast(methodRef.resolve(), PsiMethod.class);
if (method != null) {
if (method != null && JavaMethodContractUtil.isPure(method)) {
List<StandardMethodContract> contracts = JavaMethodContractUtil.getMethodContracts(method);
if (contracts.isEmpty() || !contracts.get(0).isTrivial()) {
// Do not track if method reference may have different results
myMethodReferenceResults.merge(methodRef, value, (a, b) -> a == b ? a : DfaUnknownValue.getInstance());
myMethodReferenceResults.compute(methodRef, (mr, curState) -> ConstantResult.mergeValue(curState, state, value));
}
}
}
@@ -304,17 +299,7 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
private void reportConstantExpressionValue(DfaValue value, DfaMemoryState memState, PsiExpression expression, TextRange range) {
if (expression instanceof PsiLiteralExpression) return;
ExpressionChunk chunk = new ExpressionChunk(expression, range);
ConstantResult curState = myConstantExpressions.get(chunk);
if (curState == ConstantResult.UNKNOWN) return;
ConstantResult nextState = ConstantResult.UNKNOWN;
DfaConstValue dfaConst = memState.getConstantValue(value);
if (dfaConst != null) {
nextState = ConstantResult.fromConstValue(dfaConst);
if (curState != null && curState != nextState) {
nextState = ConstantResult.UNKNOWN;
}
}
myConstantExpressions.put(chunk, nextState);
myConstantExpressions.compute(chunk, (c, curState) -> ConstantResult.mergeValue(curState, memState, value));
}
@Override
@@ -431,6 +416,15 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
if (Boolean.FALSE.equals(value)) return FALSE;
return UNKNOWN;
}
@NotNull
static ConstantResult mergeValue(@Nullable ConstantResult state, @NotNull DfaMemoryState memState, @Nullable DfaValue value) {
if (state == UNKNOWN) return UNKNOWN;
DfaConstValue dfaConst = memState.getConstantValue(value);
if (dfaConst == null) return UNKNOWN;
ConstantResult nextState = fromConstValue(dfaConst);
return state == null || state == nextState ? nextState : UNKNOWN;
}
}
static class ExpressionChunk {