diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java index 25f7e4057617..71ddea2f5785 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java @@ -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)); } }); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInstructionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInstructionVisitor.java index cd2b670cc02d..e5a6f9d1f8a3 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInstructionVisitor.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInstructionVisitor.java @@ -39,7 +39,7 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor { private final Map myConstantExpressions = new HashMap<>(); private final Map myOfNullableCalls = new HashMap<>(); private final Map> myArrayStoreProblems = new HashMap<>(); - private final Map myMethodReferenceResults = new HashMap<>(); + private final Map myMethodReferenceResults = new HashMap<>(); private final Map myOutOfBoundsArrayAccesses = new HashMap<>(); private final Set myReceiverMutabilityViolation = new HashSet<>(); private final Set myArgumentMutabilityViolation = new HashSet<>(); @@ -166,7 +166,7 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor { return myConstantExpressions; } - Map getMethodReferenceResults() { + Map 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 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 {