class RuboCop::Cop::Style::RedundantSelf

Checks for redundant uses of ‘self`.

The usage of ‘self` is only needed when:

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.

@example

# 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

Constants

KERNEL_METHODS
KEYWORDS
MSG

Public Class Methods

autocorrect_incompatible_with() click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 56
def self.autocorrect_incompatible_with
  [ColonMethodCall, Layout::DotPosition]
end
new(config = nil, options = nil) click to toggle source
Calls superclass method RuboCop::Cop::Base::new
# 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

Public Instance Methods

on_and_asgn(node)
Alias for: on_or_asgn
on_args(node) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 86
def on_args(node)
  node.children.each { |arg| on_argument(arg) }
end
on_block(node) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 120
def on_block(node)
  add_scope(node, @local_variables_scopes[node])
end
Also aliased as: on_numblock
on_blockarg(node) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 90
def on_blockarg(node)
  on_argument(node)
end
on_def(node) click to toggle source

Using self.x to distinguish from local variable x

# File lib/rubocop/cop/style/redundant_self.rb, line 81
def on_def(node)
  add_scope(node)
end
Also aliased as: on_defs
on_defs(node)
Alias for: on_def
on_if(node) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 126
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|
    lhs, _rhs = *child_node

    if child_node.lvasgn_type?
      add_lhs_to_local_variables_scopes(node.condition, lhs)
    elsif child_node.masgn_type?
      add_masgn_lhs_variables(node.condition, lhs)
    end
  end
end
Also aliased as: on_while, on_until
on_in_pattern(node) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 104
def on_in_pattern(node)
  add_match_var_scopes(node)
end
on_lvasgn(node) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 99
def on_lvasgn(node)
  lhs, rhs = *node
  add_lhs_to_local_variables_scopes(rhs, lhs)
end
on_masgn(node) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 94
def on_masgn(node)
  lhs, rhs = *node
  add_masgn_lhs_variables(rhs, lhs)
end
on_numblock(node)
Alias for: on_block
on_op_asgn(node) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 74
def on_op_asgn(node)
  lhs, _op, _rhs = *node
  allow_self(lhs)
end
on_or_asgn(node) click to toggle source

Assignment of self.x

# File lib/rubocop/cop/style/redundant_self.rb, line 68
def on_or_asgn(node)
  lhs, _rhs = *node
  allow_self(lhs)
end
Also aliased as: on_and_asgn
on_send(node) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 108
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
on_while(node)
Alias for: on_if

Private Instance Methods

add_lhs_to_local_variables_scopes(rhs, lhs) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 196
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) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 204
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) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 210
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 = []) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 144
def add_scope(node, local_variables = [])
  node.each_descendant do |child_node|
    @local_variables_scopes[child_node] = local_variables
  end
end
allow_self(node) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 190
def allow_self(node)
  return unless node.send_type? && node.self_receiver?

  @allowed_send_nodes << node
end
allowed_send_node?(node) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 150
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) click to toggle source

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

# File lib/rubocop/cop/style/redundant_self.rb, line 165
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_argument(node) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 181
def on_argument(node)
  if node.mlhs_type?
    on_args(node)
  else
    name, = *node
    @local_variables_scopes[node] << name
  end
end
regular_method_call?(node) click to toggle source
# File lib/rubocop/cop/style/redundant_self.rb, line 173
def regular_method_call?(node)
  !(node.operator_method? ||
    KEYWORDS.include?(node.method_name) ||
    node.camel_case_method? ||
    node.setter_method? ||
    node.implicit_call?)
end