CountedLoopJoiningTerminal (@NotNull TerminalBlock terminalBlock, @Nullable List<PsiVariable> nonFinalVariables) { if (nonFinalVariables != null && !nonFinalVariables.isEmpty()) return null; StreamApiMigrationInspection.CountingLoopSource loopSource = terminalBlock.getLastOperation(StreamApiMigrationInspection.CountingLoopSource.class); if (loopSource == null) return null; PsiExpression initializer = loopSource.getVariable().getInitializer(); Object constantExpression = ExpressionUtils.computeConstantExpression(initializer); if (!Integer.valueOf(1).equals(constantExpression)) return null; List<PsiStatement> statements = List.of(terminalBlock.getStatements()); if (statements.isEmpty()) return null; List<PsiExpression> joinParts = extractJoinParts(statements); if (joinParts == null) return null; JoinData joinData = JoinData.extractLeftDelimiter(joinParts); List<PsiExpression> delimiterJoinParts = joinData.getDelimiterJoinParts(); if (delimiterJoinParts.isEmpty()) return null; PsiStatement loop = terminalBlock.getStreamSourceStatement(); PsiLocalVariable variable = tryCast(terminalBlock.getVariable(), PsiLocalVariable.class); if (variable == null) return null; PsiVariable targetBuilder = extractStringBuilder(statements.get(0)); if (targetBuilder == null) return null; AppendChain beforeLoopAppend = JoiningTerminal.getCallBeforeStatement(loop, targetBuilder, emptyList()); if (beforeLoopAppend == null) return null; PsiStatement beforeLoopAppendStatement = PsiTreeUtil.getParentOfType(beforeLoopAppend.outermost, PsiStatement.class); if (beforeLoopAppendStatement == null) return null; List<PsiExpression> firstIterationJoinParts = extractJoinParts(beforeLoopAppend.outermost); if (firstIterationJoinParts == null) return null; PsiElementFactory factory = JavaPsiFacade.getElementFactory(targetBuilder.getProject()); PsiExpression expression = factory.createExpressionFromText("0", variable); List<PsiExpression> replacedMainJoinParts = copyReplacingVar(joinData.getMainJoinParts(), variable, expression); if (!joinPartsAreEquivalent(replacedMainJoinParts, firstIterationJoinParts)) return null; PrefixSuffixContext context = PrefixSuffixContext.extractAndVerifyRefs(loop, beforeLoopAppendStatement, targetBuilder, terminalBlock, emptyList(), new HashSet<>(singletonList(beforeLoopAppend.outermost))); if (context == null) return null; StreamApiMigrationInspection.CountingLoopSource newSource = loopSource.withInitializer(expression); return new CountedLoopJoiningTerminal(targetBuilder, variable, joinData.getMainJoinParts(), context, delimiterJoinParts, terminalBlock, newSource, beforeLoopAppendStatement); }