mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
java redundant cast: option to ignore casts for suspicious varargs (IDEA-221139)
GitOrigin-RevId: e6a4712ddf0f3c9c5d52a9577bcff0fe14b2eefb
This commit is contained in:
committed by
intellij-monorepo-bot
parent
49ab34989f
commit
bca8fc49fa
@@ -173,6 +173,7 @@ exports.to.itself.delete.statement.fix=Delete directive
|
||||
html.classes.exposed.with.code.module.info.code.html=<html>Classes exposed with <code>module-info</code></html>
|
||||
html.ignore.overrides.of.deprecated.abstract.methods=<html>Ignore overrides of deprecated abstract methods from non-deprecated supers</html>
|
||||
ignore.casts.in.suspicious.collections.method.calls=Ignore casts in suspicious collections method calls
|
||||
ignore.casts.in.suspicious.varargs.method.calls=Ignore casts in suspicious varargs method calls
|
||||
ignore.exceptions.thrown.by.entry.points.methods=Ignore exceptions thrown by entry points methods
|
||||
ignore.in.the.same.outermost.class=Ignore in the same outermost class
|
||||
ignore.inside.deprecated.members=Ignore inside deprecated members
|
||||
|
||||
+12
-10
@@ -7,12 +7,12 @@ import com.intellij.codeInspection.miscGenerics.SuspiciousMethodCallUtil;
|
||||
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
|
||||
import com.intellij.java.analysis.JavaAnalysisBundle;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiExpressionTrimRenderer;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.RedundantCastUtil;
|
||||
import org.jdom.Element;
|
||||
import com.siyeh.ig.bugs.NullArgumentToVariableArgMethodInspection;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -26,7 +26,7 @@ public class RedundantCastInspection extends GenericsInspectionToolBase {
|
||||
@NonNls private static final String SHORT_NAME = "RedundantCast";
|
||||
|
||||
public boolean IGNORE_SUSPICIOUS_METHOD_CALLS;
|
||||
|
||||
public boolean IGNORE_SUSPICIOUS_VARARG_METHOD_CALLS = true;
|
||||
|
||||
public RedundantCastInspection() {
|
||||
myQuickFixAction = new AcceptSuggested();
|
||||
@@ -52,17 +52,11 @@ public class RedundantCastInspection extends GenericsInspectionToolBase {
|
||||
return getDescriptions(field, manager, isOnTheFly);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSettings(@NotNull Element node) throws WriteExternalException {
|
||||
if (IGNORE_SUSPICIOUS_METHOD_CALLS) {
|
||||
super.writeSettings(node);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent createOptionsPanel() {
|
||||
final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this);
|
||||
optionsPanel.addCheckbox(JavaAnalysisBundle.message("ignore.casts.in.suspicious.collections.method.calls"), "IGNORE_SUSPICIOUS_METHOD_CALLS");
|
||||
optionsPanel.addCheckbox(JavaAnalysisBundle.message("ignore.casts.in.suspicious.varargs.method.calls"), "IGNORE_SUSPICIOUS_VARARG_METHOD_CALLS");
|
||||
return optionsPanel;
|
||||
}
|
||||
|
||||
@@ -81,6 +75,14 @@ public class RedundantCastInspection extends GenericsInspectionToolBase {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (gParent instanceof PsiCallExpression && IGNORE_SUSPICIOUS_VARARG_METHOD_CALLS) {
|
||||
PsiExpressionList expressionList = (PsiExpressionList)parent;
|
||||
if (PsiTreeUtil.isAncestor(expressionList.getExpressions()[expressionList.getExpressionCount() - 1], operand, true) &&
|
||||
NullArgumentToVariableArgMethodInspection.isSuspiciousVararg((PsiCallExpression)gParent, operand.getType())) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String message = JavaAnalysisBundle.message("inspection.redundant.cast.problem.descriptor",
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
class MyTest {
|
||||
void v(Object... objects) { }
|
||||
void v(String... objects) { }
|
||||
|
||||
void m(String[] values){
|
||||
v((Object[]) values);
|
||||
v((Object[]) null);
|
||||
|
||||
v((<warning descr="Casting 'values' to 'String[]' is redundant">String[]</warning>) values);
|
||||
v((String[]) null);
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,7 @@ public class RedundantCast15Test extends LightJavaCodeInsightFixtureTestCase {
|
||||
myFixture.testHighlighting(getTestName(false) + ".java");
|
||||
}
|
||||
public void testDifferentNullness() { doTest();}
|
||||
public void testSuspiciousVarargsCall() { doTest();}
|
||||
|
||||
public void testPrimitiveWidening() { doTest(); }
|
||||
public void testCastLongLiteral() { doTest(); }
|
||||
|
||||
+58
-37
@@ -73,6 +73,16 @@ public class NullArgumentToVariableArgMethodInspection extends BaseInspection {
|
||||
return new NullArgumentToVariableArgVisitor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if it's unclear from the first glance if a method is called as varargs or not
|
||||
*
|
||||
* @return true iff {@code call} is varargs method call and {@code lastArgumentType} is {@code null} type or array type,
|
||||
* which is assignable from vararg parameter component type
|
||||
*/
|
||||
public static boolean isSuspiciousVararg(PsiCall call, PsiType lastArgumentType) {
|
||||
return NullArgumentToVariableArgVisitor.getSuspiciousVarargType(call, lastArgumentType) != null;
|
||||
}
|
||||
|
||||
private static class NullArgumentToVariableArgVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
@@ -87,6 +97,50 @@ public class NullArgumentToVariableArgMethodInspection extends BaseInspection {
|
||||
visitCall(call);
|
||||
}
|
||||
|
||||
private static PsiArrayType getSuspiciousVarargType(PsiCall call, PsiType type) {
|
||||
final boolean checkArray;
|
||||
if (PsiType.NULL.equals(type)) {
|
||||
checkArray = false;
|
||||
}
|
||||
else if (type instanceof PsiArrayType) {
|
||||
checkArray = true;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
final PsiMethod method = call.resolveMethod();
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
PsiExpressionList argumentList = call.getArgumentList();
|
||||
if (argumentList == null || parameterList.getParametersCount() != argumentList.getExpressionCount()) {
|
||||
return null;
|
||||
}
|
||||
final PsiParameter[] parameters = parameterList.getParameters();
|
||||
final PsiParameter lastParameter = parameters[parameters.length - 1];
|
||||
if (!lastParameter.isVarArgs()) {
|
||||
return null;
|
||||
}
|
||||
final PsiType type1 = lastParameter.getType();
|
||||
if (!(type1 instanceof PsiEllipsisType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiEllipsisType ellipsisType = (PsiEllipsisType)type1;
|
||||
final PsiArrayType arrayType = (PsiArrayType)ellipsisType.toArrayType();
|
||||
final PsiType componentType = arrayType.getComponentType();
|
||||
if (checkArray) {
|
||||
if (!componentType.equals(TypeUtils.getObjectType(call))) {
|
||||
return null;
|
||||
}
|
||||
if (type.isAssignableFrom(arrayType) || !arrayType.isAssignableFrom(type)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return arrayType;
|
||||
}
|
||||
|
||||
private void visitCall(PsiCall call) {
|
||||
final PsiExpressionList argumentList = call.getArgumentList();
|
||||
if (argumentList == null) {
|
||||
@@ -98,45 +152,12 @@ public class NullArgumentToVariableArgMethodInspection extends BaseInspection {
|
||||
}
|
||||
final PsiExpression lastArgument = arguments[arguments.length - 1];
|
||||
final PsiType type = lastArgument.getType();
|
||||
final boolean checkArray;
|
||||
if (PsiType.NULL.equals(type)) {
|
||||
checkArray = false;
|
||||
}
|
||||
else if (type instanceof PsiArrayType) {
|
||||
checkArray = true;
|
||||
}
|
||||
else {
|
||||
|
||||
PsiArrayType arrayType = getSuspiciousVarargType(call, type);
|
||||
if (arrayType == null) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod method = call.resolveMethod();
|
||||
if (method == null) {
|
||||
return;
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList.getParametersCount() != arguments.length) {
|
||||
return;
|
||||
}
|
||||
final PsiParameter[] parameters = parameterList.getParameters();
|
||||
final PsiParameter lastParameter = parameters[parameters.length - 1];
|
||||
if (!lastParameter.isVarArgs()) {
|
||||
return;
|
||||
}
|
||||
final PsiType type1 = lastParameter.getType();
|
||||
if (!(type1 instanceof PsiEllipsisType)) {
|
||||
return;
|
||||
}
|
||||
final PsiEllipsisType ellipsisType = (PsiEllipsisType)type1;
|
||||
final PsiType arrayType = ellipsisType.toArrayType();
|
||||
final PsiType componentType = ellipsisType.getComponentType();
|
||||
if (checkArray) {
|
||||
if (!componentType.equals(TypeUtils.getObjectType(call))) {
|
||||
return;
|
||||
}
|
||||
if (type.isAssignableFrom(arrayType) || !arrayType.isAssignableFrom(type)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
registerError(lastArgument, lastArgument, componentType, arrayType);
|
||||
registerError(lastArgument, lastArgument, arrayType.getComponentType(), arrayType);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user