class RuboCop::Cop::Style::AccessorGrouping

Checks for grouping of accessors in `class` and `module` bodies. By default it enforces accessors to be placed in grouped declarations, but it can be configured to enforce separating them in multiple declarations.

NOTE: `Sorbet` is not compatible with “grouped” style. Consider “separated” style or disabling this cop.

@example EnforcedStyle: grouped (default)

# bad
class Foo
  attr_reader :bar
  attr_reader :baz
end

# good
class Foo
  attr_reader :bar, :baz
end

@example EnforcedStyle: separated

# bad
class Foo
  attr_reader :bar, :baz
end

# good
class Foo
  attr_reader :bar
  attr_reader :baz
end

Constants

ACCESSOR_METHODS
GROUPED_MSG
SEPARATED_MSG

Public Instance Methods

on_class(node) click to toggle source
# File lib/rubocop/cop/style/accessor_grouping.rb, line 48
def on_class(node)
  class_send_elements(node).each do |macro|
    next unless accessor?(macro)

    check(macro)
  end
end
Also aliased as: on_sclass, on_module
on_module(node)
Alias for: on_class
on_sclass(node)
Alias for: on_class

Private Instance Methods

accessor?(send_node) click to toggle source
# File lib/rubocop/cop/style/accessor_grouping.rb, line 96
def accessor?(send_node)
  send_node.macro? && ACCESSOR_METHODS.include?(send_node.method_name)
end
autocorrect(corrector, node) click to toggle source
# File lib/rubocop/cop/style/accessor_grouping.rb, line 71
def autocorrect(corrector, node)
  if (preferred_accessors = preferred_accessors(node))
    corrector.replace(node, preferred_accessors)
  else
    range = range_with_surrounding_space(node.loc.expression, side: :left)
    corrector.remove(range)
  end
end
check(send_node) click to toggle source
# File lib/rubocop/cop/style/accessor_grouping.rb, line 60
def check(send_node)
  return if previous_line_comment?(send_node)
  return unless (grouped_style? && sibling_accessors(send_node).size > 1) ||
                (separated_style? && send_node.arguments.size > 1)

  message = message(send_node)
  add_offense(send_node, message: message) do |corrector|
    autocorrect(corrector, send_node)
  end
end
class_send_elements(class_node) click to toggle source
# File lib/rubocop/cop/style/accessor_grouping.rb, line 84
def class_send_elements(class_node)
  class_def = class_node.body

  if !class_def || class_def.def_type?
    []
  elsif class_def.send_type?
    [class_def]
  else
    class_def.each_child_node(:send).to_a
  end
end
group_accessors(node, accessors) click to toggle source
# File lib/rubocop/cop/style/accessor_grouping.rb, line 131
def group_accessors(node, accessors)
  accessor_names = accessors.flat_map { |accessor| accessor.arguments.map(&:source) }.uniq

  "#{node.method_name} #{accessor_names.join(', ')}"
end
grouped_style?() click to toggle source
# File lib/rubocop/cop/style/accessor_grouping.rb, line 100
def grouped_style?
  style == :grouped
end
message(send_node) click to toggle source
# File lib/rubocop/cop/style/accessor_grouping.rb, line 117
def message(send_node)
  msg = grouped_style? ? GROUPED_MSG : SEPARATED_MSG
  format(msg, accessor: send_node.method_name)
end
preferred_accessors(node) click to toggle source
# File lib/rubocop/cop/style/accessor_grouping.rb, line 122
def preferred_accessors(node)
  if grouped_style?
    accessors = sibling_accessors(node)
    group_accessors(node, accessors) if node.loc == accessors.first.loc
  else
    separate_accessors(node)
  end
end
previous_line_comment?(node) click to toggle source
# File lib/rubocop/cop/style/accessor_grouping.rb, line 80
def previous_line_comment?(node)
  comment_line?(processed_source[node.first_line - 2])
end
separate_accessors(node) click to toggle source
# File lib/rubocop/cop/style/accessor_grouping.rb, line 137
def separate_accessors(node)
  node.arguments.flat_map do |arg|
    lines = [
      *processed_source.ast_with_comments[arg].map(&:text),
      "#{node.method_name} #{arg.source}"
    ]
    if arg == node.arguments.first
      lines
    else
      indent = ' ' * node.loc.column
      lines.map { |line| "#{indent}#{line}" }
    end
  end.join("\n")
end
separated_style?() click to toggle source
# File lib/rubocop/cop/style/accessor_grouping.rb, line 104
def separated_style?
  style == :separated
end
sibling_accessors(send_node) click to toggle source
# File lib/rubocop/cop/style/accessor_grouping.rb, line 108
def sibling_accessors(send_node)
  send_node.parent.each_child_node(:send).select do |sibling|
    accessor?(sibling) &&
      sibling.method?(send_node.method_name) &&
      node_visibility(sibling) == node_visibility(send_node) &&
      !previous_line_comment?(sibling)
  end
end