////
  Do NOT edit this file by hand directly, as it is automatically generated.

  Please make any necessary changes to the cop documentation within the source files themselves.
////

= Lint

[#lintambiguousassignment]
== Lint/AmbiguousAssignment

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.7
| -
|===

Checks for mistyped shorthand assignments.

[#examples-lintambiguousassignment]
=== Examples

[source,ruby]
----
# bad
x =- y
x =+ y
x =* y
x =! y

# good
x -= y # or x = -y
x += y # or x = +y
x *= y # or x = *y
x != y # or x = !y
----

[#lintambiguousblockassociation]
== Lint/AmbiguousBlockAssociation

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.48
| 1.89
|===

Checks for ambiguous block association with method
when param passed without parentheses.

This cop also detects `do...end` blocks that are likely intended for
an enumerable method in the arguments but actually bind to the outer
method call. For example, in `render json: data.map do |x| x end`,
Ruby parses the `do...end` block as belonging to `render`, not `map`.

This cop can customize allowed methods with `AllowedMethods`.
By default, there are no allowed methods.

[#examples-lintambiguousblockassociation]
=== Examples

[source,ruby]
----
# bad
some_method a { |val| puts val }

# good
# With parentheses, there's no ambiguity.
some_method(a { |val| puts val })
# or (different meaning)
some_method(a) { |val| puts val }

# bad
render json: data.map do |item|
  item.to_h
end

# good
render json: data.map { |item| item.to_h }

# good
mapped = data.map { |item| item.to_h }
render json: mapped

# good
# Operator methods require no disambiguation
foo == bar { |b| b.baz }

# good
# Lambda arguments require no disambiguation
foo = ->(bar) { bar.baz }
----

[#allowedmethods_-__-_default_-lintambiguousblockassociation]
==== AllowedMethods: [] (default)

[source,ruby]
----
# bad
expect { do_something }.to change { object.attribute }
----

[#allowedmethods_-_change_-lintambiguousblockassociation]
==== AllowedMethods: [change]

[source,ruby]
----
# good
expect { do_something }.to change { object.attribute }
----

[#allowedpatterns_-__-_default_-lintambiguousblockassociation]
==== AllowedPatterns: [] (default)

[source,ruby]
----
# bad
expect { do_something }.to change { object.attribute }
----

[#allowedpatterns_-__change__-lintambiguousblockassociation]
==== AllowedPatterns: ['change']

[source,ruby]
----
# good
expect { do_something }.to change { object.attribute }
expect { do_something }.to not_change { object.attribute }
----

[#configurable-attributes-lintambiguousblockassociation]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowedMethods
| `[]`
| Array

| AllowedPatterns
| `[]`
| Array
|===

[#lintambiguousoperator]
== Lint/AmbiguousOperator

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.17
| 0.83
|===

Checks for ambiguous operators in the first argument of a
method invocation without parentheses.

[#examples-lintambiguousoperator]
=== Examples

[source,ruby]
----
# bad

# The `*` is interpreted as a splat operator but it could possibly be
# a `*` method invocation (i.e. `do_something.*(some_array)`).
do_something *some_array

# good

# With parentheses, there's no ambiguity.
do_something(*some_array)
----

[#references-lintambiguousoperator]
=== References

* https://rubystyle.guide#method-invocation-parens

[#lintambiguousoperatorprecedence]
== Lint/AmbiguousOperatorPrecedence

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.21
| -
|===

Looks for expressions containing multiple binary operators
where precedence is ambiguous due to lack of parentheses. For example,
in `1 + 2 * 3`, the multiplication will happen before the addition, but
lexically it appears that the addition will happen first.

The cop does not consider unary operators (ie. `!a` or `-b`) or comparison
operators (ie. `a =~ b`) because those are not ambiguous.

NOTE: Ranges are handled by `Lint/AmbiguousRange`.

[#examples-lintambiguousoperatorprecedence]
=== Examples

[source,ruby]
----
# bad
a + b * c
a || b && c
a ** b + c

# good (different precedence)
a + (b * c)
a || (b && c)
(a ** b) + c

# good (same precedence)
a + b + c
a * b / c % d
----

[#lintambiguousrange]
== Lint/AmbiguousRange

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always (Unsafe)
| 1.19
| -
|===

Checks for ambiguous ranges.

Ranges have quite low precedence, which leads to unexpected behavior when
using a range with other operators. This cop avoids that by making ranges
explicit by requiring parenthesis around complex range boundaries (anything
that is not a literal: numerics, strings, symbols, etc.).

This cop can be configured with `RequireParenthesesForMethodChains` in order to
specify whether method chains (including `self.foo`) should be wrapped in parens
by this cop.

NOTE: Regardless of this configuration, if a method receiver is a basic literal
value, it will be wrapped in order to prevent the ambiguity of `1..2.to_a`.

[#safety-lintambiguousrange]
=== Safety

The cop autocorrects by wrapping the entire boundary in parentheses, which
makes the outcome more explicit but is possible to not be the intention of the
programmer. For this reason, this cop's autocorrect is unsafe (it will not
change the behavior of the code, but will not necessarily match the
intent of the program).

[#examples-lintambiguousrange]
=== Examples

[source,ruby]
----
# bad
x || 1..2
x - 1..2
(x || 1..2)
x || 1..y || 2
1..2.to_a

# good, unambiguous
1..2
'a'..'z'
:bar..:baz
MyClass::MIN..MyClass::MAX
@min..@max
a..b
-a..b

# good, ambiguity removed
x || (1..2)
(x - 1)..2
(x || 1)..2
(x || 1)..(y || 2)
(1..2).to_a
----

[#requireparenthesesformethodchains_-false-_default_-lintambiguousrange]
==== RequireParenthesesForMethodChains: false (default)

[source,ruby]
----
# good
a.foo..b.bar
(a.foo)..(b.bar)
----

[#requireparenthesesformethodchains_-true-lintambiguousrange]
==== RequireParenthesesForMethodChains: true

[source,ruby]
----
# bad
a.foo..b.bar

# good
(a.foo)..(b.bar)
----

[#configurable-attributes-lintambiguousrange]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| RequireParenthesesForMethodChains
| `false`
| Boolean
|===

[#lintambiguousregexpliteral]
== Lint/AmbiguousRegexpLiteral

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.17
| 0.83
|===

Checks for ambiguous regexp literals in the first argument of
a method invocation without parentheses.

[#examples-lintambiguousregexpliteral]
=== Examples

[source,ruby]
----
# bad

# This is interpreted as a method invocation with a regexp literal,
# but it could possibly be `/` method invocations.
# (i.e. `do_something./(pattern)./(i)`)
do_something /pattern/i

# good

# With parentheses, there's no ambiguity.
do_something(/pattern/i)
----

[#lintarrayliteralinregexp]
== Lint/ArrayLiteralInRegexp

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always (Unsafe)
| 1.71
| -
|===

Checks for an array literal interpolated inside a regexp.

When interpolating an array literal, it is converted to a string. This means
that when inside a regexp, it acts as a character class but with additional
quotes, spaces and commas that are likely not intended. For example,
`/#{%w[a b c]}/` parses as `/["a", "b", "c"]/` (or `/["a, bc]/` without
repeated characters).

The cop can autocorrect to a character class (if all items in the array are a
single character) or alternation (if the array contains longer items).

NOTE: This only considers interpolated arrays that contain only strings, symbols,
integers, and floats. Any other type is not easily convertible to a character class
or regexp alternation.

[#safety-lintarrayliteralinregexp]
=== Safety

Autocorrection is unsafe because it will change the regexp pattern, by
removing the additional quotes, spaces and commas from the character class.

[#examples-lintarrayliteralinregexp]
=== Examples

[source,ruby]
----
# bad
/#{%w[a b c]}/

# good
/[abc]/

# bad
/#{%w[foo bar baz]}/

# good
/(?:foo|bar|baz)/

# bad - construct a regexp rather than interpolate an array of identifiers
/#{[foo, bar]}/
----

[#lintassignmentincondition]
== Lint/AssignmentInCondition

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 0.9
| 1.45
|===

Checks for assignments in the conditions of
if/while/until.

`AllowSafeAssignment` option for safe assignment.
By safe assignment we mean putting parentheses around
an assignment to indicate "I know I'm using an assignment
as a condition. It's not a mistake."

[#safety-lintassignmentincondition]
=== Safety

This cop's autocorrection is unsafe because it assumes that
the author meant to use an assignment result as a condition.

[#examples-lintassignmentincondition]
=== Examples

[source,ruby]
----
# bad
if some_var = value
  do_something
end

# good
if some_var == value
  do_something
end
----

[#allowsafeassignment_-true-_default_-lintassignmentincondition]
==== AllowSafeAssignment: true (default)

[source,ruby]
----
# good
if (some_var = value)
  do_something
end
----

[#allowsafeassignment_-false-lintassignmentincondition]
==== AllowSafeAssignment: false

[source,ruby]
----
# bad
if (some_var = value)
  do_something
end
----

[#configurable-attributes-lintassignmentincondition]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowSafeAssignment
| `true`
| Boolean
|===

[#references-lintassignmentincondition]
=== References

* https://rubystyle.guide#safe-assignment-in-condition

[#lintbigdecimalnew]
== Lint/BigDecimalNew

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.53
| -
|===

`BigDecimal.new()` is deprecated since BigDecimal 1.3.3.
This cop identifies places where `BigDecimal.new()`
can be replaced by `BigDecimal()`.

[#examples-lintbigdecimalnew]
=== Examples

[source,ruby]
----
# bad
BigDecimal.new(123.456, 3)

# good
BigDecimal(123.456, 3)
----

[#lintbinaryoperatorwithidenticaloperands]
== Lint/BinaryOperatorWithIdenticalOperands

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| No
| 0.89
| 1.69
|===

Checks for places where binary operator has identical operands.

It covers comparison operators: `==`, `===`, `=~`, `>`, `>=`, `<`, ``<=``;
bitwise operators: `|`, `^`, `&`;
boolean operators: `&&`, `||`
and "spaceship" operator - ``<=>``.

Simple arithmetic operations are allowed by this cop: `+`, `*`, `**`, `<<` and `>>`.
Although these can be rewritten in a different way, it should not be necessary to
do so. Operations such as `-` or `/` where the result will always be the same
(`x - x` will always be 0; `x / x` will always be 1) are offenses, but these
are covered by `Lint/NumericOperationWithConstantResult` instead.

[#safety-lintbinaryoperatorwithidenticaloperands]
=== Safety

This cop is unsafe as it does not consider side effects when calling methods
and thus can generate false positives, for example:

[source,ruby]
----
if wr.take_char == '\0' && wr.take_char == '\0'
  # ...
end
----

[#examples-lintbinaryoperatorwithidenticaloperands]
=== Examples

[source,ruby]
----
# bad
x.top >= x.top

if a.x != 0 && a.x != 0
  do_something
end

def child?
  left_child || left_child
end

# good
x + x
1 << 1
----

[#lintbooleansymbol]
== Lint/BooleanSymbol

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 0.50
| 1.22
|===

Checks for `:true` and `:false` symbols.
In most cases it would be a typo.

[#safety-lintbooleansymbol]
=== Safety

Autocorrection is unsafe for this cop because code relying
on `:true` or `:false` symbols will break when those are
changed to actual booleans.

[#examples-lintbooleansymbol]
=== Examples

[source,ruby]
----
# bad
:true

# good
true

# bad
:false

# good
false
----

[#lintcircularargumentreference]
== Lint/CircularArgumentReference

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.33
| -
|===

Checks for circular argument references in optional keyword
arguments and optional ordinal arguments.

NOTE: This syntax was made invalid on Ruby 2.7 - Ruby 3.3 but is allowed
again since Ruby 3.4.

[#examples-lintcircularargumentreference]
=== Examples

[source,ruby]
----
# bad
def bake(pie: pie)
  pie.heat_up
end

# good
def bake(pie:)
  pie.refrigerate
end

# good
def bake(pie: self.pie)
  pie.feed_to(user)
end

# bad
def cook(dry_ingredients = dry_ingredients)
  dry_ingredients.reduce(&:+)
end

# good
def cook(dry_ingredients = self.dry_ingredients)
  dry_ingredients.combine
end

# bad
def foo(pie = pie = pie)
  pie.heat_up
end

# good
def foo(pie)
  pie.heat_up
end

# bad
def foo(pie = cake = pie)
  [pie, cake].each(&:heat_up)
end

# good
def foo(cake = pie)
  [pie, cake].each(&:heat_up)
end
----

[#lintconstantdefinitioninblock]
== Lint/ConstantDefinitionInBlock

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.91
| 1.3
|===

Do not define constants within a block, since the block's scope does not
isolate or namespace the constant in any way.

If you are trying to define that constant once, define it outside of
the block instead, or use a variable or method if defining the constant
in the outer scope would be problematic.

For meta-programming, use `const_set`.

[#examples-lintconstantdefinitioninblock]
=== Examples

[source,ruby]
----
# bad
task :lint do
  FILES_TO_LINT = Dir['lib/*.rb']
end

# bad
describe 'making a request' do
  class TestRequest; end
end

# bad
module M
  extend ActiveSupport::Concern
  included do
    LIST = []
  end
end

# good
task :lint do
  files_to_lint = Dir['lib/*.rb']
end

# good
describe 'making a request' do
  let(:test_request) { Class.new }
  # see also `stub_const` for RSpec
end

# good
module M
  extend ActiveSupport::Concern
  included do
    const_set(:LIST, [])
  end
end
----

[#allowedmethods_-__enums__-_default_-lintconstantdefinitioninblock]
==== AllowedMethods: ['enums'] (default)

[source,ruby]
----
# good

# `enums` for Typed Enums via `T::Enum` in Sorbet.
# https://sorbet.org/docs/tenum
class TestEnum < T::Enum
  enums do
    Foo = new("foo")
  end
end
----

[#configurable-attributes-lintconstantdefinitioninblock]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowedMethods
| `enums`
| Array
|===

[#references-lintconstantdefinitioninblock]
=== References

* https://rubystyle.guide#no-constant-definition-in-block

[#lintconstantoverwritteninrescue]
== Lint/ConstantOverwrittenInRescue

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.31
| -
|===

Checks for overwriting an exception with an exception result by using ``rescue =>``.

You intended to write as `rescue StandardError`.
However, you have written `rescue => StandardError`.
In that case, the result of `rescue` will overwrite `StandardError`.

[#examples-lintconstantoverwritteninrescue]
=== Examples

[source,ruby]
----
# bad
begin
  something
rescue => StandardError
end

# good
begin
  something
rescue StandardError
end
----

[#lintconstantreassignment]
== Lint/ConstantReassignment

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.70
| 1.87
|===

Checks for constant reassignments.

Emulates Ruby's runtime warning "already initialized constant X"
when a constant is reassigned in the same file and namespace.

The cop tracks constants defined via `NAME = value` syntax as well as
class/module keyword definitions. It detects reassignment when a constant
is first defined one way and then redefined using the `NAME = value` syntax.

The cop cannot catch all offenses, like, for example, when using metaprogramming
(`Module#const_set`).

By default the cop also cannot detect reassignment across files.
When `AllCops/UseProjectIndex` is enabled and the `rubydex` gem is installed,
the cop additionally consults the project-wide index and reports reassignments
whose previous definition lives in another file.

The cop only takes into account constants assigned in a "simple" way: directly
inside class/module definition, or within another constant. Other type of assignments
(e.g., inside a conditional) are disregarded.

The cop also tracks constant removal using `Module#remove_const` with symbol
or string argument.

[#examples-lintconstantreassignment]
=== Examples

[source,ruby]
----
# bad
X = :foo
X = :bar

# bad
class A
  X = :foo
  X = :bar
end

# bad
module A
  X = :foo
  X = :bar
end

# bad
class FooError < StandardError; end
FooError = Class.new(RuntimeError)

# bad
module M; end
M = 1

# good - keep only one assignment
X = :bar

class A
  X = :bar
end

module A
  X = :bar
end

# good - use OR assignment
X = :foo
X ||= :bar

# good - use conditional assignment
X = :foo
X = :bar unless defined?(X)

# good - remove the assigned constant first
class A
  X = :foo
  remove_const :X
  X = :bar
end
----

[#lintconstantresolution]
== Lint/ConstantResolution

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Disabled
| Yes
| No
| 0.86
| 1.89
|===

Checks that certain constants are fully qualified.

This is not enabled by default because it would mark a lot of offenses
unnecessarily.

Generally, gems should fully qualify all constants to avoid conflicts with
the code that uses the gem. Enable this cop without using `Only`/`Ignore`

Large projects will over time end up with one or two constant names that
are problematic because of a conflict with a library or just internally
using the same name for a namespace and a class. To avoid too many unnecessary
offenses, enable this cop with `Only: [The, Constant, Names, Causing, Issues]`

NOTE: `Style/RedundantConstantBase` cop is disabled if this cop is enabled,
to prevent conflicting rules. This is because it respects user configurations
that want to enable this cop which is disabled by default.

When `AllCops/UseProjectIndex` is enabled and the `rubydex` gem is
installed, only genuinely ambiguous constants are reported: those
that resolve to a different declaration through the surrounding
nesting than they would fully qualified. This makes the cop practical
to enable without `Only`/`Ignore` lists.

[#examples-lintconstantresolution]
=== Examples

[source,ruby]
----
# By default checks every constant

# bad
User

# bad
User::Login

# good
::User

# good
::User::Login
----

[#only_-__login__-lintconstantresolution]
==== Only: ['Login']

[source,ruby]
----
# Restrict this cop to only being concerned about certain constants

# bad
Login

# good
::Login

# good
User::Login
----

[#ignore_-__login__-lintconstantresolution]
==== Ignore: ['Login']

[source,ruby]
----
# Restrict this cop not being concerned about certain constants

# bad
User

# good
::User::Login

# good
Login
----

[#configurable-attributes-lintconstantresolution]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| Only
| `[]`
| Array

| Ignore
| `[]`
| Array
|===

[#lintcopdirectivesyntax]
== Lint/CopDirectiveSyntax

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.72
| -
|===

Checks that `# rubocop:enable ...` and `# rubocop:disable ...` statements
are strictly formatted.

A comment can be added to the directive by prefixing it with `--`.

[#examples-lintcopdirectivesyntax]
=== Examples

[source,ruby]
----
# bad
# rubocop:disable Layout/LineLength Style/Encoding

# good
# rubocop:disable Layout/LineLength, Style/Encoding

# bad
# rubocop:disable

# good
# rubocop:disable all

# bad
# rubocop:disable Layout/LineLength # rubocop:disable Style/Encoding

# good
# rubocop:disable Layout/LineLength
# rubocop:disable Style/Encoding

# bad
# rubocop:wrongmode Layout/LineLength

# good
# rubocop:disable Layout/LineLength

# bad
# rubocop:disable Layout/LineLength comment

# good
# rubocop:disable Layout/LineLength -- comment
----

[#lintdatadefineoverride]
== Lint/DataDefineOverride

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.85
| -
|===

Checks unexpected overrides of the `Data` built-in methods
via `Data.define`.

[#examples-lintdatadefineoverride]
=== Examples

[source,ruby]
----
# bad
Bad = Data.define(:members, :clone, :to_s)
b = Bad.new(members: [], clone: true, to_s: 'bad')
b.members #=> [] (overriding `Data#members`)
b.clone #=> true (overriding `Object#clone`)
b.to_s #=> "bad" (overriding `Data#to_s`)

# good
Good = Data.define(:id, :name)
g = Good.new(id: 1, name: "foo")
g.members #=> [:id, :name]
g.clone #=> #<data Good id=1, name="foo">
----

[#lintdebugger]
== Lint/Debugger

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.14
| 1.63
|===

Checks for debug calls (such as `debugger` or `binding.pry`) that should
not be kept for production code.

The cop can be configured using `DebuggerMethods`. By default, a number of gems
debug entrypoints are configured (`Kernel`, `Byebug`, `Capybara`, `debug.rb`,
`Pry`, `Rails`, `RubyJard`, and `WebConsole`). Additional methods can be added.

Specific default groups can be disabled if necessary:

[source,yaml]
----
Lint/Debugger:
  DebuggerMethods:
    WebConsole: ~
----

You can also add your own methods by adding a new category:

[source,yaml]
----
Lint/Debugger:
  DebuggerMethods:
    MyDebugger:
      MyDebugger.debug_this
----

Some gems also ship files that will start a debugging session when required,
for example `require 'debug/start'` from `ruby/debug`. These requires can
be configured through `DebuggerRequires`. It has the same structure as
`DebuggerMethods`, which you can read about above.

[#examples-lintdebugger]
=== Examples

[source,ruby]
----
# bad (ok during development)

# using pry
def some_method
  binding.pry
  do_something
end

# bad (ok during development)

# using byebug
def some_method
  byebug
  do_something
end

# good

def some_method
  do_something
end
----

[#debuggermethods_-_my_debugger_-lintdebugger]
==== DebuggerMethods: [my_debugger]

[source,ruby]
----
# bad (ok during development)

def some_method
  my_debugger
end
----

[#debuggerrequires_-_my_debuggerstart_-lintdebugger]
==== DebuggerRequires: [my_debugger/start]

[source,ruby]
----
# bad (ok during development)

require 'my_debugger/start'
----

[#configurable-attributes-lintdebugger]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| DebuggerMethods
| `{"Kernel" => ["binding.irb", "Kernel.binding.irb"], "Byebug" => ["byebug", "remote_byebug", "Kernel.byebug", "Kernel.remote_byebug"], "Capybara" => ["page.save_and_open_page", "page.save_and_open_screenshot", "page.save_page", "page.save_screenshot", "save_and_open_page", "save_and_open_screenshot", "save_page", "save_screenshot"], "debug.rb" => ["binding.b", "binding.break", "Kernel.binding.b", "Kernel.binding.break"], "Pry" => ["binding.pry", "binding.remote_pry", "binding.pry_remote", "Kernel.binding.pry", "Kernel.binding.remote_pry", "Kernel.binding.pry_remote", "Pry.rescue", "pry"], "Rails" => ["debugger", "Kernel.debugger"], "RubyJard" => ["jard"], "WebConsole" => ["binding.console"]}`
| 

| DebuggerRequires
| `{"debug.rb" => ["debug/open", "debug/start"]}`
| 
|===

[#lintdeprecatedclassmethods]
== Lint/DeprecatedClassMethods

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.19
| -
|===

Checks for uses of the deprecated class method usages.

[#examples-lintdeprecatedclassmethods]
=== Examples

[source,ruby]
----
# bad
File.exists?(some_path)
Dir.exists?(some_path)
iterator?
attr :name, true
attr :name, false
ENV.freeze # Calling `Env.freeze` raises `TypeError` since Ruby 2.7.
ENV.clone
ENV.dup # Calling `Env.dup` raises `TypeError` since Ruby 3.1.
Socket.gethostbyname(host)
Socket.gethostbyaddr(host)

# good
File.exist?(some_path)
Dir.exist?(some_path)
block_given?
attr_accessor :name
attr_reader :name
ENV # `ENV.freeze` cannot prohibit changes to environment variables.
ENV.to_h
ENV.to_h # `ENV.dup` cannot dup `ENV`, use `ENV.to_h` to get a copy of `ENV` as a hash.
Addrinfo.getaddrinfo(nodename, service)
Addrinfo.tcp(host, port).getnameinfo
----

[#lintdeprecatedconstants]
== Lint/DeprecatedConstants

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.8
| 1.40
|===

Checks for deprecated constants.

It has `DeprecatedConstants` config. If there is an alternative method, you can set
alternative value as `Alternative`. And you can set the deprecated version as
`DeprecatedVersion`. These options can be omitted if they are not needed.

  DeprecatedConstants:
    'DEPRECATED_CONSTANT':
      Alternative: 'alternative_value'
      DeprecatedVersion: 'deprecated_version'

By default, `NIL`, `TRUE`, `FALSE`, `Net::HTTPServerException`, `Random::DEFAULT`,
`Struct::Group`, and `Struct::Passwd` are configured.

[#examples-lintdeprecatedconstants]
=== Examples

[source,ruby]
----
# bad
NIL
TRUE
FALSE
Net::HTTPServerException
Random::DEFAULT # Return value of Ruby 2 is `Random` instance, Ruby 3.0 is `Random` class.
Struct::Group
Struct::Passwd

# good
nil
true
false
Net::HTTPClientException
Random.new # `::DEFAULT` has been deprecated in Ruby 3, `.new` is compatible with Ruby 2.
Etc::Group
Etc::Passwd
----

[#configurable-attributes-lintdeprecatedconstants]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| DeprecatedConstants
| `{"NIL" => {"Alternative" => "nil", "DeprecatedVersion" => "2.4"}, "TRUE" => {"Alternative" => "true", "DeprecatedVersion" => "2.4"}, "FALSE" => {"Alternative" => "false", "DeprecatedVersion" => "2.4"}, "Net::HTTPServerException" => {"Alternative" => "Net::HTTPClientException", "DeprecatedVersion" => "2.6"}, "Random::DEFAULT" => {"Alternative" => "Random.new", "DeprecatedVersion" => "3.0"}, "Struct::Group" => {"Alternative" => "Etc::Group", "DeprecatedVersion" => "3.0"}, "Struct::Passwd" => {"Alternative" => "Etc::Passwd", "DeprecatedVersion" => "3.0"}}`
| 
|===

[#lintdeprecatedopensslconstant]
== Lint/DeprecatedOpenSSLConstant

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.84
| -
|===

Algorithmic constants for `OpenSSL::Cipher` and `OpenSSL::Digest`
deprecated since OpenSSL version 2.2.0. Prefer passing a string
instead.

[#examples-lintdeprecatedopensslconstant]
=== Examples

[source,ruby]
----
# bad
OpenSSL::Cipher::AES.new(128, :GCM)

# good
OpenSSL::Cipher.new('aes-128-gcm')

# bad
OpenSSL::Digest::SHA256.new

# good
OpenSSL::Digest.new('SHA256')

# bad
OpenSSL::Digest::SHA256.digest('foo')

# good
OpenSSL::Digest.digest('SHA256', 'foo')
----

[#lintdeprecatedreference]
== Lint/DeprecatedReference

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.89
| -
|===

Checks for calls to methods and references to constants that are documented
as deprecated with a YARD `@deprecated` tag.

The check is powered by the project-wide index, so it only runs when
`AllCops/UseProjectIndex` is enabled and the `rubydex` gem is installed.
Without the index the cop does nothing.

Only references that can be resolved without type inference are checked:
constants, method calls without an explicit receiver (or with `self`),
which are looked up in the enclosing class or module and its ancestry,
and calls whose receiver is a constant, which are looked up in that
namespace's singleton class. Calls on arbitrary objects are not checked.

References made from a definition that is itself deprecated are allowed,
so deprecated implementations can keep calling each other.

[#examples-lintdeprecatedreference]
=== Examples

[source,ruby]
----
# Given a deprecated method and constant:
#
#   class Api
#     # @deprecated Use `#new_method` instead.
#     def old_method
#     end
#
#     # @deprecated
#     OLD_TIMEOUT = 10
#   end

# bad
class Client < Api
  def call
    old_method
  end

  def timeout
    OLD_TIMEOUT
  end
end

# good
class Client < Api
  def call
    new_method
  end

  def timeout
    NEW_TIMEOUT
  end
end
----

[#lintdisjunctiveassignmentinconstructor]
== Lint/DisjunctiveAssignmentInConstructor

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| Always (Unsafe)
| 0.62
| 0.88
|===

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-lintdisjunctiveassignmentinconstructor]
=== 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`.

[#examples-lintdisjunctiveassignmentinconstructor]
=== Examples

[source,ruby]
----
# bad
def initialize
  @x ||= 1
end

# good
def initialize
  @x = 1
end
----

[#lintduplicatebranch]
== Lint/DuplicateBranch

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.3
| 1.7
|===

Checks that there are no repeated bodies
within `if/unless`, `case-when`, `case-in` and `rescue` constructs.

With `IgnoreLiteralBranches: true`, branches are not registered
as offenses if they return a basic literal value (string, symbol,
integer, float, rational, complex, `true`, `false`, or `nil`), or
return an array, hash, regexp or range that only contains one of
the above basic literal values.

With `IgnoreConstantBranches: true`, branches are not registered
as offenses if they return a constant value.

With `IgnoreDuplicateElseBranch: true`, in conditionals with multiple branches,
duplicate 'else' branches are not registered as offenses.

[#examples-lintduplicatebranch]
=== Examples

[source,ruby]
----
# bad
if foo
  do_foo
  do_something_else
elsif bar
  do_foo
  do_something_else
end

# good
if foo || bar
  do_foo
  do_something_else
end

# bad
case x
when foo
  do_foo
when bar
  do_foo
else
  do_something_else
end

# good
case x
when foo, bar
  do_foo
else
  do_something_else
end

# bad
begin
  do_something
rescue FooError
  handle_error
rescue BarError
  handle_error
end

# good
begin
  do_something
rescue FooError, BarError
  handle_error
end
----

[#ignoreliteralbranches_-true-lintduplicatebranch]
==== IgnoreLiteralBranches: true

[source,ruby]
----
# good
case size
when "small" then 100
when "medium" then 250
when "large" then 1000
else 250
end
----

[#ignoreconstantbranches_-true-lintduplicatebranch]
==== IgnoreConstantBranches: true

[source,ruby]
----
# good
case size
when "small" then SMALL_SIZE
when "medium" then MEDIUM_SIZE
when "large" then LARGE_SIZE
else MEDIUM_SIZE
end
----

[#ignoreduplicateelsebranch_-true-lintduplicatebranch]
==== IgnoreDuplicateElseBranch: true

[source,ruby]
----
# good
if foo
  do_foo
elsif bar
  do_bar
else
  do_foo
end
----

[#configurable-attributes-lintduplicatebranch]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| IgnoreLiteralBranches
| `false`
| Boolean

| IgnoreConstantBranches
| `false`
| Boolean

| IgnoreDuplicateElseBranch
| `false`
| Boolean
|===

[#lintduplicatecasecondition]
== Lint/DuplicateCaseCondition

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.45
| -
|===

Checks that there are no repeated conditions
used in case 'when' expressions.

[#examples-lintduplicatecasecondition]
=== Examples

[source,ruby]
----
# bad
case x
when 'first'
  do_something
when 'first'
  do_something_else
end

# good
case x
when 'first'
  do_something
when 'second'
  do_something_else
end
----

[#lintduplicateelsifcondition]
== Lint/DuplicateElsifCondition

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.88
| -
|===

Checks that there are no repeated conditions used in if 'elsif'.

[#examples-lintduplicateelsifcondition]
=== Examples

[source,ruby]
----
# bad
if x == 1
  do_something
elsif x == 1
  do_something_else
end

# good
if x == 1
  do_something
elsif x == 2
  do_something_else
end
----

[#lintduplicatehashkey]
== Lint/DuplicateHashKey

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.34
| 0.77
|===

Checks for duplicated keys in hash literals.
This cop considers both primitive types and constants for the hash keys.

This cop mirrors a warning in Ruby 2.2.

[#examples-lintduplicatehashkey]
=== Examples

[source,ruby]
----
# bad
hash = { food: 'apple', food: 'orange' }

# good
hash = { food: 'apple', other_food: 'orange' }
----

[#lintduplicatemagiccomment]
== Lint/DuplicateMagicComment

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.37
| -
|===

Checks for duplicated magic comments.

[#examples-lintduplicatemagiccomment]
=== Examples

[source,ruby]
----
# bad

# encoding: ascii
# encoding: ascii

# good

# encoding: ascii

# bad

# frozen_string_literal: true
# frozen_string_literal: true

# good

# frozen_string_literal: true
----

[#lintduplicatematchpattern]
== Lint/DuplicateMatchPattern

NOTE: Requires Ruby version 2.7

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.50
| -
|===

Checks that there are no repeated patterns used in `in` keywords.

[#examples-lintduplicatematchpattern]
=== Examples

[source,ruby]
----
# bad
case x
in 'first'
  do_something
in 'first'
  do_something_else
end

# good
case x
in 'first'
  do_something
in 'second'
  do_something_else
end

# bad - repeated alternate patterns with the same conditions don't depend on the order
case x
in 0 | 1
  first_method
in 1 | 0
  second_method
end

# good
case x
in 0 | 1
  first_method
in 2 | 3
  second_method
end

# bad - repeated hash patterns with the same conditions don't depend on the order
case x
in foo: a, bar: b
  first_method
in bar: b, foo: a
  second_method
end

# good
case x
in foo: a, bar: b
  first_method
in bar: b, baz: c
  second_method
end

# bad - repeated array patterns with elements in the same order
case x
in [foo, bar]
  first_method
in [foo, bar]
  second_method
end

# good
case x
in [foo, bar]
  first_method
in [bar, foo]
  second_method
end

# bad - repeated the same patterns and guard conditions
case x
in foo if bar
  first_method
in foo if bar
  second_method
end

# good
case x
in foo if bar
  first_method
in foo if baz
  second_method
end
----

[#lintduplicatemethods]
== Lint/DuplicateMethods

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.29
| 1.89
|===

Checks for duplicated instance (or singleton) method
definitions.

NOTE: Aliasing a method to itself is allowed, as it indicates that
the developer intends to suppress Ruby's method redefinition warnings.
See https://bugs.ruby-lang.org/issues/13574.

By default the cop can only detect duplicates within a single file.
When `AllCops/UseProjectIndex` is enabled and the `rubydex` gem is installed,
the cop additionally consults the project-wide index and reports methods
whose duplicate definition lives in another file.

NOTE: The project index does not record whether a definition in another
file is wrapped in a conditional, so a platform-specific redefinition in
another file may still be reported. Aliasing the method to itself (see above)
before redefining marks the redefinition as intentional and is respected
across files.

[#examples-lintduplicatemethods]
=== Examples

[source,ruby]
----
# bad
def foo
  1
end

def foo
  2
end

# bad
def foo
  1
end

alias foo bar

# good
def foo
  1
end

def bar
  2
end

# good
def foo
  1
end

alias bar foo

# good
alias foo foo
def foo
  1
end

# good
alias_method :foo, :foo
def foo
  1
end

# bad
class MyClass
  extend Forwardable

  # or with: `def_instance_delegator`, `def_delegators`, `def_instance_delegators`
  def_delegator :delegation_target, :delegated_method_name

  def delegated_method_name
  end
end

# good
class MyClass
  extend Forwardable

  def_delegator :delegation_target, :delegated_method_name

  def non_duplicated_delegated_method_name
  end
end
----

[#allcops_activesupportextensionsenabled_-false-_default_-lintduplicatemethods]
==== AllCops:ActiveSupportExtensionsEnabled: false (default)

[source,ruby]
----
# good
def foo
  1
end

delegate :foo, to: :bar
----

[#allcops_activesupportextensionsenabled_-true-lintduplicatemethods]
==== AllCops:ActiveSupportExtensionsEnabled: true

[source,ruby]
----
# bad
def foo
  1
end

delegate :foo, to: :bar

# good
def foo
  1
end

delegate :baz, to: :bar

# good - delegate with splat arguments is ignored
def foo
  1
end

delegate :foo, **options

# good - delegate inside a condition is ignored
def foo
  1
end

if cond
  delegate :foo, to: :bar
end
----

[#delegatingmethods_-__delegate__-_expose__-_default_-__delegate___-lintduplicatemethods]
==== DelegatingMethods: ['delegate', 'expose'] (default: ['delegate'])

[source,ruby]
----
# A project's own `delegate`-shaped macros can be registered so the
# methods they define are recognized (with
# `AllCops/ActiveSupportExtensionsEnabled: true`).

# bad
def foo
  1
end

expose :foo, to: :bar
----

[#configurable-attributes-lintduplicatemethods]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| DelegatingMethods
| `delegate`
| Array
|===

[#lintduplicateregexpcharacterclasselement]
== Lint/DuplicateRegexpCharacterClassElement

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.1
| -
|===

Checks for duplicate elements in `Regexp` character classes.

[#examples-lintduplicateregexpcharacterclasselement]
=== Examples

[source,ruby]
----
# bad
r = /[xyx]/

# bad
r = /[0-9x0-9]/

# good
r = /[xy]/

# good
r = /[0-9x]/
----

[#lintduplicaterequire]
== Lint/DuplicateRequire

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 0.90
| 1.28
|===

Checks for duplicate ``require``s and ``require_relative``s.

[#safety-lintduplicaterequire]
=== Safety

This cop's autocorrection is unsafe because it may break the dependency order
of `require`.

[#examples-lintduplicaterequire]
=== Examples

[source,ruby]
----
# bad
require 'foo'
require 'bar'
require 'foo'

# good
require 'foo'
require 'bar'

# good
require 'foo'
require_relative 'foo'
----

[#lintduplicaterescueexception]
== Lint/DuplicateRescueException

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.89
| -
|===

Checks that there are no repeated exceptions
used in 'rescue' expressions.

[#examples-lintduplicaterescueexception]
=== Examples

[source,ruby]
----
# bad
begin
  something
rescue FirstException
  handle_exception
rescue FirstException
  handle_other_exception
end

# good
begin
  something
rescue FirstException
  handle_exception
rescue SecondException
  handle_other_exception
end
----

[#lintduplicatesetelement]
== Lint/DuplicateSetElement

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.67
| -
|===

Checks for duplicate literal, constant, or variable elements in `Set` and `SortedSet`.

[#examples-lintduplicatesetelement]
=== Examples

[source,ruby]
----
# bad
Set[:foo, :bar, :foo]

# good
Set[:foo, :bar]

# bad
Set.new([:foo, :bar, :foo])

# good
Set.new([:foo, :bar])

# bad
[:foo, :bar, :foo].to_set

# good
[:foo, :bar].to_set

# bad
SortedSet[:foo, :bar, :foo]

# good
SortedSet[:foo, :bar]

# bad
SortedSet.new([:foo, :bar, :foo])

# good
SortedSet.new([:foo, :bar])
----

[#linteachwithobjectargument]
== Lint/EachWithObjectArgument

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.31
| -
|===

Checks if each_with_object is called with an immutable
argument. Since the argument is the object that the given block shall
make calls on to build something based on the enumerable that
each_with_object iterates over, an immutable argument makes no sense.
It's definitely a bug.

[#examples-linteachwithobjectargument]
=== Examples

[source,ruby]
----
# bad
sum = numbers.each_with_object(0) { |e, a| a += e }

# good
num = 0
sum = numbers.each_with_object(num) { |e, a| a += e }
----

[#lintelselayout]
== Lint/ElseLayout

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.17
| 1.2
|===

Checks for odd `else` block layout - like
having an expression on the same line as the `else` keyword,
which is usually a mistake.

Its autocorrection tweaks layout to keep the syntax. So, this autocorrection
is compatible correction for bad case syntax, but if your code makes a mistake
with `elsif` and `else`, you will have to correct it manually.

[#examples-lintelselayout]
=== Examples

[source,ruby]
----
# bad

if something
  # ...
else do_this
  do_that
end

# good

# This code is compatible with the bad case. It will be autocorrected like this.
if something
  # ...
else
  do_this
  do_that
end

# This code is incompatible with the bad case.
# If `do_this` is a condition, `elsif` should be used instead of `else`.
if something
  # ...
elsif do_this
  do_that
end

# bad

# For single-line conditionals using `then` the layout is disallowed
# when the `else` body is multiline because it is treated as a lint offense.
if something then on_the_same_line_as_then
else first_line
  second_line
end

# good

# For single-line conditional using `then` the layout is allowed
# when `else` body is a single-line because it is treated as intentional.

if something then on_the_same_line_as_then
else single_line
end
----

[#lintemptyblock]
== Lint/EmptyBlock

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.1
| 1.15
|===

Checks for blocks without a body.
Such empty blocks are typically an oversight or we should provide a comment
to clarify what we're aiming for.

Empty lambdas and procs are ignored by default.

NOTE: For backwards compatibility, the configuration that allows/disallows
empty lambdas and procs is called `AllowEmptyLambdas`, even though it also
applies to procs.

[#examples-lintemptyblock]
=== Examples

[source,ruby]
----
# bad
items.each { |item| }

# good
items.each { |item| puts item }
----

[#allowcomments_-true-_default_-lintemptyblock]
==== AllowComments: true (default)

[source,ruby]
----
# good
items.each do |item|
  # TODO: implement later (inner comment)
end

items.each { |item| } # TODO: implement later (inline comment)
----

[#allowcomments_-false-lintemptyblock]
==== AllowComments: false

[source,ruby]
----
# bad
items.each do |item|
  # TODO: implement later (inner comment)
end

items.each { |item| } # TODO: implement later (inline comment)
----

[#allowemptylambdas_-true-_default_-lintemptyblock]
==== AllowEmptyLambdas: true (default)

[source,ruby]
----
# good
allow(subject).to receive(:callable).and_return(-> {})

placeholder = lambda do
end
(callable || placeholder).call

proc { }

Proc.new { }
----

[#allowemptylambdas_-false-lintemptyblock]
==== AllowEmptyLambdas: false

[source,ruby]
----
# bad
allow(subject).to receive(:callable).and_return(-> {})

placeholder = lambda do
end
(callable || placeholder).call

proc { }

Proc.new { }
----

[#configurable-attributes-lintemptyblock]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowComments
| `true`
| Boolean

| AllowEmptyLambdas
| `true`
| Boolean
|===

[#lintemptyclass]
== Lint/EmptyClass

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.3
| -
|===

Checks for classes and metaclasses without a body.
Such empty classes and metaclasses are typically an oversight or we should provide a comment
to be clearer what we're aiming for.

[#examples-lintemptyclass]
=== Examples

[source,ruby]
----
# bad
class Foo
end

class Bar
  class << self
  end
end

class << obj
end

# good
class Foo
  def do_something
    # ... code
  end
end

class Bar
  class << self
    attr_reader :bar
  end
end

class << obj
  attr_reader :bar
end
----

[#allowcomments_-false-_default_-lintemptyclass]
==== AllowComments: false (default)

[source,ruby]
----
# bad
class Foo
  # TODO: implement later
end

class Bar
  class << self
    # TODO: implement later
  end
end

class << obj
  # TODO: implement later
end
----

[#allowcomments_-true-lintemptyclass]
==== AllowComments: true

[source,ruby]
----
# good
class Foo
  # TODO: implement later
end

class Bar
  class << self
    # TODO: implement later
  end
end

class << obj
  # TODO: implement later
end
----

[#configurable-attributes-lintemptyclass]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowComments
| `false`
| Boolean
|===

[#lintemptyconditionalbody]
== Lint/EmptyConditionalBody

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 0.89
| 1.73
|===

Checks for the presence of `if`, `elsif` and `unless` branches without a body.

NOTE: empty `else` branches are handled by `Style/EmptyElse`.

[#examples-lintemptyconditionalbody]
=== Examples

[source,ruby]
----
# bad
if condition
end

# bad
unless condition
end

# bad
if condition
  do_something
elsif other_condition
end

# good
if condition
  do_something
end

# good
unless condition
  do_something
end

# good
if condition
  do_something
elsif other_condition
  nil
end

# good
if condition
  do_something
elsif other_condition
  do_something_else
end
----

[#allowcomments_-true-_default_-lintemptyconditionalbody]
==== AllowComments: true (default)

[source,ruby]
----
# good
if condition
  do_something
elsif other_condition
  # noop
end
----

[#allowcomments_-false-lintemptyconditionalbody]
==== AllowComments: false

[source,ruby]
----
# bad
if condition
  do_something
elsif other_condition
  # noop
end
----

[#configurable-attributes-lintemptyconditionalbody]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowComments
| `true`
| Boolean
|===

[#lintemptyensure]
== Lint/EmptyEnsure

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 0.10
| 1.61
|===

Checks for empty `ensure` blocks.

[#examples-lintemptyensure]
=== Examples

[source,ruby]
----
# bad
def some_method
  do_something
ensure
end

# bad
begin
  do_something
ensure
end

# good
def some_method
  do_something
ensure
  do_something_else
end

# good
begin
  do_something
ensure
  do_something_else
end
----

[#lintemptyexpression]
== Lint/EmptyExpression

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.45
| -
|===

Checks for the presence of empty expressions.

[#examples-lintemptyexpression]
=== Examples

[source,ruby]
----
# bad

foo = ()
if ()
  bar
end

# good

foo = (some_expression)
if (some_expression)
  bar
end
----

[#lintemptyfile]
== Lint/EmptyFile

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.90
| -
|===

Enforces that Ruby source files are not empty.

[#examples-lintemptyfile]
=== Examples

[source,ruby]
----
# bad
# Empty file

# good
# File containing non commented source lines
----

[#allowcomments_-true-_default_-lintemptyfile]
==== AllowComments: true (default)

[source,ruby]
----
# good
# File consisting only of comments
----

[#allowcomments_-false-lintemptyfile]
==== AllowComments: false

[source,ruby]
----
# bad
# File consisting only of comments
----

[#configurable-attributes-lintemptyfile]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowComments
| `true`
| Boolean
|===

[#lintemptyinpattern]
== Lint/EmptyInPattern

NOTE: Requires Ruby version 2.7

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.16
| -
|===

Checks for the presence of `in` pattern branches without a body.

[#examples-lintemptyinpattern]
=== Examples

[source,ruby]
----
# bad
case condition
in [a]
  do_something
in [a, b]
end

# good
case condition
in [a]
  do_something
in [a, b]
  nil
end
----

[#allowcomments_-true-_default_-lintemptyinpattern]
==== AllowComments: true (default)

[source,ruby]
----
# good
case condition
in [a]
  do_something
in [a, b]
  # noop
end
----

[#allowcomments_-false-lintemptyinpattern]
==== AllowComments: false

[source,ruby]
----
# bad
case condition
in [a]
  do_something
in [a, b]
  # noop
end
----

[#configurable-attributes-lintemptyinpattern]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowComments
| `true`
| Boolean
|===

[#lintemptyinterpolation]
== Lint/EmptyInterpolation

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 0.20
| 1.76
|===

Checks for empty interpolation.

[#examples-lintemptyinterpolation]
=== Examples

[source,ruby]
----
# bad
"result is #{}"

# good
"result is #{some_result}"
----

[#lintemptywhen]
== Lint/EmptyWhen

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.45
| 0.83
|===

Checks for the presence of `when` branches without a body.

[#examples-lintemptywhen]
=== Examples

[source,ruby]
----
# bad
case foo
when bar
  do_something
when baz
end

# good
case condition
when foo
  do_something
when bar
  nil
end
----

[#allowcomments_-true-_default_-lintemptywhen]
==== AllowComments: true (default)

[source,ruby]
----
# good
case condition
when foo
  do_something
when bar
  # noop
end
----

[#allowcomments_-false-lintemptywhen]
==== AllowComments: false

[source,ruby]
----
# bad
case condition
when foo
  do_something
when bar
  # do nothing
end
----

[#configurable-attributes-lintemptywhen]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowComments
| `true`
| Boolean
|===

[#lintensurereturn]
== Lint/EnsureReturn

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.9
| 0.83
|===

Checks for `return` from an `ensure` block.
`return` from an ensure block is a dangerous code smell as it
will take precedence over any exception being raised,
and the exception will be silently thrown away as if it were rescued.

If you want to rescue some (or all) exceptions, best to do it explicitly

[#examples-lintensurereturn]
=== Examples

[source,ruby]
----
# bad
def foo
  do_something
ensure
  cleanup
  return self
end

# good
def foo
  do_something
  self
ensure
  cleanup
end

# good
def foo
  begin
    do_something
  rescue SomeException
    # Let's ignore this exception
  end
  self
ensure
  cleanup
end
----

[#references-lintensurereturn]
=== References

* https://rubystyle.guide#no-return-ensure

[#linterbnewarguments]
== Lint/ErbNewArguments

NOTE: Requires Ruby version 2.6

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.56
| -
|===

Emulates the following Ruby warnings in Ruby 2.6.

[source,console]
----
$ cat example.rb
ERB.new('hi', nil, '-', '@output_buffer')
$ ruby -rerb example.rb
example.rb:1: warning: Passing safe_level with the 2nd argument of ERB.new is
deprecated. Do not use it, and specify other arguments as keyword arguments.
example.rb:1: warning: Passing trim_mode with the 3rd argument of ERB.new is
deprecated. Use keyword argument like ERB.new(str, trim_mode:...) instead.
example.rb:1: warning: Passing eoutvar with the 4th argument of ERB.new is
deprecated. Use keyword argument like ERB.new(str, eoutvar: ...) instead.
----

Now non-keyword arguments other than first one are softly deprecated
and will be removed when Ruby 2.5 becomes EOL.
`ERB.new` with non-keyword arguments is deprecated since ERB 2.2.0.
Use `:trim_mode` and `:eoutvar` keyword arguments to `ERB.new`.
This cop identifies places where `ERB.new(str, trim_mode, eoutvar)` can
be replaced by `ERB.new(str, trim_mode: trim_mode, eoutvar: eoutvar)`.

[#examples-linterbnewarguments]
=== Examples

[source,ruby]
----
# Target codes supports Ruby 2.6 and higher only
# bad
ERB.new(str, nil, '-', '@output_buffer')

# good
ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer')

# Target codes supports Ruby 2.5 and lower only
# good
ERB.new(str, nil, '-', '@output_buffer')

# Target codes supports Ruby 2.6, 2.5 and lower
# bad
ERB.new(str, nil, '-', '@output_buffer')

# good
# Ruby standard library style
# https://github.com/ruby/ruby/commit/3406c5d
if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
  ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer')
else
  ERB.new(str, nil, '-', '@output_buffer')
end

# good
# Use `RUBY_VERSION` style
if RUBY_VERSION >= '2.6'
  ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer')
else
  ERB.new(str, nil, '-', '@output_buffer')
end
----

[#lintflipflop]
== Lint/FlipFlop

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.16
| -
|===

Looks for uses of flip-flop operator
based on the Ruby Style Guide.

Here is the history of flip-flops in Ruby.
flip-flop operator is deprecated in Ruby 2.6.0 and
the deprecation has been reverted by Ruby 2.7.0 and
backported to Ruby 2.6.
See: https://bugs.ruby-lang.org/issues/5400

[#examples-lintflipflop]
=== Examples

[source,ruby]
----
# bad
(1..20).each do |x|
  puts x if (x == 5) .. (x == 10)
end

# good
(1..20).each do |x|
  puts x if (x >= 5) && (x <= 10)
end
----

[#references-lintflipflop]
=== References

* https://rubystyle.guide#no-flip-flops

[#lintfloatcomparison]
== Lint/FloatComparison

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.89
| -
|===

Checks for the presence of precise comparison of floating point numbers.

Floating point values are inherently inaccurate, and comparing them for exact equality
is almost never the desired semantics. Comparison via the `==/!=` operators checks
floating-point value representation to be exactly the same, which is very unlikely
if you perform any arithmetic operations involving precision loss.

[#examples-lintfloatcomparison]
=== Examples

[source,ruby]
----
# bad
x == 0.1
x != 0.1

# bad
case value
when 1.0
  foo
when 2.0
  bar
end

# good - using BigDecimal
x.to_d == 0.1.to_d

# good - comparing against zero
x == 0.0
x != 0.0

# good
(x - 0.1).abs < Float::EPSILON

# good
tolerance = 0.0001
(x - 0.1).abs < tolerance

# good - comparing against nil
Float(x, exception: false) == nil

# good - using epsilon comparison in case expression
case
when (value - 1.0).abs < Float::EPSILON
  foo
when (value - 2.0).abs < Float::EPSILON
  bar
end

# Or some other epsilon based type of comparison:
# https://www.embeddeduse.com/2019/08/26/qt-compare-two-floats/
----

[#references-lintfloatcomparison]
=== References

* https://rubystyle.guide#float-comparison

[#lintfloatoutofrange]
== Lint/FloatOutOfRange

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.36
| -
|===

Identifies `Float` literals which are, like, really really really
really really really really really big. Too big. No-one needs Floats
that big. If you need a float that big, something is wrong with you.

[#examples-lintfloatoutofrange]
=== Examples

[source,ruby]
----
# bad
float = 3.0e400

# good
float = 42.9
----

[#lintformatparametermismatch]
== Lint/FormatParameterMismatch

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.33
| -
|===

This lint sees if there is a mismatch between the number of
expected fields for format/sprintf/#% and what is actually
passed as arguments.

In addition, it checks whether different formats are used in the same
format string. Do not mix numbered, unnumbered, and named formats in
the same format string.

[#examples-lintformatparametermismatch]
=== Examples

[source,ruby]
----
# bad
format('A value: %s and another: %i', a_value)

# good
format('A value: %s and another: %i', a_value, another)

# bad
format('Unnumbered format: %s and numbered: %2$s', a_value, another)

# good
format('Numbered format: %1$s and numbered %2$s', a_value, another)
----

[#linthashcomparebyidentity]
== Lint/HashCompareByIdentity

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| No
| 0.93
| -
|===

Prefer using `Hash#compare_by_identity` rather than using `object_id`
for hash keys.

This cop looks for hashes being keyed by objects' `object_id`, using
one of these methods: `key?`, `has_key?`, `fetch`, `[]` and `[]=`.

[#safety-linthashcomparebyidentity]
=== Safety

This cop is unsafe. Although unlikely, the hash could store both object
ids and other values that need be compared by value, and thus
could be a false positive.

Furthermore, this cop cannot guarantee that the receiver of one of the
methods (`key?`, etc.) is actually a hash.

[#examples-linthashcomparebyidentity]
=== Examples

[source,ruby]
----
# bad
hash = {}
hash[foo.object_id] = :bar
hash.key?(baz.object_id)

# good
hash = {}.compare_by_identity
hash[foo] = :bar
hash.key?(baz)
----

[#references-linthashcomparebyidentity]
=== References

* https://rubystyle.guide#identity-comparison

[#linthashnewwithkeywordargumentsasdefault]
== Lint/HashNewWithKeywordArgumentsAsDefault

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.69
| -
|===

Checks for the deprecated use of keyword arguments as a default in `Hash.new`.

This usage raises a warning in Ruby 3.3 and results in an error in Ruby 3.4.
In Ruby 3.4, keyword arguments will instead be used to change the behavior of a hash.
For example, the capacity option can be passed to create a hash with a certain size
if you know it in advance, for better performance.

NOTE: The following corner case may result in a false negative when upgrading from Ruby 3.3
or earlier, but it is intentionally not detected to respect the expected usage in Ruby 3.4.

[source,ruby]
----
Hash.new(capacity: 42)
----

[#examples-linthashnewwithkeywordargumentsasdefault]
=== Examples

[source,ruby]
----
# bad
Hash.new(key: :value)

# good
Hash.new({key: :value})
----

[#lintheredocmethodcallposition]
== Lint/HeredocMethodCallPosition

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Disabled
| Yes
| Always
| 0.68
| -
|===

Checks for the ordering of a method call where
the receiver of the call is a HEREDOC.

[#examples-lintheredocmethodcallposition]
=== Examples

[source,ruby]
----
# bad
<<-SQL
  bar
SQL
.strip_indent

<<-SQL
  bar
SQL
.strip_indent
.trim

# good
<<~SQL
  bar
SQL

<<~SQL.trim
  bar
SQL
----

[#references-lintheredocmethodcallposition]
=== References

* https://rubystyle.guide#heredoc-method-calls

[#lintidentitycomparison]
== Lint/IdentityComparison

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.91
| -
|===

Prefer `equal?` over `==` when comparing `object_id`.

`Object#equal?` is provided to compare objects for identity, and in contrast
`Object#==` is provided for the purpose of doing value comparison.

[#examples-lintidentitycomparison]
=== Examples

[source,ruby]
----
# bad
foo.object_id == bar.object_id
foo.object_id != baz.object_id

# good
foo.equal?(bar)
!foo.equal?(baz)
----

[#references-lintidentitycomparison]
=== References

* https://rubystyle.guide#identity-comparison

[#lintimplicitstringconcatenation]
== Lint/ImplicitStringConcatenation

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.36
| -
|===

Checks for implicit string concatenation of string literals
which are on the same line.

[#examples-lintimplicitstringconcatenation]
=== Examples

[source,ruby]
----
# bad
array = ['Item 1' 'Item 2']

# good
array = ['Item 1Item 2']
array = ['Item 1' + 'Item 2']
array = [
  'Item 1' \
  'Item 2'
]
----

[#lintincompatibleioselectwithfiberscheduler]
== Lint/IncompatibleIoSelectWithFiberScheduler

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always (Unsafe)
| 1.21
| 1.24
|===

Checks for `IO.select` that is incompatible with Fiber Scheduler since Ruby 3.0.

When an array of IO objects waiting for an exception (the third argument of `IO.select`)
is used as an argument, there is no alternative API, so offenses are not registered.

NOTE: When the method is successful the return value of `IO.select` is `[[IO]]`,
and the return value of `io.wait_readable` and `io.wait_writable` are `self`.
They are not autocorrected when assigning a return value because these types are different.
It's up to user how to handle the return value.

[#safety-lintincompatibleioselectwithfiberscheduler]
=== Safety

This cop's autocorrection is unsafe because `NoMethodError` occurs
if `require 'io/wait'` is not called.

[#examples-lintincompatibleioselectwithfiberscheduler]
=== Examples

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

# good
io.wait_readable(timeout)

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

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

[#lintineffectiveaccessmodifier]
== Lint/IneffectiveAccessModifier

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.36
| -
|===

Checks for `private` or `protected` access modifiers which are
applied to a singleton method. These access modifiers do not make
singleton methods private/protected. `private_class_method` can be
used for that.

[#examples-lintineffectiveaccessmodifier]
=== Examples

[source,ruby]
----
# bad
class C
  private

  def self.method
    puts 'hi'
  end
end

# good
class C
  def self.method
    puts 'hi'
  end

  private_class_method :method
end

# good
class C
  class << self
    private

    def method
      puts 'hi'
    end
  end
end
----

[#lintinheritexception]
== Lint/InheritException

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 0.41
| 1.89
|===

Looks for error classes inheriting from `Exception`.
It is configurable to suggest using either `StandardError` (default) or
`RuntimeError` instead.

When `AllCops/UseProjectIndex` is enabled and the `rubydex` gem is
installed, indirect inheritance is also detected: a class whose parent
(defined anywhere in the project) ultimately inherits from `Exception`
is reported, without autocorrection.

[#safety-lintinheritexception]
=== Safety

This cop's autocorrection is unsafe because `rescue` that omit
exception class handle `StandardError` and its subclasses,
but not `Exception` and its subclasses.

[#examples-lintinheritexception]
=== Examples

[#enforcedstyle_-standard_error-_default_-lintinheritexception]
==== EnforcedStyle: standard_error (default)

[source,ruby]
----
# bad

class C < Exception; end

C = Class.new(Exception)

# good

class C < StandardError; end

C = Class.new(StandardError)
----

[#enforcedstyle_-runtime_error-lintinheritexception]
==== EnforcedStyle: runtime_error

[source,ruby]
----
# bad

class C < Exception; end

C = Class.new(Exception)

# good

class C < RuntimeError; end

C = Class.new(RuntimeError)
----

[#configurable-attributes-lintinheritexception]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `standard_error`
| `standard_error`, `runtime_error`
|===

[#lintinterpolationcheck]
== Lint/InterpolationCheck

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 0.50
| 1.40
|===

Checks for interpolation in a single quoted string.

[#safety-lintinterpolationcheck]
=== Safety

This cop's autocorrection is unsafe because although it always replaces single quotes as
if it were miswritten double quotes, it is not always the case. For example,
`'#{foo} bar'` would be replaced by `"#{foo} bar"`, so the replaced code would evaluate
the expression `foo`.

[#examples-lintinterpolationcheck]
=== Examples

[source,ruby]
----
# bad
foo = 'something with #{interpolation} inside'

# good
foo = "something with #{interpolation} inside"
----

[#lintitwithoutargumentsinblock]
== Lint/ItWithoutArgumentsInBlock

NOTE: Requires Ruby version <= 3.3

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.59
| -
|===

Emulates the following Ruby warning in Ruby 3.3.

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

`it` calls without arguments will refer to the first block param in Ruby 3.4.
So use `it()` or `self.it` to ensure compatibility.

[#examples-lintitwithoutargumentsinblock]
=== Examples

[source,ruby]
----
# bad
do_something { it }

# good
do_something { it() }
do_something { self.it }
----

[#references-lintitwithoutargumentsinblock]
=== References

* https://bugs.ruby-lang.org/issues/18980

[#lintlambdawithoutliteralblock]
== Lint/LambdaWithoutLiteralBlock

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.8
| -
|===

Checks uses of lambda without a literal block.
It emulates the following warning in Ruby 3.0:

  $ ruby -vwe 'lambda(&proc {})'
  ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
  -e:1: warning: lambda without a literal block is deprecated; use the proc without
  lambda instead

This way, proc object is never converted to lambda.
Autocorrection replaces with compatible proc argument.

[#examples-lintlambdawithoutliteralblock]
=== Examples

[source,ruby]
----
# bad
lambda(&proc { do_something })
lambda(&Proc.new { do_something })

# good
proc { do_something }
Proc.new { do_something }
lambda { do_something } # If you use lambda.
----

[#lintliteralascondition]
== Lint/LiteralAsCondition

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 0.51
| -
|===

Checks for literals used as the conditions or as
operands in and/or expressions serving as the conditions of
if/while/until/case-when/case-in.

NOTE: Literals in `case-in` condition where the match variable is used in
`in` are accepted as a pattern matching.

[#examples-lintliteralascondition]
=== Examples

[source,ruby]
----
# bad
if 20
  do_something
end

# bad
# We're only interested in the left hand side being a truthy literal,
# because it affects the evaluation of the &&, whereas the right hand
# side will be conditionally executed/called and can be a literal.
if true && some_var
  do_something
end

# good
if some_var
  do_something
end

# good
# When using a boolean value for an infinite loop.
while true
  break if condition
end
----

[#lintliteralassignmentincondition]
== Lint/LiteralAssignmentInCondition

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.58
| -
|===

Checks for literal assignments in the conditions of `if`, `while`, and `until`.
It emulates the following Ruby warning:

[source,console]
----
$ ruby -we 'if x = true; end'
-e:1: warning: found `= literal' in conditional, should be ==
----

As a lint cop, it cannot be determined if `==` is appropriate as intended,
therefore this cop does not provide autocorrection.

[#examples-lintliteralassignmentincondition]
=== Examples

[source,ruby]
----
# bad
if x = 42
  do_something
end

# good
if x == 42
  do_something
end

# good
if x = y
  do_something
end
----

[#lintliteralininterpolation]
== Lint/LiteralInInterpolation

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.19
| 0.32
|===

Checks for interpolated literals.

NOTE: Array literals interpolated in regexps are not handled by this cop, but
by `Lint/ArrayLiteralInRegexp` instead.

[#examples-lintliteralininterpolation]
=== Examples

[source,ruby]
----
# bad
"result is #{10}"

# good
"result is 10"
----

[#lintloop]
== Lint/Loop

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| Always (Unsafe)
| 0.9
| 1.3
|===

Checks for uses of `begin...end while/until something`.

[#safety-lintloop]
=== Safety

The cop is unsafe because behavior can change in some cases, including
if a local variable inside the loop body is accessed outside of it, or if the
loop body raises a `StopIteration` exception (which `Kernel#loop` rescues).

[#examples-lintloop]
=== Examples

[source,ruby]
----
# bad

# using while
begin
  do_something
end while some_condition

# good

# while replacement
loop do
  do_something
  break unless some_condition
end

# bad

# using until
begin
  do_something
end until some_condition

# good

# until replacement
loop do
  do_something
  break if some_condition
end
----

[#references-lintloop]
=== References

* https://rubystyle.guide#loop-with-break

[#lintmissingcopenabledirective]
== Lint/MissingCopEnableDirective

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.52
| 1.88
|===

Checks that there is an `# rubocop:enable ...` statement
after a `# rubocop:disable ...` statement. This will prevent leaving
cop disables on wide ranges of code, that later contributors to
a file wouldn't be aware of.

You can set `MaxRangeSize` to define the maximum number of
consecutive lines a cop can be disabled for.

- `.inf` any size (default)
- `0` allows only single-line disables
- `1` means the maximum allowed is as follows:

[source,ruby]
----
# rubocop:disable SomeCop
a = 1
# rubocop:enable SomeCop
----

[#examples-lintmissingcopenabledirective]
=== Examples

[#maxrangesize_-_inf-_default_-lintmissingcopenabledirective]
==== MaxRangeSize: .inf (default)

[source,ruby]
----
# good
# rubocop:disable Layout/SpaceAroundOperators
x= 0
# rubocop:enable Layout/SpaceAroundOperators
# y = 1
# EOF

# bad
# rubocop:disable Layout/SpaceAroundOperators
x= 0
# EOF
----

[#maxrangesize_-2-lintmissingcopenabledirective]
==== MaxRangeSize: 2

[source,ruby]
----
# good
# rubocop:disable Layout/SpaceAroundOperators
x= 0
# With the previous, there are 2 lines on which cop is disabled.
# rubocop:enable Layout/SpaceAroundOperators

# bad
# rubocop:disable Layout/SpaceAroundOperators
x= 0
x += 1
# Including this, that's 3 lines on which the cop is disabled.
# rubocop:enable Layout/SpaceAroundOperators
----

[#configurable-attributes-lintmissingcopenabledirective]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| MaxRangeSize
| `Infinity`
| Float
|===

[#lintmissingsuper]
== Lint/MissingSuper

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.89
| 1.89
|===

Checks for the presence of constructors and lifecycle callbacks
without calls to `super`.

This cop does not consider `method_missing` (and `respond_to_missing?`)
because in some cases it makes sense to overtake what is considered a
missing method. In other cases, the theoretical ideal handling could be
challenging or verbose for no actual gain.

Autocorrection is not supported because the position of `super` cannot be
determined automatically.

`Object` and `BasicObject` are allowed by this cop because of their
stateless nature. However, sometimes you might want to allow other parent
classes from this cop, for example in the case of an abstract class that is
not meant to be called with `super`. In those cases, you can use the
`AllowedParentClasses` option to specify which classes should be allowed
*in addition to* `Object` and `BasicObject`.

When `AllCops/UseProjectIndex` is enabled and the `rubydex` gem is installed,
the constructor check additionally consults the project-wide index: if the
class' entire ancestry is resolvable and no ancestor defines `initialize`,
no offense is registered, since `super` would only reach the no-op
`Object#initialize`. Classes whose ancestry contains an unresolvable
superclass or mixin (e.g. one defined in a gem) are still reported.

[#examples-lintmissingsuper]
=== Examples

[source,ruby]
----
# bad
class Employee < Person
  def initialize(name, salary)
    @salary = salary
  end
end

# good
class Employee < Person
  def initialize(name, salary)
    super(name)
    @salary = salary
  end
end

# bad
Employee = Class.new(Person) do
  def initialize(name, salary)
    @salary = salary
  end
end

# good
Employee = Class.new(Person) do
  def initialize(name, salary)
    super(name)
    @salary = salary
  end
end

# bad
class Parent
  def self.inherited(base)
    do_something
  end
end

# good
class Parent
  def self.inherited(base)
    super
    do_something
  end
end

# good
class ClassWithNoParent
  def initialize
    do_something
  end
end
----

[#allowedparentclasses_-_myabstractclass_-lintmissingsuper]
==== AllowedParentClasses: [MyAbstractClass]

[source,ruby]
----
# good
class MyConcreteClass < MyAbstractClass
  def initialize
    do_something
  end
end
----

[#configurable-attributes-lintmissingsuper]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowedParentClasses
| `[]`
| Array
|===

[#lintmixedcaserange]
== Lint/MixedCaseRange

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always (Unsafe)
| 1.53
| -
|===

Checks for mixed-case character ranges since they include likely unintended characters.

Offenses are registered for regexp character classes like `/[A-z]/`
as well as range objects like `('A'..'z')`.

NOTE: `Range` objects cannot be autocorrected.

[#safety-lintmixedcaserange]
=== Safety

The cop autocorrects regexp character classes
by replacing one character range with two: `A-z` becomes `A-Za-z`.
In most cases this is probably what was originally intended
but it changes the regexp to no longer match symbols it used to include.
For this reason, this cop's autocorrect is unsafe (it will
change the behavior of the code).

[#examples-lintmixedcaserange]
=== Examples

[source,ruby]
----
# bad
r = /[A-z]/

# good
r = /[A-Za-z]/
----

[#lintmixedregexpcapturetypes]
== Lint/MixedRegexpCaptureTypes

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.85
| -
|===

Do not mix named captures and numbered captures in a `Regexp` literal
because numbered capture is ignored if they're mixed.
Replace numbered captures with non-capturing groupings or
named captures.

[#examples-lintmixedregexpcapturetypes]
=== Examples

[source,ruby]
----
# bad
/(?<foo>FOO)(BAR)/

# good
/(?<foo>FOO)(?<bar>BAR)/

# good
/(?<foo>FOO)(?:BAR)/

# good
/(FOO)(BAR)/
----

[#lintmultiplecomparison]
== Lint/MultipleComparison

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.47
| 1.1
|===

In math and Python, we can use `x < y < z` style comparison to compare
multiple values. However, we can't use the comparison in Ruby. However,
the comparison is not a syntax error. This cop checks the bad usage of
comparison operators.

[#examples-lintmultiplecomparison]
=== Examples

[source,ruby]
----
# bad
x < y < z
10 <= x <= 20

# good
x < y && y < z
10 <= x && x <= 20
----

[#lintnametypo]
== Lint/NameTypo

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.89
| -
|===

Checks for probable typos in constant and method names: a name that
does not resolve anywhere in the project, used in a namespace the
project does define, with a close-named sibling to suggest instead.

The check is powered by the project-wide index, so it only runs when
`AllCops/UseProjectIndex` is enabled and the `rubydex` gem is installed.
Without the index the cop does nothing.

Constants are checked only in qualified references (`Foo::Bar`) whose
namespace resolves in the index; bare names cannot be distinguished
from constants provided by gems or the standard library. Methods are
checked only in calls on constant receivers (`Foo.bar`) whose entire
indexed ancestry is resolved, so methods gained through gem classes or
dynamic definitions never produce offenses. In both cases an offense
requires a similarly named alternative to exist — an unknown name
alone is not reported, since the index does not see gems or the
standard library.

Names that appear as symbols or inside string literals in the same
file are never reported, since they usually belong to runtime
definitions the index cannot see (`stub_const`, `const_set`,
`define_method`, and the like).

[#examples-lintnametypo]
=== Examples

[source,ruby]
----
# bad - Services::UserCraetor is not defined, Services::UserCreator is
Services::UserCraetor.new

# good
Services::UserCreator.new

# bad - Report.generate_sumary is not defined, Report.generate_summary is
Report.generate_sumary

# good
Report.generate_summary
----

[#checkconstants_-false-lintnametypo]
==== CheckConstants: false

[source,ruby]
----
# good - constant references are not checked
Services::UserCraetor.new
----

[#checkmethods_-false-lintnametypo]
==== CheckMethods: false

[source,ruby]
----
# good - method calls are not checked
Report.generate_sumary
----

[#allowednames_-__generate_sumary__-lintnametypo]
==== AllowedNames: ['generate_sumary']

[source,ruby]
----
# good - the name is explicitly allowed
Report.generate_sumary
----

[#configurable-attributes-lintnametypo]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| CheckConstants
| `true`
| Boolean

| CheckMethods
| `true`
| Boolean

| AllowedNames
| `[]`
| Array
|===

[#lintnestedmethoddefinition]
== Lint/NestedMethodDefinition

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.32
| -
|===

Checks for nested method definitions.

[#examples-lintnestedmethoddefinition]
=== Examples

[source,ruby]
----
# bad

# `bar` definition actually produces methods in the same scope
# as the outer `foo` method. Furthermore, the `bar` method
# will be redefined every time `foo` is invoked.
def foo
  def bar
  end
end

# good

def foo
  bar = -> { puts 'hello' }
  bar.call
end

# good

# `class_eval`, `instance_eval`, `module_eval`, `class_exec`, `instance_exec`, and
# `module_exec` blocks are allowed by default.

def foo
  self.class.class_eval do
    def bar
    end
  end
end

def foo
  self.class.module_exec do
    def bar
    end
  end
end

# good

def foo
  class << self
    def bar
    end
  end
end
----

[#allowedmethods_-__-_default_-lintnestedmethoddefinition]
==== AllowedMethods: [] (default)

[source,ruby]
----
# bad
def do_something
  has_many :articles do
    def find_or_create_by_name(name)
    end
  end
end
----

[#allowedmethods_-__has_many__-lintnestedmethoddefinition]
==== AllowedMethods: ['has_many']

[source,ruby]
----
# bad
def do_something
  has_many :articles do
    def find_or_create_by_name(name)
    end
  end
end
----

[#allowedpatterns_-__-_default_-lintnestedmethoddefinition]
==== AllowedPatterns: [] (default)

[source,ruby]
----
# bad
def foo(obj)
  obj.do_baz do
    def bar
    end
  end
end
----

[#allowedpatterns_-__baz__-lintnestedmethoddefinition]
==== AllowedPatterns: ['baz']

[source,ruby]
----
# good
def foo(obj)
  obj.do_baz do
    def bar
    end
  end
end
----

[#configurable-attributes-lintnestedmethoddefinition]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowedMethods
| `[]`
| Array

| AllowedPatterns
| `[]`
| Array
|===

[#references-lintnestedmethoddefinition]
=== References

* https://rubystyle.guide#no-nested-methods

[#lintnestedpercentliteral]
== Lint/NestedPercentLiteral

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.52
| -
|===

Checks for nested percent literals.

[#examples-lintnestedpercentliteral]
=== Examples

[source,ruby]
----
# bad

# The percent literal for nested_attributes is parsed as four tokens,
# yielding the array [:name, :content, :"%i[incorrectly", :"nested]"].
attributes = {
  valid_attributes: %i[name content],
  nested_attributes: %i[name content %i[incorrectly nested]]
}

# good

# Neither is incompatible with the bad case, but probably the intended code.
attributes = {
  valid_attributes: %i[name content],
  nested_attributes: [:name, :content, %i[incorrectly nested]]
}

attributes = {
  valid_attributes: %i[name content],
  nested_attributes: [:name, :content, [:incorrectly, :nested]]
}
----

[#lintnextwithoutaccumulator]
== Lint/NextWithoutAccumulator

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.36
| -
|===

Don't omit the accumulator when calling `next` in a `reduce` block.

[#examples-lintnextwithoutaccumulator]
=== Examples

[source,ruby]
----
# bad
result = (1..4).reduce(0) do |acc, i|
  next if i.odd?
  acc + i
end

# good
result = (1..4).reduce(0) do |acc, i|
  next acc if i.odd?
  acc + i
end
----

[#lintnoreturninbeginendblocks]
== Lint/NoReturnInBeginEndBlocks

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.2
| -
|===

Checks for the presence of a `return` inside a `begin..end` block
in assignment contexts.
In this situation, the `return` will result in an exit from the current
method, possibly leading to unexpected behavior.

[#examples-lintnoreturninbeginendblocks]
=== Examples

[source,ruby]
----
# bad
@some_variable ||= begin
  return some_value if some_condition_is_met

  do_something
end

# good
@some_variable ||= begin
  if some_condition_is_met
    some_value
  else
    do_something
  end
end

# good
some_variable = if some_condition_is_met
                  return if another_condition_is_met

                  some_value
                else
                  do_something
                end
----

[#lintnonatomicfileoperation]
== Lint/NonAtomicFileOperation

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always (Unsafe)
| 1.31
| -
|===

Checks for non-atomic file operation.
And then replace it with a nearly equivalent and atomic method.

These can cause problems that are difficult to reproduce,
especially in cases of frequent file operations in parallel,
such as test runs with parallel_rspec.

For examples: creating a directory if there is none, has the following problems

An exception occurs when the directory didn't exist at the time of `exist?`,
but someone else created it before `mkdir` was executed.

Subsequent processes are executed without the directory that should be there
when the directory existed at the time of `exist?`,
but someone else deleted it shortly afterwards.

[#safety-lintnonatomicfileoperation]
=== Safety

This cop is unsafe, because autocorrection change to atomic processing.
The atomic processing of the replacement destination is not guaranteed
to be strictly equivalent to that before the replacement.

[#examples-lintnonatomicfileoperation]
=== Examples

[source,ruby]
----
# bad - race condition with another process may result in an error in `mkdir`
unless Dir.exist?(path)
  FileUtils.mkdir(path)
end

# good - atomic and idempotent creation
FileUtils.mkdir_p(path)

# bad - race condition with another process may result in an error in `remove`
if File.exist?(path)
  FileUtils.remove(path)
end

# good - atomic and idempotent removal
FileUtils.rm_f(path)
----

[#references-lintnonatomicfileoperation]
=== References

* https://rubystyle.guide#atomic-file-operations

[#lintnondeterministicrequireorder]
== Lint/NonDeterministicRequireOrder

NOTE: Requires Ruby version <= 2.7

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| Always (Unsafe)
| 0.78
| -
|===

`Dir[...]` and `Dir.glob(...)` do not make any guarantees about
the order in which files are returned. The final order is
determined by the operating system and file system.
This means that using them in cases where the order matters,
such as requiring files, can lead to intermittent failures
that are hard to debug. To ensure this doesn't happen,
always sort the list.

`Dir.glob` and `Dir[]` sort globbed results by default in Ruby 3.0.
So all bad cases are acceptable when Ruby 3.0 or higher is used.

NOTE: This cop will be deprecated and removed when supporting only Ruby 3.0 and higher.

[#safety-lintnondeterministicrequireorder]
=== Safety

This cop is unsafe in the case where sorting files changes existing
expected behavior.

[#examples-lintnondeterministicrequireorder]
=== Examples

[source,ruby]
----
# bad
Dir["./lib/**/*.rb"].each do |file|
  require file
end

# good
Dir["./lib/**/*.rb"].sort.each do |file|
  require file
end

# bad
Dir.glob(Rails.root.join(__dir__, 'test', '*.rb')) do |file|
  require file
end

# good
Dir.glob(Rails.root.join(__dir__, 'test', '*.rb')).sort.each do |file|
  require file
end

# bad
Dir['./lib/**/*.rb'].each(&method(:require))

# good
Dir['./lib/**/*.rb'].sort.each(&method(:require))

# bad
Dir.glob(Rails.root.join('test', '*.rb'), &method(:require))

# good
Dir.glob(Rails.root.join('test', '*.rb')).sort.each(&method(:require))

# good - Respect intent if `sort` keyword option is specified in Ruby 3.0 or higher.
Dir.glob(Rails.root.join(__dir__, 'test', '*.rb'), sort: false).each(&method(:require))
----

[#lintnonlocalexitfromiterator]
== Lint/NonLocalExitFromIterator

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.30
| -
|===

Checks for non-local exits from iterators without a return
value. It registers an offense under these conditions:

* No value is returned,
* the block is preceded by a method chain,
* the block has arguments,
* the method which receives the block is not `define_method`
or `define_singleton_method`,
* the return is not contained in an inner scope, e.g. a lambda or a
method definition.

[#examples-lintnonlocalexitfromiterator]
=== Examples

[source,ruby]
----
class ItemApi
  rescue_from ValidationError do |e| # non-iteration block with arg
    return { message: 'validation error' } unless e.errors # allowed
    error_array = e.errors.map do |error| # block with method chain
      return if error.suppress? # warned
      return "#{error.param}: invalid" unless error.message # allowed
      "#{error.param}: #{error.message}"
    end
    { message: 'validation error', errors: error_array }
  end

  def update_items
    transaction do # block without arguments
      return unless update_necessary? # allowed
      find_each do |item| # block without method chain
        return if item.stock == 0 # false-negative...
        item.update!(foobar: true)
      end
    end
  end
end
----

[#lintnumberconversion]
== Lint/NumberConversion

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Disabled
| Yes
| Always (Unsafe)
| 0.53
| 1.88
|===

Warns against the usage of unsafe number conversions. Unsafe
number conversion can cause an unexpected error if auto type conversion
fails. The cop prefers parsing with a number class instead.

Conversion with `Integer`, `Float`, etc. will raise an `ArgumentError`
if given input that is not numeric (eg. an empty string), whereas
`to_i`, etc. will try to convert regardless of input (``''.to_i => 0``).
As such, this cop is disabled by default because it's not necessarily
always correct to raise if a value is not numeric.

NOTE: Some values cannot be converted properly using one of the `Kernel`
methods (for instance, `Time` and `DateTime` values are allowed by this
cop by default). Similarly, Rails' duration methods do not work well
with `Integer()` and can be allowed with `AllowedMethods`. By default,
there are no allowed methods.

[#safety-lintnumberconversion]
=== Safety

Autocorrection is unsafe because it is not guaranteed that the
replacement `Kernel` methods are able to properly handle the
input if it is not a standard class.

[#examples-lintnumberconversion]
=== Examples

[source,ruby]
----
# bad

'10'.to_i
'10.2'.to_f
'10'.to_c
'1/3'.to_r
['1', '2', '3'].map(&:to_i)
foo.try(:to_f)
bar.send(:to_c)

# good

Integer('10', 10)
Float('10.2')
Complex('10')
Rational('1/3')
['1', '2', '3'].map { |i| Integer(i, 10) }
foo.try { |i| Float(i) }
bar.send { |i| Complex(i) }
----

[#allowedmethods_-__-_default_-lintnumberconversion]
==== AllowedMethods: [] (default)

[source,ruby]
----
# bad
10.minutes.to_i
----

[#allowedmethods_-_minutes_-lintnumberconversion]
==== AllowedMethods: [minutes]

[source,ruby]
----
# good
10.minutes.to_i
----

[#allowedpatterns_-__-_default_-lintnumberconversion]
==== AllowedPatterns: [] (default)

[source,ruby]
----
# bad
10.minutes.to_i
----

[#allowedpatterns_-__min___-lintnumberconversion]
==== AllowedPatterns: ['min*']

[source,ruby]
----
# good
10.minutes.to_i
----

[#allowedclasses_-_time_-datetime_-_default_-lintnumberconversion]
==== AllowedClasses: [Time, DateTime] (default)

[source,ruby]
----
# good
Time.now.to_datetime.to_i
----

[#configurable-attributes-lintnumberconversion]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowedMethods
| `[]`
| Array

| AllowedPatterns
| `[]`
| Array

| AllowedClasses
| `Time`, `DateTime`
| Array
|===

[#lintnumberedparameterassignment]
== Lint/NumberedParameterAssignment

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.9
| -
|===

Checks for uses of numbered parameter assignment.
It emulates the following warning in Ruby 2.7:

  $ ruby -ve '_1 = :value'
  ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19]
  -e:1: warning: `_1' is reserved for numbered parameter; consider another name

Assigning to a numbered parameter (from `_1` to `_9`) causes an error in Ruby 3.0.

  $ ruby -ve '_1 = :value'
  ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
  -e:1: _1 is reserved for numbered parameter

NOTE: The numbered parameters are from `_1` to `_9`. This cop checks `_0`, and over `_10`
as well to prevent confusion.

[#examples-lintnumberedparameterassignment]
=== Examples

[source,ruby]
----
# bad
_1 = :value

# good
non_numbered_parameter_name = :value
----

[#lintnumericoperationwithconstantresult]
== Lint/NumericOperationWithConstantResult

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always (Unsafe)
| 1.69
| 1.88
|===

Certain numeric operations have a constant result, usually 0 or 1.
Multiplying a number by 0 will always return 0.
Dividing a number by itself or raising it to the power of 0 will always return 1.
As such, they can be replaced with that result.
These are probably leftover from debugging, or are mistakes.
Other numeric operations that are similarly leftover from debugging or mistakes
are handled by `Lint/UselessNumericOperation`.

NOTE: This cop doesn't detect offenses for the `-` and `%` operator because it
can't determine the type of `x`. If `x` is an `Array` or `String`, it doesn't perform
a numeric operation.

[#safety-lintnumericoperationwithconstantresult]
=== Safety

This cop is unsafe because the autocorrection drops the operands, which
discards any side effects of evaluating them and can change behavior when
the result is not actually constant. For example, `x / x` raises
`ZeroDivisionError` when `x` is `0`, and returns `Float::NAN` (not `1`)
when `x` is `0.0`; replacing it with `1` silences that.

[#examples-lintnumericoperationwithconstantresult]
=== Examples

[source,ruby]
----
# bad
x * 0

# good
0

# bad
x *= 0

# good
x = 0

# bad
x / x
x ** 0

# good
1

# bad
x /= x
x **= 0

# good
x = 1
----

[#lintorassignmenttoconstant]
== Lint/OrAssignmentToConstant

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| No
| Always (Unsafe)
| 1.9
| -
|===

Checks for unintended or-assignment to a constant.

Constants should always be assigned in the same location. And its value
should always be the same. If constants are assigned in multiple
locations, the result may vary depending on the order of `require`.

[#safety-lintorassignmenttoconstant]
=== Safety

This cop is unsafe because code that is already conditionally
assigning a constant may have its behavior changed by autocorrection.

[#examples-lintorassignmenttoconstant]
=== Examples

[source,ruby]
----
# bad
CONST ||= 1

# good
CONST = 1
----

[#lintorderedmagiccomments]
== Lint/OrderedMagicComments

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 0.53
| 1.37
|===

Checks the proper ordering of magic comments and whether
a magic comment is not placed before a shebang.

[#safety-lintorderedmagiccomments]
=== Safety

This cop's autocorrection is unsafe because file encoding may change.

[#examples-lintorderedmagiccomments]
=== Examples

[source,ruby]
----
# bad

# frozen_string_literal: true
# encoding: ascii
p [''.frozen?, ''.encoding] #=> [true, #<Encoding:UTF-8>]

# good

# encoding: ascii
# frozen_string_literal: true
p [''.frozen?, ''.encoding] #=> [true, #<Encoding:US-ASCII>]

# good

#!/usr/bin/env ruby
# encoding: ascii
# frozen_string_literal: true
p [''.frozen?, ''.encoding] #=> [true, #<Encoding:US-ASCII>]
----

[#lintoutofrangeregexpref]
== Lint/OutOfRangeRegexpRef

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| No
| 0.89
| -
|===

Looks for references of `Regexp` captures that are out of range
and thus always returns nil.

[#safety-lintoutofrangeregexpref]
=== Safety

This cop is unsafe because it is naive in how it determines what
references are available based on the last encountered regexp, but
it cannot handle some cases, such as conditional regexp matches, which
leads to false positives, such as:

[source,ruby]
----
foo ? /(c)(b)/ =~ str : /(b)/ =~ str
do_something if $2
# $2 is defined for the first condition but not the second, however
# the cop will mark this as an offense.
----

This might be a good indication of code that should be refactored,
however.

[#examples-lintoutofrangeregexpref]
=== Examples

[source,ruby]
----
/(foo)bar/ =~ 'foobar'

# bad - always returns nil

puts $2 # => nil

# good

puts $1 # => foo
----

[#lintparenthesesasgroupedexpression]
== Lint/ParenthesesAsGroupedExpression

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.12
| 0.83
|===

Checks for space between the name of a called method and a left
parenthesis.

[#examples-lintparenthesesasgroupedexpression]
=== Examples

[source,ruby]
----
# bad
do_something (foo)

# good
do_something(foo)
do_something (2 + 3) * 4
do_something (foo * bar).baz
----

[#references-lintparenthesesasgroupedexpression]
=== References

* https://rubystyle.guide#parens-no-spaces

[#lintpercentstringarray]
== Lint/PercentStringArray

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| Always (Unsafe)
| 0.41
| -
|===

Checks for quotes and commas in %w, e.g. `%w('foo', "bar")`

It is more likely that the additional characters are unintended (for
example, mistranslating an array of literals to percent string notation)
rather than meant to be part of the resulting strings.

[#safety-lintpercentstringarray]
=== Safety

The cop is unsafe because the correction changes the values in the array
and that might have been done purposely.

[source,ruby]
----
%w('foo', "bar") #=> ["'foo',", '"bar"']
%w(foo bar)      #=> ['foo', 'bar']
----

[#examples-lintpercentstringarray]
=== Examples

[source,ruby]
----
# bad
%w('foo', "bar")

# good
%w(foo bar)
----

[#lintpercentsymbolarray]
== Lint/PercentSymbolArray

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.41
| -
|===

Checks for colons and commas in %i, e.g. `%i(:foo, :bar)`

It is more likely that the additional characters are unintended (for
example, mistranslating an array of literals to percent string notation)
rather than meant to be part of the resulting symbols.

[#examples-lintpercentsymbolarray]
=== Examples

[source,ruby]
----
# bad
%i(:foo, :bar)

# good
%i(foo bar)
----

[#lintraiseexception]
== Lint/RaiseException

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| Always (Unsafe)
| 0.81
| 0.86
|===

Checks for `raise` or `fail` statements which raise `Exception` or
`Exception.new`. Use `StandardError` or a specific exception class instead.

If you have defined your own namespaced `Exception` class, it is possible
to configure the cop to allow it by setting `AllowedImplicitNamespaces` to
an array with the names of the namespaces to allow. By default, this is set to
`['Gem']`, which allows `Gem::Exception` to be raised without an explicit namespace.
If not allowed, a false positive may be registered if `raise Exception` is called
within the namespace.

Alternatively, use a fully qualified name with `raise`/`fail`
(eg. `raise Namespace::Exception`).

[#safety-lintraiseexception]
=== Safety

This cop is unsafe because it will change the exception class being
raised, which is a change in behavior.

[#examples-lintraiseexception]
=== Examples

[source,ruby]
----
# bad
raise Exception, 'Error message here'
raise Exception.new('Error message here')

# good
raise StandardError, 'Error message here'
raise MyError.new, 'Error message here'
----

[#allowedimplicitnamespaces_-__gem__-_default_-lintraiseexception]
==== AllowedImplicitNamespaces: ['Gem'] (default)

[source,ruby]
----
# bad - `Foo` is not an allowed implicit namespace
module Foo
  def self.foo
    raise Exception # This is qualified to `Foo::Exception`.
  end
end

# good
module Gem
  def self.foo
    raise Exception # This is qualified to `Gem::Exception`.
  end
end

# good
module Foo
  def self.foo
    raise Foo::Exception
  end
end
----

[#configurable-attributes-lintraiseexception]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowedImplicitNamespaces
| `Gem`
| Array
|===

[#references-lintraiseexception]
=== References

* https://rubystyle.guide#raise-exception

[#lintrandone]
== Lint/RandOne

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.36
| -
|===

Checks for `rand(1)` calls.
Such calls always return `0`, and so do `rand(-1)`, `rand(1.0)`, and `rand(-1.0)`.

[#examples-lintrandone]
=== Examples

[source,ruby]
----
# bad
rand 1
Kernel.rand(-1)
rand 1.0
rand(-1.0)

# good
0 # just use 0 instead
----

[#lintredundantcopdisabledirective]
== Lint/RedundantCopDisableDirective

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.76
| -
|===

Detects instances of rubocop:disable comments that can be
removed without causing any offenses to be reported. It's implemented
as a cop in that it inherits from the Cop base class and calls
add_offense. The unusual part of its implementation is that it doesn't
have any on_* methods or an investigate method. This means that it
doesn't take part in the investigation phase when the other cops do
their work. Instead, it waits until it's called in a later stage of the
execution. The reason it can't be implemented as a normal cop is that
it depends on the results of all other cops to do its work.

[#examples-lintredundantcopdisabledirective]
=== Examples

[source,ruby]
----
# bad
# rubocop:disable Layout/LineLength
x += 1
# rubocop:enable Layout/LineLength

# good
x += 1
----

[#lintredundantcopenabledirective]
== Lint/RedundantCopEnableDirective

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.76
| -
|===

Detects instances of rubocop:enable comments that can be
removed.

When a comment enables all cops at once `rubocop:enable all`
the cop checks whether any cop was actually enabled.

[#examples-lintredundantcopenabledirective]
=== Examples

[source,ruby]
----
# bad
foo = 1
# rubocop:enable Layout/LineLength

# good
foo = 1

# bad
# rubocop:disable Style/StringLiterals
foo = "1"
# rubocop:enable Style/StringLiterals
baz
# rubocop:enable all

# good
# rubocop:disable Style/StringLiterals
foo = "1"
# rubocop:enable all
baz
----

[#lintredundantdirglobsort]
== Lint/RedundantDirGlobSort

NOTE: Requires Ruby version 3.0

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always (Unsafe)
| 1.8
| 1.26
|===

Sort globbed results by default in Ruby 3.0.
This cop checks for redundant `sort` method to `Dir.glob` and `Dir[]`.

[#safety-lintredundantdirglobsort]
=== Safety

This cop is unsafe, in case of having a file and a directory with
identical names, since directory will be loaded before the file, which
will break `exe/files.rb` that rely on `exe.rb` file.

[#examples-lintredundantdirglobsort]
=== Examples

[source,ruby]
----
# bad
Dir.glob('./lib/**/*.rb').sort.each do |file|
end

Dir['./lib/**/*.rb'].sort.each do |file|
end

# good
Dir.glob('./lib/**/*.rb').each do |file|
end

Dir['./lib/**/*.rb'].each do |file|
end
----

[#lintredundantregexpquantifiers]
== Lint/RedundantRegexpQuantifiers

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.53
| -
|===

Checks for redundant quantifiers inside `Regexp` literals.

It is always allowed when interpolation is used in a regexp literal,
because it's unknown what kind of string will be expanded as a result:

[source,ruby]
----
/(?:a*#{interpolation})?/x
----

[#examples-lintredundantregexpquantifiers]
=== Examples

[source,ruby]
----
# bad
/(?:x+)+/

# good
/(?:x)+/

# good
/(?:x+)/

# bad
/(?:x+)?/

# good
/(?:x)*/

# good
/(?:x*)/
----

[#lintredundantrequirestatement]
== Lint/RedundantRequireStatement

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.76
| 1.73
|===

Checks for unnecessary `require` statement.

The following features are unnecessary `require` statement because
they are already loaded. e.g. Ruby 2.2:

  ruby -ve 'p $LOADED_FEATURES.reject { |feature| %r|/| =~ feature }'
  ruby 2.2.8p477 (2017-09-14 revision 59906) [x86_64-darwin13]
  ["enumerator.so", "rational.so", "complex.so", "thread.rb"]

Below are the features that each `TargetRubyVersion` targets.

  * 2.0+ ... `enumerator`
  * 2.1+ ... `thread`
  * 2.2+ ... Add `rational` and `complex` above
  * 2.7+ ... Add `ruby2_keywords` above
  * 3.1+ ... Add `fiber` above
  * 3.2+ ... Add `set` above
  * 4.0+ ... Add `pathname` above

This cop target those features.

[#examples-lintredundantrequirestatement]
=== Examples

[source,ruby]
----
# bad
require 'unloaded_feature'
require 'thread'

# good
require 'unloaded_feature'
----

[#lintredundantsafenavigation]
== Lint/RedundantSafeNavigation

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| Always (Unsafe)
| 0.93
| 1.79
|===

Checks for redundant safe navigation calls.
Use cases where a constant, named in camel case for classes and modules is `nil` are rare,
and an offense is not detected when the receiver is a constant. The detection also applies
to `self`, and to literal receivers, except for `nil`.

For all receivers, the `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`,
and `equal?` methods are checked by default.
These are customizable with `AllowedMethods` option.

The `AllowedMethods` option specifies nil-safe methods,
in other words, it is a method that is allowed to skip safe navigation.
Note that the `AllowedMethod` option is not an option that specifies methods
for which to suppress (allow) this cop's check.

In the example below, the safe navigation operator (`&.`) is unnecessary
because `NilClass` has methods like `respond_to?` and `is_a?`.

The `InferNonNilReceiver` option specifies whether to look into previous code
paths to infer if the receiver can't be nil. This check is unsafe because the receiver
can be redefined between the safe navigation call and previous regular method call.
It does the inference only in the current scope, e.g. within the same method definition etc.

The `AdditionalNilMethods` option specifies additional custom methods which are
defined on `NilClass`. When `InferNonNilReceiver` is set, they are used to determine
whether the receiver can be nil.

[#safety-lintredundantsafenavigation]
=== Safety

This cop is unsafe, because autocorrection can change the return type of
the expression. An offending expression that previously could return `nil`
will be autocorrected to never return `nil`.

[#examples-lintredundantsafenavigation]
=== Examples

[source,ruby]
----
# bad
CamelCaseConst&.do_something

# good
CamelCaseConst.do_something

# bad
foo.to_s&.strip
foo.to_i&.zero?
foo.to_f&.zero?
foo.to_a&.size
foo.to_h&.size

# good
foo.to_s.strip
foo.to_i.zero?
foo.to_f.zero?
foo.to_a.size
foo.to_h.size

# bad
do_something if attrs&.respond_to?(:[])

# good
do_something if attrs.respond_to?(:[])

# bad
foo&.bar ? foo&.bar.baz : qux

# good
foo&.bar ? foo.bar.baz : qux

# bad
if foo&.bar
  foo&.bar.baz
end

# good
if foo&.bar
  foo.bar.baz
end

# bad
while node&.is_a?(BeginNode)
  node = node.parent
end

# good
while node.is_a?(BeginNode)
  node = node.parent
end

# good - without `&.` this changes the return value for `nil`
foo&.respond_to?(:to_a)
foo&.respond_to?(:class)

# bad - for `nil`s conversion methods return default values for the type
foo&.to_h || {}
foo&.to_h { |k, v| [k, v] } || {}
foo&.to_a || []
foo&.to_i || 0
foo&.to_f || 0.0
foo&.to_s || ''

# good
foo.to_h
foo.to_h { |k, v| [k, v] }
foo.to_a
foo.to_i
foo.to_f
foo.to_s

# bad
self&.foo

# good
self.foo
----

[#allowedmethods_-_nil_safe_method_-lintredundantsafenavigation]
==== AllowedMethods: [nil_safe_method]

[source,ruby]
----
# bad
do_something if attrs&.nil_safe_method(:[])

# good
do_something if attrs.nil_safe_method(:[])
do_something if attrs&.not_nil_safe_method(:[])
----

[#infernonnilreceiver_-false-_default_-lintredundantsafenavigation]
==== InferNonNilReceiver: false (default)

[source,ruby]
----
# good
foo.bar
foo&.baz
----

[#infernonnilreceiver_-true-lintredundantsafenavigation]
==== InferNonNilReceiver: true

[source,ruby]
----
# bad
foo.bar
foo&.baz # would raise on previous line if `foo` is nil

# good
foo.bar
foo.baz

# bad
if foo.condition?
  foo&.bar
end

# good
if foo.condition?
  foo.bar
end

# good (different scopes)
def method1
  foo.bar
end

def method2
  foo&.bar
end
----

[#additionalnilmethods_-_present__-lintredundantsafenavigation]
==== AdditionalNilMethods: [present?]

[source,ruby]
----
# good
foo.present?
foo&.bar
----

[#configurable-attributes-lintredundantsafenavigation]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowedMethods
| `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`, `equal?`
| Array

| InferNonNilReceiver
| `false`
| Boolean

| AdditionalNilMethods
| `present?`, `blank?`, `try`, `try!`
| Array
|===

[#lintredundantsplatexpansion]
== Lint/RedundantSplatExpansion

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.76
| 1.7
|===

Checks for unneeded usages of splat expansion.

[#examples-lintredundantsplatexpansion]
=== Examples

[source,ruby]
----
# bad
a = *[1, 2, 3]
a = *'a'
a = *1
['a', 'b', *%w(c d e), 'f', 'g']

# good
c = [1, 2, 3]
a = *c
a, b = *c
a, *b = *c
a = *1..10
a = ['a']
['a', 'b', 'c', 'd', 'e', 'f', 'g']

# bad
do_something(*['foo', 'bar', 'baz'])

# good
do_something('foo', 'bar', 'baz')

# bad
begin
  foo
rescue *[StandardError, ApplicationError]
  bar
end

# good
begin
  foo
rescue StandardError, ApplicationError
  bar
end

# bad
case foo
when *[1, 2, 3]
  bar
else
  baz
end

# good
case foo
when 1, 2, 3
  bar
else
  baz
end
----

[#allowpercentliteralarrayargument_-true-_default_-lintredundantsplatexpansion]
==== AllowPercentLiteralArrayArgument: true (default)

[source,ruby]
----
# good
do_something(*%w[foo bar baz])
----

[#allowpercentliteralarrayargument_-false-lintredundantsplatexpansion]
==== AllowPercentLiteralArrayArgument: false

[source,ruby]
----
# bad
do_something(*%w[foo bar baz])
----

[#configurable-attributes-lintredundantsplatexpansion]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowPercentLiteralArrayArgument
| `true`
| Boolean
|===

[#lintredundantstringcoercion]
== Lint/RedundantStringCoercion

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.19
| 0.77
|===

Checks for string conversion in string interpolation, `print`, `puts`, and `warn` arguments,
which is redundant.

[#examples-lintredundantstringcoercion]
=== Examples

[source,ruby]
----
# bad
"result is #{something.to_s}"
print something.to_s
puts something.to_s
warn something.to_s

# good
"result is #{something}"
print something
puts something
warn something
----

[#references-lintredundantstringcoercion]
=== References

* https://rubystyle.guide#no-to-s

[#lintredundanttypeconversion]
== Lint/RedundantTypeConversion

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.72
| -
|===

Checks for redundant uses of `to_s`, `to_sym`, `to_i`, `to_f`, `to_d`, `to_r`, `to_c`,
`to_a`, `to_h`, and `to_set`.

When one of these methods is called on an object of the same type, that object
is returned, making the call unnecessary. The cop detects conversion methods called
on object literals, class constructors, class `[]` methods, and the `Kernel` methods
`String()`, `Integer()`, `Float()`, BigDecimal(), `Rational()`, `Complex()`, and `Array()`.

Specifically, these cases are detected for each conversion method:

* `to_s` when called on a string literal, interpolated string, heredoc,
  or with `String.new` or `String()`.
* `to_sym` when called on a symbol literal or interpolated symbol.
* `to_i` when called on an integer literal or with `Integer()`.
* `to_f` when called on a float literal or with `Float()`.
* `to_d` when called with `BigDecimal()`.
* `to_r` when called on a rational literal or with `Rational()`.
* `to_c` when called on a complex literal or with `Complex()`.
* `to_a` when called on an array literal, or with `Array.new`, `Array()` or `Array[]`.
* `to_h` when called on a hash literal, or with `Hash.new`, `Hash()` or `Hash[]`.
* `to_set` when called on `Set.new` or `Set[]`.

In all cases, chaining one of the same `to_*` conversion methods listed above is redundant.

The cop can also register an offense for chaining conversion methods on methods that are
expected to return a specific type regardless of receiver (eg. `foo.inspect.to_s` and
`foo.to_json.to_s`).

[#examples-lintredundanttypeconversion]
=== Examples

[source,ruby]
----
# bad
"text".to_s
:sym.to_sym
42.to_i
8.5.to_f
12r.to_r
1i.to_c
[].to_a
{}.to_h
Set.new.to_set

# good
"text"
:sym
42
8.5
12r
1i
[]
{}
Set.new

# bad
Integer(var).to_i

# good
Integer(var)

# good - chaining to a type constructor with exceptions suppressed
# in this case, `Integer()` could return `nil`
Integer(var, exception: false).to_i

# bad
BigDecimal(var).to_d

# good
BigDecimal(var)

# bad - chaining the same conversion
foo.to_s.to_s

# good
foo.to_s

# bad - chaining a conversion to a method that is expected to return the same type
foo.inspect.to_s
foo.to_json.to_s

# good
foo.inspect
foo.to_json
----

[#lintredundantwithindex]
== Lint/RedundantWithIndex

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.50
| -
|===

Checks for redundant `with_index`.

[#examples-lintredundantwithindex]
=== Examples

[source,ruby]
----
# bad
ary.each_with_index do |v|
  v
end

# good
ary.each do |v|
  v
end

# bad
ary.each.with_index do |v|
  v
end

# good
ary.each do |v|
  v
end
----

[#lintredundantwithobject]
== Lint/RedundantWithObject

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 0.51
| 1.88
|===

Checks for redundant `with_object`.

[#safety-lintredundantwithobject]
=== Safety

This cop's autocorrection is unsafe because the return value changes:
`each_with_object` returns the memo object, while the corrected `each` returns
the receiver. This matters when the result of the expression is used.

[#examples-lintredundantwithobject]
=== Examples

[source,ruby]
----
# bad
ary.each_with_object([]) do |v|
  v
end

# good
ary.each do |v|
  v
end

# bad
ary.each.with_object([]) do |v|
  v
end

# good
ary.each do |v|
  v
end
----

[#lintrefinementimportmethods]
== Lint/RefinementImportMethods

NOTE: Requires Ruby version 3.1

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always (Unsafe)
| 1.27
| 1.88
|===

Checks if `include` or `prepend` is called in `refine` block.
These methods are deprecated and should be replaced with `Refinement#import_methods`.

It emulates deprecation warnings in Ruby 3.1. Functionality has been removed in Ruby 3.2.

[#safety-lintrefinementimportmethods]
=== Safety

This cop's autocorrection is unsafe because `include M` will affect the included class
if any changes are made to module `M`.
On the other hand, `import_methods M` uses a snapshot of method definitions,
thus it will not be affected if module `M` changes.

[#examples-lintrefinementimportmethods]
=== Examples

[source,ruby]
----
# bad
refine Foo do
  include Bar
end

# bad
refine Foo do
  prepend Bar
end

# good
refine Foo do
  import_methods Bar
end
----

[#lintregexpascondition]
== Lint/RegexpAsCondition

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.51
| 0.86
|===

Checks for regexp literals used as `match-current-line`.
If a regexp literal is in condition, the regexp matches `$_` implicitly.

[#examples-lintregexpascondition]
=== Examples

[source,ruby]
----
# bad
if /foo/
  do_something
end

# good
if /foo/ =~ $_
  do_something
end
----

[#lintrequireparentheses]
== Lint/RequireParentheses

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.18
| -
|===

Checks for method calls with at least one argument where no parentheses
are used around the parameter list, and the call could be misread as an
operand of a boolean operator (`&&` or `||`). Two forms are flagged:

* a predicate method whose last argument is a `&&`/`||` expression, and
* any method whose first argument is a ternary expression with a
  `&&`/`||` condition.

The idea behind warning for these constructs is that the user might
be under the impression that the return value from the method call is
an operand of &&/||.

[#examples-lintrequireparentheses]
=== Examples

[source,ruby]
----
# bad
if day.is? :tuesday && month == :jan
  # ...
end

# good
if day.is?(:tuesday) && month == :jan
  # ...
end

# bad
foo a && b ? c : d

# good
foo(a && b ? c : d)
----

[#lintrequirerangeparentheses]
== Lint/RequireRangeParentheses

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.32
| -
|===

Checks that a range literal is enclosed in parentheses when the end of the range is
at a line break.

NOTE: The following is maybe intended for `(42..)`. But, compatible is `42..do_something`.
So, this cop does not provide autocorrection because it is left to user.

[source,ruby]
----
case condition
when 42..
  do_something
end
----

[#examples-lintrequirerangeparentheses]
=== Examples

[source,ruby]
----
# bad - Represents `(1..42)`, not endless range.
1..
42

# good - It's incompatible, but your intentions when using endless range may be:
(1..)
42

# good
1..42

# good
(1..42)

# good
(1..
42)
----

[#lintrequirerelativeselfpath]
== Lint/RequireRelativeSelfPath

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.22
| -
|===

Checks for a file requiring itself with `require_relative`.

[#examples-lintrequirerelativeselfpath]
=== Examples

[source,ruby]
----
# bad

# foo.rb
require_relative 'foo'
require_relative 'bar'

# good

# foo.rb
require_relative 'bar'
----

[#lintrescueexception]
== Lint/RescueException

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.9
| 0.27
|===

Checks for `rescue` blocks targeting the `Exception` class.

[#examples-lintrescueexception]
=== Examples

[source,ruby]
----
# bad
begin
  do_something
rescue Exception
  handle_exception
end

# good
begin
  do_something
rescue ArgumentError
  handle_exception
end
----

[#references-lintrescueexception]
=== References

* https://rubystyle.guide#no-blind-rescues

[#lintrescuetype]
== Lint/RescueType

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.49
| -
|===

Checks for arguments to `rescue` that will result in a `TypeError`
if an exception is raised.

[#examples-lintrescuetype]
=== Examples

[source,ruby]
----
# bad
begin
  bar
rescue nil
  baz
end

# bad
def foo
  bar
rescue 1, 'a', "#{b}", 0.0, [], {}
  baz
end

# good
begin
  bar
rescue
  baz
end

# good
def foo
  bar
rescue NameError
  baz
end
----

[#lintreturninvoidcontext]
== Lint/ReturnInVoidContext

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.50
| -
|===

Checks for the use of a return with a value in a context
where the value will be ignored. (initialize and setter methods)

[#examples-lintreturninvoidcontext]
=== Examples

[source,ruby]
----
# bad
def initialize
  foo
  return :qux if bar?
  baz
end

def foo=(bar)
  return 42
end

# good
def initialize
  foo
  return if bar?
  baz
end

def foo=(bar)
  return
end
----

[#lintsafenavigationchain]
== Lint/SafeNavigationChain

NOTE: Requires Ruby version 2.3

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 0.47
| 1.89
|===

The safe navigation operator returns nil if the receiver is
nil. If you chain an ordinary method call after a safe
navigation operator, it raises NoMethodError. We should use a
safe navigation operator after a safe navigation operator.
This cop checks for the problem outlined above.

[#safety-lintsafenavigationchain]
=== Safety

This cop's autocorrection is unsafe because it changes the behavior of
the code: `x&.foo.bar` raises `NoMethodError` when `x` or `x&.foo` is `nil`,
whereas the corrected `x&.foo&.bar` returns `nil` instead. The autocorrection
also assumes that extending safe navigation through the chain is intended,
while removing the first `&.` may be what was intended instead.

[#examples-lintsafenavigationchain]
=== Examples

[source,ruby]
----
# bad
x&.foo.bar
x&.foo + bar
x&.foo[bar]

# good
x&.foo&.bar
x&.foo || bar
----

[#configurable-attributes-lintsafenavigationchain]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowedMethods
| `present?`, `blank?`, `presence`, `try`, `try!`, `in?`
| Array
|===

[#lintsafenavigationconsistency]
== Lint/SafeNavigationConsistency

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 0.55
| 1.85
|===

Checks that if safe navigation is used in an `&&` or `||` condition,
consistent and appropriate safe navigation, without excess or deficiency,
is used for all method calls on the same object.

[#safety-lintsafenavigationconsistency]
=== Safety

Autocorrection is unsafe because if the receiver is not a local variable
but a method call, it may not be idempotent. For example, replacing
`foo&.bar` with `foo.bar` could raise `NoMethodError` if `foo` returns
`nil` on a subsequent call.

[#examples-lintsafenavigationconsistency]
=== Examples

[source,ruby]
----
# bad
foo&.bar && foo&.baz

# good
foo&.bar && foo.baz

# bad
foo.bar && foo&.baz

# good
foo.bar && foo.baz

# bad
foo&.bar || foo.baz

# good
foo&.bar || foo&.baz

# bad
foo.bar || foo&.baz

# good
foo.bar || foo.baz

# bad
foo&.bar && (foobar.baz || foo&.baz)

# good
foo&.bar && (foobar.baz || foo.baz)
----

[#configurable-attributes-lintsafenavigationconsistency]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowedMethods
| `present?`, `blank?`, `presence`, `try`, `try!`
| Array
|===

[#lintsafenavigationwithempty]
== Lint/SafeNavigationWithEmpty

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.62
| 0.87
|===

Checks to make sure safe navigation isn't used with `empty?` in
a conditional.

While the safe navigation operator is generally a good idea, when
checking `foo&.empty?` in a conditional, `foo` being `nil` will actually
do the opposite of what the author intends.

[#examples-lintsafenavigationwithempty]
=== Examples

[source,ruby]
----
# bad
return if foo&.empty?
return unless foo&.empty?

# good
return if foo && foo.empty?
return unless foo && foo.empty?
----

[#lintscriptpermission]
== Lint/ScriptPermission

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.49
| 0.50
|===

Checks if a file which has a shebang line as
its first line is granted execute permission.

[#examples-lintscriptpermission]
=== Examples

[source,ruby]
----
# bad

# A file which has a shebang line as its first line is not
# granted execute permission.

#!/usr/bin/env ruby
puts 'hello, world'

# good

# A file which has a shebang line as its first line is
# granted execute permission.

#!/usr/bin/env ruby
puts 'hello, world'

# good

# A file which has not a shebang line as its first line is not
# granted execute permission.

puts 'hello, world'
----

[#lintselfassignment]
== Lint/SelfAssignment

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.89
| -
|===

Checks for self-assignments.

[#examples-lintselfassignment]
=== Examples

[source,ruby]
----
# bad
foo = foo
foo, bar = foo, bar
Foo = Foo
hash['foo'] = hash['foo']
obj.attr = obj.attr

# good
foo = bar
foo, bar = bar, foo
Foo = Bar
hash['foo'] = hash['bar']
obj.attr = obj.attr2

# good (method calls possibly can return different results)
hash[foo] = hash[foo]
----

[#allowrbsinlineannotation_-false-_default_-lintselfassignment]
==== AllowRBSInlineAnnotation: false (default)

[source,ruby]
----
# bad
foo = foo #: Integer
foo, bar = foo, bar #: Integer
Foo = Foo #: Integer
hash['foo'] = hash['foo'] #: Integer
obj.attr = obj.attr #: Integer
----

[#allowrbsinlineannotation_-true-lintselfassignment]
==== AllowRBSInlineAnnotation: true

[source,ruby]
----
# good
foo = foo #: Integer
foo, bar = foo, bar #: Integer
Foo = Foo #: Integer
hash['foo'] = hash['foo'] #: Integer
obj.attr = obj.attr #: Integer
----

[#configurable-attributes-lintselfassignment]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowRBSInlineAnnotation
| `false`
| Boolean
|===

[#lintsendwithmixinargument]
== Lint/SendWithMixinArgument

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.75
| -
|===

Checks for `send`, `public_send`, and `__send__` methods
when using mix-in.

`include` and `prepend` methods were private methods until Ruby 2.0,
they were mixed-in via `send` method. This cop uses Ruby 2.1 or
higher style that can be called by public methods.
And `extend` method that was originally a public method is also targeted
for style unification.

[#examples-lintsendwithmixinargument]
=== Examples

[source,ruby]
----
# bad
Foo.send(:include, Bar)
Foo.send(:prepend, Bar)
Foo.send(:extend, Bar)

# bad
Foo.public_send(:include, Bar)
Foo.public_send(:prepend, Bar)
Foo.public_send(:extend, Bar)

# bad
Foo.__send__(:include, Bar)
Foo.__send__(:prepend, Bar)
Foo.__send__(:extend, Bar)

# good
Foo.include Bar
Foo.prepend Bar
Foo.extend Bar
----

[#lintshadowedargument]
== Lint/ShadowedArgument

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.52
| -
|===

Checks for shadowed arguments.

This cop has `IgnoreImplicitReferences` configuration option.
It means argument shadowing is used in order to pass parameters
to zero arity `super` when `IgnoreImplicitReferences` is `true`.

[#examples-lintshadowedargument]
=== Examples

[source,ruby]
----
# bad
do_something do |foo|
  foo = 42
  puts foo
end

def do_something(foo)
  foo = 42
  puts foo
end

# good
do_something do |foo|
  foo = foo + 42
  puts foo
end

def do_something(foo)
  foo = foo + 42
  puts foo
end

def do_something(foo)
  puts foo
end
----

[#ignoreimplicitreferences_-false-_default_-lintshadowedargument]
==== IgnoreImplicitReferences: false (default)

[source,ruby]
----
# bad
def do_something(foo)
  foo = 42
  super
end

def do_something(foo)
  foo = super
  bar
end
----

[#ignoreimplicitreferences_-true-lintshadowedargument]
==== IgnoreImplicitReferences: true

[source,ruby]
----
# good
def do_something(foo)
  foo = 42
  super
end

def do_something(foo)
  foo = super
  bar
end
----

[#configurable-attributes-lintshadowedargument]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| IgnoreImplicitReferences
| `false`
| Boolean
|===

[#lintshadowedexception]
== Lint/ShadowedException

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.41
| -
|===

Checks for a rescued exception that gets shadowed by a
less specific exception being rescued before a more specific
exception is rescued.

An exception is considered shadowed if it is rescued after its
ancestor is, or if it and its ancestor are both rescued in the
same `rescue` statement. In both cases, the more specific rescue is
unnecessary because it is covered by rescuing the less specific
exception. (ie. `rescue Exception, StandardError` has the same behavior
whether `StandardError` is included or not, because all ``StandardError``s
are rescued by `rescue Exception`).

[#examples-lintshadowedexception]
=== Examples

[source,ruby]
----
# bad

begin
  something
rescue Exception
  handle_exception
rescue StandardError
  handle_standard_error
end

# bad
begin
  something
rescue Exception, StandardError
  handle_error
end

# good

begin
  something
rescue StandardError
  handle_standard_error
rescue Exception
  handle_exception
end

# good, however depending on runtime environment.
#
# This is a special case for system call errors.
# System dependent error code depends on runtime environment.
# For example, whether `Errno::EAGAIN` and `Errno::EWOULDBLOCK` are
# the same error code or different error code depends on environment.
# This good case is for `Errno::EAGAIN` and `Errno::EWOULDBLOCK` with
# the same error code.
begin
  something
rescue Errno::EAGAIN, Errno::EWOULDBLOCK
  handle_standard_error
end
----

[#lintshadowingouterlocalvariable]
== Lint/ShadowingOuterLocalVariable

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Disabled
| Yes
| No
| 0.9
| 1.76
|===

Checks for the use of local variable names from an outer scope
in block arguments or block-local variables. This mirrors the warning
given by `ruby -cw` prior to Ruby 2.6:
"shadowing outer local variable - foo".

The cop is now disabled by default to match the upstream Ruby behavior.
It's useful, however, if you'd like to avoid shadowing variables from outer
scopes, which some people consider an anti-pattern that makes it harder
to keep track of what's going on in a program.

NOTE: Shadowing of variables in block passed to `Ractor.new` is allowed
because `Ractor` should not access outer variables.
eg. following style is encouraged:

[source,ruby]
----
worker_id, pipe = env
Ractor.new(worker_id, pipe) do |worker_id, pipe|
end
----

[#examples-lintshadowingouterlocalvariable]
=== Examples

[source,ruby]
----
# bad
def some_method
  foo = 1

  2.times do |foo| # shadowing outer `foo`
    do_something(foo)
  end
end

# good
def some_method
  foo = 1

  2.times do |bar|
    do_something(bar)
  end
end
----

[#lintsharedmutabledefault]
== Lint/SharedMutableDefault

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.70
| -
|===

Checks for `Hash` creation with a mutable default value.
Creating a `Hash` in such a way will share the default value
across all keys, causing unexpected behavior when modifying it.

For example, when the `Hash` was created with an `Array` as the argument,
calling `hash[:foo] << 'bar'` will also change the value of all
other keys that have not been explicitly assigned to.

[#examples-lintsharedmutabledefault]
=== Examples

[source,ruby]
----
# bad
Hash.new([])
Hash.new({})
Hash.new(Array.new)
Hash.new(Hash.new)

# okay -- In rare cases that intentionally have this behavior,
#   without disabling the cop, you can set the default explicitly.
h = Hash.new
h.default = []
h[:a] << 1
h[:b] << 2
h # => {:a => [1, 2], :b => [1, 2]}

# okay -- beware this will discard mutations and only remember assignments
Hash.new { Array.new }
Hash.new { Hash.new }
Hash.new { {} }
Hash.new { [] }

# good - frozen solution will raise an error when mutation attempted
Hash.new([].freeze)
Hash.new({}.freeze)

# good - using a proc will create a new object for each key
h = Hash.new
h.default_proc = ->(h, k) { [] }
h.default_proc = ->(h, k) { {} }

# good - using a block will create a new object for each key
Hash.new { |h, k| h[k] = [] }
Hash.new { |h, k| h[k] = {} }
----

[#references-lintsharedmutabledefault]
=== References

* https://rubystyle.guide#no-mutable-defaults

[#lintstructnewoverride]
== Lint/StructNewOverride

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.81
| -
|===

Checks unexpected overrides of the `Struct` built-in methods
via `Struct.new`.

[#examples-lintstructnewoverride]
=== Examples

[source,ruby]
----
# bad
Bad = Struct.new(:members, :clone, :count)
b = Bad.new([], true, 1)
b.members #=> [] (overriding `Struct#members`)
b.clone #=> true (overriding `Object#clone`)
b.count #=> 1 (overriding `Enumerable#count`)

# good
Good = Struct.new(:id, :name)
g = Good.new(1, "foo")
g.members #=> [:id, :name]
g.clone #=> #<struct Good id=1, name="foo">
g.count #=> 2
----

[#lintsuppressedexception]
== Lint/SuppressedException

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.9
| 1.12
|===

Checks for `rescue` blocks with no body.

[#examples-lintsuppressedexception]
=== Examples

[source,ruby]
----
# bad
def some_method
  do_something
rescue
end

# bad
begin
  do_something
rescue
end

# good
def some_method
  do_something
rescue
  handle_exception
end

# good
begin
  do_something
rescue
  handle_exception
end
----

[#allowcomments_-true-_default_-lintsuppressedexception]
==== AllowComments: true (default)

[source,ruby]
----
# good
def some_method
  do_something
rescue
  # do nothing
end

# good
begin
  do_something
rescue
  # do nothing
end
----

[#allowcomments_-false-lintsuppressedexception]
==== AllowComments: false

[source,ruby]
----
# bad
def some_method
  do_something
rescue
  # do nothing
end

# bad
begin
  do_something
rescue
  # do nothing
end
----

[#allownil_-true-_default_-lintsuppressedexception]
==== AllowNil: true (default)

[source,ruby]
----
# good
def some_method
  do_something
rescue
  nil
end

# good
begin
  do_something
rescue
  # do nothing
end

# good
do_something rescue nil
----

[#allownil_-false-lintsuppressedexception]
==== AllowNil: false

[source,ruby]
----
# bad
def some_method
  do_something
rescue
  nil
end

# bad
begin
  do_something
rescue
  nil
end

# bad
do_something rescue nil
----

[#configurable-attributes-lintsuppressedexception]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowComments
| `true`
| Boolean

| AllowNil
| `true`
| Boolean
|===

[#references-lintsuppressedexception]
=== References

* https://rubystyle.guide#dont-hide-exceptions

[#lintsuppressedexceptioninnumberconversion]
== Lint/SuppressedExceptionInNumberConversion

NOTE: Requires Ruby version 2.6

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always (Unsafe)
| 1.72
| -
|===

Checks for cases where exceptions unrelated to the numeric constructors `Integer()`,
`Float()`, `BigDecimal()`, `Complex()`, and `Rational()` may be unintentionally swallowed.

[#safety-lintsuppressedexceptioninnumberconversion]
=== Safety

The cop is unsafe for autocorrection because unexpected errors occurring in the argument
passed to numeric constructor (e.g., `Integer()`) can lead to incompatible behavior.
For example, changing it to `Integer(potential_exception_method_call, exception: false)`
ensures that exceptions raised by `potential_exception_method_call` are not ignored.

[source,ruby]
----
Integer(potential_exception_method_call) rescue nil
----

[#examples-lintsuppressedexceptioninnumberconversion]
=== Examples

[source,ruby]
----
# bad
Integer(arg) rescue nil

# bad
begin
  Integer(arg)
rescue
  nil
end

# bad
begin
  Integer(arg)
rescue
end

# good
Integer(arg, exception: false)
----

[#lintsymbolconversion]
== Lint/SymbolConversion

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.9
| 1.16
|===

Checks for uses of literal strings converted to
a symbol where a literal symbol could be used instead.

There are two possible styles for this cop.
`strict` (default) will register an offense for any incorrect usage.
`consistent` additionally requires hashes to use the same style for
every symbol key (ie. if any symbol key needs to be quoted it requires
all keys to be quoted).

[#examples-lintsymbolconversion]
=== Examples

[source,ruby]
----
# bad
'string'.to_sym
:symbol.to_sym
'underscored_string'.to_sym
:'underscored_symbol'
'hyphenated-string'.to_sym
"string_#{interpolation}".to_sym

# good
:string
:symbol
:underscored_string
:underscored_symbol
:'hyphenated-string'
:"string_#{interpolation}"
----

[#enforcedstyle_-strict-_default_-lintsymbolconversion]
==== EnforcedStyle: strict (default)

[source,ruby]
----
# bad
{
  'a': 1,
  "b": 2,
  'c-d': 3
}

# good (don't quote keys that don't require quoting)
{
  a: 1,
  b: 2,
  'c-d': 3
}
----

[#enforcedstyle_-consistent-lintsymbolconversion]
==== EnforcedStyle: consistent

[source,ruby]
----
# bad
{
  a: 1,
  'b-c': 2
}

# good (quote all keys if any need quoting)
{
  'a': 1,
  'b-c': 2
}

# good (no quoting required)
{
  a: 1,
  b: 2
}
----

[#configurable-attributes-lintsymbolconversion]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `strict`
| `strict`, `consistent`
|===

[#lintsyntax]
== Lint/Syntax

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.9
| -
|===

Repacks Parser's diagnostics/errors
into RuboCop's offenses.

[#linttoenumarguments]
== Lint/ToEnumArguments

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.1
| -
|===

Ensures that `to_enum`/`enum_for`, called for the current method,
has correct arguments.

[#examples-linttoenumarguments]
=== Examples

[source,ruby]
----
# bad
def foo(x, y = 1)
  return to_enum(__callee__, x) # `y` is missing
end

# good
def foo(x, y = 1)
  # Alternatives to `__callee__` are `__method__` and `:foo`.
  return to_enum(__callee__, x, y)
end

# good
def foo(x, y = 1)
  # It is also allowed if it is wrapped in some method like Sorbet.
  return to_enum(T.must(__callee__), x, y)
end
----

[#linttojson]
== Lint/ToJSON

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.66
| -
|===

Checks to make sure `#to_json` includes an optional argument.
When overriding `#to_json`, callers may invoke JSON
generation via `JSON.generate(your_obj)`. Since `JSON#generate` allows
for an optional argument, your method should too.

[#examples-linttojson]
=== Examples

[source,ruby]
----
# bad - incorrect arity
def to_json
  JSON.generate([x, y])
end

# good - preserving args
def to_json(*args)
  JSON.generate([x, y], *args)
end

# good - discarding args
def to_json(*_args)
  JSON.generate([x, y])
end
----

[#linttoplevelreturnwithargument]
== Lint/TopLevelReturnWithArgument

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.89
| -
|===

Checks for top level return with arguments. If there is a
top-level return statement with an argument, then the argument is
always ignored. This is detected automatically since Ruby 2.7.

[#examples-linttoplevelreturnwithargument]
=== Examples

[source,ruby]
----
# bad
return 1

# good
return
----

[#configurable-attributes-linttoplevelreturnwithargument]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| Exclude
| `+**/*.jb+`
| Array
|===

[#linttrailingcommainattributedeclaration]
== Lint/TrailingCommaInAttributeDeclaration

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 0.90
| 1.61
|===

Checks for trailing commas in attribute declarations, such as
`#attr_reader`. Leaving a trailing comma will nullify the next method
definition by overriding it with a getter method.

[#examples-linttrailingcommainattributedeclaration]
=== Examples

[source,ruby]
----
# bad
class Foo
  attr_reader :foo,

  def bar
    puts "Unreachable."
  end
end

# good
class Foo
  attr_reader :foo

  def bar
    puts "No problem!"
  end
end
----

[#linttriplequotes]
== Lint/TripleQuotes

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.9
| -
|===

Checks for "triple quotes" (strings delimited by any odd number
of quotes greater than 1).

Ruby allows multiple strings to be implicitly concatenated by just
being adjacent in a statement (ie. `"foo""bar" == "foobar"`). This sometimes
gives the impression that there is something special about triple quotes, but
in fact it is just extra unnecessary quotes and produces the same string. Each
pair of quotes produces an additional concatenated empty string, so the result
is still only the "actual" string within the delimiters.

NOTE: Although this cop is called triple quotes, the same behavior is present
for strings delimited by 5, 7, etc. quotation marks.

[#examples-linttriplequotes]
=== Examples

[source,ruby]
----
# bad
"""
  A string
"""

# bad
'''
  A string
'''

# good
"
  A string
"

# good
<<STRING
  A string
STRING

# good (but not the same spacing as the bad case)
'A string'
----

[#lintunderscoreprefixedvariablename]
== Lint/UnderscorePrefixedVariableName

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.21
| -
|===

Checks for underscore-prefixed variables that are actually
used.

Since block keyword arguments cannot be arbitrarily named at call
sites, the `AllowKeywordBlockArguments` will allow use of underscore-
prefixed block keyword arguments.

[#examples-lintunderscoreprefixedvariablename]
=== Examples

[#allowkeywordblockarguments_-false-_default_-lintunderscoreprefixedvariablename]
==== AllowKeywordBlockArguments: false (default)

[source,ruby]
----
# bad

[1, 2, 3].each do |_num|
  do_something(_num)
end

query(:sales) do |_id:, revenue:, cost:|
  {_id: _id, profit: revenue - cost}
end

# good

[1, 2, 3].each do |num|
  do_something(num)
end

[1, 2, 3].each do |_num|
  do_something # not using `_num`
end
----

[#allowkeywordblockarguments_-true-lintunderscoreprefixedvariablename]
==== AllowKeywordBlockArguments: true

[source,ruby]
----
# good

query(:sales) do |_id:, revenue:, cost:|
  {_id: _id, profit: revenue - cost}
end
----

[#configurable-attributes-lintunderscoreprefixedvariablename]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowKeywordBlockArguments
| `false`
| Boolean
|===

[#lintunescapedbracketinregexp]
== Lint/UnescapedBracketInRegexp

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.68
| -
|===

Checks for Regexps (both literals and via `Regexp.new` / `Regexp.compile`)
that contain unescaped `]` characters.

It emulates the following Ruby warning:

[source,ruby]
----
$ ruby -e '/abc]123/'
-e:1: warning: regular expression has ']' without escape: /abc]123/
----

[#examples-lintunescapedbracketinregexp]
=== Examples

[source,ruby]
----
# bad
/abc]123/
%r{abc]123}
Regexp.new('abc]123')
Regexp.compile('abc]123')

# good
/abc\]123/
%r{abc\]123}
Regexp.new('abc\]123')
Regexp.compile('abc\]123')
----

[#lintunexpectedblockarity]
== Lint/UnexpectedBlockArity

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| No
| No
| 1.5
| -
|===

Checks for a block that is known to need more positional
block arguments than are given (by default this is configured for
`Enumerable` methods needing 2 arguments). Optional arguments are allowed,
although they don't generally make sense as the default value will
be used. Blocks that have no receiver, or take splatted arguments
(ie. `*args`) are always accepted.

Keyword arguments (including `**kwargs`) do not get counted towards
this, as they are not used by the methods in question.

Method names and their expected arity can be configured like this:

[source,yaml]
----
Methods:
  inject: 2
  reduce: 2
----

[#safety-lintunexpectedblockarity]
=== Safety

This cop matches for method names only and hence cannot tell apart
methods with same name in different classes, which may lead to a
false positive.

[#examples-lintunexpectedblockarity]
=== Examples

[source,ruby]
----
# bad
values.reduce {}
values.min { |a| a }
values.sort { |a; b| a + b }

# good
values.reduce { |memo, obj| memo << obj }
values.min { |a, b| a <=> b }
values.sort { |*x| x[0] <=> x[1] }
----

[#configurable-attributes-lintunexpectedblockarity]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| Methods
| `{"chunk_while" => 2, "each_with_index" => 2, "each_with_object" => 2, "inject" => 2, "max" => 2, "min" => 2, "minmax" => 2, "reduce" => 2, "slice_when" => 2, "sort" => 2}`
| 
|===

[#lintunifiedinteger]
== Lint/UnifiedInteger

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.43
| -
|===

Checks for using Fixnum or Bignum constant.

[#examples-lintunifiedinteger]
=== Examples

[source,ruby]
----
# bad
1.is_a?(Fixnum)
1.is_a?(Bignum)

# good
1.is_a?(Integer)
----

[#lintunmodifiedreduceaccumulator]
== Lint/UnmodifiedReduceAccumulator

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.1
| 1.5
|===

Looks for `reduce` or `inject` blocks where the value returned (implicitly or
explicitly) does not include the accumulator. A block is considered valid as
long as at least one return value includes the accumulator.

If the accumulator is not included in the return value, then the entire
block will just return a transformation of the last element value, and
could be rewritten as such without a loop.

Also catches instances where an index of the accumulator is returned, as
this may change the type of object being retained.

NOTE: For the purpose of reducing false positives, this cop only flags
returns in `reduce` blocks where the element is the only variable in
the expression (since we will not be able to tell what other variables
relate to via static analysis).

[#examples-lintunmodifiedreduceaccumulator]
=== Examples

[source,ruby]
----
# bad
(1..4).reduce(0) do |acc, el|
  el * 2
end

# bad, may raise a NoMethodError after the first iteration
%w(a b c).reduce({}) do |acc, letter|
  acc[letter] = true
end

# good
(1..4).reduce(0) do |acc, el|
  acc + el * 2
end

# good, element is returned but modified using the accumulator
values.reduce do |acc, el|
  el << acc
  el
end

# good, returns the accumulator instead of the index
%w(a b c).reduce({}) do |acc, letter|
  acc[letter] = true
  acc
end

# good, at least one branch returns the accumulator
values.reduce(nil) do |result, value|
  break result if something?
  value
end

# good, recursive
keys.reduce(self) { |result, key| result[key] }

# ignored as the return value cannot be determined
enum.reduce do |acc, el|
  x = foo(acc, el)
  bar(x)
end
----

[#lintunreachablecode]
== Lint/UnreachableCode

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.9
| -
|===

Checks for unreachable code.
The check is based on the presence of flow-of-control
statements in non-final position in `begin` (implicit) blocks.

[#examples-lintunreachablecode]
=== Examples

[source,ruby]
----
# bad
def some_method
  return
  do_something
end

# bad
def some_method
  if cond
    return
  else
    return
  end
  do_something
end

# good
def some_method
  do_something
end
----

[#lintunreachableloop]
== Lint/UnreachableLoop

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.89
| 1.7
|===

Checks for loops that will have at most one iteration.

A loop that can never reach the second iteration is a possible error in the code.
In rare cases where only one iteration (or at most one iteration) is intended behavior,
the code should be refactored to use `if` conditionals.

NOTE: Block methods that are used with ``Enumerable``s are considered to be loops.

`AllowedPatterns` can be used to match against the block receiver in order to allow
code that would otherwise be registered as an offense (eg. `times` used not in an
`Enumerable` context).

[#examples-lintunreachableloop]
=== Examples

[source,ruby]
----
# bad
while node
  do_something(node)
  node = node.parent
  break
end

# good
while node
  do_something(node)
  node = node.parent
end

# bad
def verify_list(head)
  item = head
  begin
    if verify(item)
      return true
    else
      return false
    end
  end while(item)
end

# good
def verify_list(head)
  item = head
  begin
    if verify(item)
      item = item.next
    else
      return false
    end
  end while(item)

  true
end

# bad
def find_something(items)
  items.each do |item|
    if something?(item)
      return item
    else
      raise NotFoundError
    end
  end
end

# good
def find_something(items)
  items.each do |item|
    if something?(item)
      return item
    end
  end
  raise NotFoundError
end

# bad
2.times { raise ArgumentError }
----

[#allowedpatterns_-___exactly_at_least_at_most____d_____times__-_default_-lintunreachableloop]
==== AllowedPatterns: ['(exactly|at_least|at_most)\(\d+\)\.times'] (default)

[source,ruby]
----
# good
exactly(2).times { raise StandardError }
----

[#configurable-attributes-lintunreachableloop]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowedPatterns
| `(?-mix:(exactly\|at_least\|at_most)\(\d+\)\.times)`
| Array
|===

[#lintunreachablepatternbranch]
== Lint/UnreachablePatternBranch

NOTE: Requires Ruby version 2.7

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.85
| -
|===

Checks for unreachable `in` pattern branches in `case...in` statements.

An `in` branch is unreachable when a previous branch uses an unguarded
catch-all pattern that matches any value unconditionally. Any `in` branches
(and `else`) that follow such a catch-all are dead code.

A catch-all pattern is one of:

* A bare variable capture (`in x`)
* An underscore (`in _`)
* A pattern alias where the left side is a catch-all (`in _ => y`)
* An alternation pattern where at least one alternative is a catch-all
  (`in _ | Integer`)

NOTE: A catch-all pattern with a guard clause (e.g., `in _ if condition`)
does NOT make subsequent branches unreachable because the guard might
not be satisfied.

[#examples-lintunreachablepatternbranch]
=== Examples

[source,ruby]
----
# bad
case value
in Integer
  handle_integer
in x
  handle_other
in String
  handle_string
else
  handle_else
end

# good
case value
in Integer
  handle_integer
in String
  handle_string
in x
  handle_other
end

# bad - else is unreachable after catch-all
case value
in Integer
  handle_integer
in _
  handle_other
else
  handle_else
end

# good - guard clause means catch-all might not match
case value
in x if x.positive?
  handle_positive
in Integer
  handle_integer
else
  handle_other
end
----

[#lintunusedblockargument]
== Lint/UnusedBlockArgument

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 0.21
| 1.61
|===

Checks for unused block arguments.

[#examples-lintunusedblockargument]
=== Examples

[source,ruby]
----
# bad
do_something do |used, unused|
  puts used
end

do_something do |bar|
  puts :foo
end

define_method(:foo) do |bar|
  puts :baz
end

# good
do_something do |used, _unused|
  puts used
end

do_something do
  puts :foo
end

define_method(:foo) do |_bar|
  puts :baz
end
----

[#ignoreemptyblocks_-true-_default_-lintunusedblockargument]
==== IgnoreEmptyBlocks: true (default)

[source,ruby]
----
# good
do_something { |unused| }
----

[#ignoreemptyblocks_-false-lintunusedblockargument]
==== IgnoreEmptyBlocks: false

[source,ruby]
----
# bad
do_something { |unused| }
----

[#allowunusedkeywordarguments_-false-_default_-lintunusedblockargument]
==== AllowUnusedKeywordArguments: false (default)

[source,ruby]
----
# bad
do_something do |unused: 42|
  foo
end
----

[#allowunusedkeywordarguments_-true-lintunusedblockargument]
==== AllowUnusedKeywordArguments: true

[source,ruby]
----
# good
do_something do |unused: 42|
  foo
end
----

[#configurable-attributes-lintunusedblockargument]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| IgnoreEmptyBlocks
| `true`
| Boolean

| AllowUnusedKeywordArguments
| `false`
| Boolean
|===

[#references-lintunusedblockargument]
=== References

* https://rubystyle.guide#underscore-unused-vars

[#lintunusedmethodargument]
== Lint/UnusedMethodArgument

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 0.21
| 1.69
|===

Checks for unused method arguments.

[#examples-lintunusedmethodargument]
=== Examples

[source,ruby]
----
# bad
def some_method(used, unused, _unused_but_allowed)
  puts used
end

# good
def some_method(used, _unused, _unused_but_allowed)
  puts used
end
----

[#allowunusedkeywordarguments_-false-_default_-lintunusedmethodargument]
==== AllowUnusedKeywordArguments: false (default)

[source,ruby]
----
# bad
def do_something(used, unused: 42)
  used
end
----

[#allowunusedkeywordarguments_-true-lintunusedmethodargument]
==== AllowUnusedKeywordArguments: true

[source,ruby]
----
# good
def do_something(used, unused: 42)
  used
end
----

[#ignoreemptymethods_-true-_default_-lintunusedmethodargument]
==== IgnoreEmptyMethods: true (default)

[source,ruby]
----
# good
def do_something(unused)
end
----

[#ignoreemptymethods_-false-lintunusedmethodargument]
==== IgnoreEmptyMethods: false

[source,ruby]
----
# bad
def do_something(unused)
end
----

[#ignorenotimplementedmethods_-true-_default_-lintunusedmethodargument]
==== IgnoreNotImplementedMethods: true (default)

[source,ruby]
----
# with default value of `NotImplementedExceptions: ['NotImplementedError']`

# good
def do_something(unused)
  raise NotImplementedError
end

def do_something_else(unused)
  fail "TODO"
end
----

[#ignorenotimplementedmethods_-true-lintunusedmethodargument]
==== IgnoreNotImplementedMethods: true

[source,ruby]
----
# with `NotImplementedExceptions: ['AbstractMethodError']`

# good
def do_something(unused)
  raise AbstractMethodError
end
----

[#ignorenotimplementedmethods_-false-lintunusedmethodargument]
==== IgnoreNotImplementedMethods: false

[source,ruby]
----
# bad
def do_something(unused)
  raise NotImplementedError
end

def do_something_else(unused)
  fail "TODO"
end
----

[#configurable-attributes-lintunusedmethodargument]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowUnusedKeywordArguments
| `false`
| Boolean

| IgnoreEmptyMethods
| `true`
| Boolean

| IgnoreNotImplementedMethods
| `true`
| Boolean

| NotImplementedExceptions
| `NotImplementedError`
| Array
|===

[#references-lintunusedmethodargument]
=== References

* https://rubystyle.guide#underscore-unused-vars

[#lintunusedprivatemethod]
== Lint/UnusedPrivateMethod

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Disabled
| Yes
| No
| 1.89
| -
|===

Checks for private instance methods that are not referenced anywhere
in the project.

The check is powered by the project-wide index, so it only runs when
`AllCops/UseProjectIndex` is enabled and the `rubydex` gem is installed.
Without the index the cop does nothing.

A method counts as referenced when a call with its name appears anywhere
in the indexed project (regardless of the receiver), when it is the source
of an `alias`, or when its name appears in the same file as a symbol or
inside a string literal (covering `send(:name)` and declarative DSLs like
`before_action :name`). Methods defined in classes or modules with
descendants are not checked, since they may be invoked through `super`
or inherited dispatch, and neither are methods whose names are built
dynamically (e.g. `send("do_#{action}")`).

The cop is disabled by default because symbol-based references from
*other* files (e.g. a Rails callback declared in a concern) cannot be
detected and would be reported as false positives. It is best suited
for occasional dead-code sweeps rather than permanent enforcement.

[#examples-lintunusedprivatemethod]
=== Examples

[source,ruby]
----
# bad - `helper` is never referenced anywhere in the project
class Service
  def call
    do_something
  end

  private

  def helper
  end
end

# good
class Service
  def call
    do_something(helper)
  end

  private

  def helper
  end
end
----

[#linturiescapeunescape]
== Lint/UriEscapeUnescape

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.50
| -
|===

Identifies places where `URI.escape` can be replaced by
`CGI.escape`, `URI.encode_www_form`, or `URI.encode_www_form_component`
depending on your specific use case.
Also this cop identifies places where `URI.unescape` can be replaced by
`CGI.unescape`, `URI.decode_www_form`,
or `URI.decode_www_form_component` depending on your specific use case.

[#examples-linturiescapeunescape]
=== Examples

[source,ruby]
----
# bad
URI.escape('http://example.com')
URI.encode('http://example.com')

# good
CGI.escape('http://example.com')
URI.encode_uri_component(uri) # Since Ruby 3.1
URI.encode_www_form([['example', 'param'], ['lang', 'en']])
URI.encode_www_form(page: 10, locale: 'en')
URI.encode_www_form_component('http://example.com')

# bad
URI.unescape(enc_uri)
URI.decode(enc_uri)

# good
CGI.unescape(enc_uri)
URI.decode_uri_component(uri) # Since Ruby 3.1
URI.decode_www_form(enc_uri)
URI.decode_www_form_component(enc_uri)
----

[#linturiregexp]
== Lint/UriRegexp

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 0.50
| -
|===

Identifies places where `URI.regexp` is obsolete and should not be used.

For Ruby 3.3 or lower, use `URI::DEFAULT_PARSER.make_regexp`.
For Ruby 3.4 or higher, use `URI::RFC2396_PARSER.make_regexp`.

NOTE: If you need to support both Ruby 3.3 and lower as well as Ruby 3.4 and higher,
consider manually changing the code as follows:

[source,ruby]
----
defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
----

[#examples-linturiregexp]
=== Examples

[source,ruby]
----
# bad
URI.regexp('http://example.com')

# good - Ruby 3.3 or lower
URI::DEFAULT_PARSER.make_regexp('http://example.com')

# good - Ruby 3.4 or higher
URI::RFC2396_PARSER.make_regexp('http://example.com')
----

[#lintuselessaccessmodifier]
== Lint/UselessAccessModifier

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 0.20
| 1.61
|===

Checks for redundant access modifiers, including those with no
code, those which are repeated, those which are on top-level, 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-lintuselessaccessmodifier]
=== Examples

[source,ruby]
----
# 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

# bad
private # this is useless (access modifiers have no effect on top-level)

def method
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-lintuselessaccessmodifier]
==== ContextCreatingMethods: concerning

[source,ruby]
----
# 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-lintuselessaccessmodifier]
==== MethodCreatingMethods: delegate

[source,ruby]
----
# 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
----

[#configurable-attributes-lintuselessaccessmodifier]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| ContextCreatingMethods
| `[]`
| Array

| MethodCreatingMethods
| `[]`
| Array
|===

[#lintuselessassignment]
== Lint/UselessAssignment

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 0.11
| 1.66
|===

Checks for every useless assignment to local variable in every
scope.
The basic idea for this cop was from the warning of `ruby -cw`:

[source,console]
----
assigned but unused variable - foo
----

Currently this cop has advanced logic that detects unreferenced
reassignments and properly handles varied cases such as branch, loop,
rescue, ensure, etc.

This cop's autocorrection avoids cases like `a ||= 1` because removing assignment from
operator assignment can cause `NameError` if this assignment has been used to declare
a local variable. For example, replacing `a ||= 1` with `a || 1` may cause
"undefined local variable or method `a' for main:Object (NameError)".

NOTE: Given the assignment `foo = 1, bar = 2`, removing unused variables
can lead to a syntax error, so this case is not autocorrected.

[#examples-lintuselessassignment]
=== Examples

[source,ruby]
----
# bad
def some_method
  some_var = 1
  do_something
end

# good
def some_method
  some_var = 1
  do_something(some_var)
end
----

[#references-lintuselessassignment]
=== References

* https://rubystyle.guide#underscore-unused-vars

[#lintuselessconstantscoping]
== Lint/UselessConstantScoping

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.72
| -
|===

Checks for useless constant scoping. Private constants must be defined using
`private_constant`. Even if `private` access modifier is used, it is public scope despite
its appearance.

It does not support autocorrection due to behavior change and multiple ways to fix it.
Or a public constant may be intended.

[#examples-lintuselessconstantscoping]
=== Examples

[source,ruby]
----
# bad
class Foo
  private
  PRIVATE_CONST = 42
end

# good
class Foo
  PRIVATE_CONST = 42
  private_constant :PRIVATE_CONST
end

# good
class Foo
  PUBLIC_CONST = 42 # If private scope is not intended.
end
----

[#lintuselessdefaultvalueargument]
== Lint/UselessDefaultValueArgument

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| No
| Always (Unsafe)
| 1.76
| -
|===

Checks for usage of method `fetch` or `Array.new` with default value argument
and block. In such cases, block will always be used as default value.

This cop emulates Ruby warning "block supersedes default value argument" which
applies to `Array.new`, `Array#fetch`, `Hash#fetch`, `ENV.fetch` and
`Thread#fetch`.

A `fetch` call without a receiver is considered a custom method and does not register
an offense.

[#safety-lintuselessdefaultvalueargument]
=== Safety

This cop is unsafe because the receiver could have nonstandard implementation
of `fetch`, or be a class other than the one listed above.

It is also unsafe because default value argument could have side effects:

[source,ruby]
----
def x(a) = puts "side effect"
Array.new(5, x(1)) { 2 }
----

so removing it would change behavior.

[#examples-lintuselessdefaultvalueargument]
=== Examples

[source,ruby]
----
# bad
x.fetch(key, default_value) { block_value }
Array.new(size, default_value) { block_value }

# good
x.fetch(key) { block_value }
Array.new(size) { block_value }

# also good - in case default value argument is desired instead
x.fetch(key, default_value)
Array.new(size, default_value)

# good - keyword arguments aren't registered as offenses
x.fetch(key, keyword: :arg) { block_value }
----

[#allowedreceivers_-__rails_cache__-lintuselessdefaultvalueargument]
==== AllowedReceivers: ['Rails.cache']

[source,ruby]
----
# good
Rails.cache.fetch(name, options) { block }
----

[#configurable-attributes-lintuselessdefaultvalueargument]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowedReceivers
| `[]`
| Array
|===

[#lintuselessdefined]
== Lint/UselessDefined

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.69
| -
|===

Checks for calls to `defined?` with strings or symbols as the argument.
Such calls will always return `'expression'`, you probably meant to
check for the existence of a constant, method, or variable instead.

`defined?` is part of the Ruby syntax and doesn't behave like normal methods.
You can safely pass in what you are checking for directly, without encountering
a `NameError`.

When interpolation is used, oftentimes it is not possible to write the
code with `defined?`. In these cases, switch to one of the more specific methods:

* `class_variable_defined?`
* `const_defined?`
* `method_defined?`
* `instance_variable_defined?`
* `binding.local_variable_defined?`

[#examples-lintuselessdefined]
=== Examples

[source,ruby]
----
# bad
defined?('FooBar')
defined?(:FooBar)
defined?(:foo_bar)
defined?('foo_bar')

# good
defined?(FooBar)
defined?(foo_bar)

# bad - interpolation
bar = 'Bar'
defined?("Foo::#{bar}::Baz")

# good
bar = 'Bar'
defined?(Foo) && Foo.const_defined?(bar) && Foo.const_get(bar).const_defined?(:Baz)
----

[#lintuselesselsewithoutrescue]
== Lint/UselessElseWithoutRescue

NOTE: Requires Ruby version <= 2.5

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.17
| 1.31
|===

Checks for useless `else` in `begin..end` without `rescue`.

NOTE: This syntax is no longer valid on Ruby 2.6 or higher.

[#examples-lintuselesselsewithoutrescue]
=== Examples

[source,ruby]
----
# bad
begin
  do_something
else
  do_something_else # This will never be run.
end

# good
begin
  do_something
rescue
  handle_errors
else
  do_something_else
end
----

[#lintuselessmethoddefinition]
== Lint/UselessMethodDefinition

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| Command-line only (Unsafe)
| 0.90
| 1.61
|===

Checks for useless method definitions, specifically: empty constructors
and methods just delegating to `super`.

[#safety-lintuselessmethoddefinition]
=== Safety

This cop is unsafe as it can register false positives for cases when an empty
constructor just overrides the parent constructor, which is bad anyway.

[#examples-lintuselessmethoddefinition]
=== Examples

[source,ruby]
----
# bad
def initialize
  super
end

def method
  super
end

# good - with default arguments
def initialize(x = Object.new)
  super
end

# good
def initialize
  super
  initialize_internals
end

def method(*args)
  super(:extra_arg, *args)
end
----

[#lintuselessnumericoperation]
== Lint/UselessNumericOperation

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Always
| 1.66
| -
|===

Certain numeric operations have no impact, being:
Adding or subtracting 0, multiplying or dividing by 1 or raising to the power of 1.
These are probably leftover from debugging, or are mistakes.

[#examples-lintuselessnumericoperation]
=== Examples

[source,ruby]
----
# bad
x + 0
x - 0
x * 1
x / 1
x ** 1

# good
x

# bad
x += 0
x -= 0
x *= 1
x /= 1
x **= 1

# good
x = x
----

[#lintuselessor]
== Lint/UselessOr

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Command-line only (Unsafe)
| 1.76
| 1.82
|===

Checks for useless OR (`||` and `or`) expressions.

Some methods always return a truthy value, even when called
on `nil` (e.g. `nil.to_i` evaluates to `0`). Therefore, OR expressions
appended after these methods will never evaluate.

[#safety-lintuselessor]
=== Safety

As shown in the examples below, there are generally two possible ways to correct the
offense, but this cop's autocorrection always chooses the option that preserves the
current behavior. While this does not change how the code behaves, that option is not
necessarily the appropriate fix in every situation. For this reason, the autocorrection
provided by this cop is considered unsafe.

[#examples-lintuselessor]
=== Examples

[source,ruby]
----
# bad
x.to_a || fallback
x.to_c || fallback
x.to_d || fallback
x.to_i || fallback
x.to_f || fallback
x.to_h || fallback
x.to_r || fallback
x.to_s || fallback
x.to_sym || fallback
x.intern || fallback
x.inspect || fallback
x.hash || fallback
x.object_id || fallback
x.__id__ || fallback

x.to_s or fallback

# good - if fallback is same as return value of method called on nil
x.to_a # nil.to_a returns []
x.to_c # nil.to_c returns (0+0i)
x.to_d # nil.to_d returns 0.0
x.to_i # nil.to_i returns 0
x.to_f # nil.to_f returns 0.0
x.to_h # nil.to_h returns {}
x.to_r # nil.to_r returns (0/1)
x.to_s # nil.to_s returns ''
x.to_sym # nil.to_sym raises an error
x.intern # nil.intern raises an error
x.inspect # nil.inspect returns "nil"
x.hash # nil.hash returns an Integer
x.object_id # nil.object_id returns an Integer
x.__id__ # nil.object_id returns an Integer

# good - if the intention is not to call the method on nil
x&.to_a || fallback
x&.to_c || fallback
x&.to_d || fallback
x&.to_i || fallback
x&.to_f || fallback
x&.to_h || fallback
x&.to_r || fallback
x&.to_s || fallback
x&.to_sym || fallback
x&.intern || fallback
x&.inspect || fallback
x&.hash || fallback
x&.object_id || fallback
x&.__id__ || fallback

x&.to_s or fallback
----

[#lintuselessrescue]
== Lint/UselessRescue

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.43
| -
|===

Checks for useless ``rescue``s, which only reraise rescued exceptions.

[#examples-lintuselessrescue]
=== Examples

[source,ruby]
----
# bad
def foo
  do_something
rescue
  raise
end

# bad
def foo
  do_something
rescue => e
  raise # or 'raise e', or 'raise $!', or 'raise $ERROR_INFO'
end

# good
def foo
  do_something
rescue
  do_cleanup
  raise
end

# bad (latest rescue)
def foo
  do_something
rescue ArgumentError
  # noop
rescue
  raise
end

# good (not the latest rescue)
def foo
  do_something
rescue ArgumentError
  raise
rescue
  # noop
end
----

[#lintuselessruby2keywords]
== Lint/UselessRuby2Keywords

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| No
| 1.23
| -
|===

Looks for `ruby2_keywords` calls for methods that do not need it.

`ruby2_keywords` should only be called on methods that accept an argument splat
(`\*args`) but do not have explicit keyword arguments (`k:` or `k: true`) or
a keyword splat (`**kwargs`).

[#examples-lintuselessruby2keywords]
=== Examples

[source,ruby]
----
# good (splat argument without keyword arguments)
ruby2_keywords def foo(*args); end

# bad (no arguments)
ruby2_keywords def foo; end

# good
def foo; end

# bad (positional argument)
ruby2_keywords def foo(arg); end

# good
def foo(arg); end

# bad (double splatted argument)
ruby2_keywords def foo(**args); end

# good
def foo(**args); end

# bad (keyword arguments)
ruby2_keywords def foo(i:, j:); end

# good
def foo(i:, j:); end

# bad (splat argument with keyword arguments)
ruby2_keywords def foo(*args, i:, j:); end

# good
def foo(*args, i:, j:); end

# bad (splat argument with double splat)
ruby2_keywords def foo(*args, **kwargs); end

# good
def foo(*args, **kwargs); end

# bad (ruby2_keywords given a symbol)
def foo; end
ruby2_keywords :foo

# good
def foo; end

# bad (ruby2_keywords with dynamic method)
define_method(:foo) { |arg| }
ruby2_keywords :foo

# good
define_method(:foo) { |arg| }
----

[#lintuselesssettercall]
== Lint/UselessSetterCall

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| Always (Unsafe)
| 0.13
| 1.2
|===

Checks for setter call to local variable as the final
expression of a function definition.

[#safety-lintuselesssettercall]
=== Safety

There are edge cases in which the local variable references a
value that is also accessible outside the local scope. This is not
detected by the cop, and it can yield a false positive.

As well, autocorrection is unsafe because the method's
return value will be changed.

[#examples-lintuselesssettercall]
=== Examples

[source,ruby]
----
# bad
def something
  x = Something.new
  x.attr = 5
end

# good
def something
  x = Something.new
  x.attr = 5
  x
end
----

[#lintuselesstimes]
== Lint/UselessTimes

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| Command-line only (Unsafe)
| 0.91
| 1.61
|===

Checks for uses of `Integer#times` that will never yield
(when the integer ``<= 0``) or that will only ever yield once
(`1.times`).

[#safety-lintuselesstimes]
=== Safety

This cop is unsafe as `times` returns its receiver, which is
*usually* OK, but might change behavior.

[#examples-lintuselesstimes]
=== Examples

[source,ruby]
----
# bad
-5.times { do_something }
0.times { do_something }
1.times { do_something  }
1.times { |i| do_something(i) }

# good
do_something
do_something(1)
----

[#lintvoid]
== Lint/Void

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 0.9
| 1.61
|===

Checks for operators, variables, literals, lambda, proc and nonmutating
methods used in void context.

`each` blocks are allowed to prevent false positives.
For example, the expression inside the `each` block below.
It's not void, especially when the receiver is an `Enumerator`:

[source,ruby]
----
enumerator = [1, 2, 3].filter
enumerator.each { |item| item >= 2 } #=> [2, 3]
----

NOTE: The last expression in an assignment method definition such as `def foo=(arg)`
is not flagged. Ruby discards it (the method returns its argument), but the method can
still be called directly and its return value relied upon, so flagging it would be a
false positive for this lint.

NOTE: A constant used in a void context is flagged but not autocorrected, since
referencing a constant can trigger autoloading side effects (e.g. forcing a file to
load before a monkey-patch), so removing it may change behavior.

[#examples-lintvoid]
=== Examples

[#checkformethodswithnosideeffects_-false-_default_-lintvoid]
==== CheckForMethodsWithNoSideEffects: false (default)

[source,ruby]
----
# bad
def some_method
  some_num * 10
  do_something
end

def some_method(some_var)
  some_var
  do_something
end
----

[#checkformethodswithnosideeffects_-true-lintvoid]
==== CheckForMethodsWithNoSideEffects: true

[source,ruby]
----
# bad
def some_method(some_array)
  some_array.sort
  do_something(some_array)
end

# good
def some_method
  do_something
  some_num * 10
end

def some_method(some_var)
  do_something
  some_var
end

def some_method(some_array)
  some_array.sort!
  do_something(some_array)
end
----

[#configurable-attributes-lintvoid]
=== Configurable attributes

|===
| Name | Default value | Configurable values

| CheckForMethodsWithNoSideEffects
| `false`
| Boolean
|===
