class RuboCop::Cop::Style::GuardClause

ok
foo || raise(‘exception’) if something
# good
end
ok
else
foo || raise(‘exception’)
if something
# bad
ok
raise ‘exception’ if something
# good
end
ok
else
raise ‘exception’
if something
# bad
end
work if something
def test
# also good
end
work
return unless something
def test
# good
end
end
work
if something
def test
# bad
@example
expression
Use a guard clause instead of wrapping the code inside a conditional

def accepted_form?(node, ending: false)

def accepted_form?(node, ending: false)
  accepted_if?(node, ending) || node.condition.multiline? ||
    node.parent&.assignment?
end

def accepted_if?(node, ending)

def accepted_if?(node, ending)
  return true if node.modifier_form? || node.ternary?
  if ending
    node.else?
  else
    !node.else? || node.elsif?
  end
end

def check_ending_if(node)

def check_ending_if(node)
  return if accepted_form?(node, ending: true) || !min_body_length?(node)
  register_offense(node, 'return', opposite_keyword(node))
end

def guard_clause_source(guard_clause)

def guard_clause_source(guard_clause)
  parent = guard_clause.parent
  if parent.and_type? || parent.or_type?
    guard_clause.parent.source
  else
    guard_clause.source
  end
end

def on_def(node)

def on_def(node)
  body = node.body
  return unless body
  if body.if_type?
    check_ending_if(body)
  elsif body.begin_type?
    final_expression = body.children.last
    check_ending_if(final_expression) if final_expression&.if_type?
  end
end

def on_if(node)

def on_if(node)
  return if accepted_form?(node)
  guard_clause_in_if = node.if_branch&.guard_clause?
  guard_clause_in_else = node.else_branch&.guard_clause?
  guard_clause = guard_clause_in_if || guard_clause_in_else
  return unless guard_clause
  kw = if guard_clause_in_if
         node.loc.keyword.source
       else
         opposite_keyword(node)
       end
  register_offense(node, guard_clause_source(guard_clause), kw)
end

def opposite_keyword(node)

def opposite_keyword(node)
  node.if? ? 'unless' : 'if'
end

def register_offense(node, scope_exiting_keyword, conditional_keyword)

def register_offense(node, scope_exiting_keyword, conditional_keyword)
  condition, = node.node_parts
  example = [scope_exiting_keyword,
             conditional_keyword,
             condition.source].join(' ')
  if too_long_for_single_line?(node, example)
    example = "#{conditional_keyword} #{condition.source}; " \
              "#{scope_exiting_keyword}; end"
  end
  add_offense(node.loc.keyword, message: format(MSG, example: example))
end

def too_long_for_single_line?(node, example)

def too_long_for_single_line?(node, example)
  max = max_line_length
  max && node.source_range.column + example.length > max
end