rubocop 1.43.0 → 1.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +50 -0
- data/lib/rubocop/config_loader.rb +12 -15
- data/lib/rubocop/cop/corrector.rb +10 -2
- data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +1 -6
- data/lib/rubocop/cop/gemspec/development_dependencies.rb +107 -0
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +11 -3
- data/lib/rubocop/cop/layout/block_end_newline.rb +7 -1
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -5
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +6 -9
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +0 -2
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +62 -112
- data/lib/rubocop/cop/lint/else_layout.rb +2 -6
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +10 -7
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +11 -1
- data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -3
- data/lib/rubocop/cop/lint/useless_rescue.rb +15 -1
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +9 -1
- data/lib/rubocop/cop/lint/void.rb +17 -10
- data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +2 -5
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +40 -18
- data/lib/rubocop/cop/mixin/line_length_help.rb +3 -1
- data/lib/rubocop/cop/registry.rb +12 -7
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +18 -10
- data/lib/rubocop/cop/style/block_delimiters.rb +8 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +2 -9
- data/lib/rubocop/cop/style/comparable_clamp.rb +125 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +0 -6
- data/lib/rubocop/cop/style/infinite_loop.rb +2 -5
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +114 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +11 -5
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/min_max_comparison.rb +11 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +0 -4
- data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -5
- data/lib/rubocop/cop/style/one_line_conditional.rb +2 -5
- data/lib/rubocop/cop/style/operator_method_call.rb +1 -1
- data/lib/rubocop/cop/style/redundant_conditional.rb +0 -4
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +16 -10
- data/lib/rubocop/cop/style/require_order.rb +2 -9
- data/lib/rubocop/cop/style/semicolon.rb +24 -2
- data/lib/rubocop/cop/variable_force.rb +1 -1
- data/lib/rubocop/formatter.rb +0 -1
- data/lib/rubocop/rspec/expect_offense.rb +5 -3
- data/lib/rubocop/server/cache.rb +3 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +3 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad37375bb32d669c2c9ac877f9a8522829c76495e41bffb9796663807dfbcf2d
|
4
|
+
data.tar.gz: 8efe81401a312e4e7f438509aa1dfa7929d505d8797863dc55c97212573fbfda
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ece75066f9a765556559a906b11feef8d68bd6fe72a160c378bd10f59c5aab66d2e1b034a0932a7cc6aeab09275e1758e3680fbb0e05e79567deefd975e94bf
|
7
|
+
data.tar.gz: b1ed9f275eb702308fb17406da11b13ae79ed7453ba4145c857e5192004469c0c6ec07bab8030f6de0831bcebfb19dda4a9a484ea830d237de6c2154f571b03b
|
data/README.md
CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
53
53
|
in your `Gemfile`:
|
54
54
|
|
55
55
|
```rb
|
56
|
-
gem 'rubocop', '~> 1.
|
56
|
+
gem 'rubocop', '~> 1.44', require: false
|
57
57
|
```
|
58
58
|
|
59
59
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
data/config/default.yml
CHANGED
@@ -262,6 +262,22 @@ Gemspec/DeprecatedAttributeAssignment:
|
|
262
262
|
Include:
|
263
263
|
- '**/*.gemspec'
|
264
264
|
|
265
|
+
Gemspec/DevelopmentDependencies:
|
266
|
+
Description: Checks that development dependencies are specified in Gemfile rather than gemspec.
|
267
|
+
Enabled: pending
|
268
|
+
VersionAdded: '1.44'
|
269
|
+
EnforcedStyle: Gemfile
|
270
|
+
SupportedStyles:
|
271
|
+
- Gemfile
|
272
|
+
- gems.rb
|
273
|
+
- gemspec
|
274
|
+
AllowedGems:
|
275
|
+
- bundler
|
276
|
+
Include:
|
277
|
+
- '**/*.gemspec'
|
278
|
+
- '**/Gemfile'
|
279
|
+
- '**/gems.rb'
|
280
|
+
|
265
281
|
Gemspec/DuplicatedAssignment:
|
266
282
|
Description: 'An attribute assignment method calls should be listed only once in a gemspec.'
|
267
283
|
Enabled: true
|
@@ -3431,6 +3447,11 @@ Style/CommentedKeyword:
|
|
3431
3447
|
VersionAdded: '0.51'
|
3432
3448
|
VersionChanged: '1.19'
|
3433
3449
|
|
3450
|
+
Style/ComparableClamp:
|
3451
|
+
Description: 'Enforces the use of `Comparable#clamp` instead of comparison by minimum and maximum.'
|
3452
|
+
Enabled: pending
|
3453
|
+
VersionAdded: '1.44'
|
3454
|
+
|
3434
3455
|
Style/ConcatArrayLiterals:
|
3435
3456
|
Description: 'Enforces the use of `Array#push(item)` instead of `Array#concat([item])` to avoid redundant array literals.'
|
3436
3457
|
Enabled: pending
|
@@ -4031,6 +4052,35 @@ Style/InverseMethods:
|
|
4031
4052
|
:select: :reject
|
4032
4053
|
:select!: :reject!
|
4033
4054
|
|
4055
|
+
Style/InvertibleUnlessCondition:
|
4056
|
+
Description: 'Favor `if` with inverted condition over `unless`.'
|
4057
|
+
Enabled: false
|
4058
|
+
VersionAdded: '1.44'
|
4059
|
+
# `InverseMethods` are methods that can be inverted in a `unless` condition.
|
4060
|
+
# The relationship of inverse methods needs to be defined in both directions.
|
4061
|
+
# Keys and values both need to be defined as symbols.
|
4062
|
+
InverseMethods:
|
4063
|
+
:!=: :==
|
4064
|
+
:>: :<=
|
4065
|
+
:<=: :>
|
4066
|
+
:<: :>=
|
4067
|
+
:>=: :<
|
4068
|
+
:!~: :=~
|
4069
|
+
:zero?: :nonzero?
|
4070
|
+
:nonzero?: :zero?
|
4071
|
+
:any?: :none?
|
4072
|
+
:none?: :any?
|
4073
|
+
:even?: :odd?
|
4074
|
+
:odd?: :even?
|
4075
|
+
# `ActiveSupport` defines some common inverse methods. They are listed below,
|
4076
|
+
# and not enabled by default.
|
4077
|
+
# :present?: :blank?
|
4078
|
+
# :blank?: :present?
|
4079
|
+
# :include?: :exclude?
|
4080
|
+
# :exclude?: :include?
|
4081
|
+
# :one?: :many?
|
4082
|
+
# :many?: :one?
|
4083
|
+
|
4034
4084
|
Style/IpAddresses:
|
4035
4085
|
Description: "Don't include literal IP addresses in code."
|
4036
4086
|
Enabled: false
|
@@ -111,10 +111,17 @@ module RuboCop
|
|
111
111
|
end
|
112
112
|
|
113
113
|
merge_with_default(config, config_file).tap do |merged_config|
|
114
|
-
|
114
|
+
unless possible_new_cops?(merged_config)
|
115
|
+
pending_cops = pending_cops_only_qualified(merged_config.pending_cops)
|
116
|
+
warn_on_pending_cops(pending_cops) unless pending_cops.empty?
|
117
|
+
end
|
115
118
|
end
|
116
119
|
end
|
117
120
|
|
121
|
+
def pending_cops_only_qualified(pending_cops)
|
122
|
+
pending_cops.select { |cop| Cop::Registry.qualified_cop?(cop.name) }
|
123
|
+
end
|
124
|
+
|
118
125
|
def possible_new_cops?(config)
|
119
126
|
disable_pending_cops || enable_pending_cops ||
|
120
127
|
config.disabled_new_cops? || config.enabled_new_cops?
|
@@ -167,8 +174,6 @@ module RuboCop
|
|
167
174
|
BANNER
|
168
175
|
|
169
176
|
def warn_on_pending_cops(pending_cops)
|
170
|
-
return if pending_cops.empty?
|
171
|
-
|
172
177
|
warn Rainbow(PENDING_BANNER).yellow
|
173
178
|
|
174
179
|
pending_cops.each { |cop| warn_pending_cop cop }
|
@@ -241,18 +246,10 @@ module RuboCop
|
|
241
246
|
raise
|
242
247
|
end
|
243
248
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
permitted_symbols: [],
|
249
|
-
aliases: true,
|
250
|
-
filename: filename)
|
251
|
-
end
|
252
|
-
else # Ruby < 2.6
|
253
|
-
def yaml_safe_load!(yaml_code, filename)
|
254
|
-
YAML.safe_load(yaml_code, [Regexp, Symbol], [], true, filename)
|
255
|
-
end
|
249
|
+
def yaml_safe_load!(yaml_code, filename)
|
250
|
+
YAML.safe_load(
|
251
|
+
yaml_code, permitted_classes: [Regexp, Symbol], aliases: true, filename: filename
|
252
|
+
)
|
256
253
|
end
|
257
254
|
end
|
258
255
|
|
@@ -86,8 +86,16 @@ module RuboCop
|
|
86
86
|
range1 = to_range(node_or_range1)
|
87
87
|
range2 = to_range(node_or_range2)
|
88
88
|
|
89
|
-
|
90
|
-
|
89
|
+
if range1.end_pos == range2.begin_pos
|
90
|
+
insert_before(range1, range2.source)
|
91
|
+
remove(range2)
|
92
|
+
elsif range2.end_pos == range1.begin_pos
|
93
|
+
insert_before(range2, range1.source)
|
94
|
+
remove(range1)
|
95
|
+
else
|
96
|
+
replace(range1, range2.source)
|
97
|
+
replace(range2, range1.source)
|
98
|
+
end
|
91
99
|
end
|
92
100
|
|
93
101
|
private
|
@@ -18,7 +18,7 @@ module RuboCop
|
|
18
18
|
current_range = declaration_with_comment(node)
|
19
19
|
previous_range = declaration_with_comment(previous_declaration)
|
20
20
|
|
21
|
-
->(corrector) {
|
21
|
+
->(corrector) { corrector.swap(current_range, previous_range) }
|
22
22
|
end
|
23
23
|
|
24
24
|
private
|
@@ -32,11 +32,6 @@ module RuboCop
|
|
32
32
|
|
33
33
|
range_between(begin_pos, end_pos)
|
34
34
|
end
|
35
|
-
|
36
|
-
def swap_range(corrector, range1, range2)
|
37
|
-
corrector.insert_before(range2, range1.source)
|
38
|
-
corrector.remove(range1)
|
39
|
-
end
|
40
35
|
end
|
41
36
|
end
|
42
37
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Gemspec
|
6
|
+
# Enforce that development dependencies for a gem are specified in
|
7
|
+
# `Gemfile`, rather than in the `gemspec` using
|
8
|
+
# `add_development_dependency`. Alternatively, using `EnforcedStyle:
|
9
|
+
# gemspec`, enforce that all dependencies are specified in `gemspec`,
|
10
|
+
# rather than in `Gemfile`.
|
11
|
+
#
|
12
|
+
# @example EnforcedStyle: Gemfile (default)
|
13
|
+
# # Specify runtime dependencies in your gemspec,
|
14
|
+
# # but all other dependencies in your Gemfile.
|
15
|
+
#
|
16
|
+
# # bad
|
17
|
+
# # example.gemspec
|
18
|
+
# s.add_development_dependency "foo"
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# # Gemfile
|
22
|
+
# gem "foo"
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# # gems.rb
|
26
|
+
# gem "foo"
|
27
|
+
#
|
28
|
+
# # good (with AllowedGems: ["bar"])
|
29
|
+
# # example.gemspec
|
30
|
+
# s.add_development_dependency "bar"
|
31
|
+
#
|
32
|
+
# @example EnforcedStyle: gems.rb
|
33
|
+
# # Specify runtime dependencies in your gemspec,
|
34
|
+
# # but all other dependencies in your Gemfile.
|
35
|
+
# #
|
36
|
+
# # Identical to `EnforcedStyle: Gemfile`, but with a different error message.
|
37
|
+
# # Rely on Bundler/GemFilename to enforce the use of `Gemfile` vs `gems.rb`.
|
38
|
+
#
|
39
|
+
# # bad
|
40
|
+
# # example.gemspec
|
41
|
+
# s.add_development_dependency "foo"
|
42
|
+
#
|
43
|
+
# # good
|
44
|
+
# # Gemfile
|
45
|
+
# gem "foo"
|
46
|
+
#
|
47
|
+
# # good
|
48
|
+
# # gems.rb
|
49
|
+
# gem "foo"
|
50
|
+
#
|
51
|
+
# # good (with AllowedGems: ["bar"])
|
52
|
+
# # example.gemspec
|
53
|
+
# s.add_development_dependency "bar"
|
54
|
+
#
|
55
|
+
# @example EnforcedStyle: gemspec
|
56
|
+
# # Specify all dependencies in your gemspec.
|
57
|
+
#
|
58
|
+
# # bad
|
59
|
+
# # Gemfile
|
60
|
+
# gem "foo"
|
61
|
+
#
|
62
|
+
# # good
|
63
|
+
# # example.gemspec
|
64
|
+
# s.add_development_dependency "foo"
|
65
|
+
#
|
66
|
+
# # good (with AllowedGems: ["bar"])
|
67
|
+
# # Gemfile
|
68
|
+
# gem "bar"
|
69
|
+
#
|
70
|
+
class DevelopmentDependencies < Base
|
71
|
+
include ConfigurableEnforcedStyle
|
72
|
+
|
73
|
+
MSG = 'Specify development dependencies in %<preferred>s.'
|
74
|
+
RESTRICT_ON_SEND = %i[add_development_dependency gem].freeze
|
75
|
+
|
76
|
+
# @!method add_development_dependency?(node)
|
77
|
+
def_node_matcher :add_development_dependency?, <<~PATTERN
|
78
|
+
(send _ :add_development_dependency (str #forbidden_gem? ...))
|
79
|
+
PATTERN
|
80
|
+
|
81
|
+
# @!method gem?(node)
|
82
|
+
def_node_matcher :gem?, <<~PATTERN
|
83
|
+
(send _ :gem (str #forbidden_gem? ...))
|
84
|
+
PATTERN
|
85
|
+
|
86
|
+
def on_send(node)
|
87
|
+
case style
|
88
|
+
when :Gemfile, :'gems.rb'
|
89
|
+
add_offense(node) if add_development_dependency?(node)
|
90
|
+
when :gemspec
|
91
|
+
add_offense(node) if gem?(node)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def forbidden_gem?(gem_name)
|
98
|
+
!cop_config['AllowedGems'].include?(gem_name)
|
99
|
+
end
|
100
|
+
|
101
|
+
def message(_range)
|
102
|
+
format(MSG, preferred: style)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -31,9 +31,17 @@ module RuboCop
|
|
31
31
|
(send nil? :let
|
32
32
|
(sym :config))
|
33
33
|
(args)
|
34
|
-
|
35
|
-
(
|
36
|
-
(const
|
34
|
+
{
|
35
|
+
(send
|
36
|
+
(const
|
37
|
+
(const nil? :RuboCop) :Config) :new)
|
38
|
+
(send
|
39
|
+
(const
|
40
|
+
(const nil? :RuboCop) :Config) :new
|
41
|
+
(hash (pair (send (send (send nil? :described_class) :badge) :to_s)
|
42
|
+
(send nil? :cop_config))))
|
43
|
+
}
|
44
|
+
)
|
37
45
|
PATTERN
|
38
46
|
|
39
47
|
def on_block(node)
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
46
46
|
def register_offense(node)
|
47
47
|
add_offense(node.loc.end, message: message(node)) do |corrector|
|
48
48
|
offense_range = offense_range(node)
|
49
|
-
replacement =
|
49
|
+
replacement = replacement(node)
|
50
50
|
|
51
51
|
if (heredoc = last_heredoc_argument(node.body))
|
52
52
|
corrector.remove(offense_range)
|
@@ -79,6 +79,12 @@ module RuboCop
|
|
79
79
|
)
|
80
80
|
end
|
81
81
|
|
82
|
+
def replacement(node)
|
83
|
+
end_with_method_chain = node.loc.end.join(end_of_method_chain(node).loc.expression.end)
|
84
|
+
|
85
|
+
"\n#{end_with_method_chain.source.strip}"
|
86
|
+
end
|
87
|
+
|
82
88
|
def end_of_method_chain(node)
|
83
89
|
return node unless node.parent&.call_type?
|
84
90
|
|
@@ -144,7 +144,7 @@ module RuboCop
|
|
144
144
|
def expected_column(left_paren, elements)
|
145
145
|
if line_break_after_left_paren?(left_paren, elements)
|
146
146
|
source_indent = processed_source.line_indentation(first_argument_line(elements))
|
147
|
-
new_indent = source_indent -
|
147
|
+
new_indent = source_indent - configured_indentation_width
|
148
148
|
|
149
149
|
new_indent.negative? ? 0 : new_indent
|
150
150
|
elsif all_elements_aligned?(elements)
|
@@ -184,10 +184,6 @@ module RuboCop
|
|
184
184
|
end
|
185
185
|
end
|
186
186
|
|
187
|
-
def indentation_width
|
188
|
-
@config.for_cop('Layout/IndentationWidth')['Width'] || 2
|
189
|
-
end
|
190
|
-
|
191
187
|
def line_break_after_left_paren?(left_paren, elements)
|
192
188
|
elements.first && elements.first.loc.line > left_paren.line
|
193
189
|
end
|
@@ -22,6 +22,7 @@ module RuboCop
|
|
22
22
|
# RUBY
|
23
23
|
#
|
24
24
|
class HeredocIndentation < Base
|
25
|
+
include Alignment
|
25
26
|
include Heredoc
|
26
27
|
extend AutoCorrector
|
27
28
|
|
@@ -37,7 +38,7 @@ module RuboCop
|
|
37
38
|
heredoc_indent_type = heredoc_indent_type(node)
|
38
39
|
|
39
40
|
if heredoc_indent_type == '~'
|
40
|
-
expected_indent_level = base_indent_level(node) +
|
41
|
+
expected_indent_level = base_indent_level(node) + configured_indentation_width
|
41
42
|
return if expected_indent_level == body_indent_level
|
42
43
|
else
|
43
44
|
return unless body_indent_level.zero?
|
@@ -66,9 +67,9 @@ module RuboCop
|
|
66
67
|
current_indent_type = "<<#{heredoc_indent_type}"
|
67
68
|
|
68
69
|
if current_indent_type == '<<~'
|
69
|
-
width_message(
|
70
|
+
width_message(configured_indentation_width)
|
70
71
|
else
|
71
|
-
type_message(
|
72
|
+
type_message(configured_indentation_width, current_indent_type)
|
72
73
|
end
|
73
74
|
end
|
74
75
|
|
@@ -89,7 +90,7 @@ module RuboCop
|
|
89
90
|
|
90
91
|
body = heredoc_body(node)
|
91
92
|
|
92
|
-
expected_indent = base_indent_level(node) +
|
93
|
+
expected_indent = base_indent_level(node) + configured_indentation_width
|
93
94
|
actual_indent = indent_level(body)
|
94
95
|
increase_indent_level = expected_indent - actual_indent
|
95
96
|
|
@@ -122,7 +123,7 @@ module RuboCop
|
|
122
123
|
def indented_body(node)
|
123
124
|
body = heredoc_body(node)
|
124
125
|
body_indent_level = indent_level(body)
|
125
|
-
correct_indent_level = base_indent_level(node) +
|
126
|
+
correct_indent_level = base_indent_level(node) + configured_indentation_width
|
126
127
|
body.gsub(/^[^\S\r\n]{#{body_indent_level}}/, ' ' * correct_indent_level)
|
127
128
|
end
|
128
129
|
|
@@ -148,10 +149,6 @@ module RuboCop
|
|
148
149
|
node.source[/^<<([~-])/, 1]
|
149
150
|
end
|
150
151
|
|
151
|
-
def indentation_width
|
152
|
-
@config.for_cop('Layout/IndentationWidth')['Width'] || 2
|
153
|
-
end
|
154
|
-
|
155
152
|
def heredoc_body(node)
|
156
153
|
node.loc.heredoc_body.source
|
157
154
|
end
|
@@ -178,8 +178,6 @@ module RuboCop
|
|
178
178
|
def multi_dimensional_array?(node, token, side: :right)
|
179
179
|
offset = side == :right ? -1 : +1
|
180
180
|
i = index_for(node, token) + offset
|
181
|
-
# TODO: change this type check once
|
182
|
-
# https://github.com/rubocop/rubocop-ast/pull/240 is merged
|
183
181
|
i += offset while processed_source.tokens_within(node)[i].new_line?
|
184
182
|
if side == :right
|
185
183
|
processed_source.tokens_within(node)[i].right_bracket?
|
@@ -11,6 +11,8 @@ module RuboCop
|
|
11
11
|
# File.exists?(some_path)
|
12
12
|
# Dir.exists?(some_path)
|
13
13
|
# iterator?
|
14
|
+
# attr :name, true
|
15
|
+
# attr :name, false
|
14
16
|
# ENV.freeze # Calling `Env.freeze` raises `TypeError` since Ruby 2.7.
|
15
17
|
# ENV.clone
|
16
18
|
# ENV.dup # Calling `Env.dup` raises `TypeError` since Ruby 3.1.
|
@@ -21,6 +23,8 @@ module RuboCop
|
|
21
23
|
# File.exist?(some_path)
|
22
24
|
# Dir.exist?(some_path)
|
23
25
|
# block_given?
|
26
|
+
# attr_accessor :name
|
27
|
+
# attr_reader :name
|
24
28
|
# ENV # `ENV.freeze` cannot prohibit changes to environment variables.
|
25
29
|
# ENV.to_h
|
26
30
|
# ENV.to_h # `ENV.dup` cannot dup `ENV`, use `ENV.to_h` to get a copy of `ENV` as a hash.
|
@@ -29,138 +33,84 @@ module RuboCop
|
|
29
33
|
class DeprecatedClassMethods < Base
|
30
34
|
extend AutoCorrector
|
31
35
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
36
|
+
MSG = '`%<current>s` is deprecated in favor of `%<prefer>s`.'
|
37
|
+
RESTRICT_ON_SEND = %i[
|
38
|
+
attr clone dup exists? freeze gethostbyaddr gethostbyname iterator?
|
39
|
+
].freeze
|
40
|
+
|
41
|
+
PREFERRED_METHDOS = {
|
42
|
+
clone: 'to_h',
|
43
|
+
dup: 'to_h',
|
44
|
+
exists?: 'exist?',
|
45
|
+
gethostbyaddr: 'Addrinfo#getnameinfo',
|
46
|
+
gethostbyname: 'Addrinfo#getaddrinfo',
|
47
|
+
iterator?: 'block_given?'
|
48
|
+
}.freeze
|
37
49
|
|
38
|
-
|
50
|
+
DIR_ENV_FILE_CONSTANTS = %i[Dir ENV File].freeze
|
39
51
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
s(:const, nil, class_constant),
|
51
|
-
s(:const, s(:cbase), class_constant)
|
52
|
-
]
|
53
|
-
else
|
54
|
-
[nil]
|
55
|
-
end
|
56
|
-
end
|
52
|
+
# @!method deprecated_class_method?(node)
|
53
|
+
def_node_matcher :deprecated_class_method?, <<~PATTERN
|
54
|
+
{
|
55
|
+
(send (const {cbase nil?} {:ENV}) {:clone :dup :freeze})
|
56
|
+
(send (const {cbase nil?} {:File :Dir}) :exists? _)
|
57
|
+
(send (const {cbase nil?} :Socket) {:gethostbyaddr :gethostbyname} ...)
|
58
|
+
(send nil? :attr _ boolean)
|
59
|
+
(send nil? :iterator?)
|
60
|
+
}
|
61
|
+
PATTERN
|
57
62
|
|
58
|
-
|
59
|
-
|
60
|
-
end
|
63
|
+
def on_send(node)
|
64
|
+
return unless deprecated_class_method?(node)
|
61
65
|
|
62
|
-
|
63
|
-
|
64
|
-
|
66
|
+
offense_range = offense_range(node)
|
67
|
+
prefer = preferred_method(node)
|
68
|
+
message = format(MSG, current: offense_range.source, prefer: prefer)
|
65
69
|
|
66
|
-
|
70
|
+
add_offense(offense_range, message: message) do |corrector|
|
71
|
+
next if socket_const?(node.receiver)
|
67
72
|
|
68
|
-
|
69
|
-
|
73
|
+
if node.method?(:freeze)
|
74
|
+
corrector.replace(node, 'ENV')
|
75
|
+
else
|
76
|
+
corrector.replace(offense_range, prefer)
|
77
|
+
end
|
70
78
|
end
|
71
79
|
end
|
72
80
|
|
73
|
-
|
74
|
-
# This class exists to add abstraction and clean naming
|
75
|
-
# to the replacements for deprecated objects
|
76
|
-
class Replacement
|
77
|
-
attr_reader :method, :class_constant
|
78
|
-
|
79
|
-
def initialize(method, class_constant: nil, instance_method: false)
|
80
|
-
@method = method
|
81
|
-
@class_constant = class_constant
|
82
|
-
@instance_method = instance_method
|
83
|
-
end
|
84
|
-
|
85
|
-
def to_s
|
86
|
-
[class_constant, method].compact.join(delimiter)
|
87
|
-
end
|
88
|
-
|
89
|
-
private
|
90
|
-
|
91
|
-
def delimiter
|
92
|
-
instance_method? ? INSTANCE_METHOD_DELIMITER : CLASS_METHOD_DELIMITER
|
93
|
-
end
|
81
|
+
private
|
94
82
|
|
95
|
-
|
96
|
-
|
83
|
+
def offense_range(node)
|
84
|
+
if socket_const?(node.receiver) || dir_env_file_const?(node.receiver)
|
85
|
+
node.loc.expression.begin.join(node.loc.selector.end)
|
86
|
+
elsif node.method?(:attr)
|
87
|
+
node
|
88
|
+
else
|
89
|
+
node.loc.selector
|
97
90
|
end
|
98
91
|
end
|
99
92
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
Replacement.new(:exist?, class_constant: :File),
|
105
|
-
|
106
|
-
DeprecatedClassMethod.new(:exists?, class_constant: :Dir) =>
|
107
|
-
Replacement.new(:exist?, class_constant: :Dir),
|
108
|
-
|
109
|
-
DeprecatedClassMethod.new(:iterator?) => Replacement.new(:block_given?),
|
110
|
-
|
111
|
-
DeprecatedClassMethod.new(:freeze, class_constant: :ENV) =>
|
112
|
-
Replacement.new(nil, class_constant: :ENV),
|
93
|
+
def preferred_method(node)
|
94
|
+
if node.method?(:attr)
|
95
|
+
boolean_argument = node.arguments[1].source
|
96
|
+
preferred_attr_method = boolean_argument == 'true' ? 'attr_accessor' : 'attr_reader'
|
113
97
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
DeprecatedClassMethod.new(:dup, class_constant: :ENV) =>
|
118
|
-
Replacement.new(:to_h, class_constant: :ENV),
|
119
|
-
|
120
|
-
DeprecatedClassMethod.new(:gethostbyaddr, class_constant: :Socket, correctable: false) =>
|
121
|
-
Replacement.new(:getnameinfo, class_constant: :Addrinfo, instance_method: true),
|
122
|
-
|
123
|
-
DeprecatedClassMethod.new(:gethostbyname, class_constant: :Socket, correctable: false) =>
|
124
|
-
Replacement.new(:getaddrinfo, class_constant: :Addrinfo, instance_method: true)
|
125
|
-
}.freeze
|
98
|
+
"#{preferred_attr_method} #{node.first_argument.source}"
|
99
|
+
elsif dir_env_file_const?(node.receiver)
|
100
|
+
prefer = PREFERRED_METHDOS[node.method_name]
|
126
101
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
INSTANCE_METHOD_DELIMITER = '#'
|
131
|
-
|
132
|
-
def on_send(node)
|
133
|
-
check(node) do |deprecated|
|
134
|
-
prefer = replacement(deprecated)
|
135
|
-
message = format(MSG, current: deprecated, prefer: prefer)
|
136
|
-
current_method = node.loc.selector
|
137
|
-
|
138
|
-
add_offense(current_method, message: message) do |corrector|
|
139
|
-
next unless deprecated.correctable?
|
140
|
-
|
141
|
-
if (preferred_method = prefer.method)
|
142
|
-
corrector.replace(current_method, preferred_method)
|
143
|
-
else
|
144
|
-
corrector.remove(node.loc.dot)
|
145
|
-
corrector.remove(current_method)
|
146
|
-
end
|
147
|
-
end
|
102
|
+
prefer ? "#{node.receiver.source}.#{prefer}" : 'ENV'
|
103
|
+
else
|
104
|
+
PREFERRED_METHDOS[node.method_name]
|
148
105
|
end
|
149
106
|
end
|
150
107
|
|
151
|
-
|
152
|
-
|
153
|
-
def check(node)
|
154
|
-
DEPRECATED_METHODS_OBJECT.each_key do |deprecated|
|
155
|
-
next unless deprecated.class_nodes.include?(node.receiver)
|
156
|
-
next unless node.method?(deprecated.method)
|
157
|
-
|
158
|
-
yield deprecated
|
159
|
-
end
|
108
|
+
def socket_const?(node)
|
109
|
+
node&.short_name == :Socket
|
160
110
|
end
|
161
111
|
|
162
|
-
def
|
163
|
-
|
112
|
+
def dir_env_file_const?(node)
|
113
|
+
DIR_ENV_FILE_CONSTANTS.include?(node&.short_name)
|
164
114
|
end
|
165
115
|
end
|
166
116
|
end
|
@@ -41,6 +41,7 @@ module RuboCop
|
|
41
41
|
# do_that
|
42
42
|
# end
|
43
43
|
class ElseLayout < Base
|
44
|
+
include Alignment
|
44
45
|
include RangeHelp
|
45
46
|
extend AutoCorrector
|
46
47
|
|
@@ -81,12 +82,7 @@ module RuboCop
|
|
81
82
|
corrector.insert_after(node.loc.else, "\n")
|
82
83
|
|
83
84
|
blank_range = range_between(node.loc.else.end_pos, first_else.loc.expression.begin_pos)
|
84
|
-
indentation
|
85
|
-
corrector.replace(blank_range, indentation)
|
86
|
-
end
|
87
|
-
|
88
|
-
def indentation_width
|
89
|
-
@config.for_cop('Layout/IndentationWidth')['Width'] || 2
|
85
|
+
corrector.replace(blank_range, indentation(node))
|
90
86
|
end
|
91
87
|
end
|
92
88
|
end
|