class RuboCop::Cop::Style::AccessorGrouping


end
attr_reader :baz
attr_reader :bar
class Foo
# good
end
attr_reader :bar, :baz
class Foo
# bad
@example EnforcedStyle: separated
end
attr_reader :baz
may_be_intended_annotation :baz
attr_reader :bax
sig { returns(String) }
attr_reader :bar
# may be intended comment for bar.
class Foo
# good
end
attr_reader :bar, :bax, :baz
class Foo
# good
end
attr_reader :baz
attr_reader :bax
attr_reader :bar
class Foo
# bad
@example EnforcedStyle: grouped (default)
as it might be intended like Sorbet.
NOTE: If there is a method call before the accessor method it is always allowed
but it can be configured to enforce separating them in multiple declarations.
By default it enforces accessors to be placed in grouped declarations,
Checks for grouping of accessors in ‘class` and `module` bodies.

def autocorrect(corrector, node)

def autocorrect(corrector, node)
  if (preferred_accessors = preferred_accessors(node))
    corrector.replace(node, preferred_accessors)
  else
    range = range_with_surrounding_space(node.source_range, side: :left)
    corrector.remove(range)
  end
end

def check(send_node)

def check(send_node)
  return if previous_line_comment?(send_node) || !groupable_accessor?(send_node)
  return unless (grouped_style? && groupable_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

def class_send_elements(class_node)

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

def group_accessors(node, accessors)

def group_accessors(node, accessors)
  accessor_names = accessors.flat_map { |accessor| accessor.arguments.map(&:source) }.uniq
  "#{node.method_name} #{accessor_names.join(', ')}"
end

def groupable_accessor?(node)

def groupable_accessor?(node)
  return true unless (previous_expression = node.left_siblings.last)
  # Accessors with Sorbet `sig { ... }` blocks shouldn't be groupable.
  if previous_expression.block_type?
    previous_expression.child_nodes.each do |child_node|
      break previous_expression = child_node if child_node.send_type?
    end
  end
  return true unless previous_expression.send_type?
  previous_expression.attribute_accessor? || previous_expression.access_modifier?
end

def groupable_sibling_accessors(send_node)

def groupable_sibling_accessors(send_node)
  send_node.parent.each_child_node(:send).select do |sibling|
    sibling.attribute_accessor? &&
      sibling.method?(send_node.method_name) &&
      node_visibility(sibling) == node_visibility(send_node) &&
      groupable_accessor?(sibling) && !previous_line_comment?(sibling)
  end
end

def grouped_style?

def grouped_style?
  style == :grouped
end

def message(send_node)

def message(send_node)
  msg = grouped_style? ? GROUPED_MSG : SEPARATED_MSG
  format(msg, accessor: send_node.method_name)
end

def on_class(node)

def on_class(node)
  class_send_elements(node).each do |macro|
    next unless macro.attribute_accessor?
    check(macro)
  end
end

def preferred_accessors(node)

def preferred_accessors(node)
  if grouped_style?
    accessors = groupable_sibling_accessors(node)
    group_accessors(node, accessors) if node.loc == accessors.first.loc
  else
    separate_accessors(node)
  end
end

def previous_line_comment?(node)

def previous_line_comment?(node)
  comment_line?(processed_source[node.first_line - 2])
end

def separate_accessors(node)

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

def separated_style?

def separated_style?
  style == :separated
end