Skip to content

Commit

Permalink
Add new Lint/DeprecatedConstants cop
Browse files Browse the repository at this point in the history
This PR adds new `Lint/DeprecatedConstants` cop.

This cop 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.
By default, `NIL`, `TRUE`, `FALSE` and `Random::DEFAULT` are configured.

```ruby
# bad
NIL
TRUE
FALSE
Random::DEFAULT # Return value of Ruby 2 is `Random` instance, Ruby 3.0 is `Random` class.

# good
nil
true
false
Random.new # `::DEFAULT` has been deprecated in Ruby 3, `.new` is compatible with Ruby 2.
```

The following are these sources of information.

- Remove (deprecated) `NIL`, `TRUE`, and `FALSE` ... ruby/ruby@62554ca
- Deprecate `Random::DEFAULT` ... https://bugs.ruby-lang.org/issues/17351
  • Loading branch information
koic committed Jan 5, 2021
1 parent 1d75a82 commit b95afa7
Show file tree
Hide file tree
Showing 5 changed files with 247 additions and 0 deletions.
1 change: 1 addition & 0 deletions changelog/new_add_new_deprecated_constants_cop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#9324](https://github.com/rubocop-hq/rubocop/pull/9324): Add new `Lint/DeprecatedConstants` cop. ([@koic][])
28 changes: 28 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1469,6 +1469,34 @@ Lint/DeprecatedClassMethods:
Enabled: true
VersionAdded: '0.19'

Lint/DeprecatedConstants:
Description: 'Checks for deprecated constants.'
Enabled: pending
VersionAdded: '<<next>>'
# You can configure deprecated constants.
# 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'
#
DeprecatedConstants:
'NIL':
Alternative: 'nil'
DeprecatedVersion: '2.4'
'TRUE':
Alternative: 'true'
DeprecatedVersion: '2.4'
'FALSE':
Alternative: 'false'
DeprecatedVersion: '2.4'
'Random::DEFAULT':
Alternative: 'Random.new'
DeprecatedVersion: '3.0'

Lint/DeprecatedOpenSSLConstant:
Description: "Don't use algorithm constants for `OpenSSL::Cipher` and `OpenSSL::Digest`."
Enabled: true
Expand Down
1 change: 1 addition & 0 deletions lib/rubocop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@
require_relative 'rubocop/cop/lint/constant_resolution'
require_relative 'rubocop/cop/lint/debugger'
require_relative 'rubocop/cop/lint/deprecated_class_methods'
require_relative 'rubocop/cop/lint/deprecated_constants'
require_relative 'rubocop/cop/lint/deprecated_open_ssl_constant'
require_relative 'rubocop/cop/lint/disjunctive_assignment_in_constructor'
require_relative 'rubocop/cop/lint/duplicate_branch'
Expand Down
75 changes: 75 additions & 0 deletions lib/rubocop/cop/lint/deprecated_constants.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Lint
# This cop 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` and `Random::DEFAULT` are configured.
#
# @example
#
# # bad
# NIL
# TRUE
# FALSE
# Random::DEFAULT # Return value of Ruby 2 is `Random` instance, Ruby 3.0 is `Random` class.
#
# # good
# nil
# true
# false
# Random.new # `::DEFAULT` has been deprecated in Ruby 3, `.new` is compatible with Ruby 2.
#
class DeprecatedConstants < Base
extend AutoCorrector

SUGGEST_GOOD_MSG = 'Use `%<good>s` instead of `%<bad>s`%<deprecated_message>s.'
DO_NOT_USE_MSG = 'Do not use `%<bad>s`%<deprecated_message>s.'

def on_const(node)
constant = node.absolute? ? consntant_name(node, node.short_name.to_s) : node.source
return unless (deprecated_constant = deprecated_constants[constant])

alternative = deprecated_constant['Alternative']
version = deprecated_constant['DeprecatedVersion']

add_offense(node, message: message(alternative, node.source, version)) do |corrector|
corrector.replace(node, alternative)
end
end

private

def consntant_name(node, nested_constant_name)
return nested_constant_name unless node.namespace.const_type?

consntant_name(node.namespace, "#{node.namespace.short_name}::#{nested_constant_name}")
end

def message(good, bad, deprecated_version)
deprecated_message = ", deprecated since Ruby #{deprecated_version}" if deprecated_version

if good
format(SUGGEST_GOOD_MSG, good: good, bad: bad, deprecated_message: deprecated_message)
else
format(DO_NOT_USE_MSG, bad: bad, deprecated_message: deprecated_message)
end
end

def deprecated_constants
cop_config.fetch('DeprecatedConstants', {})
end
end
end
end
end
142 changes: 142 additions & 0 deletions spec/rubocop/cop/lint/deprecated_constants_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Lint::DeprecatedConstants, :config do
let(:cop_config) do
{
'DeprecatedConstants' => {
'NIL' => { 'Alternative' => 'nil', 'DeprecatedVersion' => '2.4' },
'TRUE' => { 'Alternative' => 'true', 'DeprecatedVersion' => '2.4' },
'FALSE' => { 'Alternative' => 'false', 'DeprecatedVersion' => '2.4' },
'Random::DEFAULT' => { 'Alternative' => 'Random.new', 'DeprecatedVersion' => '3.0' },
'Triple::Nested::Constant' => { 'Alternative' => 'Value', 'DeprecatedVersion' => '2.4' },
'Have::No::Alternative' => { 'DeprecatedVersion' => '2.4' },
'Have::No::DeprecatedVersion' => { 'Alternative' => 'Value' }
}
}
end

it 'registers and corrects an offense when using `NIL`' do
expect_offense(<<~RUBY)
NIL
^^^ Use `nil` instead of `NIL`, deprecated since Ruby 2.4.
RUBY

expect_correction(<<~RUBY)
nil
RUBY
end

it 'registers and corrects an offense when using `TRUE`' do
expect_offense(<<~RUBY)
TRUE
^^^^ Use `true` instead of `TRUE`, deprecated since Ruby 2.4.
RUBY

expect_correction(<<~RUBY)
true
RUBY
end

it 'registers and corrects an offense when using `FALSE`' do
expect_offense(<<~RUBY)
FALSE
^^^^^ Use `false` instead of `FALSE`, deprecated since Ruby 2.4.
RUBY

expect_correction(<<~RUBY)
false
RUBY
end

it 'registers and corrects an offense when using `Random::DEFAULT`' do
expect_offense(<<~RUBY)
Random::DEFAULT
^^^^^^^^^^^^^^^ Use `Random.new` instead of `Random::DEFAULT`, deprecated since Ruby 3.0.
RUBY

expect_correction(<<~RUBY)
Random.new
RUBY
end

it 'registers and corrects an offense when using `::NIL`' do
expect_offense(<<~RUBY)
::NIL
^^^^^ Use `nil` instead of `::NIL`, deprecated since Ruby 2.4.
RUBY

expect_correction(<<~RUBY)
nil
RUBY
end

it 'registers and corrects an offense when using `::TRUE`' do
expect_offense(<<~RUBY)
::TRUE
^^^^^^ Use `true` instead of `::TRUE`, deprecated since Ruby 2.4.
RUBY

expect_correction(<<~RUBY)
true
RUBY
end

it 'registers and corrects an offense when using `::FALSE`' do
expect_offense(<<~RUBY)
::FALSE
^^^^^^^ Use `false` instead of `::FALSE`, deprecated since Ruby 2.4.
RUBY

expect_correction(<<~RUBY)
false
RUBY
end

it 'registers and corrects an offense when using `::Random::DEFAULT`' do
expect_offense(<<~RUBY)
::Random::DEFAULT
^^^^^^^^^^^^^^^^^ Use `Random.new` instead of `::Random::DEFAULT`, deprecated since Ruby 3.0.
RUBY

expect_correction(<<~RUBY)
Random.new
RUBY
end

it 'registers and corrects an offense when using `::Triple::Nested::Constant`' do
expect_offense(<<~RUBY)
::Triple::Nested::Constant
^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `Value` instead of `::Triple::Nested::Constant`, deprecated since Ruby 2.4.
RUBY

expect_correction(<<~RUBY)
Value
RUBY
end

it 'registers and corrects an offense when using deprecated methods that have no alternative' do
expect_offense(<<~RUBY)
Have::No::Alternative
^^^^^^^^^^^^^^^^^^^^^ Do not use `Have::No::Alternative`, deprecated since Ruby 2.4.
RUBY

expect_no_corrections
end

it 'registers and corrects an offense when using deprecated methods that have no deprecated version' do
expect_offense(<<~RUBY)
Have::No::DeprecatedVersion
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `Value` instead of `Have::No::DeprecatedVersion`.
RUBY

expect_correction(<<~RUBY)
Value
RUBY
end

it 'does not register an offense when not using deprecated consntant' do
expect_no_offenses(<<~RUBY)
Foo::TRUE
RUBY
end
end

0 comments on commit b95afa7

Please sign in to comment.