class RuboCop::Cop::Style::AccessModifierDeclarations

Access modifiers should be declared to apply to a group of methods or inline before each method, depending on configuration. EnforcedStyle config covers only method definitions. Applications of visibility methods to symbols can be controlled using AllowModifiersOnSymbols config. Also, the visibility of ‘attr*` methods can be controlled using AllowModifiersOnAttrs config.

In Ruby 3.0, ‘attr*` methods now return an array of defined method names as symbols. So we can write the modifier and `attr*` in inline style. AllowModifiersOnAttrs config allows `attr*` methods to be written in inline style without modifying applications that have been maintained for a long time in group style. Furthermore, developers who are not very familiar with Ruby may know that the modifier applies to `def`, but they may not know that it also applies to `attr*` methods. It would be easier to understand if we could write `attr*` methods in inline style.

@safety

Autocorrection is not safe, because the visibility of dynamically
defined methods can vary depending on the state determined by
the group access modifier.

@example EnforcedStyle: group (default)

# bad
class Foo

  private def bar; end
  private def baz; end

end

# good
class Foo

  private

  def bar; end
  def baz; end

end

@example EnforcedStyle: inline

# bad
class Foo

  private

  def bar; end
  def baz; end

end

# good
class Foo

  private def bar; end
  private def baz; end

end

@example AllowModifiersOnSymbols: true (default)

# good
class Foo

  private :bar, :baz
  private *%i[qux quux]
  private *METHOD_NAMES

end

@example AllowModifiersOnSymbols: false

# bad
class Foo

  private :bar, :baz
  private *%i[qux quux]
  private *METHOD_NAMES

end

@example AllowModifiersOnAttrs: true (default)

# good
class Foo

  public attr_reader :bar
  protected attr_writer :baz
  private attr_accessor :qux
  private attr :quux

  def public_method; end

  private

  def private_method; end

end

@example AllowModifiersOnAttrs: false

# bad
class Foo

  public attr_reader :bar
  protected attr_writer :baz
  private attr_accessor :qux
  private attr :quux

end

Constants

ALLOWED_NODE_TYPES
GROUP_STYLE_MESSAGE
INLINE_STYLE_MESSAGE
RESTRICT_ON_SEND

Public Instance Methods

on_send(node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 146
def on_send(node)
  return unless node.access_modifier?
  return if ALLOWED_NODE_TYPES.include?(node.parent&.type)
  return if allow_modifiers_on_symbols?(node)
  return if allow_modifiers_on_attrs?(node)

  if offense?(node)
    add_offense(node.loc.selector) do |corrector|
      autocorrect(corrector, node)
    end
    opposite_style_detected
  else
    correct_style_detected
  end
end

Private Instance Methods

access_modifier_is_inlined?(node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 205
def access_modifier_is_inlined?(node)
  node.arguments.any?
end
access_modifier_is_not_inlined?(node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 209
def access_modifier_is_not_inlined?(node)
  !access_modifier_is_inlined?(node)
end
allow_modifiers_on_attrs?(node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 187
def allow_modifiers_on_attrs?(node)
  cop_config['AllowModifiersOnAttrs'] && access_modifier_with_attr?(node)
end
allow_modifiers_on_symbols?(node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 183
def allow_modifiers_on_symbols?(node)
  cop_config['AllowModifiersOnSymbols'] && access_modifier_with_symbol?(node)
end
autocorrect(corrector, node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 164
def autocorrect(corrector, node)
  case style
  when :group
    def_node = find_corresponding_def_node(node)
    return unless def_node

    replace_def(corrector, node, def_node)
  when :inline
    remove_node(corrector, node)
    select_grouped_def_nodes(node).each do |grouped_def_node|
      insert_inline_modifier(corrector, grouped_def_node, node.method_name)
    end
  end
end
def_source(node, def_node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 279
def def_source(node, def_node)
  [*processed_source.ast_with_comments[node].map(&:text), def_node.source].join("\n")
end
find_argument_less_modifier_node(node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 240
def find_argument_less_modifier_node(node)
  return unless (parent = node.parent)

  parent.each_child_node(:send).find do |child|
    child.method?(node.method_name) && child.arguments.empty?
  end
end
find_corresponding_def_node(node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 229
def find_corresponding_def_node(node)
  if access_modifier_with_symbol?(node)
    method_name = node.first_argument.respond_to?(:value) && node.first_argument.value
    node.parent.each_child_node(:def).find do |child|
      child.method?(method_name)
    end
  else
    node.first_argument
  end
end
group_style?() click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 197
def group_style?
  style == :group
end
inline_style?() click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 201
def inline_style?
  style == :inline
end
insert_inline_modifier(corrector, node, modifier_name) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 271
def insert_inline_modifier(corrector, node, modifier_name)
  corrector.insert_before(node, "#{modifier_name} ")
end
message(range) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 219
def message(range)
  access_modifier = range.source

  if group_style?
    format(GROUP_STYLE_MESSAGE, access_modifier: access_modifier)
  elsif inline_style?
    format(INLINE_STYLE_MESSAGE, access_modifier: access_modifier)
  end
end
offense?(node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 191
def offense?(node)
  (group_style? && access_modifier_is_inlined?(node) &&
    !right_siblings_same_inline_method?(node)) ||
    (inline_style? && access_modifier_is_not_inlined?(node))
end
percent_symbol_array?(node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 179
def percent_symbol_array?(node)
  node.array_type? && node.percent_literal?(:symbol)
end
remove_node(corrector, node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 275
def remove_node(corrector, node)
  corrector.remove(range_with_comments_and_lines(node))
end
replace_def(corrector, node, def_node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 254
def replace_def(corrector, node, def_node)
  source = def_source(node, def_node)
  argument_less_modifier_node = find_argument_less_modifier_node(node)
  if argument_less_modifier_node
    corrector.insert_after(argument_less_modifier_node, "\n\n#{source}")
  elsif (ancestor = node.each_ancestor(:block, :class, :module).first)

    corrector.insert_before(ancestor.loc.end, "#{node.method_name}\n\n#{source}\n")
  else
    corrector.replace(node, "#{node.method_name}\n\n#{source}")
    return
  end

  remove_node(corrector, def_node)
  remove_node(corrector, node)
end
right_siblings_same_inline_method?(node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 213
def right_siblings_same_inline_method?(node)
  node.right_siblings.any? do |sibling|
    sibling.send_type? && sibling.method?(node.method_name) && !sibling.arguments.empty?
  end
end
select_grouped_def_nodes(node) click to toggle source
# File lib/rubocop/cop/style/access_modifier_declarations.rb, line 248
def select_grouped_def_nodes(node)
  node.right_siblings.take_while do |sibling|
    !(sibling.send_type? && sibling.bare_access_modifier_declaration?)
  end.select(&:def_type?)
end