class RuboCop::Cop::Style::IfUnlessModifier

Checks for if and unless statements that would fit on one line if written as a modifier if/unless. The maximum line length is configurable.

Constants

ASSIGNMENT_TYPES

Public Instance Methods

autocorrect(node) click to toggle source
# File lib/rubocop/cop/style/if_unless_modifier.rb, line 53
def autocorrect(node)
  cond, body, _else = if_node_parts(node)

  oneline =
    "#{body.source} #{node.loc.keyword.source} " + cond.source
  first_line_comment = processed_source.comments.find do |c|
    c.loc.line == node.loc.line
  end
  if first_line_comment
    oneline << ' ' << first_line_comment.loc.expression.source
  end
  oneline = "(#{oneline})" if parenthesize?(node)

  ->(corrector) { corrector.replace(node.source_range, oneline) }
end
message(keyword) click to toggle source
# File lib/rubocop/cop/style/if_unless_modifier.rb, line 16
def message(keyword)
  "Favor modifier `#{keyword}` usage when having a single-line body."            ' Another good alternative is the usage of control flow `&&`/`||`.'
end
method_uses_parens?(node, limit) click to toggle source
# File lib/rubocop/cop/style/if_unless_modifier.rb, line 48
def method_uses_parens?(node, limit)
  source = node.source_range.source_line[0...limit.loc.column]
  source =~ /\s*\(\s*$/
end
on_if(node) click to toggle source
# File lib/rubocop/cop/style/if_unless_modifier.rb, line 21
def on_if(node)
  # discard ternary ops, if/else and modifier if/unless nodes
  return if ternary?(node)
  return if modifier_if?(node)
  return if elsif?(node)
  return if if_else?(node)
  return if node.chained?
  return unless fit_within_line_as_modifier_form?(node)
  return if nested_conditional?(node)
  add_offense(node, :keyword, message(node.loc.keyword.source))
end
parenthesize?(node) click to toggle source
# File lib/rubocop/cop/style/if_unless_modifier.rb, line 33
def parenthesize?(node)
  # Parenthesize corrected expression if changing to modifier-if form
  # would change the meaning of the parent expression
  # (due to the low operator precedence of modifier-if)
  return false if node.parent.nil?
  return true if ASSIGNMENT_TYPES.include?(node.parent.type)

  if node.parent.send_type?
    _receiver, _name, *args = *node.parent
    return !method_uses_parens?(node.parent, args.first)
  end

  false
end

Private Instance Methods

nested_conditional?(node) click to toggle source

returns false if the then or else children are conditionals

# File lib/rubocop/cop/style/if_unless_modifier.rb, line 72
def nested_conditional?(node)
  node.children[1, 2].any? { |child| child && child.type == :if }
end