class RuboCop::Cop::Lint::UselessAccessModifier

Checks for redundant access modifiers, including those with no code, those which are repeated, and leading `public` modifiers in a class or module body. Conditionally-defined methods are considered as always being defined, and thus access modifiers guarding such methods are not redundant.

This cop has `ContextCreatingMethods` option. The default setting value is an empty array that means no method is specified. This setting is an array of methods which, when called, are known to create its own context in the module's current access context.

It also has `MethodCreatingMethods` option. The default setting value is an empty array that means no method is specified. This setting is an array of methods which, when called, are known to create other methods in the module's current access context.

@example

# bad
class Foo
  public # this is redundant (default access is public)

  def method
  end
end

# bad
class Foo
  # The following is redundant (methods defined on the class'
  # singleton class are not affected by the private modifier)
  private

  def self.method3
  end
end

# bad
class Foo
  protected

  define_method(:method2) do
  end

  protected # this is redundant (repeated from previous modifier)

  [1,2,3].each do |i|
    define_method("foo#{i}") do
    end
  end
end

# bad
class Foo
  private # this is redundant (no following methods are defined)
end

# good
class Foo
  private # this is not redundant (a method is defined)

  def method2
  end
end

# good
class Foo
  # The following is not redundant (conditionally defined methods are
  # considered as always defining a method)
  private

  if condition?
    def method
    end
  end
end

# good
class Foo
  protected # this is not redundant (a method is defined)

  define_method(:method2) do
  end
end

@example ContextCreatingMethods: concerning

# Lint/UselessAccessModifier:
#   ContextCreatingMethods:
#     - concerning

# good
require 'active_support/concern'
class Foo
  concerning :Bar do
    def some_public_method
    end

    private

    def some_private_method
    end
  end

  # this is not redundant because `concerning` created its own context
  private

  def some_other_private_method
  end
end

@example MethodCreatingMethods: delegate

# Lint/UselessAccessModifier:
#   MethodCreatingMethods:
#     - delegate

# good
require 'active_support/core_ext/module/delegation'
class Foo
  # this is not redundant because `delegate` creates methods
  private

  delegate :method_a, to: :method_b
end

Constants

MSG

Public Instance Methods

on_block(node) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 139
def on_block(node)
  return unless eval_call?(node)

  check_node(node.body)
end
Also aliased as: on_numblock
on_class(node) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 133
def on_class(node)
  check_node(node.body)
end
Also aliased as: on_module, on_sclass
on_module(node)
Alias for: on_class
on_numblock(node)
Alias for: on_block
on_sclass(node)
Alias for: on_class

Private Instance Methods

access_modifier?(node) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 187
def access_modifier?(node)
  node.bare_access_modifier? || node.method?(:private_class_method)
end
any_context_creating_methods?(child) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 277
        def any_context_creating_methods?(child)
          cop_config.fetch('ContextCreatingMethods', []).any? do |m|
            matcher_name = "#{m}_block?".to_sym
            unless respond_to?(matcher_name)
              self.class.def_node_matcher matcher_name, <<~PATTERN
                ({block numblock} (send {nil? const} {:#{m}} ...) ...)
              PATTERN
            end

            public_send(matcher_name, child)
          end
        end
any_method_definition?(child) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 254
        def any_method_definition?(child)
          cop_config.fetch('MethodCreatingMethods', []).any? do |m|
            matcher_name = "#{m}_method?".to_sym
            unless respond_to?(matcher_name)
              self.class.def_node_matcher matcher_name, <<~PATTERN
                {def (send nil? :#{m} ...)}
              PATTERN
            end

            public_send(matcher_name, child)
          end
        end
autocorrect(corrector, node) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 149
def autocorrect(corrector, node)
  range = range_by_whole_lines(node.source_range, include_final_newline: true)

  corrector.remove(range)
end
check_child_nodes(node, unused, cur_vis) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 200
def check_child_nodes(node, unused, cur_vis)
  node.child_nodes.each do |child|
    if child.send_type? && access_modifier?(child)
      cur_vis, unused = check_send_node(child, cur_vis, unused)
    elsif method_definition?(child)
      unused = nil
    elsif start_of_new_scope?(child)
      check_scope(child)
    elsif !child.defs_type?
      cur_vis, unused = check_child_nodes(child, unused, cur_vis)
    end
  end

  [cur_vis, unused]
end
check_new_visibility(node, unused, new_vis, cur_vis) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 227
def check_new_visibility(node, unused, new_vis, cur_vis)
  # does this modifier just repeat the existing visibility?
  if new_vis == cur_vis
    add_offense(node, message: format(MSG, current: cur_vis)) do |corrector|
      autocorrect(corrector, node)
    end
  else
    # was the previous modifier never applied to any defs?
    if unused
      add_offense(unused, message: format(MSG, current: cur_vis)) do |corrector|
        autocorrect(corrector, unused)
      end
    end
    # once we have already warned about a certain modifier, don't
    # warn again even if it is never applied to any method defs
    unused = node
  end

  [new_vis, unused]
end
check_node(node) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 175
def check_node(node)
  return if node.nil?

  if node.begin_type?
    check_scope(node)
  elsif node.send_type? && node.bare_access_modifier?
    add_offense(node, message: format(MSG, current: node.method_name)) do |corrector|
      autocorrect(corrector, node)
    end
  end
end
check_scope(node) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 191
def check_scope(node)
  cur_vis, unused = check_child_nodes(node, nil, :public)
  return unless unused

  add_offense(unused, message: format(MSG, current: cur_vis)) do |corrector|
    autocorrect(corrector, unused)
  end
end
check_send_node(node, cur_vis, unused) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 216
def check_send_node(node, cur_vis, unused)
  if node.bare_access_modifier?
    check_new_visibility(node, unused, node.method_name, cur_vis)
  elsif node.method?(:private_class_method) && !node.arguments?
    add_offense(node, message: format(MSG, current: node.method_name)) do |corrector|
      autocorrect(corrector, node)
    end
    [cur_vis, unused]
  end
end
eval_call?(child) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 271
def eval_call?(child)
  class_or_instance_eval?(child) ||
    class_or_module_or_struct_new_call?(child) ||
    any_context_creating_methods?(child)
end
method_definition?(child) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 248
def method_definition?(child)
  static_method_definition?(child) ||
    dynamic_method_definition?(child) ||
    any_method_definition?(child)
end
start_of_new_scope?(child) click to toggle source
# File lib/rubocop/cop/lint/useless_access_modifier.rb, line 267
def start_of_new_scope?(child)
  child.module_type? || child.class_type? || child.sclass_type? || eval_call?(child)
end