diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterMapKeySetContains.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterMapKeySetContains.java new file mode 100644 index 000000000000..7a33e555d87d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterMapKeySetContains.java @@ -0,0 +1,10 @@ +// "Replace with 'Map.containsKey()'" "true" +import java.util.Map; + +class Test { + void test(Map map, String key) { + if(map.containsKey(key)) { + System.out.println("contains"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterMapValuesContains.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterMapValuesContains.java new file mode 100644 index 000000000000..69880ce4d1e9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterMapValuesContains.java @@ -0,0 +1,10 @@ +// "Replace with 'Map.containsValue()'" "true" +import java.util.Map; + +class Test { + void test(Map map, String key) { + if(map.containsValue(key)) { + System.out.println("contains"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeMapKeySetContains.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeMapKeySetContains.java new file mode 100644 index 000000000000..94266af649fe --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeMapKeySetContains.java @@ -0,0 +1,10 @@ +// "Replace with 'Map.containsKey()'" "true" +import java.util.Map; + +class Test { + void test(Map map, String key) { + if(map.keySet().contains(key)) { + System.out.println("contains"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeMapValuesContains.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeMapValuesContains.java new file mode 100644 index 000000000000..beae61d5ba0f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeMapValuesContains.java @@ -0,0 +1,10 @@ +// "Replace with 'Map.containsValue()'" "true" +import java.util.Map; + +class Test { + void test(Map map, String key) { + if(map.values().contains(key)) { + System.out.println("contains"); + } + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java index 371b99b0dd4c..4181e746a2e8 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java @@ -60,12 +60,15 @@ public class RedundantCollectionOperationInspection extends AbstractBaseJavaLoca private static final CallMatcher LIST_SORT = instanceCall(CommonClassNames.JAVA_UTIL_LIST, "sort").parameterTypes( CommonClassNames.JAVA_UTIL_COMPARATOR); private static final CallMatcher ITERABLE_ITERATOR = instanceCall(CommonClassNames.JAVA_LANG_ITERABLE, "iterator").parameterCount(0); + private static final CallMatcher MAP_KEY_SET = instanceCall(CommonClassNames.JAVA_UTIL_MAP, "keySet").parameterCount(0); + private static final CallMatcher MAP_VALUES = instanceCall(CommonClassNames.JAVA_UTIL_MAP, "values").parameterCount(0); private static final CallMapper HANDLERS = new CallMapper() .register(TO_ARRAY, AsListToArrayHandler::handler) .register(CONTAINS_ALL, ContainsAllSingletonHandler::handler) .register(CONTAINS, SingletonContainsHandler::handler) + .register(CONTAINS, MapKeySetContainsHandler::handler) .register(anyOf(CONTAINS, CONTAINS_KEY), ContainsBeforeAddRemoveHandler::handler) .register(REMOVE_BY_INDEX, RedundantIndexOfHandler::handler) .register(AS_LIST, RedundantAsListForIterationHandler::handler) @@ -403,6 +406,48 @@ public class RedundantCollectionOperationInspection extends AbstractBaseJavaLoca } } + private static class MapKeySetContainsHandler implements RedundantCollectionOperationHandler { + private final String myReplacementMethod; + + private MapKeySetContainsHandler(String method) { + myReplacementMethod = method; + } + + @NotNull + @Override + public String getReplacement() { + return "Map." + myReplacementMethod + "()"; + } + + @Override + public void performFix(@NotNull Project project, @NotNull PsiMethodCallExpression call) { + PsiMethodCallExpression qualifierCall = MethodCallUtils.getQualifierMethodCall(call); + if (qualifierCall == null) return; + PsiExpression mapExpression = qualifierCall.getMethodExpression().getQualifierExpression(); + if (mapExpression == null) return; + CommentTracker ct = new CommentTracker(); + ct.replaceAndRestoreComments(qualifierCall, mapExpression); + ExpressionUtils.bindCallTo(call, myReplacementMethod); + } + + static RedundantCollectionOperationHandler handler(PsiMethodCallExpression call) { + PsiMethodCallExpression qualifierCall = MethodCallUtils.getQualifierMethodCall(call); + String replacementMethod; + if (MAP_KEY_SET.test(qualifierCall)) { + replacementMethod = "containsKey"; + } + else if (MAP_VALUES.test(qualifierCall)) { + replacementMethod = "containsValue"; + } + else { + return null; + } + PsiExpression mapExpression = qualifierCall.getMethodExpression().getQualifierExpression(); + if (mapExpression == null) return null; + return new MapKeySetContainsHandler(replacementMethod); + } + } + private static class RedundantAsListForIterationHandler implements RedundantCollectionOperationHandler { @Override public String getProblemName() {