/
deprecated_constants.rb
84 lines (72 loc) · 2.94 KB
/
deprecated_constants.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# frozen_string_literal: true
module RuboCop
module Cop
module Lint
# 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, and `Random::DEFAULT`
# are configured.
#
# @example
#
# # bad
# NIL
# TRUE
# FALSE
# Net::HTTPServerException
# Random::DEFAULT # Return value of Ruby 2 is `Random` instance, Ruby 3.0 is `Random` class.
#
# # good
# nil
# true
# false
# Net::HTTPClientException
# 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)
# FIXME: Workaround for "`undefined method `expression' for nil:NilClass`" when processing
# `__ENCODING__`. It is better to be able to work without this condition.
# Maybe further investigation of RuboCop AST will lead to an essential solution.
return unless node.loc
constant = node.absolute? ? constant_name(node, node.short_name) : node.source
return unless (deprecated_constant = deprecated_constants[constant])
alternative = deprecated_constant['Alternative']
version = deprecated_constant['DeprecatedVersion']
return if target_ruby_version < version.to_f
add_offense(node, message: message(alternative, node.source, version)) do |corrector|
corrector.replace(node, alternative)
end
end
private
def constant_name(node, nested_constant_name)
return nested_constant_name.to_s unless node.namespace.const_type?
constant_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