From 58b4cb2dd3e9b244746ab5fcdbc4534e5db01b82 Mon Sep 17 00:00:00 2001 From: Artemiy Sartakov Date: Fri, 11 Oct 2019 15:46:23 +0700 Subject: [PATCH] ExplicitArrayFillingInspection: check if assigned value is default for type in case when implicit cast happens (IDEA-CR-53316) GitOrigin-RevId: a26c1aa3aa621018965d7153d744b46cf365d4f8 --- .../ExplicitArrayFillingInspection.java | 28 ++++++++++++------- .../afterEmptyByteArray.java | 8 ++++++ .../afterInitializerWithDefaultValues.java | 8 ++++++ .../beforeEmptyByteArray.java | 11 ++++++++ .../beforeInitializerWithDefaultValues.java | 11 ++++++++ 5 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 java/java-tests/testData/inspection/explicitArrayFilling/afterEmptyByteArray.java create mode 100644 java/java-tests/testData/inspection/explicitArrayFilling/afterInitializerWithDefaultValues.java create mode 100644 java/java-tests/testData/inspection/explicitArrayFilling/beforeEmptyByteArray.java create mode 100644 java/java-tests/testData/inspection/explicitArrayFilling/beforeInitializerWithDefaultValues.java diff --git a/java/java-impl/src/com/intellij/codeInspection/ExplicitArrayFillingInspection.java b/java/java-impl/src/com/intellij/codeInspection/ExplicitArrayFillingInspection.java index 66c061919ce4..79fba47d0c9a 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ExplicitArrayFillingInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/ExplicitArrayFillingInspection.java @@ -62,8 +62,9 @@ public class ExplicitArrayFillingInspection extends AbstractBaseJavaLocalInspect PsiExpression rValue = assignment.getRExpression(); if (rValue == null) return; if (!isChangedInLoop(loop, rValue)) { - Object defaultValue = PsiTypesUtil.getDefaultValue(assignment.getType()); - if (isDefaultValue(rValue, defaultValue) && isFilledWithDefaultValues(container.getQualifier(), statement, defaultValue)) { + PsiType lType = container.getElementType(); + Object defaultValue = PsiTypesUtil.getDefaultValue(lType); + if (isDefaultValue(rValue, defaultValue, lType) && isFilledWithDefaultValues(container.getQualifier(), statement, defaultValue)) { holder.registerProblem(statement, getRange(statement, ProblemHighlightType.WARNING), InspectionsBundle.message("inspection.explicit.array.filling.redundant.loop.description"), QuickFixFactory.getInstance().createDeleteFix(statement)); @@ -88,9 +89,15 @@ public class ExplicitArrayFillingInspection extends AbstractBaseJavaLocalInspect .anyMatch(call -> !ClassUtils.isImmutable(call.getType()) && !ConstructionUtils.isEmptyArrayInitializer(call)); } - private boolean isDefaultValue(@NotNull PsiExpression expression, @Nullable Object defaultValue) { + private boolean isDefaultValue(@NotNull PsiExpression expression, @Nullable Object defaultValue, @Nullable PsiType lType) { if (ExpressionUtils.isNullLiteral(expression) && defaultValue == null) return true; Object constantValue = ExpressionUtils.computeConstantExpression(expression); + PsiType rType = expression.getType(); + if (rType instanceof PsiPrimitiveType && lType instanceof PsiPrimitiveType) { + if (defaultValue instanceof Number && constantValue instanceof Number) { + return ((Number)defaultValue).doubleValue() == ((Number)constantValue).doubleValue(); + } + } return constantValue != null && constantValue.equals(defaultValue); } @@ -160,11 +167,12 @@ public class ExplicitArrayFillingInspection extends AbstractBaseJavaLocalInspect } private boolean isNewArrayCreation(@Nullable PsiExpression expression, @Nullable Object defaultValue) { - PsiNewExpression newExpression = tryCast(PsiUtil.skipParenthesizedExprDown(expression), PsiNewExpression.class); - if (newExpression == null) return false; - PsiArrayInitializerExpression initializer = newExpression.getArrayInitializer(); + PsiExpression arrInitExpr = PsiUtil.skipParenthesizedExprDown(expression); + PsiNewExpression newExpression = tryCast(arrInitExpr, PsiNewExpression.class); + PsiArrayInitializerExpression initializer = + newExpression == null ? tryCast(arrInitExpr, PsiArrayInitializerExpression.class) : newExpression.getArrayInitializer(); if (initializer == null) return true; - return Arrays.stream(initializer.getInitializers()).allMatch(init -> isDefaultValue(init, defaultValue)); + return Arrays.stream(initializer.getInitializers()).allMatch(init -> isDefaultValue(init, defaultValue, init.getType())); } @Nullable @@ -252,7 +260,7 @@ public class ExplicitArrayFillingInspection extends AbstractBaseJavaLocalInspect CommentTracker ct = new CommentTracker(); PsiElement result; if (myIsRhsConstant) { - String cast = getCast(project, container.getElementType(), rValue.getType()); + String cast = getCast(statement, container.getElementType(), rValue.getType()); String replacement = CommonClassNames.JAVA_UTIL_ARRAYS + ".fill(" + ct.text(container.getQualifier()) + ", " + cast + ct.text(rValue) + ");"; result = ct.replaceAndRestoreComments(statement, replacement); @@ -268,10 +276,10 @@ public class ExplicitArrayFillingInspection extends AbstractBaseJavaLocalInspect } @NotNull - private static String getCast(@NotNull Project project, @Nullable PsiType elementType, @Nullable PsiType rType) { + private static String getCast(@NotNull PsiElement context, @Nullable PsiType elementType, @Nullable PsiType rType) { if (elementType == null || rType == null) return ""; PsiType assignTo = tryCast(elementType, PsiPrimitiveType.class); - if (assignTo == null) assignTo = JavaPsiFacade.getElementFactory(project).createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT); + if (assignTo == null) assignTo = TypeUtils.getObjectType(context); return TypeConversionUtil.isAssignable(assignTo, rType) ? "" : "(" + elementType.getCanonicalText() + ")"; } } diff --git a/java/java-tests/testData/inspection/explicitArrayFilling/afterEmptyByteArray.java b/java/java-tests/testData/inspection/explicitArrayFilling/afterEmptyByteArray.java new file mode 100644 index 000000000000..235f42a69b9b --- /dev/null +++ b/java/java-tests/testData/inspection/explicitArrayFilling/afterEmptyByteArray.java @@ -0,0 +1,8 @@ +// "Delete element" "true" + +class Test { + + void fillByteArray() { + byte[] plaintext = new byte[10]; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/explicitArrayFilling/afterInitializerWithDefaultValues.java b/java/java-tests/testData/inspection/explicitArrayFilling/afterInitializerWithDefaultValues.java new file mode 100644 index 000000000000..f584932f754a --- /dev/null +++ b/java/java-tests/testData/inspection/explicitArrayFilling/afterInitializerWithDefaultValues.java @@ -0,0 +1,8 @@ +// "Delete element" "true" + +class Test { + + void fillByteArray() { + byte[] plaintext = {0,0,0,0,0}; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/explicitArrayFilling/beforeEmptyByteArray.java b/java/java-tests/testData/inspection/explicitArrayFilling/beforeEmptyByteArray.java new file mode 100644 index 000000000000..a95a24a59b70 --- /dev/null +++ b/java/java-tests/testData/inspection/explicitArrayFilling/beforeEmptyByteArray.java @@ -0,0 +1,11 @@ +// "Delete element" "true" + +class Test { + + void fillByteArray() { + byte[] plaintext = new byte[10]; + for (int counter = 0; counter < plaintext.length; counter++) { + plaintext[counter] = 0; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/explicitArrayFilling/beforeInitializerWithDefaultValues.java b/java/java-tests/testData/inspection/explicitArrayFilling/beforeInitializerWithDefaultValues.java new file mode 100644 index 000000000000..fb80bcb29e10 --- /dev/null +++ b/java/java-tests/testData/inspection/explicitArrayFilling/beforeInitializerWithDefaultValues.java @@ -0,0 +1,11 @@ +// "Delete element" "true" + +class Test { + + void fillByteArray() { + byte[] plaintext = {0,0,0,0,0}; + for (int counter = 0; counter < plaintext.length; counter++) { + plaintext[counter] = 0; + } + } +} \ No newline at end of file