diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterEmptyIterator.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterEmptyIterator.java new file mode 100644 index 000000000000..a23363cbb36f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/afterEmptyIterator.java @@ -0,0 +1,8 @@ +// "Replace with 'Collections.emptyIterator()'" "true" +import java.util.*; + +class Test { + Iterator test() { + return Collections.emptyIterator(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeEmptyIterator.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeEmptyIterator.java new file mode 100644 index 000000000000..980f6722220b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantCollectionOperation/beforeEmptyIterator.java @@ -0,0 +1,8 @@ +// "Replace with 'Collections.emptyIterator()'" "true" +import java.util.*; + +class Test { + Iterator test() { + return new ArrayList().iterator(); + } +} \ 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 d93dc5852b6c..27cc34a0e503 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantCollectionOperationInspection.java @@ -35,6 +35,11 @@ public class RedundantCollectionOperationInspection extends AbstractBaseJavaLoca staticCall(CommonClassNames.JAVA_UTIL_COLLECTIONS, "singleton", "singletonList").parameterCount(1), staticCall(CommonClassNames.JAVA_UTIL_LIST, "of").parameterTypes("E"), staticCall(CommonClassNames.JAVA_UTIL_SET, "of").parameterTypes("E")); + private static final CallMatcher EMPTY_COLLECTION = + anyOf( + staticCall(CommonClassNames.JAVA_UTIL_COLLECTIONS, "emptyList", "emptySet").parameterCount(0), + staticCall(CommonClassNames.JAVA_UTIL_LIST, "of").parameterCount(0), + staticCall(CommonClassNames.JAVA_UTIL_SET, "of").parameterCount(0)); private static final CallMatcher CONTAINS_ALL = instanceCall(CommonClassNames.JAVA_UTIL_COLLECTION, "containsAll").parameterTypes(CommonClassNames.JAVA_UTIL_COLLECTION); private static final CallMatcher CONTAINS = @@ -54,6 +59,7 @@ public class RedundantCollectionOperationInspection extends AbstractBaseJavaLoca private static final CallMatcher COLLECTIONS_SORT = staticCall(CommonClassNames.JAVA_UTIL_COLLECTIONS, "sort"); 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 CallMapper HANDLERS = new CallMapper() @@ -63,7 +69,8 @@ public class RedundantCollectionOperationInspection extends AbstractBaseJavaLoca .register(anyOf(CONTAINS, CONTAINS_KEY), ContainsBeforeAddRemoveHandler::handler) .register(REMOVE_BY_INDEX, RedundantIndexOfHandler::handler) .register(AS_LIST, RedundantAsListForIterationHandler::handler) - .register(AS_LIST, RedundantSortAsListHandler::handler); + .register(AS_LIST, RedundantSortAsListHandler::handler) + .register(ITERABLE_ITERATOR, RedundantEmptyIteratorHandler::handler); @NotNull @Override @@ -517,6 +524,33 @@ public class RedundantCollectionOperationInspection extends AbstractBaseJavaLoca } } + private static class RedundantEmptyIteratorHandler implements RedundantCollectionOperationHandler { + @Override + public void performFix(@NotNull Project project, @NotNull PsiMethodCallExpression call) { + PsiType type = call.getType(); + PsiType elementType = PsiUtil.substituteTypeParameter(type, CommonClassNames.JAVA_UTIL_ITERATOR, 0, false); + elementType = GenericsUtil.getVariableTypeByExpressionType(elementType); + String replacement = CommonClassNames.JAVA_UTIL_COLLECTIONS + "." + + (elementType == null ? "" : "<" + elementType.getCanonicalText() + ">") + "emptyIterator()"; + PsiElement result = new CommentTracker().replaceAndRestoreComments(call, replacement); + RemoveRedundantTypeArgumentsUtil.removeRedundantTypeArguments(result); + JavaCodeStyleManager.getInstance(project).shortenClassReferences(result); + } + + @NotNull + @Override + public String getReplacement() { + return "Collections.emptyIterator()"; + } + + static RedundantEmptyIteratorHandler handler(PsiMethodCallExpression call) { + if (!PsiUtil.isLanguageLevel7OrHigher(call)) return null; + PsiExpression qualifier = PsiUtil.skipParenthesizedExprDown(call.getMethodExpression().getQualifierExpression()); + if (!EMPTY_COLLECTION.matches(qualifier) && !ConstructionUtils.isEmptyCollectionInitializer(qualifier)) return null; + return new RedundantEmptyIteratorHandler(); + } + } + private static class RedundantCollectionOperationFix implements LocalQuickFix { private final RedundantCollectionOperationHandler myHandler;