@Nullable
      static PrefixSuffixContext extractAndVerifyRefs(@NotNull PsiStatement finalAppendPredecessor,
                                                      @NotNull PsiStatement firstAppendSuccessor,
                                                      @NotNull PsiVariable targetBuilder,
                                                      @NotNull TerminalBlock terminalBlock,
                                                      @NotNull List<PsiLocalVariable> possibleVariablesBeforeLoop,
                                                      @NotNull Set<PsiMethodCallExpression> allowedReferencePlaces) {
        AppendChain afterLoopAppend = getCallAfterStatement(finalAppendPredecessor, targetBuilder);

        List<PsiDeclarationStatement> declarations = getDeclarations(possibleVariablesBeforeLoop);
        if(declarations == null) return null;
        AppendChain beforeLoopAppend = getCallBeforeStatement(firstAppendSuccessor, targetBuilder, declarations);
        List<PsiExpression> builderStrInitializers = null;
        PsiMethodCallExpression afterLoopAppendCall = afterLoopAppend != null ? afterLoopAppend.outermost : null;
        PsiMethodCallExpression beforeLoopAppendCall = beforeLoopAppend != null ? beforeLoopAppend.outermost : null;
        if(targetBuilder instanceof PsiLocalVariable) {
          if(!canBeMadeNonFinal((PsiLocalVariable)targetBuilder, terminalBlock.getStreamSourceStatement())) return null;

          List<PsiElement> refs = StreamEx.of(ReferencesSearch.search(targetBuilder).findAll())
            .map(PsiReference::getElement)
            .remove(e -> PsiTreeUtil.isAncestor(targetBuilder, e, false) ||
                         PsiTreeUtil.isAncestor(terminalBlock.getStreamSourceStatement(), e, false))
            .toList();
          if (afterLoopAppend != null) {
            allowedReferencePlaces.add(afterLoopAppend.first);
          }
          if (beforeLoopAppend != null) {
            allowedReferencePlaces.add(beforeLoopAppend.first);
          }

          boolean allowed = areReferencesAllowed(refs, allowedReferencePlaces);
          if (!allowed) {
            PsiMethodCallExpression newAfterLoopAppend = tryExtractCombinedToString(afterLoopAppendCall, refs);
            if (newAfterLoopAppend == null) return null;
            afterLoopAppendCall = newAfterLoopAppend;
          }
          builderStrInitializers = extractStringBuilderInitializer(targetBuilder.getInitializer());
          if(builderStrInitializers == null) return null;
        }
        List<PsiExpression> prefixJoinParts = extractJoinParts(beforeLoopAppendCall);
        if (prefixJoinParts == null) return null;
        if(builderStrInitializers != null) {
          prefixJoinParts.addAll(0, builderStrInitializers);
        }
        if (afterLoopAppend != null && VariableAccessUtils.variableIsUsed(targetBuilder, afterLoopAppendCall.getArgumentList())) {
          return null;
        }
        List<PsiExpression> suffixJoinParts = extractJoinParts(afterLoopAppendCall);
        if (suffixJoinParts == null) return null;
        return new PrefixSuffixContext(beforeLoopAppendCall, afterLoopAppendCall, prefixJoinParts, suffixJoinParts);
      }
@Nullable
      static PrefixSuffixContext extractAndVerifyRefs(@NotNull PsiStatement finalAppendPredecessor,
                                                      @NotNull PsiStatement firstAppendSuccessor,
                                                      @NotNull PsiVariable targetBuilder,
                                                      @NotNull TerminalBlock terminalBlock,
                                                      @NotNull List<PsiLocalVariable> possibleVariablesBeforeLoop,
                                                      @NotNull Set<PsiMethodCallExpression> allowedReferencePlaces)