[java-inspections] Redundant keySet()/values(): support entrySet(); avoid warning inside Map implementations (IDEA-346005)

GitOrigin-RevId: ebf925ab3ff7c1357248a65201fe654aada0f4e8
This commit is contained in:
Tagir Valeev
2024-09-19 12:36:40 +02:00
committed by intellij-monorepo-bot
parent 6e23889cc9
commit be4f6cd282
3 changed files with 31 additions and 1 deletions

View File

@@ -72,6 +72,7 @@ public final class RedundantCollectionOperationInspection extends AbstractBaseJa
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 CallMatcher MAP_ENTRY_SET = instanceCall(CommonClassNames.JAVA_UTIL_MAP, "entrySet").parameterCount(0);
private static final CallMatcher MAP_PUT_ALL =
instanceCall(CommonClassNames.JAVA_UTIL_MAP, "putAll").parameterTypes(CommonClassNames.JAVA_UTIL_MAP);
private static final CallMatcher MAP_OF =
@@ -93,7 +94,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(anyOf(MAP_KEY_SET, MAP_VALUES, MAP_ENTRY_SET), 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"));
@@ -454,6 +455,11 @@ public final class RedundantCollectionOperationInspection extends AbstractBaseJa
}
static RedundantMapViewHandler handler(PsiMethodCallExpression call) {
PsiExpression qualifier = call.getMethodExpression().getQualifierExpression();
if (qualifier == null || qualifier instanceof PsiThisExpression) {
// We are inside Map implementation
return null;
}
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")) {

View File

@@ -3,13 +3,25 @@ import java.util.*;
class Test {
void test(Map<String, String> map) {
if (map.isEmpty()) return;
if (map.isEmpty()) return;
if (map.isEmpty()) return;
map.remove("oops");
map.values().remove("oops");
map.entrySet().remove("oops");
if (map.size() > 10) return;
if (map.size() > 10) return;
if (map.size() > 10) return;
map.clear();
map.clear();
map.clear();
}
static abstract class MyMap extends AbstractMap<String, String> {
public int size() {
return keySet().size();
}
abstract public Set<K> keySet();
}
}

View File

@@ -5,11 +5,23 @@ class Test {
void test(Map<String, String> map) {
if (map.ke<caret>ySet().isEmpty()) return;
if (map.values().isEmpty()) return;
if (map.entrySet().isEmpty()) return;
map.keySet().remove("oops");
map.values().remove("oops");
map.entrySet().remove("oops");
if (map.keySet().size() > 10) return;
if (map.values().size() > 10) return;
if (map.entrySet().size() > 10) return;
map.keySet().clear();
map.values().clear();
map.entrySet().clear();
}
static abstract class MyMap extends AbstractMap<String, String> {
public int size() {
return keySet().size();
}
abstract public Set<K> keySet();
}
}