@NotNull
  public PsiVariable[] getOutputVariables(boolean collectVariablesAtExitPoints) {
    PsiVariable[] myOutputVariables =
        ControlFlowUtil.getOutputVariables(
            myControlFlow, myFlowStart, myFlowEnd, myExitPoints.toArray());
    if (collectVariablesAtExitPoints) {
      // variables declared in selected block used in return statements are to be considered output
      // variables when extracting guard methods
      final Set<PsiVariable> outputVariables = new HashSet<>(Arrays.asList(myOutputVariables));
      for (PsiStatement statement : myExitStatements) {
        statement.accept(
            new JavaRecursiveElementVisitor() {

              @Override
              public void visitReferenceExpression(PsiReferenceExpression expression) {
                super.visitReferenceExpression(expression);
                final PsiElement resolved = expression.resolve();
                if (resolved instanceof PsiVariable) {
                  final PsiVariable variable = (PsiVariable) resolved;
                  if (isWrittenInside(variable)) {
                    outputVariables.add(variable);
                  }
                }
              }

              private boolean isWrittenInside(final PsiVariable variable) {
                final List<Instruction> instructions = myControlFlow.getInstructions();
                for (int i = myFlowStart; i < myFlowEnd; i++) {
                  Instruction instruction = instructions.get(i);
                  if (instruction instanceof WriteVariableInstruction
                      && variable.equals(((WriteVariableInstruction) instruction).variable)) {
                    return true;
                  }
                }

                return false;
              }
            });
      }

      myOutputVariables = outputVariables.toArray(new PsiVariable[outputVariables.size()]);
    }
    Arrays.sort(myOutputVariables, PsiUtil.BY_POSITION);
    return myOutputVariables;
  }