mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Java inspection: convert the intentions "Replace Equality with Equals" and "Replace Equality with Safe Equals" into a single INFORMATION-level inspection (IDEA-157727)
This commit is contained in:
@@ -796,6 +796,10 @@
|
||||
key="if.to.assertion.name" groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.control.flow.issues" enabledByDefault="true" level="INFORMATION"
|
||||
implementationClass="com.siyeh.ig.asserttoif.IfToAssertionInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="ReplaceEqualityWithEquals" bundle="com.siyeh.InspectionGadgetsBundle"
|
||||
key="replace.equality.with.equals.name" groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.control.flow.issues" enabledByDefault="true" level="INFORMATION"
|
||||
implementationClass="com.siyeh.ig.equality.ReplaceEqualityWithEqualsInspection"/>
|
||||
|
||||
<!--group.names.data.flow.issues-->
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="BooleanVariableAlwaysNegated" bundle="com.siyeh.InspectionGadgetsBundle"
|
||||
|
||||
+4
-1
@@ -2198,4 +2198,7 @@ assert.to.if.name=Replace Assert with If Statement
|
||||
assert.to.if.descriptor=Replace 'assert' with 'if' statement
|
||||
if.to.assertion.name=Replace If with Assert Statement
|
||||
if.to.assertion.descriptor=Replace 'if' with 'assert' statement
|
||||
|
||||
replace.equality.with.equals.name=Replace Equality with Equals
|
||||
replace.equality.with.equals.descriptor=Replace ''{0}'' with ''{1}equals()''
|
||||
replace.equality.with.safe.equals.name=Replace Equality with Safe Equals
|
||||
replace.equality.with.safe.equals.descriptor=Replace ''{0}'' with safe ''{1}equals()''
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* 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.equality;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.PsiReplacementUtil;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import com.siyeh.ig.psiutils.ParenthesesUtils;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ReplaceEqualityWithEqualsInspection extends BaseInspection {
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message("replace.equality.with.equals.name");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message("replace.equality.with.equals.descriptor", infos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new ObjectEqualityVisitor();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected InspectionGadgetsFix[] buildFixes(Object... infos) {
|
||||
return new InspectionGadgetsFix[]{new EqualsFix(infos), new SafeEqualsFix(infos)};
|
||||
}
|
||||
|
||||
private static void doFixImpl(@NotNull PsiElement element) {
|
||||
final PsiBinaryExpression exp = (PsiBinaryExpression)element;
|
||||
final PsiExpression lhs = exp.getLOperand();
|
||||
final PsiExpression rhs = exp.getROperand();
|
||||
if (rhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression strippedLhs = ParenthesesUtils.stripParentheses(lhs);
|
||||
if (strippedLhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression strippedRhs = ParenthesesUtils.stripParentheses(rhs);
|
||||
if (strippedRhs == null) {
|
||||
return;
|
||||
}
|
||||
final String lhText = strippedLhs.getText();
|
||||
final String rhText = strippedRhs.getText();
|
||||
|
||||
final String prefix = exp.getOperationTokenType().equals(JavaTokenType.EQEQ) ? "" : "!";
|
||||
@NonNls final String expString;
|
||||
if (ParenthesesUtils.getPrecedence(strippedLhs) > ParenthesesUtils.METHOD_CALL_PRECEDENCE) {
|
||||
expString = prefix + '(' + lhText + ").equals(" + rhText + ')';
|
||||
}
|
||||
else {
|
||||
expString = prefix + lhText + ".equals(" + rhText + ')';
|
||||
}
|
||||
PsiReplacementUtil.replaceExpression(exp, expString);
|
||||
}
|
||||
|
||||
private static void doSafeFixImpl(PsiElement element) {
|
||||
final PsiBinaryExpression exp = (PsiBinaryExpression)element;
|
||||
final PsiExpression lhs = exp.getLOperand();
|
||||
final PsiExpression rhs = exp.getROperand();
|
||||
if (rhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression strippedLhs =
|
||||
ParenthesesUtils.stripParentheses(lhs);
|
||||
if (strippedLhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression strippedRhs =
|
||||
ParenthesesUtils.stripParentheses(rhs);
|
||||
if (strippedRhs == null) {
|
||||
return;
|
||||
}
|
||||
final String lhsText = strippedLhs.getText();
|
||||
final String rhsText = strippedRhs.getText();
|
||||
final PsiJavaToken operationSign = exp.getOperationSign();
|
||||
final IElementType tokenType = operationSign.getTokenType();
|
||||
final String signText = operationSign.getText();
|
||||
@NonNls final StringBuilder newExpression = new StringBuilder();
|
||||
if (PsiUtil.isLanguageLevel7OrHigher(element) && ClassUtils.findClass("java.util.Objects", element) != null) {
|
||||
if (tokenType.equals(JavaTokenType.NE)) {
|
||||
newExpression.append('!');
|
||||
}
|
||||
newExpression.append("java.util.Objects.equals(").append(lhsText).append(',').append(rhsText).append(')');
|
||||
}
|
||||
else {
|
||||
newExpression.append(lhsText).append("==null?").append(rhsText).append(signText).append(" null:");
|
||||
if (tokenType.equals(JavaTokenType.NE)) {
|
||||
newExpression.append('!');
|
||||
}
|
||||
if (ParenthesesUtils.getPrecedence(strippedLhs) > ParenthesesUtils.METHOD_CALL_PRECEDENCE) {
|
||||
newExpression.append('(').append(lhsText).append(')');
|
||||
}
|
||||
else {
|
||||
newExpression.append(lhsText);
|
||||
}
|
||||
newExpression.append(".equals(").append(rhsText).append(')');
|
||||
}
|
||||
PsiReplacementUtil.replaceExpressionAndShorten(exp, newExpression.toString());
|
||||
}
|
||||
|
||||
private static class SafeEqualsFix extends InspectionGadgetsFix {
|
||||
private final Object[] myInfos;
|
||||
|
||||
public SafeEqualsFix(Object... infos) {
|
||||
myInfos = infos;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message("replace.equality.with.safe.equals.descriptor", myInfos);
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return InspectionGadgetsBundle.message("replace.equality.with.safe.equals.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFix(Project project, ProblemDescriptor descriptor) {
|
||||
doSafeFixImpl(descriptor.getPsiElement());
|
||||
}
|
||||
}
|
||||
|
||||
private static class EqualsFix extends InspectionGadgetsFix {
|
||||
private final Object[] myInfos;
|
||||
|
||||
public EqualsFix(Object... infos) {
|
||||
myInfos = infos;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message("replace.equality.with.equals.descriptor", myInfos);
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return InspectionGadgetsBundle.message("replace.equality.with.equals.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFix(Project project, ProblemDescriptor descriptor) {
|
||||
doFixImpl(descriptor.getPsiElement());
|
||||
}
|
||||
}
|
||||
|
||||
private static class ObjectEqualityVisitor extends BaseInspectionVisitor {
|
||||
@Override
|
||||
public void visitBinaryExpression(PsiBinaryExpression expression) {
|
||||
super.visitBinaryExpression(expression);
|
||||
final IElementType tokenType = expression.getOperationTokenType();
|
||||
if (!tokenType.equals(JavaTokenType.NE) &&
|
||||
!tokenType.equals(JavaTokenType.EQEQ)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression lhs = expression.getLOperand();
|
||||
final PsiType lhsType = lhs.getType();
|
||||
if (lhsType == null || lhsType instanceof PsiPrimitiveType || TypeConversionUtil.isEnumType(lhsType)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression rhs = expression.getROperand();
|
||||
if (rhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType rhsType = rhs.getType();
|
||||
if (rhsType == null || rhsType instanceof PsiPrimitiveType || TypeConversionUtil.isEnumType(rhsType)) {
|
||||
return;
|
||||
}
|
||||
final String operationText = expression.getOperationSign().getText();
|
||||
final String prefix = tokenType.equals(JavaTokenType.NE) ? "!" : "";
|
||||
registerError(expression, operationText, prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<html>
|
||||
<body>
|
||||
This inspection reports <b>==</b> equality operators that compare two objects
|
||||
and offers to replace them with calls of the <b>.equals()</b> method or with the safe <b>.equals()</b> method construct.
|
||||
</body>
|
||||
</html>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class NegatedObjectOldSafeComparison {
|
||||
boolean a(Object a, Object b) {
|
||||
return a == null ? b != null : !a.equals(b);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class NegatedObjectOldSafeComparison {
|
||||
boolean a(Object a, Object b) {
|
||||
return a !=<caret> b;
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import java.util.Objects;
|
||||
|
||||
public class NegatedObjectSafeComparison {
|
||||
|
||||
boolean a(Object a, Object b) {
|
||||
return !Objects.equals(a, b);
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
public class NegatedObjectSafeComparison {
|
||||
|
||||
boolean a(Object a, Object b) {
|
||||
return a !=<caret> b;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
public class SimpleObjectComparison {
|
||||
|
||||
boolean a(Object a, Object b) {
|
||||
return a == b<caret>;
|
||||
return a == <caret>b;
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class SimpleObjectOldSafeComparison {
|
||||
boolean eq(Object a, Object b) {
|
||||
return a == null ? b == null : a.equals(b);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class SimpleObjectOldSafeComparison {
|
||||
boolean eq(Object a, Object b) {
|
||||
return a == <caret>b;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import java.util.Objects;
|
||||
|
||||
public class SimpleObjectSafeComparison {
|
||||
boolean eq(Object a, Object b) {
|
||||
return Objects.equals(a, b);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class SimpleObjectSafeComparison {
|
||||
boolean eq(Object a, Object b) {
|
||||
return a == <caret>b;
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.equality;
|
||||
|
||||
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.equality.ReplaceEqualityWithEqualsInspection;
|
||||
|
||||
/**
|
||||
* @see ReplaceEqualityWithEqualsInspection
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class ReplaceEqualityWithEqualsInspectionTest extends IGQuickFixesTestCase {
|
||||
|
||||
public void testEnumComparison() { assertQuickfixNotAvailable(); }
|
||||
public void testNullComparison() { assertQuickfixNotAvailable(); }
|
||||
public void testPrimitiveComparison() { assertQuickfixNotAvailable(); }
|
||||
public void testSimpleObjectComparison() { doTest(InspectionGadgetsBundle.message("replace.equality.with.equals.descriptor", "==", "")); }
|
||||
public void testNegatedObjectComparison() { doTest(InspectionGadgetsBundle.message("replace.equality.with.equals.descriptor", "!=", "!")); }
|
||||
|
||||
public void testSimpleObjectSafeComparison() { doTest(InspectionGadgetsBundle.message("replace.equality.with.safe.equals.descriptor", "==", "")); }
|
||||
public void testNegatedObjectSafeComparison() { doTest(InspectionGadgetsBundle.message("replace.equality.with.safe.equals.descriptor", "!=", "!")); }
|
||||
public void testSimpleObjectOldSafeComparison() { doTest(InspectionGadgetsBundle.message("replace.equality.with.safe.equals.descriptor", "==", "")); }
|
||||
public void testNegatedObjectOldSafeComparison() { doTest(InspectionGadgetsBundle.message("replace.equality.with.safe.equals.descriptor", "!=", "!")); }
|
||||
|
||||
@Override
|
||||
protected void tuneFixture(JavaModuleFixtureBuilder builder) throws Exception {
|
||||
super.tuneFixture(builder);
|
||||
if (getTestName(false).contains("Old")) {
|
||||
builder.setLanguageLevel(LanguageLevel.JDK_1_6);
|
||||
}
|
||||
else if (getTestName(false).contains("Safe")) {
|
||||
builder.addJdk(IdeaTestUtil.getMockJdk18Path().getPath()); // MockJdk17 would work if it contained java.util.Objects
|
||||
builder.setLanguageLevel(LanguageLevel.JDK_1_7);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myFixture.enableInspections(new ReplaceEqualityWithEqualsInspection());
|
||||
myDefaultHint = "Replace";
|
||||
myRelativePath = "equality/replace_equality_with_equals";
|
||||
}
|
||||
}
|
||||
@@ -91,18 +91,6 @@
|
||||
<categoryKey>intention.category.boolean</categoryKey>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>com.siyeh.ipp.equality.ReplaceEqualityWithEqualsIntention</className>
|
||||
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
|
||||
<categoryKey>intention.category.boolean</categoryKey>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>com.siyeh.ipp.equality.ReplaceEqualityWithSafeEqualsIntention</className>
|
||||
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
|
||||
<categoryKey>intention.category.boolean</categoryKey>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>com.siyeh.ipp.trivialif.ExpandBooleanIntention</className>
|
||||
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
|
||||
|
||||
@@ -11,9 +11,6 @@ merge.else.if.intention.name=Merge 'else if'
|
||||
merge.else.if.intention.family.name=Merge Else If
|
||||
change.to.end.of.line.comment.intention.name=Replace with end-of-line comment
|
||||
change.to.end.of.line.comment.intention.family.name=Replace with End Of Line Comment
|
||||
replace.equality.with.safe.equals.intention.name=Replace '==' with safe '.equals()'
|
||||
replace.equality.with.safe.not.equals.intention.name=Replace '!=' with safe '!equals()'
|
||||
replace.equality.with.safe.equals.intention.family.name=Replace Equality with Safe Equals
|
||||
replace.for.each.loop.with.indexed.for.loop.intention.name=Replace 'for each' loop with indexed 'for' loop
|
||||
replace.for.each.loop.with.iterator.for.loop.intention.name=Replace 'for each' loop with iterator 'for' loop
|
||||
replace.for.each.loop.with.indexed.for.loop.intention.family.name=Replace For-each Loop with Indexed For Loop
|
||||
@@ -79,9 +76,6 @@ char.to.string.intention.name=Replace character literal with string
|
||||
char.to.string.intention.family.name=Replace Char with String
|
||||
replace.if.with.conditional.intention.name=Replace 'if else' with '?:'
|
||||
replace.if.with.conditional.intention.family.name=Replace If Else with Conditional
|
||||
replace.equality.with.equals.intention.name=Replace '==' with 'equals()'
|
||||
replace.equality.with.not.equals.intention.name=Replace '!=' with '!equals()'
|
||||
replace.equality.with.equals.intention.family.name=Replace Equality with Equals
|
||||
make.call.chain.into.call.sequence.intention.name=Make method call chain into call sequence
|
||||
make.call.chain.into.call.sequence.intention.family.name=Make Call Chain Into Call Sequence
|
||||
merge.call.sequence.to.chain.intention.name=Merge sequential method calls into call chain
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* 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.ipp.equality;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||
|
||||
class ObjectEqualityPredicate implements PsiElementPredicate {
|
||||
|
||||
public boolean satisfiedBy(PsiElement element) {
|
||||
if (!(element instanceof PsiBinaryExpression)) {
|
||||
return false;
|
||||
}
|
||||
final PsiBinaryExpression expression = (PsiBinaryExpression)element;
|
||||
final IElementType tokenType = expression.getOperationTokenType();
|
||||
if (!tokenType.equals(JavaTokenType.NE) &&
|
||||
!tokenType.equals(JavaTokenType.EQEQ)) {
|
||||
return false;
|
||||
}
|
||||
final PsiExpression lhs = expression.getLOperand();
|
||||
final PsiType lhsType = lhs.getType();
|
||||
if (lhsType == null || lhsType instanceof PsiPrimitiveType || TypeConversionUtil.isEnumType(lhsType)) {
|
||||
return false;
|
||||
}
|
||||
final PsiExpression rhs = expression.getROperand();
|
||||
if (rhs == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiType rhsType = rhs.getType();
|
||||
return !(rhsType == null || rhsType instanceof PsiPrimitiveType || TypeConversionUtil.isEnumType(rhsType));
|
||||
}
|
||||
}
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* 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.ipp.equality;
|
||||
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.psi.PsiBinaryExpression;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.siyeh.IntentionPowerPackBundle;
|
||||
import com.siyeh.ig.PsiReplacementUtil;
|
||||
import com.siyeh.ig.psiutils.ParenthesesUtils;
|
||||
import com.siyeh.ipp.base.MutablyNamedIntention;
|
||||
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ReplaceEqualityWithEqualsIntention extends MutablyNamedIntention {
|
||||
|
||||
@Override
|
||||
protected String getTextForElement(PsiElement element) {
|
||||
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)element;
|
||||
final IElementType tokenType = binaryExpression.getOperationTokenType();
|
||||
if (JavaTokenType.NE.equals(tokenType)) {
|
||||
return IntentionPowerPackBundle.message("replace.equality.with.not.equals.intention.name");
|
||||
}
|
||||
else {
|
||||
return IntentionPowerPackBundle.message("replace.equality.with.equals.intention.name");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiElementPredicate getElementPredicate() {
|
||||
return new ObjectEqualityPredicate();
|
||||
}
|
||||
|
||||
public void processIntention(@NotNull PsiElement element) {
|
||||
final PsiBinaryExpression exp = (PsiBinaryExpression)element;
|
||||
final PsiExpression lhs = exp.getLOperand();
|
||||
final PsiExpression rhs = exp.getROperand();
|
||||
if (rhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression strippedLhs = ParenthesesUtils.stripParentheses(lhs);
|
||||
if (strippedLhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression strippedRhs = ParenthesesUtils.stripParentheses(rhs);
|
||||
if (strippedRhs == null) {
|
||||
return;
|
||||
}
|
||||
final String lhText = strippedLhs.getText();
|
||||
final String rhText = strippedRhs.getText();
|
||||
|
||||
final String prefix = exp.getOperationTokenType().equals(JavaTokenType.EQEQ) ? "" : "!";
|
||||
@NonNls final String expString;
|
||||
if (ParenthesesUtils.getPrecedence(strippedLhs) > ParenthesesUtils.METHOD_CALL_PRECEDENCE) {
|
||||
expString = prefix + '(' + lhText + ").equals(" + rhText + ')';
|
||||
}
|
||||
else {
|
||||
expString = prefix + lhText + ".equals(" + rhText + ')';
|
||||
}
|
||||
PsiReplacementUtil.replaceExpression(exp, expString);
|
||||
}
|
||||
}
|
||||
-92
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* 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.ipp.equality;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.IntentionPowerPackBundle;
|
||||
import com.siyeh.ig.PsiReplacementUtil;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import com.siyeh.ig.psiutils.ParenthesesUtils;
|
||||
import com.siyeh.ipp.base.MutablyNamedIntention;
|
||||
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ReplaceEqualityWithSafeEqualsIntention extends MutablyNamedIntention {
|
||||
|
||||
@Override
|
||||
protected String getTextForElement(PsiElement element) {
|
||||
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)element;
|
||||
if (JavaTokenType.NE.equals(binaryExpression.getOperationTokenType())) {
|
||||
return IntentionPowerPackBundle.message("replace.equality.with.safe.not.equals.intention.name");
|
||||
}
|
||||
else {
|
||||
return IntentionPowerPackBundle.message("replace.equality.with.safe.equals.intention.name");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiElementPredicate getElementPredicate() {
|
||||
return new ObjectEqualityPredicate();
|
||||
}
|
||||
|
||||
public void processIntention(PsiElement element) {
|
||||
final PsiBinaryExpression exp = (PsiBinaryExpression)element;
|
||||
final PsiExpression lhs = exp.getLOperand();
|
||||
final PsiExpression rhs = exp.getROperand();
|
||||
if (rhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression strippedLhs =
|
||||
ParenthesesUtils.stripParentheses(lhs);
|
||||
if (strippedLhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression strippedRhs =
|
||||
ParenthesesUtils.stripParentheses(rhs);
|
||||
if (strippedRhs == null) {
|
||||
return;
|
||||
}
|
||||
final String lhsText = strippedLhs.getText();
|
||||
final String rhsText = strippedRhs.getText();
|
||||
final PsiJavaToken operationSign = exp.getOperationSign();
|
||||
final IElementType tokenType = operationSign.getTokenType();
|
||||
final String signText = operationSign.getText();
|
||||
@NonNls final StringBuilder newExpression = new StringBuilder();
|
||||
if (PsiUtil.isLanguageLevel7OrHigher(element) && ClassUtils.findClass("java.util.Objects", element) != null) {
|
||||
if (tokenType.equals(JavaTokenType.NE)) {
|
||||
newExpression.append('!');
|
||||
}
|
||||
newExpression.append("java.util.Objects.equals(").append(lhsText).append(',').append(rhsText).append(')');
|
||||
}
|
||||
else {
|
||||
newExpression.append(lhsText).append("==null?").append(rhsText).append(signText).append(" null:");
|
||||
if (tokenType.equals(JavaTokenType.NE)) {
|
||||
newExpression.append('!');
|
||||
}
|
||||
if (ParenthesesUtils.getPrecedence(strippedLhs) > ParenthesesUtils.METHOD_CALL_PRECEDENCE) {
|
||||
newExpression.append('(').append(lhsText).append(')');
|
||||
}
|
||||
else {
|
||||
newExpression.append(lhsText);
|
||||
}
|
||||
newExpression.append(".equals(").append(rhsText).append(')');
|
||||
}
|
||||
PsiReplacementUtil.replaceExpressionAndShorten(exp, newExpression.toString());
|
||||
}
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
public class X {
|
||||
boolean f(Object o) {
|
||||
return o.equals(this);
|
||||
}
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
public class X {
|
||||
boolean f(Object o) {
|
||||
return <spot>o == this</spot>;
|
||||
}
|
||||
}
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
<html><body>This intention replaces an <b>==</b> equality operator with an <b>equals()</b> method call.
|
||||
</body>
|
||||
</html>
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
public class X {
|
||||
boolean f(Object o) {
|
||||
return o == null ? o1 == null : o.equals(o1);
|
||||
}
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
public class X {
|
||||
boolean f(Object o, Object o1) {
|
||||
return <spot>o == o1</spot>;
|
||||
}
|
||||
}
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
<html><body>This intention replaces an <b>==</b> equality operator with a safe <b>equals()</b> method call construct.
|
||||
</body>
|
||||
</html>
|
||||
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
package com.siyeh.ipp.equality.replace_equality_with_safe_equals;
|
||||
|
||||
public class EnumComparison {
|
||||
|
||||
enum E { A, B }
|
||||
|
||||
boolean a(E a, E b) {
|
||||
return a ==<caret> b;
|
||||
}
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
package com.siyeh.ipp.equality.replace_equality_with_safe_equals;
|
||||
|
||||
public class NegatedObjectComparison {
|
||||
|
||||
boolean a(Object a, Object b) {
|
||||
return a !=<caret> b;
|
||||
}
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
package com.siyeh.ipp.equality.replace_equality_with_safe_equals;
|
||||
|
||||
public class NegatedObjectComparison {
|
||||
|
||||
boolean a(Object a, Object b) {
|
||||
return a == null ? b != null : !a.equals(b);
|
||||
}
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
package com.siyeh.ipp.equality.replace_equality_with_safe_equals;
|
||||
|
||||
public class NullComparison {
|
||||
|
||||
boolean a(Object a) {
|
||||
return a ==<caret> null;
|
||||
}
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
package com.siyeh.ipp.equality.replace_equality_with_safe_equals;
|
||||
|
||||
public class PrimitiveComparison {
|
||||
|
||||
boolean a(int i, int j) {
|
||||
return i <caret>== j;
|
||||
}
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
package com.siyeh.ipp.equality.replace_equality_with_safe_equals;
|
||||
|
||||
public class SimpleObjectComparison {
|
||||
|
||||
boolean a(Object a, Object b) {
|
||||
return a == b<caret>;
|
||||
}
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
package com.siyeh.ipp.equality.replace_equality_with_safe_equals;
|
||||
|
||||
public class SimpleObjectComparison {
|
||||
|
||||
boolean a(Object a, Object b) {
|
||||
return a == null ? b == null : a.equals(b);
|
||||
}
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* 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.ipp.equality;
|
||||
|
||||
import com.siyeh.IntentionPowerPackBundle;
|
||||
import com.siyeh.ipp.IPPTestCase;
|
||||
|
||||
/**
|
||||
* @see com.siyeh.ipp.equality.ReplaceEqualityWithEqualsIntention
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class ReplaceEqualityWithEqualsIntentionTest extends IPPTestCase {
|
||||
|
||||
public void testEnumComparison() { assertIntentionNotAvailable(); }
|
||||
public void testNullComparison() { assertIntentionNotAvailable(); }
|
||||
public void testPrimitiveComparison() { assertIntentionNotAvailable(); }
|
||||
public void testSimpleObjectComparison() { doTest(); }
|
||||
public void testNegatedObjectComparison() { doTest(IntentionPowerPackBundle.message("replace.equality.with.not.equals.intention.name")); }
|
||||
|
||||
@Override
|
||||
protected String getIntentionName() {
|
||||
return IntentionPowerPackBundle.message("replace.equality.with.equals.intention.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRelativePath() {
|
||||
return "equality/replace_equality_with_equals";
|
||||
}
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* 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.ipp.equality;
|
||||
|
||||
import com.siyeh.IntentionPowerPackBundle;
|
||||
import com.siyeh.ipp.IPPTestCase;
|
||||
|
||||
/**
|
||||
* @see com.siyeh.ipp.equality.ReplaceEqualityWithSafeEqualsIntention
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class ReplaceEqualityWithSafeEqualsIntentionTest extends IPPTestCase {
|
||||
|
||||
public void testEnumComparison() { assertIntentionNotAvailable(); }
|
||||
public void testNullComparison() { assertIntentionNotAvailable(); }
|
||||
public void testPrimitiveComparison() { assertIntentionNotAvailable(); }
|
||||
public void testSimpleObjectComparison() { doTest(); }
|
||||
public void testNegatedObjectComparison() { doTest(IntentionPowerPackBundle.message("replace.equality.with.safe.not.equals.intention.name")); }
|
||||
|
||||
@Override
|
||||
protected String getIntentionName() {
|
||||
return IntentionPowerPackBundle.message("replace.equality.with.safe.equals.intention.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRelativePath() {
|
||||
return "equality/replace_equality_with_safe_equals";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user