From e728e7eda8dddd3403b7f03e2037f49f3618b8ca Mon Sep 17 00:00:00 2001 From: Artemiy Sartakov Date: Fri, 26 Jul 2019 12:08:35 +0700 Subject: [PATCH] ExplicitArrayFillingInspection: suggest Arrays.fill in cases when filled value is immutable (IDEA-CR-50510) GitOrigin-RevId: a9d5627d25572edeb2f920aff62d108dd6f183ac --- .../ExplicitArrayFillingInspection.java | 11 +++++++---- .../afterEmptyArrayCreation.java | 13 +++++++++++++ .../afterImmutableObjectFromMethod.java | 15 +++++++++++++++ .../explicitArrayFilling/afterSuppliersArray.java | 12 ++++++++++++ .../afterTernaryWithMutable.java | 12 ++++++++++++ .../beforeEmptyArrayCreation.java | 13 +++++++++++++ .../beforeImmutableObjectFromMethod.java | 15 +++++++++++++++ .../beforeSuppliersArray.java | 12 ++++++++++++ .../beforeTernaryWithMutable.java | 12 ++++++++++++ 9 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/inspection/explicitArrayFilling/afterEmptyArrayCreation.java create mode 100644 java/java-tests/testData/inspection/explicitArrayFilling/afterImmutableObjectFromMethod.java create mode 100644 java/java-tests/testData/inspection/explicitArrayFilling/afterSuppliersArray.java create mode 100644 java/java-tests/testData/inspection/explicitArrayFilling/afterTernaryWithMutable.java create mode 100644 java/java-tests/testData/inspection/explicitArrayFilling/beforeEmptyArrayCreation.java create mode 100644 java/java-tests/testData/inspection/explicitArrayFilling/beforeImmutableObjectFromMethod.java create mode 100644 java/java-tests/testData/inspection/explicitArrayFilling/beforeSuppliersArray.java create mode 100644 java/java-tests/testData/inspection/explicitArrayFilling/beforeTernaryWithMutable.java diff --git a/java/java-impl/src/com/intellij/codeInspection/ExplicitArrayFillingInspection.java b/java/java-impl/src/com/intellij/codeInspection/ExplicitArrayFillingInspection.java index 6219e6f4cd30..875257a43a46 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ExplicitArrayFillingInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/ExplicitArrayFillingInspection.java @@ -13,7 +13,6 @@ import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTypesUtil; import com.intellij.util.ObjectUtils; import com.siyeh.ig.psiutils.*; @@ -73,9 +72,13 @@ public class ExplicitArrayFillingInspection extends AbstractBaseJavaLocalInspect } private boolean isChangedInLoop(@NotNull CountingLoop loop, @NotNull PsiExpression rValue) { - return VariableAccessUtils.collectUsedVariables(rValue).contains(loop.getCounter()) || - SideEffectChecker.mayHaveSideEffects(rValue) || - PsiTreeUtil.findChildOfType(rValue, PsiNewExpression.class, false) != null; + if (VariableAccessUtils.collectUsedVariables(rValue).contains(loop.getCounter()) || + SideEffectChecker.mayHaveSideEffects(rValue)) { + return true; + } + return ExpressionUtils.nonStructuralChildren(rValue) + .filter(c -> c instanceof PsiCallExpression) + .anyMatch(call -> !ClassUtils.isImmutable(call.getType()) && !ConstructionUtils.isEmptyArrayInitializer(call)); } private void registerProblem(@NotNull PsiForStatement statement, boolean isSetAll) { diff --git a/java/java-tests/testData/inspection/explicitArrayFilling/afterEmptyArrayCreation.java b/java/java-tests/testData/inspection/explicitArrayFilling/afterEmptyArrayCreation.java new file mode 100644 index 000000000000..6bbae5c85c70 --- /dev/null +++ b/java/java-tests/testData/inspection/explicitArrayFilling/afterEmptyArrayCreation.java @@ -0,0 +1,13 @@ +// "Replace loop with 'Arrays.fill()' method call" "true" + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; + +class Test { + private void test2() { + int[][] arr = new int[10][]; + Arrays.fill(arr, new int[0]); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/explicitArrayFilling/afterImmutableObjectFromMethod.java b/java/java-tests/testData/inspection/explicitArrayFilling/afterImmutableObjectFromMethod.java new file mode 100644 index 000000000000..97f9d8f853a5 --- /dev/null +++ b/java/java-tests/testData/inspection/explicitArrayFilling/afterImmutableObjectFromMethod.java @@ -0,0 +1,15 @@ +// "Replace loop with 'Arrays.fill()' method call" "true" + +import java.util.Arrays; + +class Test { + + void test() { + final String[] arr = new String[2]; + Arrays.fill(arr, getString()); + } + + private static String getString() { + return "foo"; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/explicitArrayFilling/afterSuppliersArray.java b/java/java-tests/testData/inspection/explicitArrayFilling/afterSuppliersArray.java new file mode 100644 index 000000000000..f8e4eed47900 --- /dev/null +++ b/java/java-tests/testData/inspection/explicitArrayFilling/afterSuppliersArray.java @@ -0,0 +1,12 @@ +// "Replace loop with 'Arrays.fill()' method call" "true" + +import java.util.Arrays; + +class Test { + + private void testLambdas() { + Supplier[] arr = new Supplier[10]; + Arrays.fill(arr, () -> new int[10]); + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/explicitArrayFilling/afterTernaryWithMutable.java b/java/java-tests/testData/inspection/explicitArrayFilling/afterTernaryWithMutable.java new file mode 100644 index 000000000000..db63db5b1a1a --- /dev/null +++ b/java/java-tests/testData/inspection/explicitArrayFilling/afterTernaryWithMutable.java @@ -0,0 +1,12 @@ +// "Replace loop with 'Arrays.setAll()' method call" "true" + +import java.util.Arrays; + +class Test { + + void test(boolean choice) { + Object[] arr = new Object[10]; + Arrays.setAll(arr, i -> (choice ? "foo" : new Object())); + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/explicitArrayFilling/beforeEmptyArrayCreation.java b/java/java-tests/testData/inspection/explicitArrayFilling/beforeEmptyArrayCreation.java new file mode 100644 index 000000000000..f333557740b4 --- /dev/null +++ b/java/java-tests/testData/inspection/explicitArrayFilling/beforeEmptyArrayCreation.java @@ -0,0 +1,13 @@ +// "Replace loop with 'Arrays.fill()' method call" "true" + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +class Test { + private void test2() { + int[][] arr = new int[10][]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new int[0]; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/explicitArrayFilling/beforeImmutableObjectFromMethod.java b/java/java-tests/testData/inspection/explicitArrayFilling/beforeImmutableObjectFromMethod.java new file mode 100644 index 000000000000..5eefdecf10d5 --- /dev/null +++ b/java/java-tests/testData/inspection/explicitArrayFilling/beforeImmutableObjectFromMethod.java @@ -0,0 +1,15 @@ +// "Replace loop with 'Arrays.fill()' method call" "true" + +class Test { + + void test() { + final String[] arr = new String[2]; + for (int i = 0; i < arr.length; i++) { + arr[i] = getString(); + } + } + + private static String getString() { + return "foo"; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/explicitArrayFilling/beforeSuppliersArray.java b/java/java-tests/testData/inspection/explicitArrayFilling/beforeSuppliersArray.java new file mode 100644 index 000000000000..d81017059781 --- /dev/null +++ b/java/java-tests/testData/inspection/explicitArrayFilling/beforeSuppliersArray.java @@ -0,0 +1,12 @@ +// "Replace loop with 'Arrays.fill()' method call" "true" + +class Test { + + private void testLambdas() { + Supplier[] arr = new Supplier[10]; + for (int i = 0; i < arr.length; i++) { + arr[i] = () -> new int[10]; + } + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/explicitArrayFilling/beforeTernaryWithMutable.java b/java/java-tests/testData/inspection/explicitArrayFilling/beforeTernaryWithMutable.java new file mode 100644 index 000000000000..0f1162897a46 --- /dev/null +++ b/java/java-tests/testData/inspection/explicitArrayFilling/beforeTernaryWithMutable.java @@ -0,0 +1,12 @@ +// "Replace loop with 'Arrays.setAll()' method call" "true" + +class Test { + + void test(boolean choice) { + Object[] arr = new Object[10]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (choice ? "foo" : new Object()); + } + } + +} \ No newline at end of file