From 8ce43b883c433ccd4ad4f4a3a73eedefdc5ccc80 Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Thu, 21 Feb 2019 17:40:46 +0300 Subject: [PATCH] Java: Intention that wraps list/set/map with Collections.unmodifiable - handle ternary 'if' (IDEA-93154) --- .../impl/WrapWithUnmodifiableAction.java | 17 +++++++++++++---- .../afterListTernaryIf.java | 12 ++++++++++++ .../beforeListTernaryIf.java | 12 ++++++++++++ .../beforeUnmodifiedListTernaryIf.java | 12 ++++++++++++ 4 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/wrapWithUnmodifiable/afterListTernaryIf.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/wrapWithUnmodifiable/beforeListTernaryIf.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/wrapWithUnmodifiable/beforeUnmodifiedListTernaryIf.java diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/WrapWithUnmodifiableAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/WrapWithUnmodifiableAction.java index 82728b599c54..dce1aa586b60 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/WrapWithUnmodifiableAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/WrapWithUnmodifiableAction.java @@ -13,6 +13,7 @@ import com.intellij.psi.util.PsiTypesUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; import com.siyeh.ig.psiutils.CommentTracker; +import com.siyeh.ig.psiutils.ExpressionUtils; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,7 +38,7 @@ public class WrapWithUnmodifiableAction extends BaseIntentionAction { PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(expression.getType()); if (psiClass != null) { - PsiClass expectedClass = PsiUtil.resolveClassInClassTypeOnly(PsiTypesUtil.getExpectedTypeByParent(expression)); + PsiClass expectedClass = PsiUtil.resolveClassInClassTypeOnly(getExpectedType(expression)); if (expectedClass != null) { GlobalSearchScope scope = psiClass.getResolveScope(); @@ -97,7 +98,7 @@ public class WrapWithUnmodifiableAction extends BaseIntentionAction { } PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(expression.getType()); if (psiClass != null) { - PsiClass expectedClass = PsiUtil.resolveClassInClassTypeOnly(PsiTypesUtil.getExpectedTypeByParent(expression)); + PsiClass expectedClass = PsiUtil.resolveClassInClassTypeOnly(getExpectedType(expression)); if (expectedClass != null) { GlobalSearchScope scope = psiClass.getResolveScope(); @@ -122,6 +123,14 @@ public class WrapWithUnmodifiableAction extends BaseIntentionAction { return false; } + private static PsiType getExpectedType(@NotNull PsiExpression expression) { + final PsiElement parent = PsiUtil.skipParenthesizedExprUp(expression.getParent()); + if (parent instanceof PsiConditionalExpression) { + return getExpectedType((PsiConditionalExpression)parent); + } + return PsiTypesUtil.getExpectedTypeByParent(expression); + } + private static boolean isInheritorChain(PsiClass psiClass, String collectionClassName, PsiClass expectedClass, @@ -133,13 +142,13 @@ public class WrapWithUnmodifiableAction extends BaseIntentionAction { InheritanceUtil.isInheritorOrSelf(collectionClass, expectedClass, true); } - private static boolean isUnmodifiable(PsiExpression expression) { + private static boolean isUnmodifiable(@NotNull PsiExpression expression) { PsiMethodCallExpression methodCall = tryCast(expression, PsiMethodCallExpression.class); if (isUnmodifiableCall(methodCall)) { return true; } - PsiExpressionList expressionList = tryCast(PsiUtil.skipParenthesizedExprUp(expression.getParent()), PsiExpressionList.class); + PsiExpressionList expressionList = tryCast(ExpressionUtils.getPassThroughParent(expression), PsiExpressionList.class); if (expressionList != null && expressionList.getExpressionCount() == 1) { methodCall = tryCast(expressionList.getParent(), PsiMethodCallExpression.class); if (isUnmodifiableCall(methodCall)) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/wrapWithUnmodifiable/afterListTernaryIf.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/wrapWithUnmodifiable/afterListTernaryIf.java new file mode 100644 index 000000000000..1cad65cd7981 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/wrapWithUnmodifiable/afterListTernaryIf.java @@ -0,0 +1,12 @@ +// "Wrap with unmodifiable list" "true" +import java.util.Collections; +import java.util.List; +import java.util.ArrayList; + +class C { + List test(boolean b) { + List result1 = new ArrayList<>(); + List result2 = new ArrayList<>(); + return b ? Collections.unmodifiableList(result1) : result2; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/wrapWithUnmodifiable/beforeListTernaryIf.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/wrapWithUnmodifiable/beforeListTernaryIf.java new file mode 100644 index 000000000000..e2da49a3d776 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/wrapWithUnmodifiable/beforeListTernaryIf.java @@ -0,0 +1,12 @@ +// "Wrap with unmodifiable list" "true" +import java.util.Collections; +import java.util.List; +import java.util.ArrayList; + +class C { + List test(boolean b) { + List result1 = new ArrayList<>(); + List result2 = new ArrayList<>(); + return b ? result1 : result2; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/wrapWithUnmodifiable/beforeUnmodifiedListTernaryIf.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/wrapWithUnmodifiable/beforeUnmodifiedListTernaryIf.java new file mode 100644 index 000000000000..d50c373ef344 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/wrapWithUnmodifiable/beforeUnmodifiedListTernaryIf.java @@ -0,0 +1,12 @@ +// "Wrap with unmodifiable list" "false" +import java.util.Collections; +import java.util.List; +import java.util.ArrayList; + +class C { + List test(boolean b) { + List result1 = new ArrayList<>(); + List result2 = new ArrayList<>(); + return Collections.unmodifiableList(b ? result1 : result2); + } +} \ No newline at end of file