mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-01 19:02:13 +07:00
make incompatible interface inspection less expensive in the presence of classes with a lot of subclasses
This commit is contained in:
+8
-18
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2007 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.
|
||||
@@ -27,15 +27,13 @@ public class CastToIncompatibleInterfaceInspection extends BaseInspection {
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"casting.to.incompatible.interface.display.name");
|
||||
return InspectionGadgetsBundle.message("casting.to.incompatible.interface.display.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"casting.to.incompatible.interface.problem.descriptor");
|
||||
return InspectionGadgetsBundle.message("casting.to.incompatible.interface.problem.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -43,12 +41,10 @@ public class CastToIncompatibleInterfaceInspection extends BaseInspection {
|
||||
return new CastToIncompatibleInterfaceVisitor();
|
||||
}
|
||||
|
||||
private static class CastToIncompatibleInterfaceVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
private static class CastToIncompatibleInterfaceVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitTypeCastExpression(
|
||||
@NotNull PsiTypeCastExpression expression) {
|
||||
public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) {
|
||||
super.visitTypeCastExpression(expression);
|
||||
final PsiTypeElement castTypeElement = expression.getCastType();
|
||||
if (castTypeElement == null) {
|
||||
@@ -69,20 +65,14 @@ public class CastToIncompatibleInterfaceInspection extends BaseInspection {
|
||||
}
|
||||
final PsiClassType operandClassType = (PsiClassType)operandType;
|
||||
final PsiClass castClass = castClassType.resolve();
|
||||
if (castClass == null) {
|
||||
return;
|
||||
}
|
||||
if (!castClass.isInterface()) {
|
||||
if (castClass == null || !castClass.isInterface()) {
|
||||
return;
|
||||
}
|
||||
final PsiClass operandClass = operandClassType.resolve();
|
||||
if (operandClass == null) {
|
||||
if (operandClass == null || operandClass.isInterface()) {
|
||||
return;
|
||||
}
|
||||
if (operandClass.isInterface()) {
|
||||
return;
|
||||
}
|
||||
if (InheritanceUtil.existsMutualSubclass(operandClass, castClass)) {
|
||||
if (InheritanceUtil.existsMutualSubclass(operandClass, castClass, isOnTheFly())) {
|
||||
return;
|
||||
}
|
||||
registerError(castTypeElement);
|
||||
|
||||
+9
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2007 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.
|
||||
@@ -22,21 +22,18 @@ import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.psiutils.InheritanceUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class InstanceofIncompatibleInterfaceInspection
|
||||
extends BaseInspection {
|
||||
public class InstanceofIncompatibleInterfaceInspection extends BaseInspection {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"instanceof.with.incompatible.interface.display.name");
|
||||
return InspectionGadgetsBundle.message("instanceof.with.incompatible.interface.display.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"instanceof.with.incompatible.interface.problem.descriptor");
|
||||
return InspectionGadgetsBundle.message("instanceof.with.incompatible.interface.problem.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -44,12 +41,10 @@ public class InstanceofIncompatibleInterfaceInspection
|
||||
return new InstanceofIncompatibleInterfaceVisitor();
|
||||
}
|
||||
|
||||
private static class InstanceofIncompatibleInterfaceVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
private static class InstanceofIncompatibleInterfaceVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitInstanceOfExpression(
|
||||
@NotNull PsiInstanceOfExpression expression) {
|
||||
public void visitInstanceOfExpression(@NotNull PsiInstanceOfExpression expression) {
|
||||
super.visitInstanceOfExpression(expression);
|
||||
final PsiTypeElement castTypeElement = expression.getCheckType();
|
||||
if (castTypeElement == null) {
|
||||
@@ -67,20 +62,14 @@ public class InstanceofIncompatibleInterfaceInspection
|
||||
}
|
||||
final PsiClassType operandClassType = (PsiClassType)operandType;
|
||||
final PsiClass castClass = castClassType.resolve();
|
||||
if (castClass == null) {
|
||||
return;
|
||||
}
|
||||
if (!castClass.isInterface()) {
|
||||
if (castClass == null || !castClass.isInterface()) {
|
||||
return;
|
||||
}
|
||||
final PsiClass operandClass = operandClassType.resolve();
|
||||
if (operandClass == null) {
|
||||
if (operandClass == null || operandClass.isInterface()) {
|
||||
return;
|
||||
}
|
||||
if (operandClass.isInterface()) {
|
||||
return;
|
||||
}
|
||||
if (InheritanceUtil.existsMutualSubclass(operandClass, castClass)) {
|
||||
if (InheritanceUtil.existsMutualSubclass(operandClass, castClass, isOnTheFly())) {
|
||||
return;
|
||||
}
|
||||
registerError(castTypeElement);
|
||||
|
||||
+16
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2012 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.
|
||||
@@ -32,18 +32,18 @@ public class InheritanceUtil {
|
||||
|
||||
private InheritanceUtil() {}
|
||||
|
||||
public static boolean existsMutualSubclass(PsiClass class1, final PsiClass class2) {
|
||||
public static boolean existsMutualSubclass(PsiClass class1, final PsiClass class2, final boolean avoidExpensiveProcessing) {
|
||||
if (class1 instanceof PsiTypeParameter) {
|
||||
final PsiClass[] superClasses = class1.getSupers();
|
||||
for (PsiClass superClass : superClasses) {
|
||||
if (!existsMutualSubclass(superClass, class2)) {
|
||||
if (!existsMutualSubclass(superClass, class2, avoidExpensiveProcessing)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (class2 instanceof PsiTypeParameter) {
|
||||
return existsMutualSubclass(class2, class1);
|
||||
return existsMutualSubclass(class2, class1, avoidExpensiveProcessing);
|
||||
}
|
||||
|
||||
final String className = class1.getQualifiedName();
|
||||
@@ -54,18 +54,26 @@ public class InheritanceUtil {
|
||||
if (CommonClassNames.JAVA_LANG_OBJECT.equals(class2Name)) {
|
||||
return true;
|
||||
}
|
||||
if (class1.isInheritor(class2, true) ||
|
||||
class2.isInheritor(class1, true)) {
|
||||
if (class1.isInheritor(class2, true) || class2.isInheritor(class1, true)) {
|
||||
return true;
|
||||
}
|
||||
final SearchScope scope = GlobalSearchScope.allScope(class1.getProject());
|
||||
final Query<PsiClass> search = ClassInheritorsSearch.search(class1, scope, true, true);
|
||||
return !search.forEach(new Processor<PsiClass>() {
|
||||
final boolean[] result = new boolean[1];
|
||||
search.forEach(new Processor<PsiClass>() {
|
||||
int count = 0;
|
||||
|
||||
@Override
|
||||
public boolean process(PsiClass inheritor) {
|
||||
return !inheritor.equals(class2) && !inheritor.isInheritor(class2, true);
|
||||
count++;
|
||||
if (inheritor.equals(class2) || inheritor.isInheritor(class2, true) || (avoidExpensiveProcessing && count > 20)) {
|
||||
result[0] = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return result[0];
|
||||
}
|
||||
|
||||
public static boolean hasImplementation(PsiClass aClass) {
|
||||
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
package com.siyeh.igtest.bugs;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CastToIncompatibleInterfaceInspection {
|
||||
public void foo()
|
||||
{
|
||||
List list = (List) new HashMap();
|
||||
List list2 = (List) new ArrayList();
|
||||
if(new HashMap() instanceof List)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.siyeh.ig.LightInspectionTestCase;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class CastToIncompatibleInterfaceInspectionTest extends LightInspectionTestCase {
|
||||
|
||||
public void testSimple() {
|
||||
doTest("class X { " +
|
||||
" I list = (/*Cast to incompatible interface 'I'*/I/**/) new C(); " +
|
||||
"}" +
|
||||
"interface I {}" +
|
||||
"class C {}");
|
||||
}
|
||||
|
||||
public void testHashMap() {
|
||||
doTest("import java.util.HashMap;" +
|
||||
"import java.util.List;" +
|
||||
"class X {" +
|
||||
" List l = (/*Cast to incompatible interface 'List'*/List/**/) new HashMap();" +
|
||||
"}");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LocalInspectionTool getInspection() {
|
||||
return new CastToIncompatibleInterfaceInspection();
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.siyeh.ig.LightInspectionTestCase;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class InstanceofIncompatibleInterfaceInspectionTest extends LightInspectionTestCase {
|
||||
|
||||
public void testHashMap() {
|
||||
doTest("import java.util.HashMap;" +
|
||||
"import java.util.List;" +
|
||||
"class X {" +
|
||||
" void m() {" +
|
||||
" if(new HashMap() instanceof /*'instanceof' incompatible interface 'List'*/List/**/);" +
|
||||
" }" +
|
||||
"}");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LocalInspectionTool getInspection() {
|
||||
return new InstanceofIncompatibleInterfaceInspection();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user