From 5f86f8cb468b3c92ef5da2a9def75831e28c52ac Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Thu, 28 Jun 2018 17:40:00 +0700 Subject: [PATCH] ExpressionUtils#isArrayCreationExpression; used in SideEffectChecker Fixes IDEA-194652 IDEA found side effect in primitive array creation --- .../impl/analysis/GenericsHighlightUtil.java | 15 +++++---------- .../codeInsight/JavaTargetElementEvaluator.java | 6 +++--- .../inline/InlineToAnonymousClassProcessor.java | 3 ++- .../usages/impl/rules/JavaUsageTypeProvider.java | 7 ++----- .../inspection/obviousNotNull/afterArray.java | 11 +++++++++++ .../inspection/obviousNotNull/beforeArray.java | 11 +++++++++++ ...ltOfObjectAllocationIgnoredInspectionBase.java | 4 ++-- .../RawUseOfParameterizedTypeInspection.java | 3 ++- .../com/siyeh/ig/psiutils/ExpressionUtils.java | 15 ++++++++++++++- .../com/siyeh/ig/psiutils/SideEffectChecker.java | 2 +- 10 files changed, 53 insertions(+), 24 deletions(-) create mode 100644 java/java-tests/testData/inspection/obviousNotNull/afterArray.java create mode 100644 java/java-tests/testData/inspection/obviousNotNull/beforeArray.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 99d391eb8209..0861e2b14431 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -28,6 +28,7 @@ import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.util.*; import com.intellij.util.ArrayUtilRt; import com.intellij.util.containers.ContainerUtil; +import com.siyeh.ig.psiutils.ExpressionUtils; import gnu.trove.THashMap; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; @@ -645,13 +646,8 @@ public class GenericsHighlightUtil { final PsiType retErasure2 = TypeConversionUtil.erasure(superMethod.getReturnType()); boolean differentReturnTypeErasure = !Comparing.equal(retErasure1, retErasure2); - if (checkEqualsSuper && atLeast17) { - if (retErasure1 != null && retErasure2 != null) { - differentReturnTypeErasure = !TypeConversionUtil.isAssignable(retErasure1, retErasure2); - } - else { - differentReturnTypeErasure = !(retErasure1 == null && retErasure2 == null); - } + if (checkEqualsSuper && atLeast17 && retErasure1 != null && retErasure2 != null) { + differentReturnTypeErasure = !TypeConversionUtil.isAssignable(retErasure1, retErasure2); } if (differentReturnTypeErasure && @@ -838,8 +834,7 @@ public class GenericsHighlightUtil { @Nullable static HighlightInfo checkEnumInstantiation(@NotNull PsiElement expression, @Nullable PsiClass aClass) { if (aClass != null && aClass.isEnum() && - (!(expression instanceof PsiNewExpression) || - ((PsiNewExpression)expression).getArrayDimensions().length == 0 && ((PsiNewExpression)expression).getArrayInitializer() == null)) { + !(expression instanceof PsiNewExpression && ExpressionUtils.isArrayCreationExpression((PsiNewExpression)expression))) { String description = JavaErrorMessages.message("enum.types.cannot.be.instantiated"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); } @@ -1011,7 +1006,7 @@ public class GenericsHighlightUtil { return highlightInfo; } PsiClass superClass = superMethod.getMethod().getContainingClass(); - if (languageLevel.equals(LanguageLevel.JDK_1_5) && + if (languageLevel == LanguageLevel.JDK_1_5 && superClass != null && superClass.isInterface()) { String description = JavaErrorMessages.message("override.not.allowed.in.interfaces"); diff --git a/java/java-impl/src/com/intellij/codeInsight/JavaTargetElementEvaluator.java b/java/java-impl/src/com/intellij/codeInsight/JavaTargetElementEvaluator.java index efa9821ba818..f900a3641b58 100644 --- a/java/java-impl/src/com/intellij/codeInsight/JavaTargetElementEvaluator.java +++ b/java/java-impl/src/com/intellij/codeInsight/JavaTargetElementEvaluator.java @@ -17,6 +17,7 @@ import com.intellij.util.BitUtil; import com.intellij.util.Processor; import com.intellij.util.ThreeState; import com.intellij.util.containers.ContainerUtil; +import com.siyeh.ig.psiutils.ExpressionUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -211,9 +212,8 @@ public class JavaTargetElementEvaluator extends TargetElementEvaluatorEx2 implem @Nullable public Collection getTargetCandidates(@NotNull PsiReference reference) { PsiElement parent = reference.getElement().getParent(); - if (parent instanceof PsiMethodCallExpression || parent instanceof PsiNewExpression && - ((PsiNewExpression)parent).getArrayDimensions().length == 0 && - ((PsiNewExpression)parent).getArrayInitializer() == null) { + if (parent instanceof PsiMethodCallExpression || + parent instanceof PsiNewExpression && !ExpressionUtils.isArrayCreationExpression((PsiNewExpression)parent)) { PsiCallExpression callExpr = (PsiCallExpression)parent; boolean allowStatics = false; PsiExpression qualifier = callExpr instanceof PsiMethodCallExpression ? ((PsiMethodCallExpression)callExpr).getMethodExpression().getQualifierExpression() diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassProcessor.java index 0d2013fd3ba4..6f8d8c0f09d2 100644 --- a/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassProcessor.java @@ -33,6 +33,7 @@ import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.MultiMap; +import com.siyeh.ig.psiutils.ExpressionUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -267,7 +268,7 @@ public class InlineToAnonymousClassProcessor extends BaseRefactoringProcessor { private void replaceNewOrType(final PsiNewExpression psiNewExpression, final PsiClassType superType) { try { - if (psiNewExpression.getArrayDimensions().length == 0 && psiNewExpression.getArrayInitializer() == null) { + if (!ExpressionUtils.isArrayCreationExpression(psiNewExpression)) { new InlineToAnonymousConstructorProcessor(myClass, psiNewExpression, superType).run(); } else { diff --git a/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java b/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java index 4d643bc9036c..a866c4c80df2 100644 --- a/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java +++ b/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java @@ -22,6 +22,7 @@ import com.intellij.psi.impl.PsiSuperMethodImplUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.usages.PsiElementUsageTarget; import com.intellij.usages.UsageTarget; +import com.siyeh.ig.psiutils.ExpressionUtils; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -233,7 +234,7 @@ public class JavaUsageTypeProvider implements UsageTypeProviderEx { if (isAnonymousClassOf(psiNewExpression.getAnonymousClass(), targets)) { return UsageType.CLASS_ANONYMOUS_NEW_OPERATOR; } - if (isNewArrayCreation(psiNewExpression)) { + if (ExpressionUtils.isArrayCreationExpression(psiNewExpression)) { return UsageType.CLASS_NEW_ARRAY; } return UsageType.CLASS_NEW_OPERATOR; @@ -243,10 +244,6 @@ public class JavaUsageTypeProvider implements UsageTypeProviderEx { return null; } - private static boolean isNewArrayCreation(@NotNull PsiNewExpression expression){ - return expression.getArrayDimensions().length > 0 || expression.getArrayInitializer() != null; - } - private static boolean isAnonymousClassOf(@Nullable PsiAnonymousClass anonymousClass, @NotNull UsageTarget[] targets) { if (anonymousClass == null) { return false; diff --git a/java/java-tests/testData/inspection/obviousNotNull/afterArray.java b/java/java-tests/testData/inspection/obviousNotNull/afterArray.java new file mode 100644 index 000000000000..14d11932dda8 --- /dev/null +++ b/java/java-tests/testData/inspection/obviousNotNull/afterArray.java @@ -0,0 +1,11 @@ +// "Remove redundant null-check" "true" + +import java.util.Objects; + +public class Test { + void test() { + foo(); + } + + native int foo(); +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/obviousNotNull/beforeArray.java b/java/java-tests/testData/inspection/obviousNotNull/beforeArray.java new file mode 100644 index 000000000000..9a0b5e2adfd0 --- /dev/null +++ b/java/java-tests/testData/inspection/obviousNotNull/beforeArray.java @@ -0,0 +1,11 @@ +// "Remove redundant null-check" "true" + +import java.util.Objects; + +public class Test { + void test() { + Objects.requireNonNull(new int[foo()]); + } + + native int foo(); +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ResultOfObjectAllocationIgnoredInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ResultOfObjectAllocationIgnoredInspectionBase.java index 0ee937b2e43d..f7f54ba79887 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ResultOfObjectAllocationIgnoredInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ResultOfObjectAllocationIgnoredInspectionBase.java @@ -20,6 +20,7 @@ import com.intellij.util.containers.OrderedSet; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.psiutils.ExpressionUtils; import org.jetbrains.annotations.NotNull; public class ResultOfObjectAllocationIgnoredInspectionBase extends BaseInspection { @@ -53,8 +54,7 @@ public class ResultOfObjectAllocationIgnoredInspectionBase extends BaseInspectio return; } final PsiNewExpression newExpression = (PsiNewExpression)expression; - final PsiExpression[] arrayDimensions = newExpression.getArrayDimensions(); - if (arrayDimensions.length != 0 || newExpression.getArrayInitializer() != null) { + if (ExpressionUtils.isArrayCreationExpression(newExpression)) { return; } final PsiJavaCodeReferenceElement reference = newExpression.getClassOrAnonymousClassReference(); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/RawUseOfParameterizedTypeInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/RawUseOfParameterizedTypeInspection.java index a69b0c844124..ba5ab7f3be92 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/RawUseOfParameterizedTypeInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/RawUseOfParameterizedTypeInspection.java @@ -22,6 +22,7 @@ import com.intellij.psi.util.PsiUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.psiutils.ExpressionUtils; import com.siyeh.ig.psiutils.LibraryUtil; import com.siyeh.ig.psiutils.MethodCallUtils; import com.siyeh.ig.psiutils.MethodUtils; @@ -99,7 +100,7 @@ public class RawUseOfParameterizedTypeInspection extends BaseInspection { if (ignoreObjectConstruction) { return; } - if (ignoreUncompilable && (expression.getArrayInitializer() != null || expression.getArrayDimensions().length > 0)) { + if (ignoreUncompilable && ExpressionUtils.isArrayCreationExpression(expression)) { //array creation can (almost) never be generic return; } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java index 8d380d721e7c..0cdf6a26c2c5 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java @@ -15,7 +15,10 @@ */ package com.siyeh.ig.psiutils; -import com.intellij.codeInsight.*; +import com.intellij.codeInsight.AnnotationUtil; +import com.intellij.codeInsight.CodeInsightUtilCore; +import com.intellij.codeInsight.NullableNotNullManager; +import com.intellij.codeInsight.PsiEquivalenceUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; @@ -1338,4 +1341,14 @@ public class ExpressionUtils { } return null; } + + /** + * Returns true if given new-expression creates an array rather than an object. + * + * @param expression expression to check + * @return true if given new-expression creates an array + */ + public static boolean isArrayCreationExpression(@NotNull PsiNewExpression expression) { + return expression.getArrayInitializer() != null || expression.getArrayDimensions().length > 0; + } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SideEffectChecker.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SideEffectChecker.java index 31b7bb794b03..1785de226e49 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SideEffectChecker.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SideEffectChecker.java @@ -174,7 +174,7 @@ public class SideEffectChecker { @Override public void visitNewExpression(@NotNull PsiNewExpression expression) { - if(!isSideEffectFreeConstructor(expression)) { + if (!ExpressionUtils.isArrayCreationExpression(expression) && !isSideEffectFreeConstructor(expression)) { if (addSideEffect(expression)) return; } super.visitNewExpression(expression);