mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 04:51:24 +07:00
IDEA-187214 Stream to loop inspection: support Java 10 toUnmodifiableList/Set/Map
This commit is contained in:
@@ -50,7 +50,7 @@ public class StreamToLoopInspection extends AbstractBaseJavaLocalInspectionTool
|
||||
// To quickly filter out most of the non-interesting method calls
|
||||
private static final Set<String> SUPPORTED_TERMINALS = ContainerUtil.set(
|
||||
"count", "sum", "summaryStatistics", "reduce", "collect", "findFirst", "findAny", "anyMatch", "allMatch", "noneMatch", "toArray",
|
||||
"average", "forEach", "forEachOrdered", "min", "max", "toList", "toSet");
|
||||
"average", "forEach", "forEachOrdered", "min", "max", "toList", "toSet", "toImmutableList", "toImmutableSet");
|
||||
|
||||
@SuppressWarnings("PublicField")
|
||||
public boolean SUPPORT_UNKNOWN_SOURCES = false;
|
||||
|
||||
@@ -100,6 +100,12 @@ abstract class TerminalOperation extends Operation {
|
||||
if(name.equals("toSet") && args.length == 0) {
|
||||
return ToCollectionTerminalOperation.toSet(resultType);
|
||||
}
|
||||
if(name.equals("toImmutableList") && args.length == 0) {
|
||||
return new WrappedCollectionTerminalOperation(ToCollectionTerminalOperation.toList(resultType), "unmodifiableList");
|
||||
}
|
||||
if(name.equals("toImmutableSet") && args.length == 0) {
|
||||
return new WrappedCollectionTerminalOperation(ToCollectionTerminalOperation.toSet(resultType), "unmodifiableSet");
|
||||
}
|
||||
if((name.equals("anyMatch") || name.equals("allMatch") || name.equals("noneMatch")) && args.length == 1) {
|
||||
FunctionHelper fn = FunctionHelper.create(args[0], 1);
|
||||
return fn == null ? null : new MatchTerminalOperation(fn, name);
|
||||
@@ -174,13 +180,20 @@ abstract class TerminalOperation extends Operation {
|
||||
case "toList":
|
||||
if (collectorArgs.length != 0) return null;
|
||||
return ToCollectionTerminalOperation.toList(resultType);
|
||||
case "toUnmodifiableList":
|
||||
if (collectorArgs.length != 0) return null;
|
||||
return new WrappedCollectionTerminalOperation(ToCollectionTerminalOperation.toList(resultType), "unmodifiableList");
|
||||
case "toSet":
|
||||
if (collectorArgs.length != 0) return null;
|
||||
return ToCollectionTerminalOperation.toSet(resultType);
|
||||
case "toUnmodifiableSet":
|
||||
if (collectorArgs.length != 0) return null;
|
||||
return new WrappedCollectionTerminalOperation(ToCollectionTerminalOperation.toSet(resultType), "unmodifiableSet");
|
||||
case "toCollection":
|
||||
if (collectorArgs.length != 1) return null;
|
||||
fn = FunctionHelper.create(collectorArgs[0], 0);
|
||||
return fn == null ? null : new ToCollectionTerminalOperation(resultType, fn, null);
|
||||
case "toUnmodifiableMap":
|
||||
case "toMap": {
|
||||
if (collectorArgs.length < 2 || collectorArgs.length > 4) return null;
|
||||
FunctionHelper key = FunctionHelper.create(collectorArgs[0], 1);
|
||||
@@ -191,7 +204,10 @@ abstract class TerminalOperation extends Operation {
|
||||
? FunctionHelper.create(collectorArgs[3], 0)
|
||||
: FunctionHelper.newObjectSupplier(resultType, CommonClassNames.JAVA_UTIL_HASH_MAP);
|
||||
if(supplier == null) return null;
|
||||
return new ToMapTerminalOperation(key, value, merger, supplier, resultType);
|
||||
CollectorBasedTerminalOperation operation = new ToMapTerminalOperation(key, value, merger, supplier, resultType);
|
||||
return collectorName.equals("toUnmodifiableMap")
|
||||
? new WrappedCollectionTerminalOperation(operation, "unmodifiableMap")
|
||||
: operation;
|
||||
}
|
||||
case "reducing":
|
||||
switch (collectorArgs.length) {
|
||||
@@ -605,10 +621,14 @@ abstract class TerminalOperation extends Operation {
|
||||
|
||||
@Override
|
||||
String initAccumulator(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
return initAccumulator(inVar, context, true);
|
||||
}
|
||||
|
||||
String initAccumulator(StreamVariable inVar, StreamToLoopReplacementContext context, boolean canBeFinal) {
|
||||
transform(context, inVar.getName());
|
||||
PsiType resultType = correctReturnType(myType);
|
||||
return context
|
||||
.declareResult(myAccNameSupplier.apply(context), resultType, myMostAbstractAllowedType, getSupplier(), ResultKind.FINAL);
|
||||
return context.declareResult(myAccNameSupplier.apply(context), resultType, myMostAbstractAllowedType, getSupplier(),
|
||||
canBeFinal ? ResultKind.FINAL : ResultKind.UNKNOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -711,6 +731,33 @@ abstract class TerminalOperation extends Operation {
|
||||
}
|
||||
}
|
||||
|
||||
static class WrappedCollectionTerminalOperation extends TerminalOperation {
|
||||
private final CollectorBasedTerminalOperation myDelegate;
|
||||
private final String myWrapper;
|
||||
|
||||
public WrappedCollectionTerminalOperation(CollectorBasedTerminalOperation delegate, String wrapper) {
|
||||
myDelegate = delegate;
|
||||
myWrapper = wrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerReusedElements(Consumer<PsiElement> consumer) {
|
||||
myDelegate.registerReusedElements(consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preprocessVariables(StreamToLoopReplacementContext context, StreamVariable inVar, StreamVariable outVar) {
|
||||
myDelegate.preprocessVariables(context, inVar, outVar);
|
||||
}
|
||||
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
String acc = myDelegate.initAccumulator(inVar, context, false);
|
||||
context.setFinisher(CommonClassNames.JAVA_UTIL_COLLECTIONS + "." + myWrapper + "(" + acc + ")");
|
||||
return myDelegate.getAccumulatorUpdater(inVar, acc);
|
||||
}
|
||||
}
|
||||
|
||||
static class ToCollectionTerminalOperation extends CollectorBasedTerminalOperation {
|
||||
private final boolean myList;
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// "Fix all 'Stream API call chain can be replaced with loop' problems in file" "true"
|
||||
package java.util.stream;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class Collectors {
|
||||
public static native <T> Collector<T, ?, List<T>> toUnmodifiableList();
|
||||
public static native <T> Collector<T, ?, Set<T>> toUnmodifiableSet();
|
||||
public static native <T, K, U> Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper);
|
||||
}
|
||||
|
||||
class MyFile {
|
||||
public static List<String> testList(String[] args) {
|
||||
List<String> result = new ArrayList<>();
|
||||
for (String arg : args) {
|
||||
if (arg != null) {
|
||||
result.add(arg);
|
||||
}
|
||||
}
|
||||
List<String> list = Collections.unmodifiableList(result);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static Set<String> testSet(String[] args) {
|
||||
Set<String> set = new HashSet<>();
|
||||
for (String arg : args) {
|
||||
if (arg != null) {
|
||||
set.add(arg);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
public static Map<String, String> testMap(String[] args) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
for (String arg : args) {
|
||||
if (arg != null) {
|
||||
if (map.put(arg.trim(), arg) != null) {
|
||||
throw new IllegalStateException("Duplicate key");
|
||||
}
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// "Fix all 'Stream API call chain can be replaced with loop' problems in file" "true"
|
||||
package java.util.stream;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class Collectors {
|
||||
public static native <T> Collector<T, ?, List<T>> toUnmodifiableList();
|
||||
public static native <T> Collector<T, ?, Set<T>> toUnmodifiableSet();
|
||||
public static native <T, K, U> Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper);
|
||||
}
|
||||
|
||||
class MyFile {
|
||||
public static List<String> testList(String[] args) {
|
||||
List<String> list = Arrays.stream(args).filter(Objects::nonNull)
|
||||
.collect(Collectors.toUnmodifiab<caret>leList());
|
||||
return list;
|
||||
}
|
||||
|
||||
public static Set<String> testSet(String[] args) {
|
||||
return Arrays.stream(args).filter(Objects::nonNull)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
}
|
||||
|
||||
public static Map<String, String> testMap(String[] args) {
|
||||
return Arrays.stream(args).filter(Objects::nonNull)
|
||||
.collect(Collectors.toUnmodifiableMap(String::trim, Function.identity()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user