mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Stream API migration various fixes
1. findFirst() scenario can pull previous assignment (not declaration) now 2. anyMatch() fix did not work if there's single assignment to non-variable (e.g. array element) 3. if non-adjacent return becomes unreachable after findFirst()/anyMatch(), it returned automatically now
This commit is contained in:
+13
@@ -24,6 +24,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.controlFlow.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import one.util.streamex.StreamEx;
|
||||
@@ -152,4 +153,16 @@ abstract class MigrateToStreamFix implements LocalQuickFix {
|
||||
statement.delete();
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isReachable(PsiReturnStatement target) {
|
||||
ControlFlow flow;
|
||||
try {
|
||||
flow = ControlFlowFactory.getInstance(target.getProject())
|
||||
.getControlFlow(target.getParent(), LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance());
|
||||
}
|
||||
catch (AnalysisCanceledException e) {
|
||||
return true;
|
||||
}
|
||||
return ControlFlowUtil.isInstructionReachable(flow, flow.getStartOffset(target), 0);
|
||||
}
|
||||
}
|
||||
|
||||
+16
-2
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.PsiEquivalenceUtil;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.InitializerUsageStatus;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -52,10 +53,12 @@ class ReplaceWithFindFirstFix extends MigrateToStreamFix {
|
||||
if (!ExpressionUtils.isSimpleExpression(orElseExpression)) return null;
|
||||
stream = generateOptionalUnwrap(stream, tb, value, orElseExpression, null);
|
||||
restoreComments(loopStatement, body);
|
||||
if (nextReturnStatement.getParent() == loopStatement.getParent()) {
|
||||
boolean sibling = nextReturnStatement.getParent() == loopStatement.getParent();
|
||||
PsiElement replacement = loopStatement.replace(elementFactory.createStatementFromText("return " + stream + ";", loopStatement));
|
||||
if(sibling || !isReachable(nextReturnStatement)) {
|
||||
nextReturnStatement.delete();
|
||||
}
|
||||
return loopStatement.replace(elementFactory.createStatementFromText("return " + stream + ";", loopStatement));
|
||||
return replacement;
|
||||
}
|
||||
else {
|
||||
PsiStatement[] statements = tb.getStatements();
|
||||
@@ -84,6 +87,17 @@ class ReplaceWithFindFirstFix extends MigrateToStreamFix {
|
||||
return replaceInitializer(loopStatement, var, initializer, replacementText, status);
|
||||
}
|
||||
}
|
||||
PsiAssignmentExpression previousAssignment =
|
||||
ExpressionUtils.getAssignment(PsiTreeUtil.skipSiblingsBackward(loopStatement, PsiWhiteSpace.class, PsiComment.class));
|
||||
if(previousAssignment != null) {
|
||||
PsiExpression prevRValue = previousAssignment.getRExpression();
|
||||
PsiExpression prevLValue = previousAssignment.getLExpression();
|
||||
if(prevRValue != null && prevLValue instanceof PsiReferenceExpression && ((PsiReferenceExpression)prevLValue).resolve() == var) {
|
||||
previousAssignment.delete();
|
||||
return loopStatement.replace(elementFactory.createStatementFromText(
|
||||
var.getName() + " = " + generateOptionalUnwrap(stream, tb, value, prevRValue, var.getType()) + ";", loopStatement));
|
||||
}
|
||||
}
|
||||
return loopStatement.replace(elementFactory.createStatementFromText(
|
||||
var.getName() + " = " + generateOptionalUnwrap(stream, tb, value, lValue, var.getType()) + ";", loopStatement));
|
||||
}
|
||||
|
||||
+28
-21
@@ -69,7 +69,11 @@ class ReplaceWithMatchFix extends MigrateToStreamFix {
|
||||
removeLoop(loopStatement);
|
||||
return returnValue.replace(elementFactory.createExpressionFromText(streamText, nextReturnStatement));
|
||||
}
|
||||
return loopStatement.replace(elementFactory.createStatementFromText("return " + streamText + ";", loopStatement));
|
||||
PsiElement result = loopStatement.replace(elementFactory.createStatementFromText("return " + streamText + ";", loopStatement));
|
||||
if(!isReachable(nextReturnStatement)) {
|
||||
nextReturnStatement.delete();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,27 +88,30 @@ class ReplaceWithMatchFix extends MigrateToStreamFix {
|
||||
if(assignment != null) {
|
||||
PsiExpression lValue = assignment.getLExpression();
|
||||
PsiExpression rValue = assignment.getRExpression();
|
||||
if (!(lValue instanceof PsiReferenceExpression) || rValue == null) return null;
|
||||
PsiElement maybeVar = ((PsiReferenceExpression)lValue).resolve();
|
||||
if(maybeVar instanceof PsiVariable) {
|
||||
// Simplify single assignments like this:
|
||||
// boolean flag = false;
|
||||
// for(....) if(...) {flag = true; break;}
|
||||
PsiVariable var = (PsiVariable)maybeVar;
|
||||
PsiExpression initializer = var.getInitializer();
|
||||
InitializerUsageStatus status = StreamApiMigrationInspection.getInitializerUsageStatus(var, loopStatement);
|
||||
if(initializer != null && status != InitializerUsageStatus.UNKNOWN) {
|
||||
String replacement;
|
||||
if(ExpressionUtils.isLiteral(initializer, Boolean.FALSE) &&
|
||||
ExpressionUtils.isLiteral(rValue, Boolean.TRUE)) {
|
||||
replacement = streamText;
|
||||
} else if(ExpressionUtils.isLiteral(initializer, Boolean.TRUE) &&
|
||||
ExpressionUtils.isLiteral(rValue, Boolean.FALSE)) {
|
||||
replacement = "!"+streamText;
|
||||
} else {
|
||||
replacement = streamText + "?" + rValue.getText() + ":" + initializer.getText();
|
||||
if ((lValue instanceof PsiReferenceExpression) && rValue != null) {
|
||||
PsiElement maybeVar = ((PsiReferenceExpression)lValue).resolve();
|
||||
if (maybeVar instanceof PsiVariable) {
|
||||
// Simplify single assignments like this:
|
||||
// boolean flag = false;
|
||||
// for(....) if(...) {flag = true; break;}
|
||||
PsiVariable var = (PsiVariable)maybeVar;
|
||||
PsiExpression initializer = var.getInitializer();
|
||||
InitializerUsageStatus status = StreamApiMigrationInspection.getInitializerUsageStatus(var, loopStatement);
|
||||
if (initializer != null && status != InitializerUsageStatus.UNKNOWN) {
|
||||
String replacement;
|
||||
if (ExpressionUtils.isLiteral(initializer, Boolean.FALSE) &&
|
||||
ExpressionUtils.isLiteral(rValue, Boolean.TRUE)) {
|
||||
replacement = streamText;
|
||||
}
|
||||
else if (ExpressionUtils.isLiteral(initializer, Boolean.TRUE) &&
|
||||
ExpressionUtils.isLiteral(rValue, Boolean.FALSE)) {
|
||||
replacement = "!" + streamText;
|
||||
}
|
||||
else {
|
||||
replacement = streamText + "?" + rValue.getText() + ":" + initializer.getText();
|
||||
}
|
||||
return replaceInitializer(loopStatement, var, initializer, replacement, status);
|
||||
}
|
||||
return replaceInitializer(loopStatement, var, initializer, replacement, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// "Replace with anyMatch()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testAssignment(List<String> data) {
|
||||
String[] found = {"no"};
|
||||
if (data.stream().map(String::trim).anyMatch(trimmed -> !trimmed.isEmpty())) {
|
||||
found[0] = "yes";
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// "Replace with anyMatch()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
boolean find(List<String> data) {
|
||||
if(data != null) {
|
||||
return data.stream().map(String::trim).anyMatch(trimmed -> trimmed.startsWith("xyz"));
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// "Replace with findFirst()" "true"
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Main {
|
||||
private int getInitialSize() {return 0;}
|
||||
|
||||
public void testMap(Map<String, List<String>> map) throws Exception {
|
||||
int firstSize = 10;
|
||||
|
||||
System.out.println(firstSize);
|
||||
|
||||
// loop
|
||||
// comment
|
||||
firstSize = map.values().stream().filter(Objects::nonNull).findFirst().map(List::size).orElse(getInitialSize());
|
||||
System.out.println(firstSize);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace with findFirst()" "true"
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public static String find(List<List<String>> list) {
|
||||
if(list == null) {
|
||||
System.out.println("oops");
|
||||
return "";
|
||||
} else {
|
||||
return list.stream().flatMap(Collection::stream).filter(string -> string.startsWith("ABC")).findFirst().orElse(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace with anyMatch()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testAssignment(List<String> data) {
|
||||
String[] found = {"no"};
|
||||
for(String str : da<caret>ta) {
|
||||
String trimmed = str.trim();
|
||||
if(!trimmed.isEmpty()) {
|
||||
found[0] = "yes";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// "Replace with anyMatch()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
boolean find(List<String> data) {
|
||||
if(data != null) {
|
||||
for (String e : da<caret>ta) {
|
||||
String trimmed = e.trim();
|
||||
if (trimmed.startsWith("xyz")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// "Replace with findFirst()" "true"
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Main {
|
||||
private int getInitialSize() {return 0;}
|
||||
|
||||
public void testMap(Map<String, List<String>> map) throws Exception {
|
||||
int firstSize = 10;
|
||||
|
||||
System.out.println(firstSize);
|
||||
|
||||
firstSize = getInitialSize();
|
||||
// loop
|
||||
for(List<String> list : map.valu<caret>es()) {
|
||||
if(list != null) {
|
||||
firstSize = list.size();
|
||||
// comment
|
||||
break;
|
||||
}
|
||||
}
|
||||
System.out.println(firstSize);
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// "Replace with findFirst()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public static String find(List<List<String>> list) {
|
||||
if(list == null) {
|
||||
System.out.println("oops");
|
||||
return "";
|
||||
} else {
|
||||
for (List<String> innerList : lis<caret>t) {
|
||||
for (String string : innerList) {
|
||||
if (string.startsWith("ABC")) {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user