diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java index dcb6b192a3af..e29355b85b9c 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/SimplifyStreamApiCallChainsInspection.java @@ -80,7 +80,10 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns return new JavaElementVisitor() { @Override public void visitMethodCallExpression(PsiMethodCallExpression methodCall) { - final PsiMethod method = methodCall.resolveMethod(); + PsiMethod method = methodCall.resolveMethod(); + if(method == null) return; + PsiClass psiClass = method.getContainingClass(); + if(psiClass == null) return; if (isCallOf(method, CommonClassNames.JAVA_UTIL_COLLECTION, STREAM_METHOD, 0)) { handleCollectionStream(methodCall); } @@ -90,27 +93,28 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns else if (isCallOf(method, CommonClassNames.JAVA_UTIL_OPTIONAL, IS_PRESENT_METHOD, 0)) { handleOptionalIsPresent(methodCall); } - else if (isCallOf(method, CommonClassNames.JAVA_UTIL_STREAM_STREAM, ANY_MATCH_METHOD, 1)) { + else if (isStreamCall(method, ANY_MATCH_METHOD)) { if(isParentNegated(methodCall)) { boolean argNegated = isArgumentLambdaNegated(methodCall); registerMatchFix(methodCall, - new SimplifyMatchNegationFix(argNegated ? "!Stream.anyMatch(x -> !(...))" : "!Stream.anyMatch(...)", + new SimplifyMatchNegationFix( + "!" + psiClass.getName() + (argNegated ? ".anyMatch(x -> !(...))" : ".anyMatch(...)"), argNegated ? ALL_MATCH_METHOD : NONE_MATCH_METHOD)); } } - else if (isCallOf(method, CommonClassNames.JAVA_UTIL_STREAM_STREAM, NONE_MATCH_METHOD, 1)) { + else if (isStreamCall(method, NONE_MATCH_METHOD)) { if(isParentNegated(methodCall)) { - registerMatchFix(methodCall, new SimplifyMatchNegationFix("!Stream.noneMatch(...)", ANY_MATCH_METHOD)); + registerMatchFix(methodCall, new SimplifyMatchNegationFix("!"+psiClass.getName()+".noneMatch(...)", ANY_MATCH_METHOD)); } if(isArgumentLambdaNegated(methodCall)) { - registerMatchFix(methodCall, new SimplifyMatchNegationFix("Stream.noneMatch(x -> !(...))", ALL_MATCH_METHOD)); + registerMatchFix(methodCall, new SimplifyMatchNegationFix(psiClass.getName()+".noneMatch(x -> !(...))", ALL_MATCH_METHOD)); } } - else if (isCallOf(method, CommonClassNames.JAVA_UTIL_STREAM_STREAM, ALL_MATCH_METHOD, 1)) { + else if (isStreamCall(method, ALL_MATCH_METHOD)) { if(isArgumentLambdaNegated(methodCall)) { boolean parentNegated = isParentNegated(methodCall); registerMatchFix(methodCall, - new SimplifyMatchNegationFix(parentNegated ? "!Stream.allMatch(x -> !(...))" : "Stream.allMatch(x -> !(...))", + new SimplifyMatchNegationFix((parentNegated ? "!" : "") + psiClass.getName() + ".allMatch(x -> !(...))", parentNegated ? ANY_MATCH_METHOD : NONE_MATCH_METHOD)); } } @@ -311,6 +315,14 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns return false; } + static boolean isStreamCall(@Nullable PsiMethod method, @NotNull String methodName) { + if (method == null || !methodName.equals(method.getName()) || method.getParameterList().getParametersCount() != 1) { + return false; + } + final PsiClass containingClass = method.getContainingClass(); + return containingClass != null && InheritanceUtil.isInheritor(containingClass, CommonClassNames.JAVA_UTIL_STREAM_BASE_STREAM); + } + interface CallChainFix { String getName(); void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor); @@ -627,11 +639,11 @@ public class SimplifyStreamApiCallChainsInspection extends BaseJavaBatchLocalIns @Override public String getName() { - return "Replace "+myFrom+" with Stream."+myTo+"(...)"; + return "Replace "+myFrom+" with "+myTo+"(...)"; } public String getMessage() { - return myFrom+" can be replaced with Stream."+myTo+"(...)"; + return myFrom+" can be replaced with "+myTo+"(...)"; } @Override diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterAllMatchNegatedLambda.java b/java/java-tests/testData/inspection/streamApiCallChains/afterAllMatchNegatedLambda.java index 62a5fb1f6d4f..3f34513e4cab 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/afterAllMatchNegatedLambda.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterAllMatchNegatedLambda.java @@ -1,4 +1,4 @@ -// "Replace Stream.allMatch(x -> !(...)) with Stream.noneMatch(...)" "true" +// "Replace Stream.allMatch(x -> !(...)) with noneMatch(...)" "true" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterAllMatchNegatedLambdaTwice.java b/java/java-tests/testData/inspection/streamApiCallChains/afterAllMatchNegatedLambdaTwice.java index 1b682b22e4a0..960555bfce88 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/afterAllMatchNegatedLambdaTwice.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterAllMatchNegatedLambdaTwice.java @@ -1,4 +1,4 @@ -// "Replace !Stream.allMatch(x -> !(...)) with Stream.anyMatch(...)" "true" +// "Replace !Stream.allMatch(x -> !(...)) with anyMatch(...)" "true" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterAllMatchNegatedPrimitive.java b/java/java-tests/testData/inspection/streamApiCallChains/afterAllMatchNegatedPrimitive.java new file mode 100644 index 000000000000..9e50a197bf65 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterAllMatchNegatedPrimitive.java @@ -0,0 +1,10 @@ +// "Replace DoubleStream.allMatch(x -> !(...)) with noneMatch(...)" "true" + +import java.util.stream.*; + +class Test { + public boolean testAllMatch(double[] data) { + if(DoubleStream.of(data).noneMatch(d -> Double.isNaN(d))) + return true; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterAnyMatchNegated.java b/java/java-tests/testData/inspection/streamApiCallChains/afterAnyMatchNegated.java index 5d8217290911..fc0d0a971116 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/afterAnyMatchNegated.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterAnyMatchNegated.java @@ -1,4 +1,4 @@ -// "Replace !Stream.anyMatch(...) with Stream.noneMatch(...)" "true" +// "Replace !Stream.anyMatch(...) with noneMatch(...)" "true" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterAnyMatchNegatedLambdaTwice.java b/java/java-tests/testData/inspection/streamApiCallChains/afterAnyMatchNegatedLambdaTwice.java index d51ced9ee88f..fe678b9ee0ff 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/afterAnyMatchNegatedLambdaTwice.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterAnyMatchNegatedLambdaTwice.java @@ -1,4 +1,4 @@ -// "Replace !Stream.anyMatch(x -> !(...)) with Stream.allMatch(...)" "true" +// "Replace !Stream.anyMatch(x -> !(...)) with allMatch(...)" "true" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterAnyMatchNegatedPrimitive.java b/java/java-tests/testData/inspection/streamApiCallChains/afterAnyMatchNegatedPrimitive.java new file mode 100644 index 000000000000..c488190c82b3 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterAnyMatchNegatedPrimitive.java @@ -0,0 +1,10 @@ +// "Replace !LongStream.anyMatch(...) with noneMatch(...)" "true" + +import java.util.stream.*; + +class Test { + public boolean testAnyMatch(long[] data) { + if(LongStream.of(data).noneMatch(i -> i > 0)) + return true; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterNoneMatchNegated.java b/java/java-tests/testData/inspection/streamApiCallChains/afterNoneMatchNegated.java index 51b4c0b74601..f2c92cf99890 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/afterNoneMatchNegated.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterNoneMatchNegated.java @@ -1,4 +1,4 @@ -// "Replace !Stream.noneMatch(...) with Stream.anyMatch(...)" "true" +// "Replace !Stream.noneMatch(...) with anyMatch(...)" "true" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterNoneMatchNegatedLambda.java b/java/java-tests/testData/inspection/streamApiCallChains/afterNoneMatchNegatedLambda.java index e11a37fed210..b0e0724163e4 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/afterNoneMatchNegatedLambda.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterNoneMatchNegatedLambda.java @@ -1,4 +1,4 @@ -// "Replace Stream.noneMatch(x -> !(...)) with Stream.allMatch(...)" "true" +// "Replace Stream.noneMatch(x -> !(...)) with allMatch(...)" "true" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/afterNoneMatchNegatedPrimitive.java b/java/java-tests/testData/inspection/streamApiCallChains/afterNoneMatchNegatedPrimitive.java new file mode 100644 index 000000000000..b1b22f847632 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/afterNoneMatchNegatedPrimitive.java @@ -0,0 +1,10 @@ +// "Replace !IntStream.noneMatch(...) with anyMatch(...)" "true" + +import java.util.stream.*; + +class Test { + public boolean testNoneMatch(int[] data) { + if(IntStream.of(data).anyMatch(i -> i > 0)) + return true; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegated.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegated.java index df19ee9bf6fa..a347338761d7 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegated.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegated.java @@ -1,4 +1,4 @@ -// "Replace Stream.allMatch(x -> !(...)) with Stream.noneMatch(...)" "false" +// "Replace Stream.allMatch(x -> !(...)) with noneMatch(...)" "false" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegatedLambda.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegatedLambda.java index d6c2fe534a35..0b037b427bc5 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegatedLambda.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegatedLambda.java @@ -1,4 +1,4 @@ -// "Replace Stream.allMatch(x -> !(...)) with Stream.noneMatch(...)" "true" +// "Replace Stream.allMatch(x -> !(...)) with noneMatch(...)" "true" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegatedLambdaTwice.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegatedLambdaTwice.java index 7a6514bd79c7..82c4327b9723 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegatedLambdaTwice.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegatedLambdaTwice.java @@ -1,4 +1,4 @@ -// "Replace !Stream.allMatch(x -> !(...)) with Stream.anyMatch(...)" "true" +// "Replace !Stream.allMatch(x -> !(...)) with anyMatch(...)" "true" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegatedPrimitive.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegatedPrimitive.java new file mode 100644 index 000000000000..df7b88d3ec00 --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeAllMatchNegatedPrimitive.java @@ -0,0 +1,10 @@ +// "Replace DoubleStream.allMatch(x -> !(...)) with noneMatch(...)" "true" + +import java.util.stream.*; + +class Test { + public boolean testAllMatch(double[] data) { + if(DoubleStream.of(data).allMatch(d -> !Double.isNaN(d))) + return true; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegated.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegated.java index 204e69b28f30..25862a73e816 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegated.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegated.java @@ -1,4 +1,4 @@ -// "Replace !Stream.anyMatch(...) with Stream.noneMatch(...)" "true" +// "Replace !Stream.anyMatch(...) with noneMatch(...)" "true" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegatedLambda.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegatedLambda.java index 32ce1a0d7618..578e2993cdf4 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegatedLambda.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegatedLambda.java @@ -1,4 +1,4 @@ -// "Replace !Stream.anyMatch(x -> !(...)) with Stream.allMatch(...)" "false" +// "Replace !Stream.anyMatch(x -> !(...)) with allMatch(...)" "false" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegatedLambdaTwice.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegatedLambdaTwice.java index b2dfcd99b7ec..19c55ab6cf3a 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegatedLambdaTwice.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegatedLambdaTwice.java @@ -1,4 +1,4 @@ -// "Replace !Stream.anyMatch(x -> !(...)) with Stream.allMatch(...)" "true" +// "Replace !Stream.anyMatch(x -> !(...)) with allMatch(...)" "true" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegatedPrimitive.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegatedPrimitive.java new file mode 100644 index 000000000000..69a1848bd26d --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeAnyMatchNegatedPrimitive.java @@ -0,0 +1,10 @@ +// "Replace !LongStream.anyMatch(...) with noneMatch(...)" "true" + +import java.util.stream.*; + +class Test { + public boolean testAnyMatch(long[] data) { + if(!LongStream.of(data).anyMatch(i -> i > 0)) + return true; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeNoneMatchNegated.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeNoneMatchNegated.java index 2b01f91af7ac..f4133a02a7eb 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/beforeNoneMatchNegated.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeNoneMatchNegated.java @@ -1,4 +1,4 @@ -// "Replace !Stream.noneMatch(...) with Stream.anyMatch(...)" "true" +// "Replace !Stream.noneMatch(...) with anyMatch(...)" "true" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeNoneMatchNegatedLambda.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeNoneMatchNegatedLambda.java index a37b825badfe..b6de9b267794 100644 --- a/java/java-tests/testData/inspection/streamApiCallChains/beforeNoneMatchNegatedLambda.java +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeNoneMatchNegatedLambda.java @@ -1,4 +1,4 @@ -// "Replace Stream.noneMatch(x -> !(...)) with Stream.allMatch(...)" "true" +// "Replace Stream.noneMatch(x -> !(...)) with allMatch(...)" "true" import java.util.*; diff --git a/java/java-tests/testData/inspection/streamApiCallChains/beforeNoneMatchNegatedPrimitive.java b/java/java-tests/testData/inspection/streamApiCallChains/beforeNoneMatchNegatedPrimitive.java new file mode 100644 index 000000000000..6791ed98ec2a --- /dev/null +++ b/java/java-tests/testData/inspection/streamApiCallChains/beforeNoneMatchNegatedPrimitive.java @@ -0,0 +1,10 @@ +// "Replace !IntStream.noneMatch(...) with anyMatch(...)" "true" + +import java.util.stream.*; + +class Test { + public boolean testNoneMatch(int[] data) { + if(!IntStream.of(data).noneMatch(i -> i > 0)) + return true; + } +} \ No newline at end of file