mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
StreamToLoop: reuse variable if possible when the stream is used in the declaration
This commit is contained in:
+62
-42
@@ -326,7 +326,7 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
private final Set<String> myUsedNames;
|
||||
private final Set<String> myUsedLabels;
|
||||
private final List<String> myDeclarations = new ArrayList<>();
|
||||
private PsiExpression myPlaceholder;
|
||||
private PsiElement myPlaceholder;
|
||||
private final PsiElementFactory myFactory;
|
||||
private String myLabel;
|
||||
private String myFinisher;
|
||||
@@ -412,7 +412,22 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
myDeclarations.add(initStatement);
|
||||
}
|
||||
|
||||
public String declareResult(String desiredName, String type, String initializer) {
|
||||
public String declareResult(String desiredName, String type, String initializer, boolean finalResult) {
|
||||
if(finalResult && myPlaceholder.getParent() instanceof PsiVariable) {
|
||||
PsiVariable var = (PsiVariable)myPlaceholder.getParent();
|
||||
if(var.getType().equalsToText(type) && var.getParent() instanceof PsiDeclarationStatement) {
|
||||
PsiDeclarationStatement declaration = (PsiDeclarationStatement)var.getParent();
|
||||
if(declaration.getDeclaredElements().length == 1) {
|
||||
myPlaceholder = declaration;
|
||||
PsiVariable copy = (PsiVariable)var.copy();
|
||||
PsiExpression oldInitializer = copy.getInitializer();
|
||||
LOG.assertTrue(oldInitializer != null);
|
||||
oldInitializer.replace(createExpression(initializer));
|
||||
myDeclarations.add(copy.getText());
|
||||
return var.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
String name = registerVarName(Arrays.asList(desiredName, "result"));
|
||||
myDeclarations.add(type + " " + name + " = " + initializer + ";");
|
||||
if(myFinisher != null) {
|
||||
@@ -424,7 +439,7 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
|
||||
public PsiElement makeFinalReplacement() {
|
||||
LOG.assertTrue(myPlaceholder != null);
|
||||
if (myFinisher == null) {
|
||||
if (myFinisher == null || myPlaceholder instanceof PsiStatement) {
|
||||
myPlaceholder.delete();
|
||||
return null;
|
||||
}
|
||||
@@ -450,7 +465,7 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
|
||||
public String assignAndBreak(Condition condition) {
|
||||
Predicate<PsiExpression> predicate = expr -> PsiUtil.skipParenthesizedExprUp(expr.getParent()) instanceof PsiReturnStatement;
|
||||
Predicate<PsiElement> predicate = expr -> PsiUtil.skipParenthesizedExprUp(expr.getParent()) instanceof PsiReturnStatement;
|
||||
if(condition instanceof Condition.Optional) {
|
||||
condition = tryUnwrapOptional((Condition.Optional)condition, predicate);
|
||||
}
|
||||
@@ -461,26 +476,28 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
setFinisher(condition.getFalseBranch());
|
||||
return "return "+condition.getTrueBranch()+";";
|
||||
}
|
||||
String found = declareResult(condition.getCondition(), condition.getType(), condition.getFalseBranch());
|
||||
String found = declareResult(condition.getCondition(), condition.getType(), condition.getFalseBranch(), false);
|
||||
return found + " = " +condition.getTrueBranch()+";\n" + getBreakStatement();
|
||||
}
|
||||
|
||||
private Condition tryUnwrapBoolean(Condition.Boolean condition) {
|
||||
PsiExpression negation = BoolUtils.findNegation(myPlaceholder);
|
||||
if(negation != null) {
|
||||
myPlaceholder = negation;
|
||||
condition = condition.negate();
|
||||
}
|
||||
PsiElement parent = PsiUtil.skipParenthesizedExprUp(myPlaceholder.getParent());
|
||||
if(parent instanceof PsiConditionalExpression) {
|
||||
PsiConditionalExpression ternary = (PsiConditionalExpression)parent;
|
||||
if(PsiTreeUtil.isAncestor(ternary.getCondition(), myPlaceholder, false)) {
|
||||
myPlaceholder = ternary;
|
||||
PsiType type = ternary.getType();
|
||||
PsiExpression thenExpression = ternary.getThenExpression();
|
||||
PsiExpression elseExpression = ternary.getElseExpression();
|
||||
if (type != null && thenExpression != null && elseExpression != null) {
|
||||
return condition.toPlain(type.getCanonicalText(), thenExpression.getText(), elseExpression.getText());
|
||||
if (myPlaceholder instanceof PsiExpression) {
|
||||
PsiExpression negation = BoolUtils.findNegation((PsiExpression)myPlaceholder);
|
||||
if (negation != null) {
|
||||
myPlaceholder = negation;
|
||||
condition = condition.negate();
|
||||
}
|
||||
PsiElement parent = PsiUtil.skipParenthesizedExprUp(myPlaceholder.getParent());
|
||||
if (parent instanceof PsiConditionalExpression) {
|
||||
PsiConditionalExpression ternary = (PsiConditionalExpression)parent;
|
||||
if (PsiTreeUtil.isAncestor(ternary.getCondition(), myPlaceholder, false)) {
|
||||
myPlaceholder = ternary;
|
||||
PsiType type = ternary.getType();
|
||||
PsiExpression thenExpression = ternary.getThenExpression();
|
||||
PsiExpression elseExpression = ternary.getElseExpression();
|
||||
if (type != null && thenExpression != null && elseExpression != null) {
|
||||
return condition.toPlain(type.getCanonicalText(), thenExpression.getText(), elseExpression.getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -488,29 +505,32 @@ public class StreamToLoopInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Condition tryUnwrapOptional(Condition.Optional condition, Predicate<PsiExpression> predicate) {
|
||||
PsiMethodCallExpression call = ExpressionUtils.getCallForQualifier(myPlaceholder);
|
||||
if(call != null && !(call.getParent() instanceof PsiExpressionStatement)) {
|
||||
String name = call.getMethodExpression().getReferenceName();
|
||||
PsiExpression[] args = call.getArgumentList().getExpressions();
|
||||
if(args.length == 0 && "isPresent".equals(name)) {
|
||||
myPlaceholder = call;
|
||||
return new Condition.Boolean(condition.getCondition(), false);
|
||||
}
|
||||
if(args.length == 1) {
|
||||
String absentExpression = null;
|
||||
if("orElse".equals(name)) {
|
||||
absentExpression = args[0].getText();
|
||||
} else if("orElseGet".equals(name) && predicate.test(call)) {
|
||||
FunctionHelper helper = FunctionHelper.create(args[0], 0);
|
||||
if(helper != null) {
|
||||
helper.transform(this);
|
||||
absentExpression = helper.getText();
|
||||
}
|
||||
}
|
||||
if(absentExpression != null) {
|
||||
private Condition tryUnwrapOptional(Condition.Optional condition, Predicate<PsiElement> predicate) {
|
||||
if (myPlaceholder instanceof PsiExpression) {
|
||||
PsiMethodCallExpression call = ExpressionUtils.getCallForQualifier((PsiExpression)myPlaceholder);
|
||||
if (call != null && !(call.getParent() instanceof PsiExpressionStatement)) {
|
||||
String name = call.getMethodExpression().getReferenceName();
|
||||
PsiExpression[] args = call.getArgumentList().getExpressions();
|
||||
if (args.length == 0 && "isPresent".equals(name)) {
|
||||
myPlaceholder = call;
|
||||
return condition.unwrap(absentExpression);
|
||||
return new Condition.Boolean(condition.getCondition(), false);
|
||||
}
|
||||
if (args.length == 1) {
|
||||
String absentExpression = null;
|
||||
if ("orElse".equals(name)) {
|
||||
absentExpression = args[0].getText();
|
||||
}
|
||||
else if ("orElseGet".equals(name) && predicate.test(call)) {
|
||||
FunctionHelper helper = FunctionHelper.create(args[0], 0);
|
||||
if (helper != null) {
|
||||
helper.transform(this);
|
||||
absentExpression = helper.getText();
|
||||
}
|
||||
}
|
||||
if (absentExpression != null) {
|
||||
myPlaceholder = call;
|
||||
return condition.unwrap(absentExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ abstract class TerminalOperation extends Operation {
|
||||
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
String accumulator = context.declareResult("acc", myType, myIdentity.getText());
|
||||
String accumulator = context.declareResult("acc", myType, myIdentity.getText(), false);
|
||||
myUpdater.transform(context, accumulator, inVar.getName());
|
||||
return accumulator + "=" + myUpdater.getText() + ";";
|
||||
}
|
||||
@@ -331,7 +331,7 @@ abstract class TerminalOperation extends Operation {
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
String seen = context.declare("seen", "boolean", "false");
|
||||
String accumulator = context.declareResult("acc", myType, TypeConversionUtil.isPrimitive(myType) ? "0" : "null");
|
||||
String accumulator = context.declareResult("acc", myType, TypeConversionUtil.isPrimitive(myType) ? "0" : "null", false);
|
||||
myUpdater.transform(context, accumulator, inVar.getName());
|
||||
context.setFinisher(new Condition.Optional(myType, seen, accumulator));
|
||||
String ifClause = "if(!" + seen + ") {\n" +
|
||||
@@ -379,7 +379,7 @@ abstract class TerminalOperation extends Operation {
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
mySupplier.transform(context);
|
||||
String candidate = mySupplier.suggestFinalOutputNames(context, myAccumulator.getParameterName(0), "acc").get(0);
|
||||
String acc = context.declareResult(candidate, mySupplier.getResultType(), mySupplier.getText());
|
||||
String acc = context.declareResult(candidate, mySupplier.getResultType(), mySupplier.getText(), true);
|
||||
myAccumulator.transform(context, acc, inVar.getName());
|
||||
return myAccumulator.getText()+";\n";
|
||||
}
|
||||
@@ -396,7 +396,7 @@ abstract class TerminalOperation extends Operation {
|
||||
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
String sum = context.declareResult("sum", myDoubleAccumulator ? "double" : "long", "0");
|
||||
String sum = context.declareResult("sum", myDoubleAccumulator ? "double" : "long", "0", false);
|
||||
String count = context.declare("count", "long", "0");
|
||||
String seenCheck = count + ">0";
|
||||
String result = (myDoubleAccumulator ? "" : "(double)") + sum + "/" + count;
|
||||
@@ -417,7 +417,7 @@ abstract class TerminalOperation extends Operation {
|
||||
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
String arr = context.declareResult("arr", myType + "[]", "new " + myType + "[10]");
|
||||
String arr = context.declareResult("arr", myType + "[]", "new " + myType + "[10]", false);
|
||||
String count = context.declare("count", "int", "0");
|
||||
context.setFinisher("java.util.Arrays.copyOfRange("+arr+",0,"+count+")");
|
||||
return "if(" + arr + ".length==" + count + ") " + arr + "=java.util.Arrays.copyOf(" + arr + "," + count + "*2);\n" +
|
||||
@@ -517,7 +517,7 @@ abstract class TerminalOperation extends Operation {
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
transform(context, inVar.getName());
|
||||
String acc = context.declareResult(myAccNameSupplier.apply(context), myType, getSupplier());
|
||||
String acc = context.declareResult(myAccNameSupplier.apply(context), myType, getSupplier(), true);
|
||||
return getAccumulator(acc, inVar.getName());
|
||||
}
|
||||
|
||||
@@ -572,7 +572,7 @@ abstract class TerminalOperation extends Operation {
|
||||
|
||||
@Override
|
||||
public String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
String varName = context.declareResult(myAccName, myAccType, myAccInitializer);
|
||||
String varName = context.declareResult(myAccName, myAccType, myAccInitializer, asCollector() != null);
|
||||
context.setFinisher(myFinisherTemplate.replace("{acc}", varName));
|
||||
return myUpdateTemplate.replace("{item}", inVar.getName()).replace("{acc}", varName);
|
||||
}
|
||||
@@ -664,7 +664,7 @@ abstract class TerminalOperation extends Operation {
|
||||
}
|
||||
}
|
||||
String seen = context.declare("seen", "boolean", "false");
|
||||
String best = context.declareResult("best", myType, TypeConversionUtil.isPrimitive(myType) ? "0" : "null");
|
||||
String best = context.declareResult("best", myType, TypeConversionUtil.isPrimitive(myType) ? "0" : "null", false);
|
||||
String type = myType;
|
||||
context.setFinisher(new Condition.Optional(type, seen, best));
|
||||
return "if(!"+seen+" || "+myTemplate.replace("{best}", best).replace("{item}", inVar.getName()).replace("{comparator}", comparator)+") {\n" +
|
||||
@@ -820,7 +820,7 @@ abstract class TerminalOperation extends Operation {
|
||||
|
||||
@Override
|
||||
String generate(StreamVariable inVar, StreamToLoopReplacementContext context) {
|
||||
String map = context.declareResult("map", myResultType, "new java.util.HashMap<>()");
|
||||
String map = context.declareResult("map", myResultType, "new java.util.HashMap<>()", true);
|
||||
myPredicate.transform(context, inVar.getName());
|
||||
myCollector.transform(context, inVar.getName());
|
||||
context.addInitStep(map+".put(false, "+myCollector.getSupplier()+");");
|
||||
|
||||
+6
-5
@@ -6,13 +6,14 @@ import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
Map<Boolean, Map<Character, Set<String>>> map = new HashMap<>();
|
||||
map.put(false, new HashMap<>());
|
||||
map.put(true, new HashMap<>());
|
||||
final Map<Boolean, Map<Character, Set<String>>> nestedMap =
|
||||
new HashMap<>();
|
||||
nestedMap.put(false, new HashMap<>());
|
||||
nestedMap.put(true, new HashMap<>());
|
||||
for (String s : strings) {
|
||||
map.get(s.length() > 2).computeIfAbsent(s.charAt(0), k -> new HashSet<>()).add(s);
|
||||
nestedMap.get(s.length() > 2).computeIfAbsent(s.charAt(0), k -> new HashSet<>()).add(s);
|
||||
}
|
||||
System.out.println(map);
|
||||
System.out.println(nestedMap);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
+3
-3
@@ -5,13 +5,13 @@ import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Map<Integer, String> test(List<String> strings) {
|
||||
Map<Integer, String> map = new HashMap<>();
|
||||
Map<Integer, String> mapping = new HashMap<>();
|
||||
for (String str : strings) {
|
||||
if (map.put(str.length(), str) != null) {
|
||||
if (mapping.put(str.length(), str) != null) {
|
||||
throw new IllegalStateException("Duplicate key");
|
||||
}
|
||||
}
|
||||
return map;
|
||||
return mapping;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
+3
-1
@@ -6,7 +6,9 @@ import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<String> strings) {
|
||||
System.out.println(strings.stream().c<caret>ollect(Collectors.partitioningBy((String s) -> s.length() > 2, Collectors.groupingBy(s -> s.charAt(0), Collectors.toSet()))));
|
||||
final Map<Boolean, Map<Character, Set<String>>> nestedMap =
|
||||
strings.stream().c<caret>ollect(Collectors.partitioningBy((String s) -> s.length() > 2, Collectors.groupingBy(s -> s.charAt(0), Collectors.toSet())));
|
||||
System.out.println(nestedMap);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
+2
-1
@@ -5,8 +5,9 @@ import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static Map<Integer, String> test(List<String> strings) {
|
||||
return strings.stream()
|
||||
Map<Integer, String> mapping = strings.stream()
|
||||
.co<caret>llect(Collectors.toMap(String::length, str -> str));
|
||||
return mapping;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
Reference in New Issue
Block a user