123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::Cop::Lint::UselessAccessModifier

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, ::RuboCop::Cop::AutoCorrector, ::RuboCop::Cop::Base, ::RuboCop::ExcludeLimit, NodePattern::Macros, RuboCop::AST::Sexp
Instance Chain:
Inherits: RuboCop::Cop::Base
Defined in: lib/rubocop/cop/lint/useless_access_modifier.rb

Overview

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.

Examples:

# 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

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

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

Constant Summary

::RuboCop::Cop::Base - Inherited

EMPTY_OFFENSES, RESTRICT_ON_SEND

::RuboCop::Cop::RangeHelp - Included

BYTE_ORDER_MARK, NOT_GIVEN

Class Attribute Summary

::RuboCop::Cop::AutoCorrector - Extended

::RuboCop::Cop::Base - Inherited

.gem_requirements, .lint?,
.support_autocorrect?

Returns if class supports autocorrect.

.support_multiple_source?

Override if your cop should be called repeatedly for multiple investigations Between calls to on_new_investigation and on_investigation_end, the result of processed_source will remain constant.

.builtin?

Class Method Summary

::RuboCop::Cop::Base - Inherited

.autocorrect_incompatible_with

List of cops that should not try to autocorrect at the same time as this cop.

.badge

Naming.

.callbacks_needed, .cop_name, .department,
.documentation_url

Cops (other than builtin) are encouraged to implement this.

.exclude_from_registry

Call for abstract Cop classes.

.inherited,
.joining_forces

Override and return the Force class(es) you need to join.

.match?

Returns true if the cop name or the cop namespace matches any of the given names.

.new,
.requires_gem

Register a version requirement for the given gem name.

.restrict_on_send

::RuboCop::ExcludeLimit - Extended

exclude_limit

Sets up a configuration option to have an exclude limit tracked.

transform

Instance Attribute Summary

Instance Method Summary

::RuboCop::Cop::RangeHelp - Included

#add_range, #column_offset_between,
#contents_range

A range containing only the contents of a literal with delimiters (e.g.

#directions,
#effective_column

Returns the column attribute of the range, except if the range is on the first line and there’s a byte order mark at the beginning of that line, in which case 1 is subtracted from the column value.

#final_pos, #move_pos, #move_pos_str, #range_between, #range_by_whole_lines, #range_with_comments, #range_with_comments_and_lines, #range_with_surrounding_comma, #range_with_surrounding_space, #source_range

::RuboCop::Cop::Base - Inherited

#add_global_offense

Adds an offense that has no particular location.

#add_offense

Adds an offense on the specified range (or node with an expression) Unless that offense is disabled for this range, a corrector will be yielded to provide the cop the opportunity to autocorrect the offense.

#begin_investigation

Called before any investigation.

#callbacks_needed,
#cop_config

Configuration Helpers.

#cop_name, #excluded_file?,
#external_dependency_checksum

This method should be overridden when a cop’s behavior depends on state that lives outside of these locations:

#inspect,
#message

Gets called if no message is specified when calling add_offense or add_global_offense Cops are discouraged to override this; instead pass your message directly.

#name

Alias for Base#cop_name.

#offenses,
#on_investigation_end

Called after all on_…​

#on_new_investigation

Called before all on_…​

#on_other_file

Called instead of all on_…​

#parse

There should be very limited reasons for a Cop to do it’s own parsing.

#parser_engine,
#ready

Called between investigations.

#relevant_file?, #target_rails_version, #target_ruby_version, #annotate, #apply_correction, #attempt_correction,
#callback_argument

Reserved for Cop::Cop.

#complete_investigation

Called to complete an investigation.

#correct, #current_corrector,
#current_offense_locations

Reserved for Commissioner:

#current_offenses, #currently_disabled_lines, #custom_severity, #default_severity, #disable_uncorrectable, #enabled_line?, #file_name_matches_any?, #find_message, #find_severity, #range_for_original, #range_from_node_or_range, #reset_investigation, #use_corrector

::RuboCop::Cop::AutocorrectLogic - Included

::RuboCop::Cop::IgnoredNode - Included

Constructor Details

This class inherits a constructor from RuboCop::Cop::Base

Instance Method Details

#access_modifier?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 182

def access_modifier?(node)
  node.bare_access_modifier? || node.method?(:private_class_method)
end

#any_context_creating_methods?(child) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 280

def any_context_creating_methods?(child)
  cop_config.fetch('ContextCreatingMethods', []).any? do |m|
    matcher_name = :"#{m}_block?"
    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) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 257

def any_method_definition?(child)
  cop_config.fetch('MethodCreatingMethods', []).any? do |m|
    matcher_name = :"#{m}_method?"
    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) (private)

[ GitHub ]

  
# 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) (private)

Metrics/PerceivedComplexity

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 196

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 child.block_type? && included_block?(child)
      next
    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) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 226

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) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 170

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) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 186

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) (private)

Metrics/PerceivedComplexity

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 215

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

#class_or_instance_eval?(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 166

def_node_matcher :class_or_instance_eval?, <<~PATTERN
  ({block numblock} (send _ {:class_eval :instance_eval}) ...)
PATTERN

#dynamic_method_definition?(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 161

def_node_matcher :dynamic_method_definition?, <<~PATTERN
  {(send nil? :define_method ...) ({block numblock} (send nil? :define_method ...) ...)}
PATTERN

#eval_call?(child) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 274

def eval_call?(child)
  class_or_instance_eval?(child) ||
    child.class_constructor? ||
    any_context_creating_methods?(child)
end

#included_block?(block_node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 247

def included_block?(block_node)
  active_support_extensions_enabled? && block_node.method?(:included)
end

#method_definition?(child) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 251

def method_definition?(child)
  static_method_definition?(child) ||
    dynamic_method_definition?(child) ||
    any_method_definition?(child)
end

#on_block(node) Also known as: #on_numblock

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 139

def on_block(node)
  return unless eval_call?(node) || included_block?(node)

  check_node(node.body)
end

#on_class(node) Also known as: #on_module, #on_sclass

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 133

def on_class(node)
  check_node(node.body)
end

#on_module(node)

Alias for #on_class.

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 136

alias on_module on_class

#on_numblock(node)

Alias for #on_block.

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 145

alias on_numblock on_block

#on_sclass(node)

Alias for #on_class.

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 137

alias on_sclass on_class

#start_of_new_scope?(child) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 270

def start_of_new_scope?(child)
  child.module_type? || child.class_type? || child.sclass_type? || eval_call?(child)
end

#static_method_definition?(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/lint/useless_access_modifier.rb', line 156

def_node_matcher :static_method_definition?, <<~PATTERN
  {def (send nil? {:attr :attr_reader :attr_writer :attr_accessor} ...)}
PATTERN