diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index ee706e51a0ea..02915a529fc5 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -65,7 +65,7 @@ assignment.used.as.condition.display.name=Assignment used as condition assignment.used.as.condition.problem.descriptor=#ref 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 #ref conflicts with surrounding 'instanceof' check #loc +cast.conflicts.with.instanceof.problem.descriptor=Cast #ref 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 #ref #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=#ref could be replaced with ''{0}'' #loc diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspection.java index af49558bf241..b578163551a2 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspection.java @@ -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); } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/InstanceOfUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/InstanceOfUtils.java index 88621e47ed8e..68eaa0c19b66 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/InstanceOfUtils.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/InstanceOfUtils.java @@ -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()) { diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/simple/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/simple/expected.xml index c81a83943265..296b4dd3fe90 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/simple/expected.xml +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/simple/expected.xml @@ -3,6 +3,6 @@ ElseElse.java 26 - Cast to <code>(B)o</code> conflicts with surrounding 'instanceof' check #loc + Cast <code>(B)o</code> conflicts with surrounding 'instanceof' check #loc diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/bugs/CastConflictsWithInstanceofFixesTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/bugs/CastConflictsWithInstanceofFixesTest.java index 0bc1fa542875..17d6b2cff66a 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/bugs/CastConflictsWithInstanceofFixesTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/bugs/CastConflictsWithInstanceofFixesTest.java @@ -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