From 4c568edfc90c46b5fee53aa3323d62a4f026c545 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Mon, 25 Dec 2017 17:34:23 +0700 Subject: [PATCH] RedundantCollectionOperation: remove by index and contains before add/remove IDEA-182694 Inefficient uses of Collection/List.remove --- .../afterContainsRemove.java | 9 ++ .../afterContainsRemoveAnd.java | 10 ++ .../afterContainsRemoveAndAnd.java | 11 ++ .../afterRemoveByIndexSimple.java | 8 + .../afterRemoveByIndexVar.java | 8 + .../beforeContainsRemove.java | 10 ++ .../beforeContainsRemoveAnd.java | 10 ++ .../beforeContainsRemoveAndAnd.java | 11 ++ .../beforeContainsRemoveAndFirst.java | 10 ++ .../beforeRemoveByIndexSimple.java | 8 + .../beforeRemoveByIndexUsed.java | 9 ++ .../beforeRemoveByIndexVar.java | 9 ++ .../beforeRemoveByIndexWrongQualifier.java | 9 ++ .../siyeh/InspectionGadgetsBundle.properties | 4 + ...edundantCollectionOperationInspection.java | 149 +++++++++++++++++- 15 files changed, 267 insertions(+), 8 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterContainsRemove.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterContainsRemoveAnd.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterContainsRemoveAndAnd.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterRemoveByIndexSimple.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterRemoveByIndexVar.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemove.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemoveAnd.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemoveAndAnd.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemoveAndFirst.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexSimple.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexUsed.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexVar.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexWrongQualifier.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterContainsRemove.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterContainsRemove.java new file mode 100644 index 000000000000..a44351e3710c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterContainsRemove.java @@ -0,0 +1,9 @@ +// "Remove the 'contains' check" "true" +import java.util.List; + +class Test { + void test(List list, String key) { + /*contains!!!*/ + list.remove(/*remove!!!*/key); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterContainsRemoveAnd.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterContainsRemoveAnd.java new file mode 100644 index 000000000000..1d7c387042c4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterContainsRemoveAnd.java @@ -0,0 +1,10 @@ +// "Remove the 'contains' check" "true" +import java.util.List; + +class Test { + void test(List list, String key) { + if(key != null) { + list.remove(key); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterContainsRemoveAndAnd.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterContainsRemoveAndAnd.java new file mode 100644 index 000000000000..714397b41f07 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterContainsRemoveAndAnd.java @@ -0,0 +1,11 @@ +// "Remove the 'contains' check" "true" +import java.util.List; + +class Test { + void test(List list, String key) { + if(key !=/*nullcheck*/ null && !key./*check*/isEmpty() /*and*/ /*key*/ //line comment + ) { + list.remove(key); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterRemoveByIndexSimple.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterRemoveByIndexSimple.java new file mode 100644 index 000000000000..42f357bff46e --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterRemoveByIndexSimple.java @@ -0,0 +1,8 @@ +// "Use removal by object" "true" +import java.util.List; + +class Test { + void test(List list, String key) { + list.remove(key); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterRemoveByIndexVar.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterRemoveByIndexVar.java new file mode 100644 index 000000000000..fc70c33e5c39 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterRemoveByIndexVar.java @@ -0,0 +1,8 @@ +// "Use removal by object" "true" +import java.util.List; + +class Test { + void test(List list, String key) { + list.remove(key); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemove.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemove.java new file mode 100644 index 000000000000..b9b0dee481f6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemove.java @@ -0,0 +1,10 @@ +// "Remove the 'contains' check" "true" +import java.util.List; + +class Test { + void test(List list, String key) { + if(list.contains(/*contains!!!*/key)) { + list.remove(/*remove!!!*/key); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemoveAnd.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemoveAnd.java new file mode 100644 index 000000000000..e0748193a5fe --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemoveAnd.java @@ -0,0 +1,10 @@ +// "Remove the 'contains' check" "true" +import java.util.List; + +class Test { + void test(List list, String key) { + if(key != null && list.contains(key)) { + list.remove(key); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemoveAndAnd.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemoveAndAnd.java new file mode 100644 index 000000000000..4d1bef8240cb --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemoveAndAnd.java @@ -0,0 +1,11 @@ +// "Remove the 'contains' check" "true" +import java.util.List; + +class Test { + void test(List list, String key) { + if(key !=/*nullcheck*/ null && !key./*check*/isEmpty() && /*and*/ list.contains(/*key*/key//line comment + )) { + list.remove(key); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemoveAndFirst.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemoveAndFirst.java new file mode 100644 index 000000000000..444866c0742e --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeContainsRemoveAndFirst.java @@ -0,0 +1,10 @@ +// "Remove the 'contains' check" "false" +import java.util.List; + +class Test { + void test(List list, String key) { + if(list.contains(key) && key != null) { + list.remove(key); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexSimple.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexSimple.java new file mode 100644 index 000000000000..cca0cbbb1c76 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexSimple.java @@ -0,0 +1,8 @@ +// "Use removal by object" "true" +import java.util.List; + +class Test { + void test(List list, String key) { + list.remove(list.indexOf(key)); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexUsed.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexUsed.java new file mode 100644 index 000000000000..87387367db0b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexUsed.java @@ -0,0 +1,9 @@ +// "Use removal by object" "false" +import java.util.List; + +class Test { + void test(List list, String key) { + int idx = list.indexOf(key); + String x = list.remove(idx); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexVar.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexVar.java new file mode 100644 index 000000000000..e7001ecafc29 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexVar.java @@ -0,0 +1,9 @@ +// "Use removal by object" "true" +import java.util.List; + +class Test { + void test(List list, String key) { + int idx = list.indexOf(key); + list.remove(idx); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexWrongQualifier.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexWrongQualifier.java new file mode 100644 index 000000000000..1b8b35c601a8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeRemoveByIndexWrongQualifier.java @@ -0,0 +1,9 @@ +// "Use removal by object" "false" +import java.util.List; + +class Test { + void test(List list, List list2, String key) { + int idx = list.indexOf(key); + list2.remove(idx); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index 09a8cd476e07..88abb1068991 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -2247,6 +2247,10 @@ inspection.catch.ignores.exception.vm.ignored.message=Some important exceptions inspection.redundant.collection.operation.display.name=Redundant Collection operation inspection.redundant.collection.operation.fix.family.name=Simplify collection operation inspection.redundant.collection.operation.problem.arraycopy=Unnecessary collection created to copy an array +inspection.redundant.collection.removal.by.index.problem=Removal by index can be replaced with removal by object +inspection.redundant.collection.removal.by.index.fix=Use removal by object +inspection.redundant.collection.unnecessary.contains.problem=Unnecessary 'contains' check +inspection.redundant.collection.unnecessary.contains.fix=Remove the 'contains' check comments.as.content.option=Comments count as content copy.constructor.misses.field.display.name=Copy constructor misses field diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java index 777b3c4cdbb7..ffc33fd011c4 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java @@ -12,10 +12,7 @@ import com.intellij.util.ArrayUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.callMatcher.CallMapper; import com.siyeh.ig.callMatcher.CallMatcher; -import com.siyeh.ig.psiutils.CommentTracker; -import com.siyeh.ig.psiutils.ExpressionUtils; -import com.siyeh.ig.psiutils.MethodCallUtils; -import com.siyeh.ig.psiutils.ParenthesesUtils; +import com.siyeh.ig.psiutils.*; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -40,12 +37,22 @@ public class RedundantCollectionOperationInspection extends AbstractBaseJavaLoca instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "containsAll").parameterTypes(CommonClassNames.JAVA_UTIL_COLLECTION); private static final CallMatcher CONTAINS = instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "contains").parameterTypes(CommonClassNames.JAVA_LANG_OBJECT); + private static final CallMatcher REMOVE = + instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "remove").parameterTypes(CommonClassNames.JAVA_LANG_OBJECT); + private static final CallMatcher SET_ADD = + instanceCall(CommonClassNames.JAVA_UTIL_SET, "add").parameterTypes("E"); + private static final CallMatcher REMOVE_BY_INDEX = + instanceCall(CommonClassNames.JAVA_UTIL_LIST, "remove").parameterTypes("int"); + private static final CallMatcher INDEX_OF = + instanceCall(CommonClassNames.JAVA_UTIL_LIST, "indexOf").parameterTypes(CommonClassNames.JAVA_LANG_OBJECT); private static final CallMapper HANDLERS = new CallMapper() .register(TO_ARRAY, AsListToArrayHandler::handler) .register(CONTAINS_ALL, ContainsAllSingletonHandler::handler) - .register(CONTAINS, SingletonContainsHandler::handler); + .register(CONTAINS, SingletonContainsHandler::handler) + .register(CONTAINS, ContainsBeforeAddRemoveHandler::handler) + .register(REMOVE_BY_INDEX, RedundantIndexOfHandler::handler); @NotNull @Override @@ -70,9 +77,132 @@ public class RedundantCollectionOperationInspection extends AbstractBaseJavaLoca return InspectionGadgetsBundle.message("expression.can.be.replaced.problem.descriptor", getReplacement()); } - String getReplacement(); - void performFix(@NotNull Project project, @NotNull PsiMethodCallExpression call); + + @NotNull + default String getReplacement() { + throw new UnsupportedOperationException("Either getFixName or getReplacement must be defined in subclass: " + getClass()); + } + + @NotNull + default String getFixName() { + return InspectionGadgetsBundle.message("replace.with", getReplacement()); + } + } + + private static class RedundantIndexOfHandler implements RedundantCollectionOperationHandler { + + @Override + public String getProblemName() { + return InspectionGadgetsBundle.message("inspection.redundant.collection.removal.by.index.problem"); + } + + @NotNull + @Override + public String getFixName() { + return InspectionGadgetsBundle.message("inspection.redundant.collection.removal.by.index.fix"); + } + + @Override + public void performFix(@NotNull Project project, @NotNull PsiMethodCallExpression call) { + PsiExpression arg = call.getArgumentList().getExpressions()[0]; + PsiMethodCallExpression removeArg = + tryCast(ExpressionUtils.resolveExpression(arg), PsiMethodCallExpression.class); + if (removeArg == null) return; + PsiExpression indexOfArg = ArrayUtil.getFirstElement(removeArg.getArgumentList().getExpressions()); + if (indexOfArg == null) return; + CommentTracker ct = new CommentTracker(); + String text = ct.text(indexOfArg); + if (!PsiTreeUtil.isAncestor(call, removeArg, false)) { + PsiDeclarationStatement declaration = PsiTreeUtil.getParentOfType(removeArg, PsiDeclarationStatement.class); + if (declaration == null) return; + ct.delete(declaration); + } + ct.replaceAndRestoreComments(arg, text); + } + + public static RedundantCollectionOperationHandler handler(PsiMethodCallExpression call) { + PsiExpressionStatement statement = tryCast(call.getParent(), PsiExpressionStatement.class); + if (statement == null) return null; + PsiMethodCallExpression arg = + tryCast(ExpressionUtils.resolveExpression(call.getArgumentList().getExpressions()[0]), PsiMethodCallExpression.class); + if (!INDEX_OF.test(arg)) return null; + PsiExpression qualifier1 = call.getMethodExpression().getQualifierExpression(); + PsiExpression qualifier2 = arg.getMethodExpression().getQualifierExpression(); + if (qualifier1 == null || qualifier2 == null || !PsiEquivalenceUtil.areElementsEquivalent(qualifier1, qualifier2)) return null; + if (!PsiTreeUtil.isAncestor(statement, arg, true)) { + PsiDeclarationStatement declaration = PsiTreeUtil.getParentOfType(arg, PsiDeclarationStatement.class); + if (declaration == null || declaration.getDeclaredElements().length != 1) return null; + if (PsiTreeUtil.skipWhitespacesAndCommentsForward(declaration) != statement) return null; + } + return new RedundantIndexOfHandler(); + } + } + + private static class ContainsBeforeAddRemoveHandler implements RedundantCollectionOperationHandler { + @Override + public String getProblemName() { + return InspectionGadgetsBundle.message("inspection.redundant.collection.unnecessary.contains.problem"); + } + + @NotNull + @Override + public String getFixName() { + return InspectionGadgetsBundle.message("inspection.redundant.collection.unnecessary.contains.fix"); + } + + @Override + public void performFix(@NotNull Project project, @NotNull PsiMethodCallExpression call) { + PsiElement parent = PsiTreeUtil.getParentOfType(call, PsiIfStatement.class, PsiPolyadicExpression.class); + if (parent == null) return; + CommentTracker ct = new CommentTracker(); + if (parent instanceof PsiPolyadicExpression) { + PsiPolyadicExpression conjunction = (PsiPolyadicExpression)parent; + PsiExpression[] conjuncts = conjunction.getOperands(); + if (conjuncts.length == 2) { + ct.replaceAndRestoreComments(parent, ct.markUnchanged(conjuncts[0])); + } else { + PsiExpression lastConjunct = conjuncts[conjuncts.length-1]; + PsiJavaToken token = conjunction.getTokenBeforeOperand(lastConjunct); + if (token != null) { + ct.delete(token); + } + ct.deleteAndRestoreComments(lastConjunct); + } + } + else { + PsiIfStatement ifStatement = (PsiIfStatement)parent; + PsiExpressionStatement thenBody = tryCast(ControlFlowUtils.stripBraces(ifStatement.getThenBranch()), PsiExpressionStatement.class); + if (thenBody == null) return; + ct.replaceAndRestoreComments(ifStatement, ct.markUnchanged(thenBody)); + } + } + + public static RedundantCollectionOperationHandler handler(PsiMethodCallExpression call) { + PsiExpression qualifier1 = call.getMethodExpression().getQualifierExpression(); + if (qualifier1 == null) return null; + CallMatcher wantedMethod = REMOVE; + PsiElement parent = PsiUtil.skipParenthesizedExprUp(call.getParent()); + if (parent instanceof PsiExpression && BoolUtils.isNegation((PsiExpression)parent)) { + wantedMethod = SET_ADD; + parent = PsiUtil.skipParenthesizedExprUp(parent.getParent()); + } + if (parent instanceof PsiPolyadicExpression && ((PsiPolyadicExpression)parent).getOperationTokenType().equals(JavaTokenType.ANDAND) && + PsiTreeUtil.isAncestor(ArrayUtil.getLastElement(((PsiPolyadicExpression)parent).getOperands()), call, false)) { + parent = PsiUtil.skipParenthesizedExprUp(parent.getParent()); + } + PsiIfStatement ifStatement = tryCast(parent, PsiIfStatement.class); + if (ifStatement == null) return null; + if (ifStatement.getElseBranch() != null) return null; + PsiExpressionStatement thenBody = tryCast(ControlFlowUtils.stripBraces(ifStatement.getThenBranch()), PsiExpressionStatement.class); + if (thenBody == null) return null; + PsiMethodCallExpression thenCall = tryCast(thenBody.getExpression(), PsiMethodCallExpression.class); + if (!wantedMethod.test(thenCall)) return null; + PsiExpression qualifier2 = thenCall.getMethodExpression().getQualifierExpression(); + if (qualifier2 == null || !PsiEquivalenceUtil.areElementsEquivalent(qualifier1, qualifier2)) return null; + if (!PsiEquivalenceUtil.areElementsEquivalent(call.getArgumentList(), thenCall.getArgumentList())) return null; + return new ContainsBeforeAddRemoveHandler(); + } } private static class AsListToArrayHandler implements RedundantCollectionOperationHandler { @@ -110,6 +240,7 @@ public class RedundantCollectionOperationInspection extends AbstractBaseJavaLoca return InspectionGadgetsBundle.message("inspection.redundant.collection.operation.problem.arraycopy"); } + @NotNull @Override public String getReplacement() { return myReplacementMethod; @@ -191,6 +322,7 @@ public class RedundantCollectionOperationInspection extends AbstractBaseJavaLoca } private static class ContainsAllSingletonHandler implements RedundantCollectionOperationHandler { + @NotNull @Override public String getReplacement() { return "contains"; @@ -218,6 +350,7 @@ public class RedundantCollectionOperationInspection extends AbstractBaseJavaLoca } private static class SingletonContainsHandler implements RedundantCollectionOperationHandler { + @NotNull @Override public String getReplacement() { return "Objects.equals"; @@ -255,7 +388,7 @@ public class RedundantCollectionOperationInspection extends AbstractBaseJavaLoca @NotNull @Override public String getName() { - return InspectionGadgetsBundle.message("replace.with", myHandler.getReplacement()); + return myHandler.getFixName(); } @Nls