class RuboCop::Cop::Style::MixinGrouping

This cop checks for grouping of mixins in `class` and `module` bodies. By default it enforces mixins to be placed in separate declarations, but it can be configured to enforce grouping them in one declaration.

@example

EnforcedStyle: separated (default)

@bad
class Foo
  include Bar, Qox
end

@good
class Foo
  include Qox
  include Bar
end

EnforcedStyle: grouped

@bad
class Foo
  extend Bar
  extend Qox
end

@good
class Foo
  extend Qox, Bar
end

Constants

MIXIN_METHODS
MSG

Public Instance Methods

autocorrect(node) click to toggle source
# File lib/rubocop/cop/style/mixin_grouping.rb, line 48
def autocorrect(node)
  if separated_style?
    range = node.loc.expression
    correction = separate_mixins(node)
  else
    mixins = sibling_mixins(node)
    mixins.unshift(node)

    range = node.loc.expression.join(mixins.last.loc.expression)
    correction = group_mixins(node, mixins)
  end

  ->(corrector) { corrector.replace(range, correction) }
end
on_send(node) click to toggle source
# File lib/rubocop/cop/style/mixin_grouping.rb, line 42
def on_send(node)
  return unless node.macro? && MIXIN_METHODS.include?(node.method_name)

  check(node)
end

Private Instance Methods

check(send_node) click to toggle source
# File lib/rubocop/cop/style/mixin_grouping.rb, line 65
def check(send_node)
  if separated_style?
    check_separated_style(send_node)
  else
    check_grouped_style(send_node)
  end
end
check_grouped_style(send_node) click to toggle source
# File lib/rubocop/cop/style/mixin_grouping.rb, line 73
def check_grouped_style(send_node)
  return if sibling_mixins(send_node).empty?

  add_offense(send_node)
end
check_separated_style(send_node) click to toggle source
# File lib/rubocop/cop/style/mixin_grouping.rb, line 79
def check_separated_style(send_node)
  return if send_node.arguments.one?

  add_offense(send_node)
end
group_mixins(node, mixins) click to toggle source
# File lib/rubocop/cop/style/mixin_grouping.rb, line 119
def group_mixins(node, mixins)
  _receiver, mixin, *_args = *node
  all_mixin_arguments = mixins.reverse.flat_map do |m|
    m.arguments.map(&:source)
  end

  "#{mixin} #{all_mixin_arguments.join(', ')}"
end
grouped_style?() click to toggle source
# File lib/rubocop/cop/style/mixin_grouping.rb, line 101
def grouped_style?
  style == :grouped
end
indent(node) click to toggle source
# File lib/rubocop/cop/style/mixin_grouping.rb, line 128
def indent(node)
  ' ' * node.loc.column
end
message(send_node) click to toggle source
# File lib/rubocop/cop/style/mixin_grouping.rb, line 94
def message(send_node)
  suffix =
    separated_style? ? 'separate statements' : 'a single statement'

  format(MSG, send_node.method_name, suffix)
end
separate_mixins(node) click to toggle source
# File lib/rubocop/cop/style/mixin_grouping.rb, line 109
def separate_mixins(node)
  _receiver, mixin, *args = *node
  args.reverse!
  first_mixin = String.new("#{mixin} #{args.first.source}")

  args[1..-1].inject(first_mixin) do |replacement, arg|
    replacement << "\n#{indent(node)}#{mixin} #{arg.source}"
  end
end
separated_style?() click to toggle source
# File lib/rubocop/cop/style/mixin_grouping.rb, line 105
def separated_style?
  style == :separated
end
sibling_mixins(send_node) click to toggle source
# File lib/rubocop/cop/style/mixin_grouping.rb, line 85
def sibling_mixins(send_node)
  siblings = send_node.parent.each_child_node(:send)
                      .reject { |sibling| sibling == send_node }

  siblings.select do |sibling_node|
    sibling_node.method_name == send_node.method_name
  end
end