PrefixSuffixContext (@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); }