Ruby analyzer updates - January 2021

This release adds five new rules and seven new autofixes:

New rules:

DeepSource/BadOrAssignment (RB-DS1001):

Checks if the first assignment was done using an or-assignment operator. For example:

# bad, since the first assignment uses or-assignment
some_var ||= 1

# good
some_var = 1

DeepSource/DuplicateConstantAssignment (RB-DS1002):

Checks for multiple assignments for the same constant. For example:

# bad, since constants should not be reassigned
SOME_VAR = 1
SOME_VAR = 2

# good
SOME_VAR = 1

DeepSource/IoSelectWithSingleArgument (RB-DS1003):

Checks for IO.select statements with a single argument. Read more about the issue here.

# bad
IO.select([io], [], [], timeout)
IO.select([], [io], [], timeout)

# good
io.wait_readable(timeout)
io.wait_writable(timeout)

DeepSource/ExcessiveGuardClauses (RB-DS1004):

Checks for excessive guard clauses present inside a block or method. The default threshold is 4 guard clauses per block/method, although this can be tweaked via the Max option in rubocop.yml under the DeepSource/ExcessiveGuardClauses cop.

# bad
def display_cop_names?
  return true if debug?
  return false if options[:display_cop_names] == false
  return true if options[:display_cop_names]
  return false if options[:format] == 'json'
  return true if options[:display_cop_names].any?
  config.for_all_cops['DisplayCopNames']
end

# good
def display_cop_names?
  if debug?
    true
  elsif options[:display_cop_names] == false
    false
  elsif options[:display_cop_names]
    true
  elsif options[:format] == 'json'
    false
  elsif options[:display_cop_names].any?
    true
  else
    config.for_all_cops['DisplayCopNames']
  end
end

DeepSource/BinaryExpressionOperandOrder (RB-DS1005):

Checks if the operand order for a binary expression is bad. Enforces that the literal be on the right side of the expression.

x = 1

# bad
y = 1 + x

# good
y = x + 1

New autofixes:

DeepSource/BadOrAssignment (RB-DS1001):

Replaces the or-assignment for the first variable assignment with a normal assignment. Since constants should not be or-assignment, it is replaced by the normal assignment.

DeepSource/BinaryExpressionOperandOrder (RB-DS1005):

Moves the literal to the right side of the assignment. Doesn’t report an offense/autofix it if the literal is of type String.

DeepSource/IoSelectWithSingleArgument (RB-DS1003)

Replaces the IO.select block with an appropriate io.wait_readable/io.wait_writable block.

Lint/NextWithoutAccumulator (RB-LI1038):

Adds the accumulator to the next keyword in the reduce block.

Lint/RescueException (RB-LI1056):

Replaces Exception rescues with StandardError. This behavior can be tweaked via the ErrorName parameter for this cop in the RuboCop config file.

Lint/TopLevelReturnWithArgument (RB-LI1088):

Removes all arguments from the top level return keyword.

Lint/UselessAssignment (RB-LI1078):

Removes the unused variable by default. Can be tweaked via the FixType property, which takes in Remove or Replace as the argument. The latter prefixes the variable with an underscore to signify that the variable in unused.