123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::Cop::Style::RedundantSelf

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/style/redundant_self.rb

Overview

Checks for redundant uses of self.

The usage of self is only needed when:

  • Sending a message to same object with zero arguments in presence of a method name clash with an argument or a local variable.

  • Calling an attribute writer to prevent a local variable assignment.

Note, with using explicit self you can only send messages with public or protected scope, you cannot send private messages this way.

Note we allow uses of self with operators because it would be awkward otherwise. Also allows the use of self.it without arguments in blocks, as in 0.times { self.it }, following Lint/ItWithoutArgumentsInBlock cop.

Examples:

# bad
def foo(bar)
  self.baz
end

# good
def foo(bar)
  self.bar  # Resolves name clash with the argument.
end

def foo
  bar = 1
  self.bar  # Resolves name clash with the local variable.
end

def foo
  %w[x y z].select do |bar|
    self.bar == bar  # Resolves name clash with argument of the block.
  end
end

Constant Summary

::RuboCop::Cop::Base - Inherited

EMPTY_OFFENSES, RESTRICT_ON_SEND

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.

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

Returns a url to view this cops documentation online.

.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::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

Actually private methods.

#use_corrector

::RuboCop::Cop::AutocorrectLogic - Included

::RuboCop::Cop::IgnoredNode - Included

Constructor Details

.new(config = nil, options = nil) ⇒ RedundantSelf

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 60

def initialize(config = nil, options = nil)
  super
  @allowed_send_nodes = []
  @local_variables_scopes = Hash.new { |hash, key| hash[key] = [] }.compare_by_identity
end

Class Method Details

.autocorrect_incompatible_with

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 56

def self.autocorrect_incompatible_with
  [ColonMethodCall, Layout::DotPosition]
end

Instance Method Details

#add_lhs_to_local_variables_scopes(rhs, lhs) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 189

def add_lhs_to_local_variables_scopes(rhs, lhs)
  if rhs&.send_type? && !rhs.arguments.empty?
    rhs.arguments.each { |argument| @local_variables_scopes[argument] << lhs }
  else
    @local_variables_scopes[rhs] << lhs
  end
end

#add_masgn_lhs_variables(rhs, lhs) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 197

def add_masgn_lhs_variables(rhs, lhs)
  lhs.children.each do |child|
    add_lhs_to_local_variables_scopes(rhs, child.to_a.first)
  end
end

#add_match_var_scopes(in_pattern_node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 203

def add_match_var_scopes(in_pattern_node)
  in_pattern_node.each_descendant(:match_var) do |match_var_node|
    @local_variables_scopes[in_pattern_node] << match_var_node.children.first
  end
end

#add_scope(node, local_variables = []) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 138

def add_scope(node, local_variables = [])
  node.each_descendant do |child_node|
    @local_variables_scopes[child_node] = local_variables
  end
end

#allow_self(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 183

def allow_self(node)
  return unless node.send_type? && node.self_receiver?

  @allowed_send_nodes << node
end

#allowed_send_node?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 144

def allowed_send_node?(node)
  @allowed_send_nodes.include?(node) ||
    @local_variables_scopes[node].include?(node.method_name) ||
    node.each_ancestor.any? do |ancestor|
      @local_variables_scopes[ancestor].include?(node.method_name)
    end ||
    KERNEL_METHODS.include?(node.method_name)
end

#it_method_in_block?(node) ⇒ Boolean (private)

Respects Lint/ItWithoutArgumentsInBlock cop and the following Ruby 3.3’s warning:

$ ruby -e '0.times { begin; it; end }' -e:1: warning: it calls without arguments will refer to the first block param in Ruby 3.4; use it() or self.it

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 159

def it_method_in_block?(node)
  return false unless node.method?(:it)
  return false unless (block_node = node.each_ancestor(:block).first)
  return false unless block_node.arguments.empty_and_without_delimiters?

  node.arguments.empty? && !node.block_literal?
end

#on_and_asgn(node)

Alias for #on_or_asgn.

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 71

alias on_and_asgn on_or_asgn

#on_args(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 84

def on_args(node)
  node.children.each { |arg| on_argument(arg) }
end

#on_argument(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 175

def on_argument(node)
  if node.mlhs_type?
    on_args(node)
  elsif node.respond_to?(:name)
    @local_variables_scopes[node] << node.name
  end
end

#on_block(node) Also known as: #on_numblock

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 116

def on_block(node)
  add_scope(node, @local_variables_scopes[node])
end

#on_blockarg(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 88

def on_blockarg(node)
  on_argument(node)
end

#on_def(node) Also known as: #on_defs

Using self.x to distinguish from local variable x

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 79

def on_def(node)
  add_scope(node)
end

#on_defs(node)

Alias for #on_def.

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 82

alias on_defs on_def

#on_if(node) Also known as: #on_while, #on_until

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 122

def on_if(node)
  # Allow conditional nodes to use `self` in the condition if that variable
  # name is used in an `lvasgn` or `masgn` within the `if`.
  node.child_nodes.each do |child_node|
    if child_node.lvasgn_type?
      add_lhs_to_local_variables_scopes(node.condition, child_node.lhs)
    elsif child_node.masgn_type?
      add_masgn_lhs_variables(node.condition, child_node.lhs)
    end
  end
end

#on_in_pattern(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 100

def on_in_pattern(node)
  add_match_var_scopes(node)
end

#on_lvasgn(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 96

def on_lvasgn(node)
  add_lhs_to_local_variables_scopes(node.rhs, node.lhs)
end

#on_masgn(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 92

def on_masgn(node)
  add_masgn_lhs_variables(node.rhs, node.lhs)
end

#on_numblock(node)

Alias for #on_block.

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 120

alias on_numblock on_block

#on_op_asgn(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 73

def on_op_asgn(node)
  allow_self(node.lhs)
end

#on_or_asgn(node) Also known as: #on_and_asgn

Assignment of self.x

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 68

def on_or_asgn(node)
  allow_self(node.lhs)
end

#on_send(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 104

def on_send(node)
  return unless node.self_receiver? && regular_method_call?(node)
  return if node.parent&.mlhs_type?
  return if allowed_send_node?(node)
  return if it_method_in_block?(node)

  add_offense(node.receiver) do |corrector|
    corrector.remove(node.receiver)
    corrector.remove(node.loc.dot)
  end
end

#on_until(node)

Alias for #on_if.

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 134

alias on_until on_if

#on_while(node)

Alias for #on_if.

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 133

alias on_while on_if

#regular_method_call?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/redundant_self.rb', line 167

def regular_method_call?(node)
  !(node.operator_method? ||
    KEYWORDS.include?(node.method_name) ||
    node.camel_case_method? ||
    node.setter_method? ||
    node.implicit_call?)
end