class RuboCop::Cop::Style::TernaryParentheses


foo = (bar = baz) ? a : b
# bad
@example AllowSafeAssignment: false
foo = (bar = baz) ? a : b
# good
@example AllowSafeAssignment: true (default)
foo = (bar && baz) ? a : b
foo = bar.baz? ? a : b
foo = bar? ? a : b
# good
foo = bar && baz ? a : b
foo = (bar.baz?) ? a : b
foo = (bar?) ? a : b
# bad
@example EnforcedStyle: require_parentheses_when_complex
foo = (bar && baz) ? a : b
foo = (bar.baz?) ? a : b
foo = (bar?) ? a : b
# good
foo = bar && baz ? a : b
foo = bar.baz? ? a : b
foo = bar? ? a : b
# bad
@example EnforcedStyle: require_parentheses
foo = bar && baz ? a : b
foo = bar.baz? ? a : b
foo = bar? ? a : b
# good
foo = (bar && baz) ? a : b
foo = (bar.baz?) ? a : b
foo = (bar?) ? a : b
# bad
@example EnforcedStyle: require_no_parentheses (default)
as a condition. It’s not a mistake.“
an assignment to indicate ”I know I’m using an assignment
By safe assignment we mean putting parentheses around
`AllowSafeAssignment` option for safe assignment.
removing the parentheses won’t cause a different behavior.
parentheses using ‘EnforcedStyle`. Omission is only enforced when
conditions. It is configurable to enforce inclusion or omission of
This cop checks for the presence of parentheses around ternary

def autocorrect(corrector, node)

def autocorrect(corrector, node)
  condition = node.condition
  return nil if parenthesized?(condition) &&
                (safe_assignment?(condition) || unsafe_autocorrect?(condition))
  if parenthesized?(condition)
    correct_parenthesized(corrector, condition)
  else
    correct_unparenthesized(corrector, condition)
  end
end

def below_ternary_precedence?(child)

def below_ternary_precedence?(child)
  # Handle English "or", e.g. 'foo or bar ? a : b'
  (child.or_type? && child.semantic_operator?) ||
    # Handle English "and", e.g. 'foo and bar ? a : b'
    (child.and_type? && child.semantic_operator?) ||
    # Handle English "not", e.g. 'not foo ? a : b'
    (child.send_type? && child.prefix_not?)
end

def complex_condition?(condition)

complex expressions within it.
If the condition is parenthesized we recurse and check for any
def complex_condition?(condition)
  if condition.begin_type?
    condition.to_a.any? { |x| complex_condition?(x) }
  else
    !non_complex_expression?(condition)
  end
end

def correct_parenthesized(corrector, condition)

def correct_parenthesized(corrector, condition)
  corrector.remove(condition.loc.begin)
  corrector.remove(condition.loc.end)
  # Ruby allows no space between the question mark and parentheses.
  # If we remove the parentheses, we need to add a space or we'll
  # generate invalid code.
  corrector.insert_after(condition.loc.end, ' ') unless whitespace_after?(condition)
end

def correct_unparenthesized(corrector, condition)

def correct_unparenthesized(corrector, condition)
  corrector.wrap(condition, '(', ')')
end

def infinite_loop?

as they compete to add and remove the parentheses respectively.
`RedundantParentheses` cop is enabled, it will cause an infinite loop
When this cop is configured to enforce parentheses and the
def infinite_loop?
  (require_parentheses? || require_parentheses_when_complex?) &&
    redundant_parentheses_enabled?
end

def message(node)

def message(node)
  if require_parentheses_when_complex?
    command = parenthesized?(node.condition) ? 'Only use' : 'Use'
    format(MSG_COMPLEX, command: command)
  else
    command = require_parentheses? ? 'Use' : 'Omit'
    format(MSG, command: command)
  end
end

def non_complex_expression?(condition)

will be counted as a complex expression.
Anything that is not a variable, constant, or method/.method call
def non_complex_expression?(condition)
  NON_COMPLEX_TYPES.include?(condition.type) || non_complex_send?(condition)
end

def non_complex_send?(node)

def non_complex_send?(node)
  return false unless node.call_type?
  !node.operator_method? || node.method?(:[])
end

def offense?(node)

def offense?(node)
  condition = node.condition
  if safe_assignment?(condition)
    !safe_assignment_allowed?
  else
    parens = parenthesized?(condition)
    case style
    when :require_parentheses_when_complex
      complex_condition?(condition) ? !parens : parens
    else
      require_parentheses? ? !parens : parens
    end
  end
end

def on_if(node)

def on_if(node)
  return if only_closing_parenthesis_is_last_line?(node.condition)
  return unless node.ternary? && !infinite_loop? && offense?(node)
  message = message(node)
  add_offense(node.source_range, message: message) do |corrector|
    autocorrect(corrector, node)
  end
end

def only_closing_parenthesis_is_last_line?(condition)

def only_closing_parenthesis_is_last_line?(condition)
  condition.source.split("\n").last == ')'
end

def parenthesized?(node)

def parenthesized?(node)
  node.begin_type?
end

def redundant_parentheses_enabled?

def redundant_parentheses_enabled?
  @config.for_cop('Style/RedundantParentheses').fetch('Enabled')
end

def require_parentheses?

def require_parentheses?
  style == :require_parentheses
end

def require_parentheses_when_complex?

def require_parentheses_when_complex?
  style == :require_parentheses_when_complex
end

def unparenthesized_method_call?(child)

def unparenthesized_method_call?(child)
  /^[a-z]/i.match?(method_name(child)) && !child.parenthesized?
end

def unsafe_autocorrect?(condition)

def unsafe_autocorrect?(condition)
  condition.children.any? do |child|
    unparenthesized_method_call?(child) ||
      below_ternary_precedence?(child)
  end
end

def whitespace_after?(node)

def whitespace_after?(node)
  last_token = processed_source.last_token_of(node)
  last_token.space_after?
end