diff --git a/java/java-analysis-impl/resources/messages/InspectionGadgetsBundle.properties b/java/java-analysis-impl/resources/messages/InspectionGadgetsBundle.properties index e90bb0b4fd10..6c2716f9747e 100644 --- a/java/java-analysis-impl/resources/messages/InspectionGadgetsBundle.properties +++ b/java/java-analysis-impl/resources/messages/InspectionGadgetsBundle.properties @@ -80,7 +80,7 @@ equals.called.on.suspicious.object.fix.family.name=Replace with a comparison of equals.called.on.suspicious.object.fix.name=Replace with a comparison of ''{0}()'' call results non.final.field.in.equals.display.name=Non-final field referenced in 'equals()' non.final.field.in.equals.problem.descriptor=Non-final field #ref accessed in 'equals()' #loc -equals.doesnt.check.class.parameter.display.name='equals()' method which does not check class of parameter +equals.doesnt.check.class.parameter.display.name='equals()' method that does not check the class of its parameter equals.doesnt.check.class.parameter.problem.descriptor=#ref() should check the class of its parameter #loc non.final.field.in.hashcode.display.name=Non-final field referenced in 'hashCode()' non.final.field.in.hashcode.problem.descriptor=Non-final field #ref accessed in 'hashCode()' #loc diff --git a/java/java-analysis-impl/src/com/siyeh/ig/bugs/EqualsWhichDoesntCheckParameterClassInspection.java b/java/java-analysis-impl/src/com/siyeh/ig/bugs/EqualsWhichDoesntCheckParameterClassInspection.java index fa10db353af0..a3c657792c37 100644 --- a/java/java-analysis-impl/src/com/siyeh/ig/bugs/EqualsWhichDoesntCheckParameterClassInspection.java +++ b/java/java-analysis-impl/src/com/siyeh/ig/bugs/EqualsWhichDoesntCheckParameterClassInspection.java @@ -29,6 +29,9 @@ import com.siyeh.ig.psiutils.MethodUtils; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import java.util.Arrays; +import java.util.Objects; + import static com.intellij.util.ObjectUtils.tryCast; public class EqualsWhichDoesntCheckParameterClassInspection extends BaseInspection { @@ -207,6 +210,32 @@ public class EqualsWhichDoesntCheckParameterClassInspection extends BaseInspecti } } + @Override + public void visitSwitchExpression(@NotNull PsiSwitchExpression expression) { + super.visitSwitchExpression(expression); + if (isParameterReference(expression.getExpression()) && checksTypeOfExpression(expression)) { + makeChecked(); + } + } + + @Override + public void visitSwitchStatement(@NotNull PsiSwitchStatement statement) { + super.visitSwitchStatement(statement); + if (isParameterReference(statement.getExpression()) && checksTypeOfExpression(statement)) { + makeChecked(); + } + } + + private static boolean checksTypeOfExpression(@NotNull PsiSwitchBlock switchBlock) { + PsiCodeBlock body = switchBlock.getBody(); + return body != null && PsiTreeUtil.getChildrenOfTypeAsList(body, PsiSwitchLabelStatementBase.class) + .stream() + .map(PsiSwitchLabelStatementBase::getCaseLabelElementList) + .filter(Objects::nonNull) + .flatMap(list -> Arrays.stream(list.getElements())) + .anyMatch(element -> element instanceof PsiTypeTestPattern); + } + @Override public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) { super.visitTypeCastExpression(expression); diff --git a/java/java-tests/testData/ig/com/siyeh/igtest/bugs/equals_which_doesnt_check_parameter_class/EqualsWhichDoesntCheckParameterClass.java b/java/java-tests/testData/ig/com/siyeh/igtest/bugs/equals_which_doesnt_check_parameter_class/EqualsWhichDoesntCheckParameterClass.java index f99deb648a01..6d86dca314f6 100644 --- a/java/java-tests/testData/ig/com/siyeh/igtest/bugs/equals_which_doesnt_check_parameter_class/EqualsWhichDoesntCheckParameterClass.java +++ b/java/java-tests/testData/ig/com/siyeh/igtest/bugs/equals_which_doesnt_check_parameter_class/EqualsWhichDoesntCheckParameterClass.java @@ -1,5 +1,6 @@ package com.siyeh.igtest.bugs.equals_which_doesnt_check_parameter; +import java.util.Objects; import java.util.Optional; import org.apache.commons.lang3.builder.EqualsBuilder; @@ -135,4 +136,26 @@ class ReflectionEquals { public boolean equals(Object o) { return EqualsBuilder.reflectionEquals(this, o); } +} +interface MyInterface { + +} +final class MyClass implements MyInterface { + + public String str; + + @Override + public boolean equals(Object o) { // "'equals()' should check the class of its parameter" is falsely reported + if (this == o) return true; + + return switch (o) { + case MyClass c when c != null-> Objects.equals(str, c.str); + case MyInterface i -> { + System.out.println("bla bla"); + yield false; + } + case null, default -> false; + }; + } + } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/siyeh/ig/bugs/EqualsWhichDoesntCheckParameterClassInspectionTest.java b/java/java-tests/testSrc/com/siyeh/ig/bugs/EqualsWhichDoesntCheckParameterClassInspectionTest.java index 029125e2d4c8..4eaffd8c3476 100644 --- a/java/java-tests/testSrc/com/siyeh/ig/bugs/EqualsWhichDoesntCheckParameterClassInspectionTest.java +++ b/java/java-tests/testSrc/com/siyeh/ig/bugs/EqualsWhichDoesntCheckParameterClassInspectionTest.java @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.siyeh.ig.bugs; import com.intellij.codeInspection.InspectionProfileEntry; @@ -16,7 +16,7 @@ public class EqualsWhichDoesntCheckParameterClassInspectionTest extends LightJav @NotNull @Override protected LightProjectDescriptor getProjectDescriptor() { - return JAVA_8; + return JAVA_21; } @Nullable