new "'equals()' called on itself" inspection

This commit is contained in:
Bas Leijdekkers
2014-08-25 12:22:03 +02:00
parent eed5306817
commit b39445f320
6 changed files with 148 additions and 0 deletions
@@ -202,6 +202,10 @@
key="equals.between.inconvertible.types.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.probable.bugs" enabledByDefault="true" level="WARNING"
implementationClass="com.siyeh.ig.bugs.EqualsBetweenInconvertibleTypesInspection"/>
<localInspection language="JAVA" shortName="EqualsWithItself" bundle="com.siyeh.InspectionGadgetsBundle"
key="equals.with.itself.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.probable.bugs" enabledByDefault="true" level="WARNING"
implementationClass="com.siyeh.ig.bugs.EqualsWithItselfInspection"/>
<localInspection language="JAVA" suppressId="NonFinalFieldReferenceInEquals" shortName="EqualsUsesNonFinalVariable"
bundle="com.siyeh.InspectionGadgetsBundle" key="non.final.field.in.equals.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs" enabledByDefault="false" level="WARNING"
@@ -2101,3 +2101,5 @@ assignment.to.lambda.parameter.problem.descriptor=Assignment to lambda parameter
class.with.only.private.constructors.display.name=Class with only 'private' constructors should be declared 'final'
class.with.only.private.constructors.problem.descriptor=Class <code>#ref</code> with only 'private' constructors should be declared 'final'
property.value.set.to.itself.display.name=Property value set to itself
equals.with.itself.display.name='equals()' called on itself
equals.with.itself.problem.descriptor=Identical qualifier and argument to <code>#ref()</code> call
@@ -0,0 +1,75 @@
/*
* Copyright 2000-2014 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.psi.PsiExpression;
import com.intellij.psi.PsiExpressionList;
import com.intellij.psi.PsiMethodCallExpression;
import com.intellij.psi.PsiReferenceExpression;
import com.siyeh.InspectionGadgetsBundle;import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import com.siyeh.ig.psiutils.MethodCallUtils;
import com.siyeh.ig.psiutils.SideEffectChecker;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
/**
* @author Bas Leijdekkers
*/
public class EqualsWithItselfInspection extends BaseInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return InspectionGadgetsBundle.message("equals.with.itself.display.name");
}
@NotNull
@Override
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message("equals.with.itself.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new EqualsWithIfSelfVisitor();
}
private static class EqualsWithIfSelfVisitor extends BaseInspectionVisitor {
@Override
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
if (!MethodCallUtils.isEqualsCall(expression)) {
return;
}
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (qualifier == null) {
return;
}
final PsiExpressionList argumentList = expression.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
final PsiExpression argument = arguments[0];
if (!EquivalenceChecker.expressionsAreEquivalent(qualifier, argument) ||
SideEffectChecker.mayHaveSideEffects(qualifier)) {
return;
}
registerMethodCallError(expression);
}
}
}
@@ -0,0 +1,10 @@
<html>
<body>
Reports call to <b>equals()</b> were an object is compared for equality with itself.
This means that the argument and the qualifier to the call are identical.
In this case <b>equals()</b> will always return <b>true</b>.
<!-- tooltip end -->
<p>
<small>New in 14</small>
</body>
</html>
@@ -0,0 +1,23 @@
class EqualsWithItself {
boolean foo(Object o) {
return o.<warning descr="Identical qualifier and argument to 'equals()' call">equals</warning>(((o)));
}
boolean withGetter() {
return getValue().<warning descr="Identical qualifier and argument to 'equals()' call">equals</warning>(getValue());
}
boolean withMethodCall() {
return build().equals(build());
}
private Integer value = 1;
public Integer getValue() {
return value;
}
public Object build() {
return new Object();
}
}
@@ -0,0 +1,34 @@
/*
* Copyright 2000-2014 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.InspectionProfileEntry;
import com.siyeh.ig.LightInspectionTestCase;
import org.jetbrains.annotations.Nullable;
/**
* @author Bas Leijdekkers
*/
public class EqualsWithItselfInspectionTest extends LightInspectionTestCase {
public void testEqualsWithItSelf() { doTest(); }
@Nullable
@Override
protected InspectionProfileEntry getInspection() {
return new EqualsWithItselfInspection();
}
}