diff --git a/java/java-analysis-impl/resources/messages/InspectionGadgetsBundle.properties b/java/java-analysis-impl/resources/messages/InspectionGadgetsBundle.properties
index 6c8ec16f6663..613869c74c63 100644
--- a/java/java-analysis-impl/resources/messages/InspectionGadgetsBundle.properties
+++ b/java/java-analysis-impl/resources/messages/InspectionGadgetsBundle.properties
@@ -2182,7 +2182,7 @@ inspection.replace.on.literal.display.name=Replacement operation has no effect
inspection.redundant.string.operation.display.name=Redundant 'String' operation
inspection.redundant.embedded.expression.display.name=Redundant embedded expression in string template
inspection.redundant.string.fix.remove.str.processor.description=String template can be converted to a plain string literal
-inspection.redundant.string.remove.fix.name=Remove redundant ''{0}()'' call
+inspection.remove.redundant.call.fix.name=Remove redundant ''{0}()'' call
inspection.redundant.string.fix.family.name=Remove redundant call
inspection.redundant.string.call.message=Call to #ref() is redundant #loc
inspection.redundant.empty.string.argument.message=Unnecessary empty string argument
diff --git a/java/java-analysis-impl/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java b/java/java-analysis-impl/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java
index b330134b2099..af3e44e9f325 100644
--- a/java/java-analysis-impl/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java
+++ b/java/java-analysis-impl/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java
@@ -5,11 +5,11 @@ import com.intellij.codeInsight.Nullability;
import com.intellij.codeInspection.CleanupLocalInspectionTool;
import com.intellij.codeInspection.CommonQuickFixBundle;
import com.intellij.codeInspection.LocalQuickFix;
-import com.intellij.modcommand.PsiUpdateModCommandQuickFix;
import com.intellij.codeInspection.dataFlow.NullabilityUtil;
import com.intellij.codeInspection.options.OptPane;
import com.intellij.java.analysis.JavaAnalysisBundle;
import com.intellij.modcommand.ModPsiUpdater;
+import com.intellij.modcommand.PsiUpdateModCommandQuickFix;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
@@ -61,7 +61,7 @@ public final class UnnecessaryToStringCallInspection extends BaseInspection impl
@NotNull
public String getName() {
if (replacementText == null) {
- return InspectionGadgetsBundle.message("inspection.redundant.string.remove.fix.name", "toString");
+ return InspectionGadgetsBundle.message("inspection.remove.redundant.call.fix.name", "toString");
}
return CommonQuickFixBundle.message("fix.replace.with.x", replacementText);
}
diff --git a/java/java-impl-inspections/src/com/intellij/codeInspection/RedundantStreamOptionalCallInspection.java b/java/java-impl-inspections/src/com/intellij/codeInspection/RedundantStreamOptionalCallInspection.java
index 3573702ed38b..aa9f334b84b5 100644
--- a/java/java-impl-inspections/src/com/intellij/codeInspection/RedundantStreamOptionalCallInspection.java
+++ b/java/java-impl-inspections/src/com/intellij/codeInspection/RedundantStreamOptionalCallInspection.java
@@ -127,7 +127,7 @@ public final class RedundantStreamOptionalCallInspection extends AbstractBaseJav
PsiMethodCallExpression qualifierCall = MethodCallUtils.getQualifierMethodCall(call);
if (STREAM_MAP.test(qualifierCall) && qualifierCall.getMethodExpression().getTypeParameters().length == 0 &&
!isIdentityMapping(qualifierCall.getArgumentList().getExpressions()[0], false)) {
- String message = JavaBundle.message("inspection.redundant.stream.optional.call.message", name) +
+ String message = JavaBundle.message("inspection.call.message", name) +
": " + JavaBundle.message("inspection.redundant.stream.optional.call.explanation.map.flatMap");
holder.registerProblem(call, message, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, getRange(call),
new RemoveCallFix(name, "map"));
@@ -284,7 +284,7 @@ public final class RedundantStreamOptionalCallInspection extends AbstractBaseJav
String methodName = Objects.requireNonNull(call.getMethodExpression().getReferenceName());
String message = explanation != null
? JavaBundle.message("inspection.redundant.stream.optional.call.message.with.explanation", methodName, explanation)
- : JavaBundle.message("inspection.redundant.stream.optional.call.message", methodName);
+ : JavaBundle.message("inspection.call.message", methodName);
holder.registerProblem(call, message, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, getRange(call),
ArrayUtil.prepend(new RemoveCallFix(methodName), additionalFixes));
}
diff --git a/java/java-impl/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java b/java/java-impl/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java
index 184092923929..a22be2b04f0a 100644
--- a/java/java-impl/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java
+++ b/java/java-impl/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java
@@ -5,6 +5,7 @@ import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.util.InspectionMessage;
import com.intellij.codeInspection.util.IntentionName;
+import com.intellij.java.JavaBundle;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.PsiUpdateModCommandQuickFix;
import com.intellij.openapi.project.Project;
@@ -25,6 +26,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.List;
+import java.util.Objects;
import static com.intellij.util.ObjectUtils.tryCast;
import static com.siyeh.ig.callMatcher.CallMatcher.*;
@@ -78,7 +80,9 @@ public final class RedundantCollectionOperationInspection extends AbstractBaseJa
staticCall(CommonClassNames.JAVA_UTIL_COLLECTIONS, "singletonMap").parameterCount(2));
private static final CallMatcher COLLECTION_ADD_ALL =
instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "addAll").parameterTypes(CommonClassNames.JAVA_UTIL_COLLECTION);
-
+ private static final CallMatcher MAP_METHODS_SAME_ON_VIEW =
+ instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "size", "isEmpty", "clear").parameterCount(0);
+
private static final CallMapper HANDLERS =
new CallMapper()
.register(TO_ARRAY, AsListToArrayHandler::handler)
@@ -89,6 +93,7 @@ public final class RedundantCollectionOperationInspection extends AbstractBaseJa
.register(REMOVE_BY_INDEX, RedundantIndexOfHandler::handler)
.register(AS_LIST, RedundantAsListForIterationHandler::handler)
.register(AS_LIST, RedundantSortAsListHandler::handler)
+ .register(anyOf(MAP_KEY_SET, MAP_VALUES), RedundantMapViewHandler::handler)
.register(ITERABLE_ITERATOR, RedundantEmptyIteratorHandler::handler)
.register(MAP_PUT_ALL, call -> ReplaceNestedCallHandler.handler(call, MAP_OF, "put"))
.register(COLLECTION_ADD_ALL, call -> ReplaceNestedCallHandler.handler(call, SINGLETON, "add"));
@@ -423,6 +428,41 @@ public final class RedundantCollectionOperationInspection extends AbstractBaseJa
}
}
+ private static final class RedundantMapViewHandler implements RedundantCollectionOperationHandler {
+ private final @NotNull String myName;
+
+ private RedundantMapViewHandler(@NotNull String name) {
+ this.myName = name;
+ }
+
+ @Override
+ public void performFix(@NotNull Project project, @NotNull PsiMethodCallExpression call) {
+ PsiExpression qualifier = call.getMethodExpression().getQualifierExpression();
+ if (qualifier != null) {
+ new CommentTracker().replaceAndRestoreComments(call, qualifier);
+ }
+ }
+
+ @Override
+ public String getProblemName() {
+ return JavaBundle.message("inspection.call.message", myName);
+ }
+
+ @Override
+ public @NotNull String getFixName() {
+ return InspectionGadgetsBundle.message("inspection.remove.redundant.call.fix.name", myName);
+ }
+
+ static RedundantMapViewHandler handler(PsiMethodCallExpression call) {
+ PsiMethodCallExpression nextCall = ExpressionUtils.getCallForQualifier(call);
+ String callName = Objects.requireNonNull(call.getMethodExpression().getReferenceName());
+ if (MAP_METHODS_SAME_ON_VIEW.test(nextCall) || COLLECTION_REMOVE.test(nextCall) && callName.equals("keySet")) {
+ return new RedundantMapViewHandler(callName);
+ }
+ return null;
+ }
+ }
+
private static final class MapKeySetContainsHandler implements RedundantCollectionOperationHandler {
private final String myReplacementMethod;
diff --git a/java/java-impl/src/com/siyeh/ig/redundancy/RedundantStringOperationInspection.java b/java/java-impl/src/com/siyeh/ig/redundancy/RedundantStringOperationInspection.java
index 4c26eb5f1cb8..3941ff9f2655 100644
--- a/java/java-impl/src/com/siyeh/ig/redundancy/RedundantStringOperationInspection.java
+++ b/java/java-impl/src/com/siyeh/ig/redundancy/RedundantStringOperationInspection.java
@@ -927,7 +927,7 @@ public final class RedundantStringOperationInspection extends AbstractBaseJavaLo
@Override
public @Nls @NotNull String getName() {
- return InspectionGadgetsBundle.message("inspection.redundant.string.remove.fix.name", myToRemove);
+ return InspectionGadgetsBundle.message("inspection.remove.redundant.call.fix.name", myToRemove);
}
@Override
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterMapKeySetValues.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterMapKeySetValues.java
new file mode 100644
index 000000000000..504fcfdda281
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterMapKeySetValues.java
@@ -0,0 +1,15 @@
+// "Fix all 'Redundant 'Collection' operation' problems in file" "true"
+import java.util.*;
+
+class Test {
+ void test(Map map) {
+ if (map.isEmpty()) return;
+ if (map.isEmpty()) return;
+ map.remove("oops");
+ map.values().remove("oops");
+ if (map.size() > 10) return;
+ if (map.size() > 10) return;
+ map.clear();
+ map.clear();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeMapKeySetValues.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeMapKeySetValues.java
new file mode 100644
index 000000000000..e99ec0722eec
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeMapKeySetValues.java
@@ -0,0 +1,15 @@
+// "Fix all 'Redundant 'Collection' operation' problems in file" "true"
+import java.util.*;
+
+class Test {
+ void test(Map map) {
+ if (map.keySet().isEmpty()) return;
+ if (map.values().isEmpty()) return;
+ map.keySet().remove("oops");
+ map.values().remove("oops");
+ if (map.keySet().size() > 10) return;
+ if (map.values().size() > 10) return;
+ map.keySet().clear();
+ map.values().clear();
+ }
+}
\ No newline at end of file
diff --git a/java/openapi/resources/messages/JavaBundle.properties b/java/openapi/resources/messages/JavaBundle.properties
index 745953f29054..50ed2230b6ac 100644
--- a/java/openapi/resources/messages/JavaBundle.properties
+++ b/java/openapi/resources/messages/JavaBundle.properties
@@ -645,7 +645,7 @@ inspection.redundant.stream.optional.call.fix.bind.name=Merge the ''{0}()'' step
inspection.redundant.stream.optional.call.fix.name=Remove ''{0}()'' call
inspection.redundant.stream.optional.call.fix.replace.terminal=Replace the terminal operation
inspection.redundant.stream.optional.call.fix.replace.terminal.text=Replace the terminal operation with ''{0}()''
-inspection.redundant.stream.optional.call.message=Redundant ''{0}()'' call
+inspection.call.message=Redundant ''{0}()'' call
inspection.redundant.stream.optional.call.message.with.explanation=Redundant ''{0}()'' call: {1}
inspection.redundant.stream.optional.call.option.streamboxing=Report redundant boxing in Stream.map()
inspection.reflect.handle.invocation.argument.not.array=Argument is not an array type