mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-168203 StreamApiMigration: accept more standard collection constructors
This commit is contained in:
+7
-5
@@ -106,7 +106,8 @@ class CollectMigration extends BaseStreamApiMigration {
|
||||
return initializerClass != null &&
|
||||
varClass != null &&
|
||||
CommonClassNames.JAVA_UTIL_HASH_MAP.equals(initializerClass.getQualifiedName()) &&
|
||||
CommonClassNames.JAVA_UTIL_MAP.equals(varClass.getQualifiedName());
|
||||
CommonClassNames.JAVA_UTIL_MAP.equals(varClass.getQualifiedName()) &&
|
||||
!ConstructionUtils.isCustomizedEmptyCollectionInitializer(initializer);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -315,13 +316,14 @@ class CollectMigration extends BaseStreamApiMigration {
|
||||
PsiClassType rawVarType = type instanceof PsiClassType ? ((PsiClassType)type).rawType() : null;
|
||||
if (rawType != null && rawVarType != null &&
|
||||
rawType.equalsToText(CommonClassNames.JAVA_UTIL_ARRAY_LIST) &&
|
||||
(rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_LIST) || rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_COLLECTION))) {
|
||||
(rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_LIST) || rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_COLLECTION)) &&
|
||||
!ConstructionUtils.isCustomizedEmptyCollectionInitializer(initializer)) {
|
||||
collector = "toList()";
|
||||
}
|
||||
else if (rawType != null && rawVarType != null &&
|
||||
rawType.equalsToText(CommonClassNames.JAVA_UTIL_HASH_SET) &&
|
||||
(rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_SET) ||
|
||||
rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_COLLECTION))) {
|
||||
(rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_SET) || rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_COLLECTION)) &&
|
||||
!ConstructionUtils.isCustomizedEmptyCollectionInitializer(initializer)) {
|
||||
collector = "toSet()";
|
||||
}
|
||||
else {
|
||||
@@ -331,7 +333,7 @@ class CollectMigration extends BaseStreamApiMigration {
|
||||
PsiExpressionList argumentList = ((PsiNewExpression)copy).getArgumentList();
|
||||
if (argumentList != null) {
|
||||
PsiExpression arg = ArrayUtil.getFirstElement(argumentList.getExpressions());
|
||||
if (arg != null) {
|
||||
if (arg != null && !(arg.getType() instanceof PsiPrimitiveType)) {
|
||||
arg.delete();
|
||||
}
|
||||
}
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
// "Fix all 'Loop can be collapsed with Stream API' problems in file" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Test {
|
||||
void testList(List<String> input) {
|
||||
List<String> result = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toCollection(() -> new ArrayList<>(10)));
|
||||
System.out.println(result);
|
||||
|
||||
ArrayList<String> result2 = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toCollection(() -> new ArrayList<>(20)));
|
||||
System.out.println(result2);
|
||||
|
||||
// Non-empty
|
||||
ArrayList<String> result3 = new ArrayList<>(input);
|
||||
input.stream().filter(s -> !s.isEmpty()).forEach(result3::add);
|
||||
System.out.println(result3);
|
||||
}
|
||||
|
||||
void testSet(List<String> input) {
|
||||
Set<String> result = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toCollection(() -> new HashSet<>(10)));
|
||||
System.out.println(result);
|
||||
|
||||
Collection<String> result2 = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toCollection(() -> new LinkedHashSet<>(20, 0.8f)));
|
||||
System.out.println(result2);
|
||||
|
||||
// Non-empty
|
||||
AbstractSet<String> result3 = new HashSet<>(input);
|
||||
input.stream().filter(s -> !s.isEmpty()).forEach(result3::add);
|
||||
System.out.println(result3);
|
||||
|
||||
Collection<TimeUnit> result4 = input.stream().filter(s -> !s.isEmpty()).map(TimeUnit::valueOf).collect(Collectors.toCollection(() -> EnumSet.noneOf(TimeUnit.class)));
|
||||
System.out.println(result4);
|
||||
}
|
||||
|
||||
void testMap(List<String> input) {
|
||||
Map<Integer, String> result = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toMap(String::length, s -> s, (a, b) -> b, () -> new HashMap<>(10)));
|
||||
System.out.println(result);
|
||||
|
||||
Map<Integer, String> result2 = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toMap(String::length, s -> s, (a, b) -> b, () -> new HashMap<>(10, 0.8f)));
|
||||
System.out.println(result2);
|
||||
|
||||
EnumMap<TimeUnit, String> result3 = input.stream().filter(s -> !s.isEmpty()).collect(Collectors.toMap(TimeUnit::valueOf, s -> s, (a, b) -> b, () -> new EnumMap<>(TimeUnit.class)));
|
||||
System.out.println(result3);
|
||||
|
||||
// Non-empty
|
||||
EnumMap<TimeUnit, String> result4 = new EnumMap<>(result3);
|
||||
input.stream().filter(s -> !s.isEmpty()).forEach(s -> result4.put(TimeUnit.valueOf(s), s));
|
||||
System.out.println(result4);
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
// "Fix all 'Loop can be collapsed with Stream API' problems in file" "true"
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class Test {
|
||||
void testList(List<String> input) {
|
||||
List<String> result = new ArrayList<>(10);
|
||||
for (String s : in<caret>put) {
|
||||
if (!s.isEmpty()) {
|
||||
result.add(s);
|
||||
}
|
||||
}
|
||||
System.out.println(result);
|
||||
|
||||
ArrayList<String> result2 = new ArrayList<>(20);
|
||||
for (String s : input) {
|
||||
if (!s.isEmpty()) {
|
||||
result2.add(s);
|
||||
}
|
||||
}
|
||||
System.out.println(result2);
|
||||
|
||||
// Non-empty
|
||||
ArrayList<String> result3 = new ArrayList<>(input);
|
||||
for (String s : input) {
|
||||
if (!s.isEmpty()) {
|
||||
result3.add(s);
|
||||
}
|
||||
}
|
||||
System.out.println(result3);
|
||||
}
|
||||
|
||||
void testSet(List<String> input) {
|
||||
Set<String> result = new HashSet<>(10);
|
||||
for (String s : input) {
|
||||
if (!s.isEmpty()) {
|
||||
result.add(s);
|
||||
}
|
||||
}
|
||||
System.out.println(result);
|
||||
|
||||
Collection<String> result2 = new LinkedHashSet<>(20, 0.8f);
|
||||
for (String s : input) {
|
||||
if (!s.isEmpty()) {
|
||||
result2.add(s);
|
||||
}
|
||||
}
|
||||
System.out.println(result2);
|
||||
|
||||
// Non-empty
|
||||
AbstractSet<String> result3 = new HashSet<>(input);
|
||||
for (String s : input) {
|
||||
if (!s.isEmpty()) {
|
||||
result3.add(s);
|
||||
}
|
||||
}
|
||||
System.out.println(result3);
|
||||
|
||||
Collection<TimeUnit> result4 = EnumSet.noneOf(TimeUnit.class);
|
||||
for (String s : input) {
|
||||
if (!s.isEmpty()) {
|
||||
result4.add(TimeUnit.valueOf(s));
|
||||
}
|
||||
}
|
||||
System.out.println(result4);
|
||||
}
|
||||
|
||||
void testMap(List<String> input) {
|
||||
Map<Integer, String> result = new HashMap<>(10);
|
||||
for (String s : input) {
|
||||
if (!s.isEmpty()) {
|
||||
result.put(s.length(), s);
|
||||
}
|
||||
}
|
||||
System.out.println(result);
|
||||
|
||||
Map<Integer, String> result2 = new HashMap<>(10, 0.8f);
|
||||
for (String s : input) {
|
||||
if (!s.isEmpty()) {
|
||||
result2.put(s.length(), s);
|
||||
}
|
||||
}
|
||||
System.out.println(result2);
|
||||
|
||||
EnumMap<TimeUnit, String> result3 = new EnumMap<>(TimeUnit.class);
|
||||
for (String s : input) {
|
||||
if (!s.isEmpty()) {
|
||||
result3.put(TimeUnit.valueOf(s), s);
|
||||
}
|
||||
}
|
||||
System.out.println(result3);
|
||||
|
||||
// Non-empty
|
||||
EnumMap<TimeUnit, String> result4 = new EnumMap<>(result3);
|
||||
for (String s : input) {
|
||||
if (!s.isEmpty()) {
|
||||
result4.put(TimeUnit.valueOf(s), s);
|
||||
}
|
||||
}
|
||||
System.out.println(result4);
|
||||
}
|
||||
}
|
||||
+59
-7
@@ -17,13 +17,24 @@ package com.siyeh.ig.psiutils;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.ig.callMatcher.CallMatcher;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author Tagir Valeev
|
||||
*/
|
||||
public class ConstructionUtils {
|
||||
private static final Set<String> GUAVA_UTILITY_CLASSES =
|
||||
ContainerUtil.set("com.google.common.collect.Maps", "com.google.common.collect.Lists", "com.google.common.collect.Sets");
|
||||
private static final CallMatcher ENUM_SET_NONE_OF =
|
||||
CallMatcher.staticCall("java.util.EnumSet", "noneOf").parameterCount(1);
|
||||
|
||||
/**
|
||||
* Checks that given expression initializes empty StringBuilder or StringBuffer (either with explicit default capacity or not)
|
||||
*
|
||||
@@ -79,10 +90,11 @@ public class ConstructionUtils {
|
||||
expression = PsiUtil.skipParenthesizedExprDown(expression);
|
||||
if (expression instanceof PsiNewExpression) {
|
||||
PsiExpressionList argumentList = ((PsiNewExpression)expression).getArgumentList();
|
||||
if (argumentList == null || argumentList.getExpressions().length != 0) return false;
|
||||
PsiType type = expression.getType();
|
||||
return com.intellij.psi.util.InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_COLLECTION) ||
|
||||
com.intellij.psi.util.InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP);
|
||||
if (argumentList != null && argumentList.getExpressions().length == 0) {
|
||||
PsiType type = expression.getType();
|
||||
return com.intellij.psi.util.InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_COLLECTION) ||
|
||||
com.intellij.psi.util.InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP);
|
||||
}
|
||||
}
|
||||
if (expression instanceof PsiMethodCallExpression) {
|
||||
PsiMethodCallExpression call = (PsiMethodCallExpression)expression;
|
||||
@@ -94,15 +106,55 @@ public class ConstructionUtils {
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if(aClass != null) {
|
||||
String qualifiedName = aClass.getQualifiedName();
|
||||
if("com.google.common.collect.Maps".equals(qualifiedName) ||
|
||||
"com.google.common.collect.Lists".equals(qualifiedName) ||
|
||||
"com.google.common.collect.Sets".equals(qualifiedName)) {
|
||||
if (GUAVA_UTILITY_CLASSES.contains(qualifiedName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return isCustomizedEmptyCollectionInitializer(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that given expression initializes empty Collection or Map with custom initial capacity or load factor
|
||||
*
|
||||
* @param expression expression to check
|
||||
* @return true if the expression is the empty Collection or Map initializer with custom initial capacity or load factor
|
||||
*/
|
||||
@Contract("null -> false")
|
||||
public static boolean isCustomizedEmptyCollectionInitializer(PsiExpression expression) {
|
||||
expression = PsiUtil.skipParenthesizedExprDown(expression);
|
||||
if (expression instanceof PsiNewExpression) {
|
||||
PsiExpressionList argumentList = ((PsiNewExpression)expression).getArgumentList();
|
||||
if (argumentList == null || argumentList.getExpressions().length == 0) return false;
|
||||
PsiMethod constructor = ((PsiNewExpression)expression).resolveConstructor();
|
||||
if (constructor == null) return false;
|
||||
PsiClass aClass = constructor.getContainingClass();
|
||||
if (aClass == null || aClass.getQualifiedName() == null || !aClass.getQualifiedName().startsWith("java.util.")) return false;
|
||||
Predicate<PsiType> allowedParameterType = t -> t instanceof PsiPrimitiveType ||
|
||||
(t instanceof PsiClassType &&
|
||||
((PsiClassType)t).rawType().equalsToText(CommonClassNames.JAVA_LANG_CLASS));
|
||||
return Stream.of(constructor.getParameterList().getParameters()).map(PsiParameter::getType).allMatch(allowedParameterType);
|
||||
}
|
||||
if (expression instanceof PsiMethodCallExpression) {
|
||||
PsiMethodCallExpression call = (PsiMethodCallExpression)expression;
|
||||
if (ENUM_SET_NONE_OF.test(call)) return true;
|
||||
String name = call.getMethodExpression().getReferenceName();
|
||||
PsiExpressionList argumentList = call.getArgumentList();
|
||||
if (name != null && name.startsWith("new") && argumentList.getExpressions().length > 0) {
|
||||
PsiMethod method = call.resolveMethod();
|
||||
if (method != null && method.getParameterList().getParametersCount() > 0) {
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if (aClass != null) {
|
||||
String qualifiedName = aClass.getQualifiedName();
|
||||
if (GUAVA_UTILITY_CLASSES.contains(qualifiedName)) {
|
||||
return Stream.of(method.getParameterList().getParameters()).allMatch(p -> p.getType() instanceof PsiPrimitiveType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user