@Nullable
      static CountedLoopJoiningTerminal extractCountedLoopTerminal(@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);
      }
@Nullable
      static CountedLoopJoiningTerminal extractCountedLoopTerminal(@NotNull TerminalBlock terminalBlock,
                                                                   @Nullable List<PsiVariable> nonFinalVariables)