mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
SetInspectionOptionFix; used in DataFlowInspectionBase
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.intention.LowPriorityAction;
|
||||
import com.intellij.codeInspection.ex.InspectionProfileModifiableModelKt;
|
||||
import com.intellij.codeInspection.ex.InspectionToolWrapper;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SetInspectionOptionFix implements LocalQuickFix, LowPriorityAction {
|
||||
private String myShortName;
|
||||
private final String myProperty;
|
||||
private final String myMessage;
|
||||
private boolean myValue;
|
||||
|
||||
public SetInspectionOptionFix(InspectionProfileEntry inspection, String property, String message, boolean value) {
|
||||
myShortName = inspection.getShortName();
|
||||
myProperty = property;
|
||||
myMessage = message;
|
||||
myValue = value;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return myMessage;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return "Set inspection option";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
InspectionProfileModifiableModelKt.modifyAndCommitProjectProfile(project, model -> {
|
||||
InspectionToolWrapper tool = model.getInspectionTool(myShortName, project);
|
||||
if(tool == null) return;
|
||||
InspectionProfileEntry inspection = tool.getTool();
|
||||
ReflectionUtil.setField(inspection.getClass(), inspection, boolean.class, myProperty, myValue);
|
||||
});
|
||||
}
|
||||
}
|
||||
+54
-26
@@ -289,7 +289,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
|
||||
reportAlwaysFailingCalls(holder, visitor, reportedAnchors);
|
||||
|
||||
reportConstantPushes(runner, holder, reportedAnchors);
|
||||
reportConstantPushes(runner, holder, reportedAnchors, onTheFly);
|
||||
|
||||
reportNullableFunctions(visitor, holder, reportedAnchors);
|
||||
reportNullableArguments(visitor, holder, reportedAnchors);
|
||||
@@ -302,11 +302,11 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
|
||||
reportOptionalOfNullableImprovements(holder, reportedAnchors, visitor.getOfNullableCalls());
|
||||
|
||||
reportUncheckedOptionalGet(holder, visitor.getOptionalCalls(), visitor.getOptionalQualifiers());
|
||||
reportUncheckedOptionalGet(holder, visitor.getOptionalCalls(), visitor.getOptionalQualifiers(), onTheFly);
|
||||
|
||||
visitor.getBooleanCalls().forEach((call, state) -> {
|
||||
if (state != ThreeState.UNSURE && reportedAnchors.add(call)) {
|
||||
reportConstantCondition(holder, call, state.toBoolean());
|
||||
reportConstantCondition(holder, call, state.toBoolean(), onTheFly);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -315,11 +315,11 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
reportArrayAccessProblems(holder, visitor);
|
||||
|
||||
if (REPORT_CONSTANT_REFERENCE_VALUES) {
|
||||
reportConstantReferenceValues(holder, visitor, reportedAnchors);
|
||||
reportConstantReferenceValues(holder, visitor, reportedAnchors, onTheFly);
|
||||
}
|
||||
|
||||
if (REPORT_NULLABLE_METHODS_RETURNING_NOT_NULL && visitor.isAlwaysReturnsNotNull(runner.getInstructions())) {
|
||||
reportAlwaysReturnsNotNull(holder, scope);
|
||||
reportAlwaysReturnsNotNull(holder, scope, onTheFly);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
|
||||
private void reportUncheckedOptionalGet(ProblemsHolder holder,
|
||||
Map<PsiMethodCallExpression, ThreeState> calls,
|
||||
List<PsiExpression> qualifiers) {
|
||||
List<PsiExpression> qualifiers, boolean isOnTheFly) {
|
||||
if (!REPORT_UNCHECKED_OPTIONALS) return;
|
||||
for (Map.Entry<PsiMethodCallExpression, ThreeState> entry : calls.entrySet()) {
|
||||
ThreeState state = entry.getValue();
|
||||
@@ -363,12 +363,15 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
// without deep correspondence analysis
|
||||
continue;
|
||||
}
|
||||
LocalQuickFix fix = isOnTheFly ? new SetInspectionOptionFix(this, "REPORT_UNCHECKED_OPTIONALS", InspectionsBundle
|
||||
.message("inspection.data.flow.turn.off.unchecked.optional.get.quickfix"), false) : null;
|
||||
holder.registerProblem(getElementToHighlight(call),
|
||||
InspectionsBundle.message("dataflow.message.optional.get.without.is.present", optionalClass.getName()));
|
||||
InspectionsBundle.message("dataflow.message.optional.get.without.is.present", optionalClass.getName()),
|
||||
fix);
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportAlwaysReturnsNotNull(ProblemsHolder holder, PsiElement scope) {
|
||||
private void reportAlwaysReturnsNotNull(ProblemsHolder holder, PsiElement scope, boolean isOnTheFly) {
|
||||
if (!(scope.getParent() instanceof PsiMethod)) return;
|
||||
|
||||
PsiMethod method = (PsiMethod)scope.getParent();
|
||||
@@ -381,7 +384,15 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
assert annoName != null;
|
||||
String msg = "@" + NullableStuffInspectionBase.getPresentableAnnoName(nullableAnno) +
|
||||
" method '" + method.getName() + "' always returns a non-null value";
|
||||
holder.registerProblem(annoName, msg, new AddNotNullAnnotationFix(method));
|
||||
LocalQuickFix[] fixes = {new AddNotNullAnnotationFix(method)};
|
||||
if (isOnTheFly) {
|
||||
fixes = ArrayUtil.append(fixes, new SetInspectionOptionFix(this, "REPORT_NULLABLE_METHODS_RETURNING_NOT_NULL",
|
||||
InspectionsBundle
|
||||
.message(
|
||||
"inspection.data.flow.turn.off.nullable.returning.notnull.quickfix"),
|
||||
false));
|
||||
}
|
||||
holder.registerProblem(annoName, msg, fixes);
|
||||
}
|
||||
|
||||
private static void reportAlwaysFailingCalls(ProblemsHolder holder,
|
||||
@@ -417,14 +428,17 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
return call;
|
||||
}
|
||||
|
||||
private void reportConstantPushes(StandardDataFlowRunner runner, ProblemsHolder holder, Set<PsiElement> reportedAnchors) {
|
||||
private void reportConstantPushes(StandardDataFlowRunner runner,
|
||||
ProblemsHolder holder,
|
||||
Set<PsiElement> reportedAnchors,
|
||||
boolean isOnTheFly) {
|
||||
for (Instruction instruction : runner.getInstructions()) {
|
||||
if (instruction instanceof PushInstruction) {
|
||||
PsiExpression place = ((PushInstruction)instruction).getPlace();
|
||||
DfaValue value = ((PushInstruction)instruction).getValue();
|
||||
Object constant = value instanceof DfaConstValue ? ((DfaConstValue)value).getValue() : null;
|
||||
if (place instanceof PsiPolyadicExpression && constant instanceof Boolean && !isFlagCheck(place) && reportedAnchors.add(place)) {
|
||||
reportConstantCondition(holder, place, (Boolean)constant);
|
||||
reportConstantCondition(holder, place, (Boolean)constant, isOnTheFly);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -451,7 +465,10 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
});
|
||||
}
|
||||
|
||||
private static void reportConstantReferenceValues(ProblemsHolder holder, StandardInstructionVisitor visitor, Set<PsiElement> reportedAnchors) {
|
||||
private void reportConstantReferenceValues(ProblemsHolder holder,
|
||||
StandardInstructionVisitor visitor,
|
||||
Set<PsiElement> reportedAnchors,
|
||||
boolean isOnTheFly) {
|
||||
for (Pair<PsiReferenceExpression, DfaConstValue> pair : visitor.getConstantReferenceValues()) {
|
||||
PsiReferenceExpression ref = pair.first;
|
||||
if (ref.getParent() instanceof PsiReferenceExpression || !reportedAnchors.add(ref)) {
|
||||
@@ -466,8 +483,15 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
continue;
|
||||
}
|
||||
|
||||
holder.registerProblem(ref, "Value <code>#ref</code> #loc is always '" + presentableName + "'",
|
||||
new ReplaceWithConstantValueFix(presentableName, exprText));
|
||||
LocalQuickFix[] fixes = {new ReplaceWithConstantValueFix(presentableName, exprText)};
|
||||
if (isOnTheFly) {
|
||||
fixes = ArrayUtil.append(fixes, new SetInspectionOptionFix(this, "REPORT_CONSTANT_REFERENCE_VALUES",
|
||||
InspectionsBundle
|
||||
.message("inspection.data.flow.turn.off.constant.references.quickfix"),
|
||||
false));
|
||||
}
|
||||
|
||||
holder.registerProblem(ref, "Value <code>#ref</code> #loc is always '" + presentableName + "'", fixes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,13 +604,13 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
);
|
||||
}
|
||||
else {
|
||||
reportConstantCondition(holder, psiAnchor, evaluatesToTrue);
|
||||
reportConstantCondition(holder, psiAnchor, evaluatesToTrue, onTheFly);
|
||||
}
|
||||
reportedAnchors.add(psiAnchor);
|
||||
}
|
||||
}
|
||||
|
||||
private void reportConstantCondition(ProblemsHolder holder, PsiElement psiAnchor, boolean evaluatesToTrue) {
|
||||
private void reportConstantCondition(ProblemsHolder holder, PsiElement psiAnchor, boolean evaluatesToTrue, boolean isOnTheFly) {
|
||||
if (psiAnchor.getParent() instanceof PsiForeachStatement) {
|
||||
// highlighted for-each iterated value means evaluatesToTrue == "collection is always empty"
|
||||
if (!evaluatesToTrue) {
|
||||
@@ -598,12 +622,20 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
InspectionsBundle.message("dataflow.message.loop.on.empty.array") :
|
||||
InspectionsBundle.message("dataflow.message.loop.on.empty.collection"));
|
||||
}
|
||||
else if (!skipReportingConstantCondition(psiAnchor, evaluatesToTrue)) {
|
||||
final LocalQuickFix fix = createSimplifyBooleanExpressionFix(psiAnchor, evaluatesToTrue);
|
||||
String message = InspectionsBundle.message(isAtRHSOfBooleanAnd(psiAnchor) ?
|
||||
"dataflow.message.constant.condition.when.reached" :
|
||||
"dataflow.message.constant.condition", Boolean.toString(evaluatesToTrue));
|
||||
holder.registerProblem(psiAnchor, message, fix);
|
||||
else {
|
||||
boolean isAssertion = isAssertionEffectively(psiAnchor, evaluatesToTrue);
|
||||
if (!DONT_REPORT_TRUE_ASSERT_STATEMENTS || !isAssertion) {
|
||||
List<LocalQuickFix> fixes = new ArrayList<>();
|
||||
ContainerUtil.addIfNotNull(fixes, createSimplifyBooleanExpressionFix(psiAnchor, evaluatesToTrue));
|
||||
if (isAssertion && isOnTheFly) {
|
||||
fixes.add(new SetInspectionOptionFix(this, "DONT_REPORT_TRUE_ASSERT_STATEMENTS",
|
||||
InspectionsBundle.message("inspection.data.flow.turn.off.true.asserts.quickfix"), true));
|
||||
}
|
||||
String message = InspectionsBundle.message(isAtRHSOfBooleanAnd(psiAnchor) ?
|
||||
"dataflow.message.constant.condition.when.reached" :
|
||||
"dataflow.message.constant.condition", Boolean.toString(evaluatesToTrue));
|
||||
holder.registerProblem(psiAnchor, message, fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,10 +643,6 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
return LocalQuickFix.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
private boolean skipReportingConstantCondition(PsiElement psiAnchor, boolean evaluatesToTrue) {
|
||||
return DONT_REPORT_TRUE_ASSERT_STATEMENTS && isAssertionEffectively(psiAnchor, evaluatesToTrue);
|
||||
}
|
||||
|
||||
private static void reportNullableFunctions(DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors) {
|
||||
for (PsiElement expr : visitor.getProblems(NullabilityProblem.nullableFunctionReturn)) {
|
||||
if (!reportedAnchors.add(expr)) continue;
|
||||
|
||||
@@ -44,6 +44,11 @@ inspection.data.flow.display.name=Constant conditions \\& exceptions
|
||||
inspection.contract.display.name=Contract issues
|
||||
inspection.data.flow.nullable.quickfix.option=Suggest @Nullable annotation for methods that may possibly return <code>null</code> and report nullable values passed to non-annotated parameters
|
||||
inspection.data.flow.true.asserts.option=Don't report assertions with condition statically proven to be always <code>true</code>
|
||||
inspection.data.flow.turn.off.true.asserts.quickfix=Don't report always true assertions
|
||||
inspection.data.flow.turn.off.null.passed.notnull.parameter.quickfix=Don't report not-null required parameter with null-literal argument usages
|
||||
inspection.data.flow.turn.off.constant.references.quickfix=Don't report values which are guaranteed to be constant
|
||||
inspection.data.flow.turn.off.nullable.returning.notnull.quickfix=Don't report nullable methods which always return not-null value
|
||||
inspection.data.flow.turn.off.unchecked.optional.get.quickfix=Don't report Optional.get() calls without previous isPresent check
|
||||
inspection.data.flow.redundant.instanceof.quickfix=Replace with != null
|
||||
inspection.data.flow.simplify.boolean.expression.quickfix=Simplify boolean expression
|
||||
inspection.data.flow.simplify.to.assignment.quickfix.name=Simplify to normal assignment
|
||||
|
||||
Reference in New Issue
Block a user