ThenElse (@NotNull PsiIfStatement ifStatement, PsiStatement @NotNull [] thenBranch, PsiStatement @NotNull [] elseBranch, boolean isOnTheFly) { LocalEquivalenceChecker equivalence = getChecker(thenBranch, elseBranch); int thenLen = thenBranch.length; int elseLen = elseBranch.length; int minStmtCount = Math.min(thenLen, elseLen); PsiExpression condition = ifStatement.getCondition(); if (condition == null) return null; boolean conditionHasSideEffects = SideEffectChecker.mayHaveSideEffects(condition); if (!isOnTheFly && conditionHasSideEffects) return null; List<PsiLocalVariable> conditionVariables = new ArrayList<>(); boolean conditionVariablesCantBeChangedTransitively = StreamEx.ofTree((PsiElement)condition, el -> StreamEx.of(el.getChildren())) .allMatch(element -> { if (!(element instanceof PsiReferenceExpression)) { return !(element instanceof PsiMethodCallExpression); } PsiLocalVariable localVariable = tryCast(((PsiReferenceExpression)element).resolve(), PsiLocalVariable.class); if (localVariable == null) return false; conditionVariables.add(localVariable); return true; }); List<ExtractionUnit> headCommonParts = new ArrayList<>(); Set<PsiVariable> extractedVariables = new HashSet<>(); Set<PsiVariable> notEquivalentVariableDeclarations = new HashSet<>(0); extractHeadCommonParts(thenBranch, elseBranch, isOnTheFly, equivalence, minStmtCount, conditionVariables, headCommonParts, extractedVariables, notEquivalentVariableDeclarations); if (headCommonParts.isEmpty()) { // when head common parts contains e.g. first variable with different names but changes semantics and batch mode is on equivalence.mySubstitutionTable.clear(); } // set of variables which have in one branch initializer, but in other branch doesn't have initializer final Set<PsiVariable> differentDeclarationsWithoutInitializers = StreamEx.of(headCommonParts) .select(VariableDeclarationUnit.class) .map(unit -> unit.getVariableWithoutInitializer()) .nonNull() .toSet(); int extractedFromStart = headCommonParts.size(); int canBeExtractedFromThenTail = thenLen - extractedFromStart; int canBeExtractedFromElseTail = elseLen - extractedFromStart; int canBeExtractedFromTail = Math.min(canBeExtractedFromThenTail, canBeExtractedFromElseTail); List<PsiStatement> tailCommonParts = new ArrayList<>(); extractTailCommonParts(ifStatement, thenBranch, elseBranch, equivalence, thenLen, elseLen, extractedVariables, canBeExtractedFromTail, tailCommonParts, differentDeclarationsWithoutInitializers); tryAppendHeadPartsToTail(headCommonParts, canBeExtractedFromThenTail, canBeExtractedFromElseTail, canBeExtractedFromTail, tailCommonParts); Map<PsiLocalVariable, String> substitutionTable = equivalence.mySubstitutionTable; if (uncommonElseStatementsContainsThenNames(elseBranch, elseLen, headCommonParts, tailCommonParts, substitutionTable)) { return null; } if (headCommonParts.isEmpty() && tailCommonParts.isEmpty()) return null; PsiStatement thenStatement = ifStatement.getThenBranch(); PsiStatement elseStatement = ifStatement.getElseBranch(); if (thenStatement == null || elseStatement == null) return null; final CommonPartType type = getType(headCommonParts, tailCommonParts, notEquivalentVariableDeclarations.isEmpty(), thenLen, elseLen, thenStatement, elseStatement); if (type == CommonPartType.VARIABLES_ONLY && !notEquivalentVariableDeclarations.isEmpty()) return null; boolean mayChangeSemantics = mayChangeSemantics(conditionHasSideEffects, conditionVariablesCantBeChangedTransitively, headCommonParts); return new ThenElse(headCommonParts, tailCommonParts, mayChangeSemantics, type, substitutionTable); }