mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IG: warn on '==' if no common subclass is found (IDEA-178449)
This commit is contained in:
+52
-25
@@ -16,10 +16,8 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReferenceExpression;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
@@ -76,27 +74,56 @@ public class EqualsBetweenInconvertibleTypesInspection extends BaseInspection {
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new BaseEqualsVisitor() {
|
||||
void checkTypes(@NotNull PsiReferenceExpression expression, @NotNull PsiType leftType, @NotNull PsiType rightType) {
|
||||
boolean convertible = TypeUtils.areConvertible(leftType, rightType);
|
||||
if (convertible) {
|
||||
if (!WARN_IF_NO_MUTUAL_SUBCLASS_FOUND) return;
|
||||
if (leftType.isAssignableFrom(rightType) || rightType.isAssignableFrom(leftType)) return;
|
||||
PsiClass leftClass = PsiUtil.resolveClassInClassTypeOnly(leftType);
|
||||
PsiClass rightClass = PsiUtil.resolveClassInClassTypeOnly(rightType);
|
||||
if (leftClass == null || rightClass == null) return;
|
||||
if (!leftClass.isInterface() && !rightClass.isInterface()) return;
|
||||
if (!rightClass.isInterface()) {
|
||||
PsiClass tmp = leftClass;
|
||||
leftClass = rightClass;
|
||||
rightClass = tmp;
|
||||
}
|
||||
if (InheritanceUtil.existsMutualSubclass(leftClass, rightClass, isOnTheFly())) return;
|
||||
}
|
||||
if (TypeUtils.mayBeEqualByContract(leftType, rightType)) return;
|
||||
PsiElement name = expression.getReferenceNameElement();
|
||||
registerError(name == null ? expression : name, leftType, rightType, convertible);
|
||||
return new EqualsBetweenInconvertibleTypesVisitor();
|
||||
}
|
||||
|
||||
private class EqualsBetweenInconvertibleTypesVisitor extends BaseEqualsVisitor {
|
||||
|
||||
@Override
|
||||
public void visitBinaryExpression(PsiBinaryExpression expression) {
|
||||
super.visitBinaryExpression(expression);
|
||||
if (!WARN_IF_NO_MUTUAL_SUBCLASS_FOUND) return;
|
||||
final IElementType tokenType = expression.getOperationTokenType();
|
||||
if (!tokenType.equals(JavaTokenType.EQEQ) && !tokenType.equals(JavaTokenType.NE)) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
final PsiExpression lhs = expression.getLOperand();
|
||||
final PsiType lhsType = lhs.getType();
|
||||
final PsiExpression rhs = expression.getROperand();
|
||||
if (rhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType rhsType = rhs.getType();
|
||||
if (lhsType == null || rhsType == null || !TypeUtils.areConvertible(lhsType, rhsType)) {
|
||||
// red code
|
||||
return;
|
||||
}
|
||||
if (existsSharedSubclass(lhsType, rhsType)) {
|
||||
return;
|
||||
}
|
||||
registerError(expression.getOperationSign(), lhsType, rhsType, true);
|
||||
}
|
||||
|
||||
void checkTypes(@NotNull PsiReferenceExpression expression, @NotNull PsiType leftType, @NotNull PsiType rightType) {
|
||||
boolean convertible = TypeUtils.areConvertible(leftType, rightType);
|
||||
if (convertible && (!WARN_IF_NO_MUTUAL_SUBCLASS_FOUND || existsSharedSubclass(leftType, rightType))) return;
|
||||
if (TypeUtils.mayBeEqualByContract(leftType, rightType)) return;
|
||||
PsiElement name = expression.getReferenceNameElement();
|
||||
registerError(name == null ? expression : name, leftType, rightType, convertible);
|
||||
}
|
||||
|
||||
private boolean existsSharedSubclass(@NotNull PsiType leftType, @NotNull PsiType rightType) {
|
||||
if (leftType.isAssignableFrom(rightType) || rightType.isAssignableFrom(leftType)) return true;
|
||||
PsiClass leftClass = PsiUtil.resolveClassInClassTypeOnly(leftType);
|
||||
PsiClass rightClass = PsiUtil.resolveClassInClassTypeOnly(rightType);
|
||||
if (leftClass == null || rightClass == null) return true;
|
||||
if (!leftClass.isInterface() && !rightClass.isInterface()) return true;
|
||||
if (!rightClass.isInterface()) {
|
||||
PsiClass tmp = leftClass;
|
||||
leftClass = rightClass;
|
||||
rightClass = tmp;
|
||||
}
|
||||
return InheritanceUtil.existsMutualSubclass(leftClass, rightClass, isOnTheFly());
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-15
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
@@ -102,6 +88,18 @@ public class EqualsBetweenInconvertibleTypesInspectionTest extends LightInspecti
|
||||
"}");
|
||||
}
|
||||
|
||||
public void testNoCommonSubclassEqualityComparison() {
|
||||
doTest("import java.util.Date;\n" +
|
||||
"import java.util.Map;\n" +
|
||||
"import java.util.Objects;\n" +
|
||||
"\n" +
|
||||
"class X {\n" +
|
||||
" public static boolean foo(Date date, Map<String, String> map) {\n" +
|
||||
" return map /*No class found which is a subtype of both 'Map<String, String>' and 'Date'*/==/**/ date;\n" +
|
||||
" }\n" +
|
||||
"}");
|
||||
}
|
||||
|
||||
public void testCommonSubclass() {
|
||||
doTest("import java.util.Date;\n" +
|
||||
"import java.util.Map;\n" +
|
||||
|
||||
Reference in New Issue
Block a user