Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Lint/DeprecatedConstants cop #9324

Merged
merged 1 commit into from
Jan 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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