class RuboCop::Cop::Lint::DisjunctiveAssignmentInConstructor

Checks constructors for disjunctive assignments (‘||=`) that should be plain assignments.

So far, this cop is only concerned with disjunctive assignment of instance variables.

In ruby, an instance variable is nil until a value is assigned, so the disjunction is unnecessary. A plain assignment has the same effect.

@safety

This cop is unsafe because it can register a false positive when a
method is redefined in a subclass that calls super. For example:

[source,ruby]
----
class Base
  def initialize
    @config ||= 'base'
  end
end

class Derived < Base
  def initialize
    @config = 'derived'
    super
  end
end
----

Without the disjunctive assignment, `Derived` will be unable to override
the value for `@config`.

@example

# bad
def initialize
  @x ||= 1
end

# good
def initialize
  @x = 1
end

Constants

MSG

Public Instance Methods

on_def(node) click to toggle source
# File lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb, line 53
def on_def(node)
  check(node)
end

Private Instance Methods

check(node) click to toggle source

@param [DefNode] node a constructor definition

# File lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb, line 60
def check(node)
  return unless node.method?(:initialize)

  check_body(node.body)
end
check_body(body) click to toggle source
# File lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb, line 66
def check_body(body)
  return if body.nil?

  case body.type
  when :begin
    check_body_lines(body.child_nodes)
  else
    check_body_lines([body])
  end
end
check_body_lines(lines) click to toggle source

@param [Array] lines the logical lines of the constructor

# File lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb, line 78
def check_body_lines(lines)
  lines.each do |line|
    case line.type
    when :or_asgn
      check_disjunctive_assignment(line)
    else
      # Once we encounter something other than a disjunctive
      # assignment, we cease our investigation, because we can't be
      # certain that any future disjunctive assignments are offensive.
      # You're off the case, detective!
      break
    end
  end
end
check_disjunctive_assignment(node) click to toggle source

Add an offense if the LHS of the given disjunctive assignment is an instance variable.

For now, we only care about assignments to instance variables.

@param [Node] node a disjunctive assignment

# File lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb, line 99
def check_disjunctive_assignment(node)
  lhs = node.child_nodes.first
  return unless lhs.ivasgn_type?

  add_offense(node.loc.operator) do |corrector|
    corrector.replace(node.loc.operator, '=')
  end
end