IPP: don't replace with List/ImmutableList.of() when arguments are possibly null

This commit is contained in:
Bas Leijdekkers
2017-06-21 19:26:29 +02:00
parent 5721ab8957
commit d9f36ee97a
2 changed files with 70 additions and 10 deletions
@@ -15,16 +15,21 @@
*/
package com.siyeh.ipp.collections;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.IntentionPowerPackBundle;
import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
/**
* @author Bas Leijdekkers
*/
@@ -71,20 +76,21 @@ public class ReplaceWithArraysAsListIntention extends Intention implements HighP
}
private static String getReplacementMethodText(String methodName, PsiMethodCallExpression context) {
if (methodName.equals("emptyList") && context.getArgumentList().getExpressions().length == 1 &&
!PsiUtil.isLanguageLevel9OrHigher(context) && ClassUtils.findClass("com.google.common.collect.ImmutableList", context) == null) {
final PsiExpression[] arguments = context.getArgumentList().getExpressions();
if (methodName.equals("emptyList") && arguments.length == 1 &&
!PsiUtil.isLanguageLevel9OrHigher(context) && ClassUtils.findClass("com.google.common.collect.ImmutableList", context) == null) {
return "java.util.Collections.singletonList";
}
if (methodName.equals("emptyList") || methodName.equals("singletonList")) {
if (PsiUtil.isLanguageLevel9OrHigher(context)) {
return "java.util.List.of";
}
else if (ClassUtils.findClass("com.google.common.collect.ImmutableList", context) != null) {
return "com.google.common.collect.ImmutableList.of";
}
else {
return "java.util.Arrays.asList";
if (Arrays.stream(arguments).noneMatch(e -> isPossiblyNull(e))) {
if (PsiUtil.isLanguageLevel9OrHigher(context)) {
return "java.util.List.of";
}
else if (ClassUtils.findClass("com.google.common.collect.ImmutableList", context) != null) {
return "com.google.common.collect.ImmutableList.of";
}
}
return "java.util.Arrays.asList";
}
if (methodName.equals("emptySet") || methodName.equals("singleton")) {
if (PsiUtil.isLanguageLevel9OrHigher(context)) {
@@ -104,4 +110,24 @@ public class ReplaceWithArraysAsListIntention extends Intention implements HighP
}
return null;
}
private static boolean isPossiblyNull(PsiExpression expression) {
expression = ParenthesesUtils.stripParentheses(expression);
if (expression instanceof PsiReferenceExpression) {
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
final PsiElement target = referenceExpression.resolve();
if (target instanceof PsiModifierListOwner) {
final PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)target;
return NullableNotNullManager.getInstance(expression.getProject()).isNullable(modifierListOwner, false);
}
}
else if (ExpressionUtils.isNullLiteral(expression)) {
return true;
}
else if (expression instanceof PsiConditionalExpression) {
final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression)expression;
return isPossiblyNull(conditionalExpression.getThenExpression()) || isPossiblyNull(conditionalExpression.getElseExpression());
}
return false;
}
}
@@ -40,6 +40,40 @@ public class ReplaceWithArraysAsListIntentionJdk9Test extends IPPTestCase {
);
}
public void testNullArgument() {
doTest(
"import java.util.*;" +
"class X {" +
" List<String> f() {" +
" return Collections.emptyList(null/*_Replace with 'java.util.Arrays.asList()'*/, null);" +
" }" +
"}",
"import java.util.*;" +
"class X {" +
" List<String> f() {" +
" return Arrays.asList(null, null);" +
" }" +
"}");
}
public void testNullableArgument() {
doTest(
"import java.util.*;" +
"class X {" +
" List<String> f(@org.jetbrains.annotations.Nullable String a) {" +
" return Collections.emptyList(a/*_Replace with 'java.util.Arrays.asList()'*/);" +
" }" +
"}",
"import java.util.*;" +
"class X {" +
" List<String> f(@org.jetbrains.annotations.Nullable String a) {" +
" return Arrays.asList(a);" +
" }" +
"}");
}
public void testReplaceSingletonList() {
doTest(
"import java.util.*;" +