mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-111465 ("Overly-strong type cast" inspection false negative in foreach)
This commit is contained in:
+2
-2
@@ -27,8 +27,8 @@ magic.number.problem.descriptor=Magic number <code>#ref</code> #loc
|
||||
magic.number.ignore.option=Ignore constants in 'hashCode()' methods
|
||||
method.return.concrete.class.display.name=Method return of concrete class
|
||||
method.return.concrete.class.problem.descriptor=Method returns a concrete class <code>#ref</code> #loc
|
||||
overly.strong.type.cast.display.name=Overly-strong type cast
|
||||
overly.strong.type.cast.weaken.quickfix=Weaken overly-strong cast
|
||||
overly.strong.type.cast.display.name=Overly strong type cast
|
||||
overly.strong.type.cast.weaken.quickfix=Weaken overly strong cast
|
||||
concrete.class.method.parameter.display.name=Method parameter of concrete class
|
||||
concrete.class.method.parameter.problem.descriptor=Parameter ''{0}'' of concrete class <code>#ref</code> #loc
|
||||
public.method.not.in.interface.display.name='public' method not exposed in interface
|
||||
|
||||
+20
-42
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2013 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.
|
||||
@@ -20,7 +20,6 @@ import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
@@ -41,8 +40,7 @@ public class OverlyStrongTypeCastInspection extends BaseInspection {
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"overly.strong.type.cast.display.name");
|
||||
return InspectionGadgetsBundle.message("overly.strong.type.cast.display.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,17 +48,14 @@ public class OverlyStrongTypeCastInspection extends BaseInspection {
|
||||
protected String buildErrorString(Object... infos) {
|
||||
final PsiType expectedType = (PsiType)infos[0];
|
||||
final String typeText = expectedType.getPresentableText();
|
||||
return InspectionGadgetsBundle.message(
|
||||
"overly.strong.type.cast.problem.descriptor", typeText);
|
||||
return InspectionGadgetsBundle.message("overly.strong.type.cast.problem.descriptor", typeText);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JComponent createOptionsPanel() {
|
||||
return new SingleCheckboxOptionsPanel(
|
||||
InspectionGadgetsBundle.message(
|
||||
"overly.strong.type.cast.ignore.in.matching.instanceof.option"),
|
||||
this, "ignoreInMatchingInstanceof");
|
||||
return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("overly.strong.type.cast.ignore.in.matching.instanceof.option"),
|
||||
this, "ignoreInMatchingInstanceof");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,21 +68,17 @@ public class OverlyStrongTypeCastInspection extends BaseInspection {
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"overly.strong.type.cast.weaken.quickfix");
|
||||
return InspectionGadgetsBundle.message("overly.strong.type.cast.weaken.quickfix");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFix(Project project, ProblemDescriptor descriptor)
|
||||
throws IncorrectOperationException {
|
||||
public void doFix(Project project, ProblemDescriptor descriptor) {
|
||||
final PsiElement castTypeElement = descriptor.getPsiElement();
|
||||
final PsiTypeCastExpression expression =
|
||||
(PsiTypeCastExpression)castTypeElement.getParent();
|
||||
final PsiTypeCastExpression expression = (PsiTypeCastExpression)castTypeElement.getParent();
|
||||
if (expression == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType expectedType =
|
||||
ExpectedTypeUtils.findExpectedType(expression, true);
|
||||
final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, true);
|
||||
if (expectedType == null) {
|
||||
return;
|
||||
}
|
||||
@@ -96,9 +87,7 @@ public class OverlyStrongTypeCastInspection extends BaseInspection {
|
||||
return;
|
||||
}
|
||||
@NonNls
|
||||
final String newExpression =
|
||||
'(' + expectedType.getCanonicalText() + ')' +
|
||||
operand.getText();
|
||||
final String newExpression = '(' + expectedType.getCanonicalText() + ')' + operand.getText();
|
||||
replaceExpressionAndShorten(expression, newExpression);
|
||||
}
|
||||
}
|
||||
@@ -108,12 +97,10 @@ public class OverlyStrongTypeCastInspection extends BaseInspection {
|
||||
return new OverlyStrongTypeCastVisitor();
|
||||
}
|
||||
|
||||
private class OverlyStrongTypeCastVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
private class OverlyStrongTypeCastVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitTypeCastExpression(
|
||||
@NotNull PsiTypeCastExpression expression) {
|
||||
public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) {
|
||||
super.visitTypeCastExpression(expression);
|
||||
final PsiExpression operand = expression.getOperand();
|
||||
if (operand == null) {
|
||||
@@ -127,8 +114,7 @@ public class OverlyStrongTypeCastInspection extends BaseInspection {
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType expectedType =
|
||||
ExpectedTypeUtils.findExpectedType(expression, true);
|
||||
final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, true);
|
||||
if (expectedType == null) {
|
||||
return;
|
||||
}
|
||||
@@ -140,7 +126,7 @@ public class OverlyStrongTypeCastInspection extends BaseInspection {
|
||||
return;
|
||||
}
|
||||
if (expectedType.isAssignableFrom(operandType)) {
|
||||
//then it's redundant, and caught by the built-in exception
|
||||
//then it's redundant, and caught by the built-in inspection
|
||||
return;
|
||||
}
|
||||
if (isTypeParameter(expectedType)) {
|
||||
@@ -153,19 +139,15 @@ public class OverlyStrongTypeCastInspection extends BaseInspection {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (type instanceof PsiPrimitiveType ||
|
||||
expectedType instanceof PsiPrimitiveType) {
|
||||
if (type instanceof PsiPrimitiveType || expectedType instanceof PsiPrimitiveType) {
|
||||
return;
|
||||
}
|
||||
if (PsiPrimitiveType.getUnboxedType(type) != null ||
|
||||
PsiPrimitiveType.getUnboxedType(expectedType) != null) {
|
||||
if (PsiPrimitiveType.getUnboxedType(type) != null || PsiPrimitiveType.getUnboxedType(expectedType) != null) {
|
||||
return;
|
||||
}
|
||||
if (expectedType instanceof PsiClassType) {
|
||||
final PsiClassType expectedClassType =
|
||||
(PsiClassType)expectedType;
|
||||
final PsiClassType expectedRawType =
|
||||
expectedClassType.rawType();
|
||||
final PsiClassType expectedClassType = (PsiClassType)expectedType;
|
||||
final PsiClassType expectedRawType = expectedClassType.rawType();
|
||||
if (type.equals(expectedRawType)) {
|
||||
return;
|
||||
}
|
||||
@@ -180,8 +162,7 @@ public class OverlyStrongTypeCastInspection extends BaseInspection {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ignoreInMatchingInstanceof &&
|
||||
InstanceOfUtils.hasAgreeingInstanceof(expression)) {
|
||||
if (ignoreInMatchingInstanceof && InstanceOfUtils.hasAgreeingInstanceof(expression)) {
|
||||
return;
|
||||
}
|
||||
final PsiTypeElement castTypeElement = expression.getCastType();
|
||||
@@ -197,10 +178,7 @@ public class OverlyStrongTypeCastInspection extends BaseInspection {
|
||||
}
|
||||
final PsiClassType classType = (PsiClassType)type;
|
||||
final PsiClass aClass = classType.resolve();
|
||||
if (aClass == null) {
|
||||
return false;
|
||||
}
|
||||
return aClass instanceof PsiTypeParameter;
|
||||
return aClass != null && aClass instanceof PsiTypeParameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -278,6 +278,29 @@ public class ExpectedTypeUtils {
|
||||
expectedType = PsiType.BOOLEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitForeachStatement(PsiForeachStatement statement) {
|
||||
final PsiExpression iteratedValue = statement.getIteratedValue();
|
||||
if (iteratedValue == null) {
|
||||
expectedType = null;
|
||||
return;
|
||||
}
|
||||
final PsiType iteratedValueType = iteratedValue.getType();
|
||||
if (!(iteratedValueType instanceof PsiClassType)) {
|
||||
expectedType = null;
|
||||
return;
|
||||
}
|
||||
final PsiClassType classType = (PsiClassType)iteratedValueType;
|
||||
final PsiType[] parameters = classType.getParameters();
|
||||
final PsiClass iterableClass = ClassUtils.findClass(CommonClassNames.JAVA_LANG_ITERABLE, statement);
|
||||
if (iterableClass == null) {
|
||||
expectedType = null;
|
||||
}
|
||||
else {
|
||||
expectedType = JavaPsiFacade.getElementFactory(statement.getProject()).createType(iterableClass, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIfStatement(@NotNull PsiIfStatement statement) {
|
||||
expectedType = PsiType.BOOLEAN;
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.siyeh.igtest.abstraction;
|
||||
|
||||
import com.siyeh.igtest.abstraction2.SuperClass2;
|
||||
|
||||
public class CastWeakenTest extends SuperClass2 {
|
||||
public static void main(String[] args) {
|
||||
Object a = new CastWeakenTest();
|
||||
((CastWeakenTest)a).getHandle();
|
||||
}
|
||||
|
||||
protected Object getHandle() {
|
||||
return super.getHandle();
|
||||
}
|
||||
}
|
||||
+28
-22
@@ -1,23 +1,28 @@
|
||||
package com.siyeh.igtest.abstraction;
|
||||
|
||||
import com.siyeh.igtest.abstraction2.SubClass;
|
||||
import com.siyeh.igtest.abstraction2.SuperClass;
|
||||
import com.siyeh.igtest.abstraction2.SubClass2;
|
||||
package com.siyeh.igtest.abstraction.overly_strong_type_cast;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.AbstractList;
|
||||
import java.lang.reflect.Array;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
interface TestInter{}
|
||||
|
||||
public class OverlyStrongTypeCastInspection
|
||||
public class OverlyStrongTypeCast
|
||||
{
|
||||
void iterate(Object o) {
|
||||
for (Object object : (ArrayList) o) {}
|
||||
for (String s : (ArrayList<String>) o) {}
|
||||
}
|
||||
|
||||
void optional(Object foo) {
|
||||
if (foo instanceof OverlyStrongTypeCastInspection) {
|
||||
((OverlyStrongTypeCastInspection)foo).hashCode();
|
||||
if (foo instanceof SubClass2) {
|
||||
((SubClass2)foo).doSmth();
|
||||
}
|
||||
((SubClass2)foo).doSmth();
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
@@ -47,15 +52,16 @@ public class OverlyStrongTypeCastInspection
|
||||
((SubClass2)testSub).doSmth();
|
||||
}
|
||||
}
|
||||
interface Task<T extends Serializable> extends Serializable {}
|
||||
interface ConcreteTask<T extends Serializable> extends Task<T> {
|
||||
void aMethod();
|
||||
class SuperClass{
|
||||
protected void doSmth(){
|
||||
}
|
||||
}
|
||||
class SubClass extends SuperClass{
|
||||
public void doSmth(){
|
||||
}
|
||||
}
|
||||
class SubClass2 extends SubClass{
|
||||
public void doSmth(){
|
||||
super.doSmth();
|
||||
}
|
||||
}
|
||||
class Test {
|
||||
public void main(String[] argv) {
|
||||
Task<?> t = new Task<String>() {};
|
||||
if (t instanceof ConcreteTask)
|
||||
// We get a warning here that the cast can be weakened to "ConcreteTask<? extends Serializable>".
|
||||
((ConcreteTask<? extends String>)t).aMethod();
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>OverlyStrongTypeCast.java</file>
|
||||
<line>17</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Overly strong type cast</problem_class>
|
||||
<description>Cast to <code>ArrayList</code> can be weakened to 'Iterable' #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>OverlyStrongTypeCast.java</file>
|
||||
<line>18</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Overly strong type cast</problem_class>
|
||||
<description>Cast to <code>ArrayList<String></code> can be weakened to 'Iterable<String>' #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>OverlyStrongTypeCast.java</file>
|
||||
<line>25</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Overly strong type cast</problem_class>
|
||||
<description>Cast to <code>SubClass2</code> can be weakened to 'SuperClass' #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>OverlyStrongTypeCast.java</file>
|
||||
<line>31</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Overly strong type cast</problem_class>
|
||||
<description>Cast to <code>ArrayList</code> can be weakened to 'AbstractList' #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.siyeh.igtest.abstraction2;
|
||||
|
||||
public class SubClass extends SuperClass{
|
||||
public void doSmth(){
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.siyeh.igtest.abstraction2;
|
||||
|
||||
|
||||
public class SubClass2 extends SubClass{
|
||||
public void doSmth(){
|
||||
super.doSmth();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.siyeh.igtest.abstraction2;
|
||||
|
||||
public class SuperClass{
|
||||
protected void doSmth(){
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.siyeh.igtest.abstraction2;
|
||||
|
||||
public class SuperClass2 {
|
||||
protected Object getHandle() {
|
||||
return null;
|
||||
};
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.siyeh.ig.IGInspectionTestCase;
|
||||
|
||||
public class OverlyStrongTypeCastInspectionTest extends IGInspectionTestCase {
|
||||
|
||||
public void test() throws Exception {
|
||||
final OverlyStrongTypeCastInspection tool = new OverlyStrongTypeCastInspection();
|
||||
tool.ignoreInMatchingInstanceof = true;
|
||||
doTest("com/siyeh/igtest/abstraction/overly_strong_type_cast", tool);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user