diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/EqualsReplaceableByObjectsCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/EqualsReplaceableByObjectsCallInspection.java
index e95e536ceb23..5d61b6dc09f6 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/EqualsReplaceableByObjectsCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/EqualsReplaceableByObjectsCallInspection.java
@@ -30,7 +30,7 @@ import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
-import com.siyeh.ig.psiutils.VariableAccessUtils;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -100,12 +100,8 @@ public class EqualsReplaceableByObjectsCallInspection extends BaseInspection {
return;
}
final PsiExpression expression = (PsiExpression)element;
- if (myEquals) {
- PsiReplacementUtil.replaceExpressionAndShorten(expression, "java.util.Objects.equals(" + myName1 + "," + myName2 + ")");
- }
- else {
- PsiReplacementUtil.replaceExpressionAndShorten(expression, "!java.util.Objects.equals(" + myName1 + "," + myName2 + ")");
- }
+ final String expressionText = "java.util.Objects.equals(" + myName1 + "," + myName2 + ")";
+ PsiReplacementUtil.replaceExpressionAndShorten(expression, myEquals ? expressionText : "!" + expressionText);
}
}
@@ -123,6 +119,10 @@ public class EqualsReplaceableByObjectsCallInspection extends BaseInspection {
@Override
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+ final String methodName = expression.getMethodExpression().getReferenceName();
+ if (!HardcodedMethodConstants.EQUALS.equals(methodName)) {
+ return;
+ }
final PsiElement maybeBinary = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class, PsiPrefixExpression.class);
if (maybeBinary instanceof PsiBinaryExpression) {
if (processNotNullCheck((PsiBinaryExpression)maybeBinary)) {
@@ -130,69 +130,95 @@ public class EqualsReplaceableByObjectsCallInspection extends BaseInspection {
}
}
if (!checkNotNull) {
- final PsiVariable variable = ExpressionUtils.getVariable(expression.getMethodExpression().getQualifierExpression());
- if (variable == null) {
+ final PsiExpression qualifierExpression = getQualifierExpression(expression);
+ if (qualifierExpression == null) {
return;
}
- final PsiVariable otherVariable = getArgumentFromEqualsCallOn(expression, variable);
- if (otherVariable == null) {
+ final PsiExpression argumentExpression = getArgumentExpression(expression);
+ if (argumentExpression == null) {
return;
}
- registerError(expression, variable.getName(), otherVariable.getName(), true);
+ registerError(expression, qualifierExpression.getText(), argumentExpression.getText(), true);
}
}
+ private PsiExpression getQualifierExpression(PsiMethodCallExpression expression) {
+ return ParenthesesUtils.stripParentheses(expression.getMethodExpression().getQualifierExpression());
+ }
+
private boolean processNotNullCheck(PsiBinaryExpression expression) {
final IElementType tokenType = expression.getOperationTokenType();
+ final PsiExpression rightOperand = ParenthesesUtils.stripParentheses(expression.getROperand());
if (JavaTokenType.ANDAND.equals(tokenType)) {
- final PsiVariable variable = ExpressionUtils.getVariableFromNullComparison(expression.getLOperand(), false);
- if (variable == null) {
- return false;
- }
- final PsiVariable otherVariable = getArgumentFromEqualsCallOn(expression.getROperand(), variable);
- if (otherVariable == null) {
- return false;
- }
- checkEqualityBefore(expression, true, variable, otherVariable);
+ return registerProblem(expression, rightOperand, true);
}
else if (JavaTokenType.OROR.equals(tokenType)) {
- final PsiVariable variable = ExpressionUtils.getVariableFromNullComparison(expression.getLOperand(), true);
- if (variable == null) {
- return false;
+ if (rightOperand instanceof PsiPrefixExpression &&
+ JavaTokenType.EXCL.equals(((PsiPrefixExpression)rightOperand).getOperationTokenType())) {
+ final PsiExpression negatedRightOperand = ParenthesesUtils.stripParentheses(((PsiPrefixExpression)rightOperand).getOperand());
+ return registerProblem(expression, negatedRightOperand, false);
}
- final PsiExpression rhs = ParenthesesUtils.stripParentheses(expression.getROperand());
- if (!(rhs instanceof PsiPrefixExpression)) {
- return false;
- }
- final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)rhs;
- if (!JavaTokenType.EXCL.equals(prefixExpression.getOperationTokenType())) {
- return false;
- }
- final PsiVariable otherVariable = getArgumentFromEqualsCallOn(prefixExpression.getOperand(), variable);
- if (otherVariable == null) {
- return false;
- }
- checkEqualityBefore(expression, false, variable, otherVariable);
}
return true;
}
- private void checkEqualityBefore(PsiExpression expression, boolean equals, PsiVariable variable1, PsiVariable variable2) {
- final PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class);
- if (parent instanceof PsiBinaryExpression) {
- final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)parent;
- if (PsiTreeUtil.isAncestor(binaryExpression.getROperand(), expression, false)) {
- final PsiExpression lhs = binaryExpression.getLOperand();
- if (isEquality(lhs, equals, variable1, variable2)) {
- registerError(binaryExpression, variable1.getName(), variable2.getName(), Boolean.valueOf(equals));
- return;
+ /**
+ * Match the patterns, and register the error if a pattern is matched:
+ *
+ * x==null || !x.equals(y)
+ * x!=null && x.equals(y)
+ *
+ * @return true if the pattern is matched
+ */
+ private boolean registerProblem(PsiBinaryExpression expression, PsiExpression rightOperand, boolean equal) {
+ if ((rightOperand instanceof PsiMethodCallExpression)) {
+ final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)rightOperand;
+ final PsiReferenceExpression nullCheckedExpression =
+ ExpressionUtils.getReferenceExpressionFromNullComparison(expression.getLOperand(), !equal);
+ final String nullCheckedName = getQualifiedVariableName(nullCheckedExpression);
+ if (nullCheckedName != null) {
+ final PsiExpression qualifierExpression = getQualifierExpression(methodCallExpression);
+ final String qualifierName = getQualifiedVariableName(qualifierExpression);
+ if (qualifierName != null && qualifierName.equals(nullCheckedName)) {
+ final PsiExpression argumentExpression = getArgumentExpression(methodCallExpression);
+ final String argumentName = getQualifiedVariableName(argumentExpression);
+ final PsiExpression expressionToReplace =
+ argumentName != null ? checkEqualityBefore(expression, equal, qualifierName, argumentName) : expression;
+ registerError(expressionToReplace, nullCheckedExpression.getText(), argumentExpression.getText(), Boolean.valueOf(equal));
+ return true;
}
}
}
- registerError(expression, variable1.getName(), variable2.getName(), Boolean.valueOf(equals));
+ return false;
}
- private boolean isEquality(PsiExpression expression, boolean equals, PsiVariable variable1, PsiVariable variable2) {
+ /**
+ * Match the left side of the patterns:
+ *
+ * x!=y && (x==null || !x.equals(y))
+ * x==y || (x!=null && x.equals(y))
+ *
+ * @return the expression matching the pattern, or the original expression if there's no match
+ */
+ @Nullable
+ private PsiExpression checkEqualityBefore(PsiExpression expression, boolean equal, String qualifiedName1, String qualifiedName2) {
+ final PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class);
+ if (parent instanceof PsiBinaryExpression) {
+ final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)parent;
+ final IElementType tokenType = binaryExpression.getOperationTokenType();
+ if (equal && JavaTokenType.OROR.equals(tokenType) || !equal && JavaTokenType.ANDAND.equals(tokenType)) {
+ if (PsiTreeUtil.isAncestor(binaryExpression.getROperand(), expression, false)) {
+ final PsiExpression lhs = binaryExpression.getLOperand();
+ if (isEquality(lhs, equal, qualifiedName1, qualifiedName2)) {
+ return binaryExpression;
+ }
+ }
+ }
+ }
+ return expression;
+ }
+
+ private boolean isEquality(PsiExpression expression, boolean equals, String qualifiedName1, String qualifiedName2) {
expression = ParenthesesUtils.stripParentheses(expression);
if (!(expression instanceof PsiBinaryExpression)) {
return false;
@@ -208,33 +234,45 @@ public class EqualsReplaceableByObjectsCallInspection extends BaseInspection {
return false;
}
}
- final PsiExpression lhs = binaryExpression.getLOperand();
- final PsiExpression rhs = binaryExpression.getROperand();
- return (VariableAccessUtils.evaluatesToVariable(lhs, variable1) && VariableAccessUtils.evaluatesToVariable(rhs, variable2)) ||
- (VariableAccessUtils.evaluatesToVariable(lhs, variable2) && VariableAccessUtils.evaluatesToVariable(rhs, variable1));
- }
-
- private PsiVariable getArgumentFromEqualsCallOn(PsiExpression expression, PsiVariable variable) {
- expression = ParenthesesUtils.stripParentheses(expression);
- if (!(expression instanceof PsiMethodCallExpression)) {
- return null;
- }
- final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
- final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
- final String methodName = methodExpression.getReferenceName();
- if (!HardcodedMethodConstants.EQUALS.equals(methodName)) {
- return null;
- }
- final PsiExpression qualifier = methodExpression.getQualifierExpression();
- if (!VariableAccessUtils.evaluatesToVariable(qualifier, variable)) {
- return null;
- }
- final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
- final PsiExpression[] expressions = argumentList.getExpressions();
- if (expressions.length != 1) {
- return null;
- }
- return ExpressionUtils.getVariable(expressions[0]);
+ final PsiExpression leftOperand = ParenthesesUtils.stripParentheses(binaryExpression.getLOperand());
+ final PsiExpression rightOperand = ParenthesesUtils.stripParentheses(binaryExpression.getROperand());
+ final String leftName = getQualifiedVariableName(leftOperand);
+ final String rightName = getQualifiedVariableName(rightOperand);
+ return leftName != null && rightName != null &&
+ (leftName.equals(qualifiedName1) && rightName.equals(qualifiedName2) ||
+ leftName.equals(qualifiedName2) && rightName.equals(qualifiedName1));
}
}
+
+ private PsiExpression getArgumentExpression(PsiMethodCallExpression callExpression) {
+ final PsiExpression[] expressions = callExpression.getArgumentList().getExpressions();
+ return expressions.length == 1 ? ParenthesesUtils.stripParentheses(expressions[0]) : null;
+ }
+
+ /**
+ * Check if the expression is a variable name chain like "a.b.c" ("this" and "super" are allowed), and convert it into a qualified name
+ *
+ * @return the text representation of the variable chain (with parenthesis stripped), or {@code null} if it's not a variable chain
+ */
+ @Nullable
+ private static String getQualifiedVariableName(@Nullable PsiExpression expression) {
+ if (expression instanceof PsiReferenceExpression) {
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
+ final String referenceName = referenceExpression.getReferenceName();
+ if (referenceName != null && referenceExpression.resolve() instanceof PsiVariable) {
+ final PsiExpression qualifierExpression = ParenthesesUtils.stripParentheses(referenceExpression.getQualifierExpression());
+ if (qualifierExpression == null) {
+ return referenceName;
+ }
+ final String qualifierName = getQualifiedVariableName(qualifierExpression);
+ return qualifierName != null ? qualifierName + "." + referenceName : null;
+ }
+ }
+ else if (expression instanceof PsiQualifiedExpression) {
+ final PsiJavaCodeReferenceElement qualifier = ((PsiQualifiedExpression)expression).getQualifier();
+ final String name = expression instanceof PsiThisExpression ? "this" : "super";
+ return qualifier != null ? qualifier.getQualifiedName() + "." + name : name;
+ }
+ return null;
+ }
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java
index 06d6d70a47c5..950c8e6119c3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java
@@ -600,6 +600,13 @@ public class ExpressionUtils {
@Nullable
public static PsiVariable getVariableFromNullComparison(PsiExpression expression, boolean equals) {
+ final PsiReferenceExpression referenceExpression = getReferenceExpressionFromNullComparison(expression, equals);
+ final PsiElement target = referenceExpression.resolve();
+ return target instanceof PsiVariable ? (PsiVariable)target : null;
+ }
+
+ @Nullable
+ public static PsiReferenceExpression getReferenceExpressionFromNullComparison(PsiExpression expression, boolean equals) {
expression = ParenthesesUtils.stripParentheses(expression);
if (!(expression instanceof PsiPolyadicExpression)) {
return null;
@@ -620,26 +627,16 @@ public class ExpressionUtils {
if (operands.length != 2) {
return null;
}
+ PsiExpression comparedToNull = null;
if (PsiType.NULL.equals(operands[0].getType())) {
- return getVariable(operands[1]);
+ comparedToNull = operands[1];
}
else if (PsiType.NULL.equals(operands[1].getType())) {
- return getVariable(operands[0]);
+ comparedToNull = operands[0];
}
- return null;
- }
+ comparedToNull = ParenthesesUtils.stripParentheses(comparedToNull);
- public static PsiVariable getVariable(@Nullable PsiExpression expression) {
- expression = ParenthesesUtils.stripParentheses(expression);
- if (!(expression instanceof PsiReferenceExpression)) {
- return null;
- }
- final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
- final PsiElement target = referenceExpression.resolve();
- if (!(target instanceof PsiVariable)) {
- return null;
- }
- return (PsiVariable)target;
+ return comparedToNull instanceof PsiReferenceExpression ? (PsiReferenceExpression)comparedToNull : null;
}
public static boolean isConcatenation(PsiElement element) {
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionArgument.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionArgument.after.java
new file mode 100644
index 000000000000..f79fad6097c0
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionArgument.after.java
@@ -0,0 +1,7 @@
+import java.util.Objects;
+
+class T {
+ static boolean same(String t, String s) {
+ return Objects.equals(s, t + "a");
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionArgument.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionArgument.java
new file mode 100644
index 000000000000..aae5999d3032
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionArgument.java
@@ -0,0 +1,5 @@
+class T {
+ static boolean same(String t, String s) {
+ return s.equals(t + "a");
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionArgument2.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionArgument2.after.java
new file mode 100644
index 000000000000..f79fad6097c0
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionArgument2.after.java
@@ -0,0 +1,7 @@
+import java.util.Objects;
+
+class T {
+ static boolean same(String t, String s) {
+ return Objects.equals(s, t + "a");
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionArgument2.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionArgument2.java
new file mode 100644
index 000000000000..bc4780982b91
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionArgument2.java
@@ -0,0 +1,5 @@
+class T {
+ static boolean same(String t, String s) {
+ return s != null && s.equals(t + "a");
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionReciever.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionReciever.after.java
new file mode 100644
index 000000000000..6b860f87b429
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionReciever.after.java
@@ -0,0 +1,7 @@
+import java.util.Objects;
+
+class T {
+ static boolean same(String t, String s) {
+ return Objects.equals(t + "a", s);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionReciever.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionReciever.java
new file mode 100644
index 000000000000..34935424f5fc
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ExpressionReciever.java
@@ -0,0 +1,5 @@
+class T {
+ static boolean same(String t, String s) {
+ return (t + "a").equals(s);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/LongEquals.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/LongEquals.after.java
new file mode 100644
index 000000000000..89dbe2e866b0
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/LongEquals.after.java
@@ -0,0 +1,9 @@
+import java.util.Objects;
+
+class T {
+ static class P { String n; }
+
+ static boolean same(P a, P b) {
+ return Objects.equals(a.n, b.n);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/LongEquals.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/LongEquals.java
new file mode 100644
index 000000000000..8bf64f2e1869
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/LongEquals.java
@@ -0,0 +1,7 @@
+class T {
+ static class P { String n; }
+
+ static boolean same(P a, P b) {
+ return a.n == b.n || a.n != null && a.n.equals(b.n);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/LongNotEquals.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/LongNotEquals.after.java
new file mode 100644
index 000000000000..27b5495c1e8c
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/LongNotEquals.after.java
@@ -0,0 +1,9 @@
+import java.util.Objects;
+
+class T {
+ static class P { String n; }
+
+ static boolean notSame(P a, P b) {
+ return !Objects.equals(a.n, b.n);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/LongNotEquals.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/LongNotEquals.java
new file mode 100644
index 000000000000..e8e91a0ca6f8
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/LongNotEquals.java
@@ -0,0 +1,7 @@
+class T {
+ static class P { String n; }
+
+ static boolean notSame(P a, P b) {
+ return a.n != b.n && (a.n == null || !a.n.equals(b.n));
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedArgument.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedArgument.after.java
new file mode 100644
index 000000000000..645fabc98ddc
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedArgument.after.java
@@ -0,0 +1,11 @@
+import java.util.Objects;
+
+class T {
+ static class A {
+ String s;
+ }
+ A a;
+ static boolean same(T t, String s) {
+ return Objects.equals(s, t.a.s);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedArgument.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedArgument.java
new file mode 100644
index 000000000000..aac12a86faac
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedArgument.java
@@ -0,0 +1,9 @@
+class T {
+ static class A {
+ String s;
+ }
+ A a;
+ static boolean same(T t, String s) {
+ return s.equals(t.a.s);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedReciever.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedReciever.after.java
new file mode 100644
index 000000000000..e8dfb83d4efb
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedReciever.after.java
@@ -0,0 +1,11 @@
+import java.util.Objects;
+
+class T {
+ static class A {
+ String s;
+ }
+ A a;
+ static boolean same(T t, String s) {
+ return Objects.equals(t.a.s, s);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedReciever.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedReciever.java
new file mode 100644
index 000000000000..a0bceeab0215
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedReciever.java
@@ -0,0 +1,9 @@
+class T {
+ static class A {
+ String s;
+ }
+ A a;
+ static boolean same(T t, String s) {
+ return t.a.s != null && t.a.s.equals(s);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedSuperEqual.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedSuperEqual.after.java
new file mode 100644
index 000000000000..aa3904b837c6
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedSuperEqual.after.java
@@ -0,0 +1,21 @@
+import java.util.Objects;
+
+class T {
+ String s;
+
+ class A {
+ T t;
+ }
+
+ class B extends A {
+ void check(final String s) {
+ new Runnable() {
+ @Override
+ public void run() {
+ boolean b = Objects.equals(B.super.t.s, s);
+ System.out.println(b);
+ }
+ }.run();
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedSuperEqual.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedSuperEqual.java
new file mode 100644
index 000000000000..04473035ff79
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedSuperEqual.java
@@ -0,0 +1,19 @@
+class T {
+ String s;
+
+ class A {
+ T t;
+ }
+
+ class B extends A {
+ void check(final String s) {
+ new Runnable() {
+ @Override
+ public void run() {
+ boolean b = (B.super.t.s) == s || (B.super.t.s) != null && (B.super.t).s.equals(s);
+ System.out.println(b);
+ }
+ }.run();
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedThisNotEqual.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedThisNotEqual.after.java
new file mode 100644
index 000000000000..b1033d170156
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedThisNotEqual.after.java
@@ -0,0 +1,10 @@
+import java.util.Objects;
+
+class T {
+ String s;
+ class A {
+ boolean notSame(String s) {
+ return !Objects.equals(T.this.s, s);
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedThisNotEqual.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedThisNotEqual.java
new file mode 100644
index 000000000000..d31c59b6b1c2
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/QualifiedThisNotEqual.java
@@ -0,0 +1,8 @@
+class T {
+ String s;
+ class A {
+ boolean notSame(String s) {
+ return T.this.s != s && (T.this.s == null || !T.this.s.equals(s));
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ShortEquals.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ShortEquals.after.java
new file mode 100644
index 000000000000..89dbe2e866b0
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ShortEquals.after.java
@@ -0,0 +1,9 @@
+import java.util.Objects;
+
+class T {
+ static class P { String n; }
+
+ static boolean same(P a, P b) {
+ return Objects.equals(a.n, b.n);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ShortEquals.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ShortEquals.java
new file mode 100644
index 000000000000..b73d8aace910
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ShortEquals.java
@@ -0,0 +1,7 @@
+class T {
+ static class P { String n; }
+
+ static boolean same(P a, P b) {
+ return a.n != null && a.n.equals(b.n);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ShortNotEquals.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ShortNotEquals.after.java
new file mode 100644
index 000000000000..27b5495c1e8c
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ShortNotEquals.after.java
@@ -0,0 +1,9 @@
+import java.util.Objects;
+
+class T {
+ static class P { String n; }
+
+ static boolean notSame(P a, P b) {
+ return !Objects.equals(a.n, b.n);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ShortNotEquals.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ShortNotEquals.java
new file mode 100644
index 000000000000..448876cf843a
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ShortNotEquals.java
@@ -0,0 +1,7 @@
+class T {
+ static class P { String n; }
+
+ static boolean notSame(P a, P b) {
+ return a.n == null || !a.n.equals(b.n);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SimpleEquals.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SimpleEquals.after.java
new file mode 100644
index 000000000000..d71a4bd47561
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SimpleEquals.after.java
@@ -0,0 +1,7 @@
+import java.util.Objects;
+
+class T {
+ static boolean same(String t, String s) {
+ return Objects.equals(s, t);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SimpleEquals.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SimpleEquals.java
new file mode 100644
index 000000000000..94de4bd54eba
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SimpleEquals.java
@@ -0,0 +1,5 @@
+class T {
+ static boolean same(String t, String s) {
+ return s.equals(t);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SimpleNotEquals.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SimpleNotEquals.after.java
new file mode 100644
index 000000000000..4d7944100468
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SimpleNotEquals.after.java
@@ -0,0 +1,7 @@
+import java.util.Objects;
+
+class T {
+ static boolean notSame(String t, String s) {
+ return !Objects.equals(s, t);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SimpleNotEquals.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SimpleNotEquals.java
new file mode 100644
index 000000000000..e60629b0c73d
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SimpleNotEquals.java
@@ -0,0 +1,5 @@
+class T {
+ static boolean notSame(String t, String s) {
+ return !s.equals(t);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SuperEquals.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SuperEquals.after.java
new file mode 100644
index 000000000000..481f5bf0b4f4
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SuperEquals.after.java
@@ -0,0 +1,10 @@
+import java.util.Objects;
+
+class T {
+ String s;
+ static class X extends T {
+ boolean same(String s) {
+ return Objects.equals(super.s, s);
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SuperEquals.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SuperEquals.java
new file mode 100644
index 000000000000..2a7a3a8a2d6d
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/SuperEquals.java
@@ -0,0 +1,8 @@
+class T {
+ String s;
+ static class X extends T {
+ boolean same(String s) {
+ return super.s.equals(s);
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ThisEquals.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ThisEquals.after.java
new file mode 100644
index 000000000000..b9a70ad038e0
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ThisEquals.after.java
@@ -0,0 +1,8 @@
+import java.util.Objects;
+
+class T {
+ String s;
+ boolean same(String s) {
+ return Objects.equals(this.s, s);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ThisEquals.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ThisEquals.java
new file mode 100644
index 000000000000..ace88e320f0c
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/equals_replaceable_by_objects_call/ThisEquals.java
@@ -0,0 +1,6 @@
+class T {
+ String s;
+ boolean same(String s) {
+ return this.s.equals(s);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/equals_replaceable_by_objects_call/EqualsReplaceableByObjectsCall.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/equals_replaceable_by_objects_call/EqualsReplaceableByObjectsCall.java
index 49b9afbef78f..b02a5a72e455 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/equals_replaceable_by_objects_call/EqualsReplaceableByObjectsCall.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/equals_replaceable_by_objects_call/EqualsReplaceableByObjectsCall.java
@@ -8,4 +8,31 @@ class EqualsReplaceableByObjectsCall {
void ignoreNullityCheck(Object a, Object b) {
boolean c = a.equals(b);
}
+
+ void bar(T x, T y, T z) {
+ boolean b = !x.s.equals(y.s);
+ boolean c = x.s != null && x.s.equals(y.s);
+ boolean d = y.s != null && x.s.equals(y.s);
+ boolean e = x.s == null || !x.s.equals(y.s);
+ boolean f = x.s != y.s && (x.s == null || !x.s.equals(y.s));
+ boolean g = x.s != y.s || (x.s == null || !x.s.equals(y.s));
+ boolean h = x.s != y.s && (z.s == null || !x.s.equals(y.s));
+ }
+
+ void baz(T x, T y) {
+ boolean b = x.copy().equals(y.copy());
+ boolean c = x != null && x.equals(y.copy());
+ boolean d = x == null || !x.equals(y.copy());
+ boolean e = x.copy() != null && x.copy().equals(y);
+ boolean f = x.copy() == null || !x.copy().equals(y);
+ boolean g = x.copy().s != null && x.copy().s.equals(y.s);
+ boolean h = x.copy().s == null || !x.copy().s.equals(y.s);
+ boolean i = x.s == y.copy().s || (x).s != null && (x.s).equals(y.copy().s);
+ boolean j = x.s != y.copy().s && ((x).s == null || !(x.s).equals(y.copy().s));
+ }
+
+ static class T {
+ String s;
+ T copy() { T t = new T(); t.s = s; return t; }
+ }
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/equals_replaceable_by_objects_call/EqualsReplaceableByObjectsCallCheckNull.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/equals_replaceable_by_objects_call/EqualsReplaceableByObjectsCallCheckNull.java
index 5d4f1fdbe924..2336a461c554 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/equals_replaceable_by_objects_call/EqualsReplaceableByObjectsCallCheckNull.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/equals_replaceable_by_objects_call/EqualsReplaceableByObjectsCallCheckNull.java
@@ -8,4 +8,31 @@ class EqualsReplaceableByObjectsCall {
void ignoreNullityCheck(Object a, Object b) {
boolean c = a.equals(b);
}
+
+ void bar(T x, T y, T z) {
+ boolean b = !x.s.equals(y.s);
+ boolean c = x.s != null && x.s.equals(y.s);
+ boolean d = y.s != null && x.s.equals(y.s);
+ boolean e = x.s == null || !x.s.equals(y.s);
+ boolean f = x.s != y.s && (x.s == null || !x.s.equals(y.s));
+ boolean g = x.s != y.s || (x.s == null || !x.s.equals(y.s));
+ boolean h = x.s != y.s && (z.s == null || !x.s.equals(y.s));
+ }
+
+ void baz(T x, T y) {
+ boolean b = x.copy().equals(y.copy());
+ boolean c = x != null && x.equals(y.copy());
+ boolean d = x == null || !x.equals(y.copy());
+ boolean e = x.copy() != null && x.copy().equals(y);
+ boolean f = x.copy() == null || !x.copy().equals(y);
+ boolean g = x.copy().s != null && x.copy().s.equals(y.s);
+ boolean h = x.copy().s == null || !x.copy().s.equals(y.s);
+ boolean i = x.s == y.copy().s || (x).s != null && (x.s).equals(y.copy().s);
+ boolean j = x.s != y.copy().s && ((x).s == null || !(x.s).equals(y.copy().s));
+ }
+
+ static class T {
+ String s;
+ T copy() { T t = new T(); t.s = s; return t; }
+ }
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/migration/EqualsReplaceableByObjectsCallFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/migration/EqualsReplaceableByObjectsCallFixTest.java
new file mode 100644
index 000000000000..9a4afb0acd87
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/migration/EqualsReplaceableByObjectsCallFixTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2000-2016 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.fixes.migration;
+
+import com.intellij.pom.java.LanguageLevel;
+import com.intellij.testFramework.IdeaTestUtil;
+import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.IGQuickFixesTestCase;
+import com.siyeh.ig.migration.EqualsReplaceableByObjectsCallInspection;
+
+/**
+ * @author Pavel.Dolgov
+ */
+public class EqualsReplaceableByObjectsCallFixTest extends IGQuickFixesTestCase {
+
+ public void testSimpleEquals() { doTest(); }
+ public void testSimpleNotEquals() { doTest(); }
+
+ public void testQualifiedArgument() { doTest(); }
+ public void testQualifiedReciever() { doTest(); }
+
+ public void testExpressionReciever() { doTest(); }
+ public void testExpressionArgument() { doTest(); }
+ public void testExpressionArgument2() { doTest(); }
+
+ public void testLongEquals() { doTest(); }
+ public void testLongNotEquals() { doTest(); }
+ public void testShortEquals() { doTest(); }
+ public void testShortNotEquals() { doTest(); }
+
+ public void testSuperEquals() { doTest(); }
+ public void testThisEquals() { doTest(); }
+
+ public void testQualifiedThisNotEqual() { doTest(); }
+ public void testQualifiedSuperEqual() { doTest(); }
+
+ @Override
+ protected void tuneFixture(JavaModuleFixtureBuilder builder) throws Exception {
+ builder.addJdk(IdeaTestUtil.getMockJdk18Path().getPath())
+ .setLanguageLevel(LanguageLevel.JDK_1_7);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ myFixture.enableInspections(new EqualsReplaceableByObjectsCallInspection());
+ myRelativePath = "migration/equals_replaceable_by_objects_call";
+ myDefaultHint = InspectionGadgetsBundle.message("equals.replaceable.by.objects.call.quickfix");
+ }
+}