IDEA-197026 "Redundant null-check" inspection: make a quick-fix to replace "foo != null" with "foo"

Primitive type name is added to the message
This commit is contained in:
Tagir Valeev
2018-08-17 15:16:11 +07:00
parent e623b2ed38
commit a35e4128e6
5 changed files with 49 additions and 6 deletions
@@ -11,6 +11,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.ig.psiutils.CommentTracker;
import com.siyeh.ig.psiutils.ExpressionUtils;
@@ -44,8 +45,9 @@ public class ObviousNullCheckInspection extends AbstractBaseJavaLocalInspectionT
if(nullCheckParameter.myNull) {
holder.registerProblem(nullArg, InspectionsBundle.message("inspection.redundant.null.check.always.fail.message", explanation));
} else {
holder.registerProblem(nullArg, InspectionsBundle.message("inspection.redundant.null.check.message", explanation),
new RemoveNullCheckFix());
PsiReferenceExpression comparedToNull = ExpressionUtils.getReferenceExpressionFromNullComparison(nullArg, false);
LocalQuickFix fix = comparedToNull == null ? new RemoveNullCheckFix() : new RemoveExcessiveNullComparisonFix();
holder.registerProblem(nullArg, InspectionsBundle.message("inspection.redundant.null.check.message", explanation), fix);
}
}
};
@@ -56,11 +58,11 @@ public class ObviousNullCheckInspection extends AbstractBaseJavaLocalInspectionT
if (arg == null || ExpressionUtils.isNullLiteral(arg)) return null;
if (arg instanceof PsiNewExpression) return "newly created object";
if (arg instanceof PsiLiteralExpression) return "literal";
if (arg.getType() instanceof PsiPrimitiveType) return "a value of primitive type";
if (arg.getType() instanceof PsiPrimitiveType) return "a value of primitive type '" + arg.getType().getCanonicalText() + "'";
if (arg instanceof PsiPolyadicExpression && ((PsiPolyadicExpression)arg).getOperationTokenType() == JavaTokenType.PLUS) {
return "concatenation";
}
if (arg instanceof PsiThisExpression) return "this object";
if (arg instanceof PsiThisExpression) return "'this' object";
return null;
}
@@ -108,6 +110,24 @@ public class ObviousNullCheckInspection extends AbstractBaseJavaLocalInspectionT
}
}
public static class RemoveExcessiveNullComparisonFix implements LocalQuickFix {
@Nls(capitalization = Nls.Capitalization.Sentence)
@NotNull
@Override
public String getFamilyName() {
return InspectionsBundle.message("inspection.redundant.null.check.fix.notnull.family.name");
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiExpression arg = ObjectUtils.tryCast(descriptor.getStartElement(), PsiExpression.class);
if (arg == null) return;
PsiReferenceExpression comparedToNull = ExpressionUtils.getReferenceExpressionFromNullComparison(arg, false);
if (comparedToNull == null) return;
new CommentTracker().replaceAndRestoreComments(arg, comparedToNull);
}
}
public static class RemoveNullCheckFix implements LocalQuickFix {
@Nls
@NotNull
@@ -7,7 +7,7 @@ abstract class ObviousNullCheck {
abstract String getBar();
void test(String param) {
assertNotNull(<warning descr="Redundant null-check: a value of primitive type is never null">5 + 6</warning>);
assertNotNull(<warning descr="Redundant null-check: a value of primitive type 'int' is never null">5 + 6</warning>);
assertNull("Null!", param);
assertNull(param, <warning descr="Null-check will always fail: literal is never null">"Null!"</warning>);
@@ -16,7 +16,7 @@ abstract class ObviousNullCheck {
Objects.requireNonNull(<warning descr="Redundant null-check: literal is never null">"xyz"</warning>, "xyz");
Objects.requireNonNull((<warning descr="Redundant null-check: concatenation is never null">getFoo() + getBar()</warning>));
Objects.requireNonNull(<warning descr="Redundant null-check: newly created object is never null">new ArrayList()</warning>, "new returned null");
Objects.requireNonNull(<warning descr="Redundant null-check: this object is never null">this</warning>);
Objects.requireNonNull(<warning descr="Redundant null-check: 'this' object is never null">this</warning>);
String s = Objects.requireNonNull(<warning descr="Redundant null-check: literal is never null">" x "</warning>);
String s1 = trim(" x ");
@@ -0,0 +1,11 @@
// "Remove erroneous '!= null'" "true"
import java.util.Objects;
public class Test {
void test(String foo) {
Objects.requireNonNull(foo);
}
native int foo();
}
@@ -0,0 +1,11 @@
// "Remove erroneous '!= null'" "true"
import java.util.Objects;
public class Test {
void test(String foo) {
Objects.requireNonNull(foo <caret>!= null);
}
native int foo();
}
@@ -926,6 +926,7 @@ inspection.replace.with.trivial.lambda.fix.name=Replace with lambda returning ''
inspection.redundant.null.check.message=Redundant null-check: {0} is never null
inspection.redundant.null.check.always.fail.message=Null-check will always fail: {0} is never null
inspection.redundant.null.check.fix.family.name=Remove redundant null-check
inspection.redundant.null.check.fix.notnull.family.name=Remove erroneous '!= null'
inspection.comparator.result.comparison.display.name=Suspicious usage of compare method
inspection.comparator.result.comparison.problem.display.name=Comparison of compare method result with specific constant