IDEA-206497 Replace with stream: support intermediate map operations in counting loops

This commit is contained in:
Tagir Valeev
2019-02-04 14:19:52 +07:00
parent c02c63e4e0
commit 15e0df11f9
4 changed files with 64 additions and 7 deletions

View File

@@ -37,7 +37,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil.isEffectivelyFinal;
import static com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.isCallOf;
@@ -1129,14 +1128,44 @@ List<PsiExpression> builderStrInitializers = null;
@Nullable
static JoiningTerminal extractIndexBasedTerminal(@NotNull TerminalBlock terminalBlock,
@Nullable List<PsiVariable> nonFinalVariables) {
@Nullable List<PsiVariable> nonFinalVariables) {
if (nonFinalVariables != null && !nonFinalVariables.isEmpty()) return null;
SpecialFirstIterationLoop specialFirstIterationLoop = SpecialFirstIterationLoop.IndexBasedLoop.extract(terminalBlock);
StreamApiMigrationInspection.CountingLoopSource countingLoopSource =
terminalBlock.getLastOperation(StreamApiMigrationInspection.CountingLoopSource.class);
if (countingLoopSource == null) return null;
SpecialFirstIterationLoop specialFirstIterationLoop =
SpecialFirstIterationLoop.IndexBasedLoop.extract(terminalBlock, countingLoopSource);
if (specialFirstIterationLoop == null) return null;
List<PsiStatement> firstIterationStatements = specialFirstIterationLoop.getFirstIterationStatements();
List<PsiStatement> otherIterationStatements = specialFirstIterationLoop.getOtherIterationStatements();
if (firstIterationStatements.isEmpty() || otherIterationStatements.isEmpty()) return null;
int additionalPrefix = 0;
while (additionalPrefix < firstIterationStatements.size()) {
PsiStatement statement = firstIterationStatements.get(additionalPrefix);
if (additionalPrefix >= otherIterationStatements.size() || statement != otherIterationStatements.get(additionalPrefix)) {
break;
}
if (statement instanceof PsiExpressionStatement &&
JoiningTerminal.tryExtractJoinPart(((PsiExpressionStatement)statement).getExpression(), new ArrayList<>())) {
break;
}
additionalPrefix++;
}
if (additionalPrefix > 0) {
TerminalBlock newBlock =
TerminalBlock.fromStatements(countingLoopSource, firstIterationStatements.toArray(PsiStatement.EMPTY_ARRAY));
int leftOver = firstIterationStatements.size() - additionalPrefix;
while (newBlock != null && newBlock.getStatements().length < leftOver) {
newBlock = newBlock.withoutLastOperation();
}
if (newBlock != null && newBlock.getStatements().length == leftOver) {
terminalBlock = newBlock;
firstIterationStatements = firstIterationStatements.subList(additionalPrefix, firstIterationStatements.size());
otherIterationStatements = otherIterationStatements.subList(additionalPrefix, otherIterationStatements.size());
}
}
List<PsiExpression> firstIterationJoinParts = extractJoinParts(firstIterationStatements);
List<PsiExpression> otherIterationJoinParts = extractJoinParts(otherIterationStatements);

View File

@@ -272,10 +272,8 @@ class SpecialFirstIterationLoop {
sb.append(mainPart)
*/
@Nullable
static SpecialFirstIterationLoop extract(@NotNull TerminalBlock terminalBlock) {
StreamApiMigrationInspection.CountingLoopSource countingLoopSource =
terminalBlock.getLastOperation(StreamApiMigrationInspection.CountingLoopSource.class);
if (countingLoopSource == null) return null;
static SpecialFirstIterationLoop extract(@NotNull TerminalBlock terminalBlock,
StreamApiMigrationInspection.CountingLoopSource countingLoopSource) {
PsiVariable loopVar = countingLoopSource.getVariable();
PsiLocalVariable loopLocalVar = tryCast(loopVar, PsiLocalVariable.class);
if (loopLocalVar == null) return null;

View File

@@ -0,0 +1,13 @@
// "Replace with collect" "true"
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Test {
String foo(String[] lines) {
final String result = Arrays.stream(lines).collect(Collectors.joining("\n"));
// extracted into a separate var
return result;
}
}

View File

@@ -0,0 +1,17 @@
// "Replace with collect" "true"
import java.util.List;
public class Test {
String foo(String[] lines) {
final StringBuilder result = new StringBuilder();
fo<caret>r (int i = 0; i < lines.length; i++) {
final String line = lines[i];// extracted into a separate var
if (i > 0) {
result.append('\n');
}
result.append(line);
}
return result.toString();
}
}