boolean (@NotNull List<PsiStatement> statements, int count, int offset, @NotNull List<PsiExpression> expressionsToReplace, @NotNull List<PsiExpression> expressionsToIterate) { EquivalenceChecker equivalence = EquivalenceChecker.getCanonicalPsiEquivalence(); PsiExpression firstIterationExpression = null; PsiExpression curIterationExpression = null; boolean secondIteration = count == offset; int mismatchedStatements = 0; for (int index = 0; index < count; index++) { PsiStatement first = statements.get(index); PsiStatement cur = statements.get(index + offset); EquivalenceChecker.Match match = new TrackingEquivalenceChecker().statementsMatch(first, cur); if (match.isExactMismatch()) return false; if (match.isExactMatch()) continue; mismatchedStatements++; PsiElement leftDiff = match.getLeftDiff(); PsiElement rightDiff = match.getRightDiff(); if (!(leftDiff instanceof PsiExpression) || !(rightDiff instanceof PsiExpression)) return false; curIterationExpression = (PsiExpression)rightDiff; firstIterationExpression = (PsiExpression)leftDiff; if (PsiUtil.isAccessedForWriting(curIterationExpression)) return false; PsiType curType = curIterationExpression.getType(); PsiType firstType = firstIterationExpression.getType(); if (curType == null || !curType.equals(firstType)) return false; Set<PsiVariable> usedVariables; if (secondIteration) { if (!expressionsToReplace.isEmpty()) { PsiExpression firstExpressionToReplace = expressionsToReplace.get(0); if (!equivalence.expressionsAreEquivalent(firstExpressionToReplace, firstIterationExpression)) return false; if (!firstType.equals(firstExpressionToReplace.getType())) return false; } expressionsToReplace.add(firstIterationExpression); usedVariables = StreamEx.of(firstIterationExpression, curIterationExpression) .map(VariableAccessUtils::collectUsedVariables).toFlatCollection(Function.identity(), HashSet::new); } else { if (!expressionsToReplace.contains(firstIterationExpression)) return false; usedVariables = VariableAccessUtils.collectUsedVariables(curIterationExpression); } if (!usedVariables.isEmpty() && ContainerUtil.exists(statements.subList(0, count), st -> VariableAccessUtils.isAnyVariableAssigned(usedVariables, st))) { return false; } } if (secondIteration) { ContainerUtil.addIfNotNull(expressionsToIterate, firstIterationExpression); } else { if (mismatchedStatements != expressionsToReplace.size()) { return false; } } ContainerUtil.addIfNotNull(expressionsToIterate, curIterationExpression); return true; }