mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Refactor InconvertibleTypesChecker
GitOrigin-RevId: e2833d187bf6ce3c3ebd49e7efaaa30bef8a099d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
462856d81c
commit
e813c64ce2
+19
-15
@@ -22,12 +22,12 @@ import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.psiutils.InconvertibleTypesChecker;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class EqualsBetweenInconvertibleTypesInspection extends BaseInspection {
|
||||
|
||||
@@ -92,24 +92,28 @@ public class EqualsBetweenInconvertibleTypesInspection extends BaseInspection {
|
||||
!TypeUtils.areConvertible(lhsType, rhsType) /* red code */) {
|
||||
return;
|
||||
}
|
||||
createInconvertibleTypesChecker().deepCheck(lhsType, rhsType, expression.getOperationSign(), new HashSet<>(), WARN_IF_NO_MUTUAL_SUBCLASS_FOUND, isOnTheFly());
|
||||
InconvertibleTypesChecker.TypeMismatch mismatch =
|
||||
InconvertibleTypesChecker.deepCheck(lhsType, rhsType, getMutualSubclassMode());
|
||||
if (mismatch != null) {
|
||||
registerError(expression.getOperationSign(), mismatch.getLeft(), mismatch.getRight(), mismatch.isConvertible());
|
||||
}
|
||||
}
|
||||
|
||||
private InconvertibleTypesChecker.LookForMutualSubclass getMutualSubclassMode() {
|
||||
if (!WARN_IF_NO_MUTUAL_SUBCLASS_FOUND) {
|
||||
return InconvertibleTypesChecker.LookForMutualSubclass.NEVER;
|
||||
}
|
||||
return isOnTheFly()
|
||||
? InconvertibleTypesChecker.LookForMutualSubclass.IF_CHEAP
|
||||
: InconvertibleTypesChecker.LookForMutualSubclass.ALWAYS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkTypes(@NotNull PsiReferenceExpression expression, @NotNull PsiType leftType, @NotNull PsiType rightType) {
|
||||
createInconvertibleTypesChecker().checkTypes(expression, leftType, rightType, WARN_IF_NO_MUTUAL_SUBCLASS_FOUND, isOnTheFly());
|
||||
}
|
||||
|
||||
private InconvertibleTypesChecker createInconvertibleTypesChecker() {
|
||||
return new InconvertibleTypesChecker() {
|
||||
@Override
|
||||
protected void registerEqualsError(PsiElement highlightLocation,
|
||||
@NotNull PsiType leftType,
|
||||
@NotNull PsiType rightType,
|
||||
boolean convertible) {
|
||||
registerError(highlightLocation, leftType, rightType, convertible);
|
||||
}
|
||||
};
|
||||
InconvertibleTypesChecker.TypeMismatch mismatch = InconvertibleTypesChecker.checkTypes(leftType, rightType, getMutualSubclassMode());
|
||||
if (mismatch != null) {
|
||||
registerError(expression, mismatch.getLeft(), mismatch.getRight(), mismatch.isConvertible());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-86
@@ -1,86 +0,0 @@
|
||||
// Copyright 2000-2018 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.openapi.util.Couple;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.ig.psiutils.InheritanceUtil;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class InconvertibleTypesChecker {
|
||||
protected abstract void registerEqualsError(PsiElement highlightLocation,
|
||||
@NotNull PsiType leftType,
|
||||
@NotNull PsiType rightType,
|
||||
boolean convertible);
|
||||
|
||||
public void checkTypes(@NotNull PsiReferenceExpression expression,
|
||||
@NotNull PsiType leftType,
|
||||
@NotNull PsiType rightType,
|
||||
boolean warnIfNoMutualSubclassFound,
|
||||
boolean onTheFly) {
|
||||
PsiElement name = expression.getReferenceNameElement();
|
||||
if (name == null) {
|
||||
return;
|
||||
}
|
||||
if (TypeUtils.areConvertible(leftType, rightType) || TypeUtils.mayBeEqualByContract(leftType, rightType)) {
|
||||
deepCheck(leftType, rightType, name, new HashSet<>(), warnIfNoMutualSubclassFound, onTheFly);
|
||||
return;
|
||||
}
|
||||
registerEqualsError(name, leftType, rightType, false);
|
||||
}
|
||||
|
||||
protected void deepCheck(@NotNull PsiType leftType,
|
||||
@NotNull PsiType rightType,
|
||||
PsiElement highlightLocation,
|
||||
Set<Couple<PsiType>> checked,
|
||||
boolean warnIfNoMutualSubclassFound,
|
||||
boolean onTheFly) {
|
||||
if (leftType instanceof PsiCapturedWildcardType) {
|
||||
leftType = ((PsiCapturedWildcardType)leftType).getUpperBound();
|
||||
}
|
||||
if (rightType instanceof PsiCapturedWildcardType) {
|
||||
rightType = ((PsiCapturedWildcardType)rightType).getUpperBound();
|
||||
}
|
||||
if (!checked.add(Couple.of(leftType, rightType))) {
|
||||
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 (!rightClass.isInterface()) {
|
||||
PsiClass tmp = leftClass;
|
||||
leftClass = rightClass;
|
||||
rightClass = tmp;
|
||||
}
|
||||
if (leftClass == rightClass || TypeUtils.mayBeEqualByContract(leftType, rightType)) {
|
||||
// check type parameters
|
||||
if (leftType instanceof PsiClassType && rightType instanceof PsiClassType) {
|
||||
final PsiType[] leftParameters = ((PsiClassType)leftType).getParameters();
|
||||
final PsiType[] rightParameters = ((PsiClassType)rightType).getParameters();
|
||||
if (leftParameters.length == rightParameters.length) {
|
||||
for (int i = 0, length = leftParameters.length; i < length; i++) {
|
||||
final PsiType leftParameter = leftParameters[i];
|
||||
final PsiType rightParameter = rightParameters[i];
|
||||
if (!TypeUtils.areConvertible(leftParameter, rightParameter) &&
|
||||
!TypeUtils.mayBeEqualByContract(leftParameter, rightParameter)) {
|
||||
registerEqualsError(highlightLocation, leftType, rightType, false);
|
||||
return;
|
||||
}
|
||||
deepCheck(leftParameter, rightParameter, highlightLocation, checked, warnIfNoMutualSubclassFound, onTheFly);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (TypeUtils.cannotBeEqualByContract(leftType, rightType)) {
|
||||
registerEqualsError(highlightLocation, leftType, rightType, false);
|
||||
}
|
||||
else if (warnIfNoMutualSubclassFound && !InheritanceUtil.existsMutualSubclass(leftClass, rightClass, onTheFly)) {
|
||||
registerEqualsError(highlightLocation, leftType, rightType, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
// Copyright 2000-2020 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.psiutils;
|
||||
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.psi.PsiCapturedWildcardType;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiClassType;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class InconvertibleTypesChecker {
|
||||
@Contract(pure = true)
|
||||
public static @Nullable TypeMismatch checkTypes(@NotNull PsiType leftType,
|
||||
@NotNull PsiType rightType,
|
||||
@NotNull LookForMutualSubclass lookForMutualSubclass) {
|
||||
if (TypeUtils.areConvertible(leftType, rightType) || TypeUtils.mayBeEqualByContract(leftType, rightType)) {
|
||||
return deepCheck(leftType, rightType, lookForMutualSubclass);
|
||||
}
|
||||
return new TypeMismatch(leftType, rightType, false);
|
||||
}
|
||||
|
||||
public static @Nullable TypeMismatch deepCheck(@NotNull PsiType leftType,
|
||||
@NotNull PsiType rightType,
|
||||
@NotNull LookForMutualSubclass lookForMutualSubclass) {
|
||||
return deepCheck(leftType, rightType, new HashSet<>(), lookForMutualSubclass);
|
||||
}
|
||||
|
||||
private static @Nullable TypeMismatch deepCheck(@NotNull PsiType leftType,
|
||||
@NotNull PsiType rightType,
|
||||
@NotNull Set<Couple<PsiType>> checked,
|
||||
@NotNull LookForMutualSubclass lookForMutualSubclass) {
|
||||
if (leftType instanceof PsiCapturedWildcardType) {
|
||||
leftType = ((PsiCapturedWildcardType)leftType).getUpperBound();
|
||||
}
|
||||
if (rightType instanceof PsiCapturedWildcardType) {
|
||||
rightType = ((PsiCapturedWildcardType)rightType).getUpperBound();
|
||||
}
|
||||
if (!checked.add(Couple.of(leftType, rightType))) {
|
||||
return null;
|
||||
}
|
||||
if (leftType.isAssignableFrom(rightType) || rightType.isAssignableFrom(leftType)) return null;
|
||||
PsiClass leftClass = PsiUtil.resolveClassInClassTypeOnly(leftType);
|
||||
PsiClass rightClass = PsiUtil.resolveClassInClassTypeOnly(rightType);
|
||||
if (leftClass == null || rightClass == null) return null;
|
||||
if (!rightClass.isInterface()) {
|
||||
PsiClass tmp = leftClass;
|
||||
leftClass = rightClass;
|
||||
rightClass = tmp;
|
||||
}
|
||||
if (leftClass == rightClass || TypeUtils.mayBeEqualByContract(leftType, rightType)) {
|
||||
// check type parameters
|
||||
if (leftType instanceof PsiClassType && rightType instanceof PsiClassType) {
|
||||
final PsiType[] leftParameters = ((PsiClassType)leftType).getParameters();
|
||||
final PsiType[] rightParameters = ((PsiClassType)rightType).getParameters();
|
||||
if (leftParameters.length == rightParameters.length) {
|
||||
for (int i = 0, length = leftParameters.length; i < length; i++) {
|
||||
final PsiType leftParameter = leftParameters[i];
|
||||
final PsiType rightParameter = rightParameters[i];
|
||||
if (!TypeUtils.areConvertible(leftParameter, rightParameter) &&
|
||||
!TypeUtils.mayBeEqualByContract(leftParameter, rightParameter)) {
|
||||
return new TypeMismatch(leftType, rightType, false);
|
||||
}
|
||||
TypeMismatch mismatch = deepCheck(leftParameter, rightParameter, checked, lookForMutualSubclass);
|
||||
if (mismatch != null) {
|
||||
return mismatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (TypeUtils.cannotBeEqualByContract(leftType, rightType)) {
|
||||
return new TypeMismatch(leftType, rightType, false);
|
||||
}
|
||||
else if (lookForMutualSubclass != LookForMutualSubclass.NEVER &&
|
||||
!InheritanceUtil.existsMutualSubclass(leftClass, rightClass, lookForMutualSubclass == LookForMutualSubclass.IF_CHEAP)) {
|
||||
return new TypeMismatch(leftType, rightType, true);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public enum LookForMutualSubclass {
|
||||
NEVER, ALWAYS, IF_CHEAP
|
||||
}
|
||||
|
||||
public static class TypeMismatch {
|
||||
private final @NotNull PsiType myLeft;
|
||||
private final @NotNull PsiType myRight;
|
||||
private final boolean myConvertible;
|
||||
|
||||
private TypeMismatch(@NotNull PsiType left, @NotNull PsiType right, boolean convertible) {
|
||||
myLeft = left;
|
||||
myRight = right;
|
||||
myConvertible = convertible;
|
||||
}
|
||||
|
||||
public @NotNull PsiType getLeft() {
|
||||
return myLeft;
|
||||
}
|
||||
|
||||
public @NotNull PsiType getRight() {
|
||||
return myRight;
|
||||
}
|
||||
|
||||
public boolean isConvertible() {
|
||||
return myConvertible;
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-10
@@ -6,10 +6,12 @@ import com.intellij.psi.*;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.bugs.InconvertibleTypesChecker;
|
||||
import com.siyeh.ig.psiutils.InconvertibleTypesChecker;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class BaseAssertEqualsBetweenInconvertibleTypesInspection extends BaseInspection {
|
||||
protected abstract boolean checkTestNG();
|
||||
|
||||
@@ -56,15 +58,12 @@ public abstract class BaseAssertEqualsBetweenInconvertibleTypesInspection extend
|
||||
return;
|
||||
}
|
||||
|
||||
new InconvertibleTypesChecker() {
|
||||
@Override
|
||||
protected void registerEqualsError(PsiElement highlightLocation,
|
||||
@NotNull PsiType leftType,
|
||||
@NotNull PsiType rightType,
|
||||
boolean convertible) {
|
||||
AssertEqualsBetweenInconvertibleTypesVisitor.this.registerError(highlightLocation, leftType, rightType, convertible);
|
||||
}
|
||||
}.checkTypes(expression.getMethodExpression(), type1, type2, true, isOnTheFly());
|
||||
InconvertibleTypesChecker.TypeMismatch mismatch = InconvertibleTypesChecker.checkTypes(
|
||||
type1, type2, isOnTheFly() ? InconvertibleTypesChecker.LookForMutualSubclass.IF_CHEAP : InconvertibleTypesChecker.LookForMutualSubclass.ALWAYS);
|
||||
if (mismatch != null) {
|
||||
PsiElement name = Objects.requireNonNull(expression.getMethodExpression().getReferenceNameElement());
|
||||
registerError(name, mismatch.getLeft(), mismatch.getRight(), mismatch.isConvertible());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user