mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
let "Cast conflicts with instanceof" inspection check MyClass.class.cast(object) constructs (IDEA-20558)
This commit is contained in:
@@ -65,7 +65,7 @@ assignment.used.as.condition.display.name=Assignment used as condition
|
||||
assignment.used.as.condition.problem.descriptor=<code>#ref</code> used as condition #loc
|
||||
assignment.used.as.condition.replace.quickfix=Replace '=' with '=='
|
||||
cast.conflicts.with.instanceof.display.name=Cast conflicts with 'instanceof'
|
||||
cast.conflicts.with.instanceof.problem.descriptor=Cast to <code>#ref</code> conflicts with surrounding 'instanceof' check #loc
|
||||
cast.conflicts.with.instanceof.problem.descriptor=Cast <code>#ref</code> conflicts with surrounding 'instanceof' check #loc
|
||||
casting.to.incompatible.interface.display.name=Casting to incompatible interface
|
||||
casting.to.incompatible.interface.problem.descriptor=Cast to incompatible interface <code>#ref</code> #loc
|
||||
collection.added.to.self.display.name=Collection added to self
|
||||
@@ -1832,8 +1832,8 @@ ignore.instanceof.on.library.classes=Ignore instanceof on library classes
|
||||
assertequals.may.be.assertsame.quickfix=Replace with 'assertSame()'
|
||||
for.can.be.foreach.option=Report indexed 'java.util.List' loops
|
||||
for.can.be.foreach.option2=Do not report iterations over untyped collections
|
||||
cast.conflicts.with.instanceof.quickfix1=Replace cast to ''{0}'' with ''{1}''
|
||||
cast.conflicts.with.instanceof.quickfix2=Replace instanceof ''{0}'' with ''{1}''
|
||||
cast.conflicts.with.instanceof.quickfix1=Replace ''{0}'' with ''{1}'' in cast
|
||||
cast.conflicts.with.instanceof.quickfix2=Replace ''{0}'' with ''{1}'' in instanceof
|
||||
double.checked.locking.quickfix=Make ''{0}'' 'volatile'
|
||||
double.literal.may.be.float.literal.display.name='double' literal cast to 'float' could be 'float' literal
|
||||
double.literal.may.be.float.literal.problem.descriptor=<code>#ref</code> could be replaced with ''{0}'' #loc
|
||||
|
||||
+136
-54
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,20 +39,19 @@ public class CastConflictsWithInstanceofInspection extends BaseInspection {
|
||||
@Override
|
||||
@NotNull
|
||||
public String buildErrorString(Object... infos) {
|
||||
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)infos[0];
|
||||
return InspectionGadgetsBundle.message(
|
||||
"cast.conflicts.with.instanceof.problem.descriptor");
|
||||
"cast.conflicts.with.instanceof.problem.descriptor", referenceExpression.getText());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected InspectionGadgetsFix[] buildFixes(final Object... infos) {
|
||||
final PsiType castExpressionType = (PsiType)infos[0];
|
||||
final PsiInstanceOfExpression conflictingInstanceof =
|
||||
(PsiInstanceOfExpression)infos[1];
|
||||
final PsiTypeElement typeElement = conflictingInstanceof.getCheckType();
|
||||
final String castExpressionType = ((PsiTypeElement)infos[1]).getText();
|
||||
final String instanceofType = ((PsiTypeElement)infos[2]).getText();
|
||||
return new InspectionGadgetsFix[]{
|
||||
new ReplaceCastFix(typeElement, castExpressionType),
|
||||
new ReplaceInstanceofFix(typeElement, castExpressionType)
|
||||
new ReplaceCastFix(instanceofType, castExpressionType),
|
||||
new ReplaceInstanceofFix(instanceofType, castExpressionType)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -65,97 +64,180 @@ public class CastConflictsWithInstanceofInspection extends BaseInspection {
|
||||
extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitTypeCastExpression(
|
||||
@NotNull PsiTypeCastExpression expression) {
|
||||
public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) {
|
||||
super.visitTypeCastExpression(expression);
|
||||
final PsiType castType = expression.getType();
|
||||
final PsiTypeElement castType = expression.getCastType();
|
||||
if (castType == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType type = castType.getType();
|
||||
final PsiExpression operand = expression.getOperand();
|
||||
if (!(operand instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)operand;
|
||||
final PsiInstanceOfExpression conflictingInstanceof =
|
||||
InstanceOfUtils.getConflictingInstanceof(expression);
|
||||
InstanceOfUtils.getConflictingInstanceof(type, referenceExpression, expression);
|
||||
if (conflictingInstanceof == null) {
|
||||
return;
|
||||
}
|
||||
registerError(expression, castType, conflictingInstanceof);
|
||||
final PsiTypeElement instanceofTypeElement = conflictingInstanceof.getCheckType();
|
||||
if (instanceofTypeElement == null) {
|
||||
return;
|
||||
}
|
||||
registerError(expression, referenceExpression, castType, instanceofTypeElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
|
||||
super.visitMethodCallExpression(expression);
|
||||
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
|
||||
final String methodName = methodExpression.getReferenceName();
|
||||
if (!"cast".equals(methodName)) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod method = expression.resolveMethod();
|
||||
if (method == null) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
}
|
||||
final String qualifiedName = containingClass.getQualifiedName();
|
||||
if (!"java.lang.Class".equals(qualifiedName)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
if (!(qualifier instanceof PsiClassObjectAccessExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiClassObjectAccessExpression classObjectAccessExpression = (PsiClassObjectAccessExpression)qualifier;
|
||||
final PsiTypeElement operand = classObjectAccessExpression.getOperand();
|
||||
final PsiType castType = operand.getType();
|
||||
if (!(castType instanceof PsiClassType)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpressionList argumentList = expression.getArgumentList();
|
||||
final PsiExpression[] arguments = argumentList.getExpressions();
|
||||
if (arguments.length != 1) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression argument = arguments[0];
|
||||
if (!(argument instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)argument;
|
||||
final PsiInstanceOfExpression conflictingInstanceof =
|
||||
InstanceOfUtils.getConflictingInstanceof(castType, referenceExpression, expression);
|
||||
if (conflictingInstanceof == null) {
|
||||
return;
|
||||
}
|
||||
final PsiTypeElement instanceofTypeElement = conflictingInstanceof.getCheckType();
|
||||
registerError(expression, referenceExpression, operand, instanceofTypeElement);
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class ReplaceFix extends InspectionGadgetsFix {
|
||||
|
||||
protected final PsiTypeElement myInstanceofTypeElement;
|
||||
protected final PsiType myCastType;
|
||||
|
||||
protected ReplaceFix(@NotNull PsiTypeElement instanceofTypeElement,
|
||||
@NotNull PsiType castType) {
|
||||
myInstanceofTypeElement = instanceofTypeElement;
|
||||
myCastType = castType;
|
||||
protected ReplaceFix() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFix(Project project, ProblemDescriptor descriptor)
|
||||
throws IncorrectOperationException {
|
||||
final PsiTypeCastExpression typeCastExpression =
|
||||
(PsiTypeCastExpression)descriptor.getPsiElement();
|
||||
final PsiTypeElement castTypeElement =
|
||||
typeCastExpression.getCastType();
|
||||
if (castTypeElement == null) {
|
||||
protected final void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
final PsiTypeElement castTypeElement;
|
||||
final PsiTypeElement instanceofTypeElement;
|
||||
if (element instanceof PsiTypeCastExpression) {
|
||||
final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression)element;
|
||||
final PsiExpression operand = typeCastExpression.getOperand();
|
||||
if (!(operand instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
}
|
||||
castTypeElement = typeCastExpression.getCastType();
|
||||
if (castTypeElement == null) {
|
||||
return;
|
||||
}
|
||||
final PsiInstanceOfExpression conflictingInstanceof =
|
||||
InstanceOfUtils.getConflictingInstanceof(castTypeElement.getType(), (PsiReferenceExpression)operand, element);
|
||||
instanceofTypeElement = conflictingInstanceof.getCheckType();
|
||||
if (instanceofTypeElement == null) {
|
||||
return;
|
||||
}
|
||||
castTypeElement.replace(instanceofTypeElement);
|
||||
} else if (element instanceof PsiMethodCallExpression) {
|
||||
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)element;
|
||||
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
if (!(qualifier instanceof PsiClassObjectAccessExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiClassObjectAccessExpression classObjectAccessExpression = (PsiClassObjectAccessExpression)qualifier;
|
||||
castTypeElement = classObjectAccessExpression.getOperand();
|
||||
final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
|
||||
final PsiExpression[] arguments = argumentList.getExpressions();
|
||||
if (arguments.length != 1) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression argument = arguments[0];
|
||||
if (!(argument instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiInstanceOfExpression conflictingInstanceof =
|
||||
InstanceOfUtils.getConflictingInstanceof(castTypeElement.getType(), (PsiReferenceExpression)argument, element);
|
||||
instanceofTypeElement = conflictingInstanceof.getCheckType();
|
||||
if (instanceofTypeElement == null) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
final PsiElement newElement =
|
||||
replace(castTypeElement, myInstanceofTypeElement, project);
|
||||
final JavaCodeStyleManager codeStyleManager =
|
||||
JavaCodeStyleManager.getInstance(project);
|
||||
final PsiElement newElement = replace(castTypeElement, instanceofTypeElement);
|
||||
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
|
||||
codeStyleManager.shortenClassReferences(newElement);
|
||||
}
|
||||
|
||||
protected abstract PsiElement replace(PsiTypeElement castTypeElement,
|
||||
PsiTypeElement instanceofTypeElement,
|
||||
Project project);
|
||||
protected abstract PsiElement replace(PsiTypeElement castTypeElement, PsiTypeElement instanceofTypeElement);
|
||||
}
|
||||
|
||||
private static class ReplaceCastFix extends ReplaceFix {
|
||||
|
||||
public ReplaceCastFix(PsiTypeElement instanceofTypeElement,
|
||||
PsiType castType) {
|
||||
super(instanceofTypeElement, castType);
|
||||
private String myInstanceofType;
|
||||
private String myCastType;
|
||||
|
||||
public ReplaceCastFix(String instanceofType, String castType) {
|
||||
myInstanceofType = instanceofType;
|
||||
myCastType = castType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"cast.conflicts.with.instanceof.quickfix1",
|
||||
myCastType.getPresentableText(),
|
||||
myInstanceofTypeElement.getType().getPresentableText());
|
||||
return InspectionGadgetsBundle.message("cast.conflicts.with.instanceof.quickfix1", myCastType, myInstanceofType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PsiElement replace(PsiTypeElement castTypeElement,
|
||||
PsiTypeElement instanceofTypeElement,
|
||||
Project project) {
|
||||
protected PsiElement replace(PsiTypeElement castTypeElement, PsiTypeElement instanceofTypeElement) {
|
||||
return castTypeElement.replace(instanceofTypeElement);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ReplaceInstanceofFix extends ReplaceFix {
|
||||
|
||||
public ReplaceInstanceofFix(PsiTypeElement instanceofTypeElement,
|
||||
PsiType castExpressionType) {
|
||||
super(instanceofTypeElement, castExpressionType);
|
||||
private final String myInstanceofType;
|
||||
private final String myCastType;
|
||||
|
||||
public ReplaceInstanceofFix(String instanceofType, String castType) {
|
||||
myInstanceofType = instanceofType;
|
||||
myCastType = castType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"cast.conflicts.with.instanceof.quickfix2",
|
||||
myInstanceofTypeElement.getType().getPresentableText(),
|
||||
myCastType.getPresentableText());
|
||||
return InspectionGadgetsBundle.message("cast.conflicts.with.instanceof.quickfix2", myInstanceofType, myCastType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PsiElement replace(PsiTypeElement castTypeElement,
|
||||
PsiTypeElement instanceofTypeElement,
|
||||
Project project) {
|
||||
protected PsiElement replace(PsiTypeElement castTypeElement, PsiTypeElement instanceofTypeElement) {
|
||||
return instanceofTypeElement.replace(castTypeElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2007-2010 Bas Leijdekkers
|
||||
* Copyright 2007-2011 Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,40 +20,26 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class InstanceOfUtils {
|
||||
|
||||
private InstanceOfUtils() {
|
||||
}
|
||||
private InstanceOfUtils() {}
|
||||
|
||||
@Nullable
|
||||
public static PsiInstanceOfExpression getConflictingInstanceof(@NotNull PsiTypeCastExpression expression) {
|
||||
final PsiType castType = expression.getType();
|
||||
public static PsiInstanceOfExpression getConflictingInstanceof(PsiType castType, PsiReferenceExpression operand, PsiElement context) {
|
||||
if (!(castType instanceof PsiClassType)) {
|
||||
return null;
|
||||
}
|
||||
final PsiClassType classType = (PsiClassType)castType;
|
||||
final PsiClassType rawType = classType.rawType();
|
||||
final PsiExpression operand = expression.getOperand();
|
||||
if (!(operand instanceof PsiReferenceExpression)) {
|
||||
return null;
|
||||
}
|
||||
final PsiReferenceExpression referenceExpression =
|
||||
(PsiReferenceExpression)operand;
|
||||
final InstanceofChecker checker = new InstanceofChecker(
|
||||
referenceExpression, rawType, false);
|
||||
PsiElement parent = PsiTreeUtil.getParentOfType(expression,
|
||||
PsiIfStatement.class,
|
||||
PsiConditionalExpression.class,
|
||||
PsiPolyadicExpression.class);
|
||||
final InstanceofChecker checker = new InstanceofChecker(operand, rawType, false);
|
||||
PsiElement parent = PsiTreeUtil.getParentOfType(context, PsiIfStatement.class, PsiConditionalExpression.class,
|
||||
PsiPolyadicExpression.class);
|
||||
while (parent != null) {
|
||||
parent.accept(checker);
|
||||
if (checker.hasAgreeingInstanceof()) {
|
||||
return null;
|
||||
}
|
||||
parent = PsiTreeUtil.getParentOfType(parent,
|
||||
PsiPolyadicExpression.class, PsiIfStatement.class,
|
||||
parent = PsiTreeUtil.getParentOfType(parent, PsiPolyadicExpression.class, PsiIfStatement.class,
|
||||
PsiConditionalExpression.class);
|
||||
}
|
||||
if (checker.hasAgreeingInstanceof()) {
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
<problem>
|
||||
<file>ElseElse.java</file>
|
||||
<line>26</line>
|
||||
<description>Cast to <code>(B)o</code> conflicts with surrounding 'instanceof' check #loc</description>
|
||||
<description>Cast <code>(B)o</code> conflicts with surrounding 'instanceof' check #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
|
||||
+2
-2
@@ -30,11 +30,11 @@ public class CastConflictsWithInstanceofFixesTest extends IGQuickFixesTestCase {
|
||||
}
|
||||
|
||||
public void testReplaceCastInDeclaration() {
|
||||
doTest("replaceCastInDeclaration", "Replace cast");
|
||||
doTest("replaceCastInDeclaration", "Replace 'Integer' with 'String' in cast");
|
||||
}
|
||||
|
||||
public void testReplaceInstanceOf() {
|
||||
doTest("replaceInstanceOf", "Replace instanceof");
|
||||
doTest("replaceInstanceOf", "Replace 'String' with 'Integer' in instanceof");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user