JoiningTerminal (@NotNull TerminalBlock terminalBlock, @Nullable List<PsiVariable> nonFinalVariables) { if (nonFinalVariables != null && !nonFinalVariables.isEmpty()) return null; 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<? extends PsiStatement> firstIterationStatements = specialFirstIterationLoop.getFirstIterationStatements(); List<? extends 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); if (firstIterationJoinParts == null || otherIterationJoinParts == null) return null; JoinData joinData = JoinData.extractLeftDelimiter(otherIterationJoinParts); if (!joinPartsAreEquivalent(joinData.getMainJoinParts(), firstIterationJoinParts)) return null; if (firstIterationStatements.isEmpty()) return null; PsiVariable targetBuilder = extractStringBuilder(firstIterationStatements.get(0)); if (targetBuilder == null) return null; PsiStatement loop = terminalBlock.getStreamSourceStatement(); PrefixSuffixContext context = PrefixSuffixContext.extractAndVerifyRefs(loop, loop, targetBuilder, terminalBlock, emptyList(), new HashSet<>(emptyList())); if (context == null) return null; return new IndexBasedJoiningTerminal(targetBuilder, terminalBlock.getVariable(), firstIterationJoinParts, context, joinData.getDelimiterJoinParts(), terminalBlock); }