@Nullable
  static BooleanReturnModel from(@NotNull PsiCodeBlock body, PsiReturnStatement @NotNull [] returns) {
    List<PsiExpression> terminal = new ArrayList<>();
    boolean earlyValue = false;
    int earlyCount = 0;
    boolean hasReturnInLoopOrSwitch = false;
    for (PsiReturnStatement returnStatement : returns) {
      if (!hasReturnInLoopOrSwitch) {
        hasReturnInLoopOrSwitch = isInLoopOrSwitch(body, returnStatement);
      }
      PsiExpression returnValue = returnStatement.getReturnValue();
      if (returnValue == null || !PsiTypes.booleanType().equals(returnValue.getType())) return null;
      if (ControlFlowUtils.blockCompletesWithStatement(body, returnStatement)) {
        terminal.add(returnValue);
      }
      else {
        PsiLiteralExpression literal = ExpressionUtils.getLiteral(returnValue);
        if (literal == null) return null;
        Boolean literalValue = ObjectUtils.tryCast(literal.getValue(), Boolean.class);
        if (literalValue == null) return null;
        if (earlyCount == 0) {
          earlyValue = literalValue;
        }
        else if (earlyValue != literalValue) {
          return null;
        }
        earlyCount++;
      }
    }
    if (earlyCount == 0) return null;
    int terminalCount = 0;
    for (PsiExpression value : terminal) {
      PsiLiteralExpression literal = ExpressionUtils.getLiteral(value);
      if (literal == null || !(literal.getValue() instanceof Boolean)) {
        terminalCount++;
      }
      else if (literal.getValue().equals(earlyValue)) {
        earlyCount++;
      }
    }
    return new BooleanReturnModel(earlyValue, earlyCount, terminalCount, hasReturnInLoopOrSwitch);
  }
@Nullable
  static BooleanReturnModel from(@NotNull PsiCodeBlock body, PsiReturnStatement @NotNull [] returns)