rubocop 1.6.1 → 1.9.1
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/LICENSE.txt +1 -1
- data/README.md +4 -3
- data/config/default.yml +145 -19
- data/lib/rubocop.rb +16 -1
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +5 -4
- data/lib/rubocop/comment_config.rb +6 -6
- data/lib/rubocop/config.rb +13 -7
- data/lib/rubocop/config_loader.rb +11 -14
- data/lib/rubocop/config_loader_resolver.rb +21 -4
- data/lib/rubocop/config_obsoletion.rb +5 -3
- data/lib/rubocop/config_store.rb +12 -1
- data/lib/rubocop/cop/base.rb +2 -1
- data/lib/rubocop/cop/exclude_limit.rb +26 -0
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +3 -2
- data/lib/rubocop/cop/generator.rb +1 -3
- data/lib/rubocop/cop/internal_affairs.rb +6 -1
- data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +68 -0
- data/lib/rubocop/cop/internal_affairs/example_description.rb +89 -0
- data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +61 -0
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +64 -0
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +145 -0
- data/lib/rubocop/cop/layout/class_structure.rb +7 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +56 -20
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +16 -2
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +14 -0
- data/lib/rubocop/cop/layout/line_length.rb +2 -1
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -10
- data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +1 -0
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
- data/lib/rubocop/cop/layout/space_before_brackets.rb +67 -0
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +13 -10
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -2
- data/lib/rubocop/cop/lint/ambiguous_assignment.rb +59 -0
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +7 -2
- data/lib/rubocop/cop/lint/deprecated_constants.rb +80 -0
- data/lib/rubocop/cop/lint/duplicate_branch.rb +64 -2
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +44 -0
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +10 -6
- data/lib/rubocop/cop/lint/number_conversion.rb +41 -6
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +47 -0
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +39 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +2 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +50 -0
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +50 -17
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -11
- data/lib/rubocop/cop/lint/symbol_conversion.rb +103 -0
- data/lib/rubocop/cop/lint/triple_quotes.rb +71 -0
- data/lib/rubocop/cop/lint/unreachable_loop.rb +17 -0
- data/lib/rubocop/cop/message_annotator.rb +4 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
- data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/allowed_identifiers.rb +18 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -0
- data/lib/rubocop/cop/mixin/code_length.rb +3 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +1 -11
- data/lib/rubocop/cop/mixin/configurable_max.rb +1 -0
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +1 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +3 -1
- data/lib/rubocop/cop/mixin/uncommunicative_name.rb +5 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +59 -5
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +38 -5
- data/lib/rubocop/cop/naming/variable_name.rb +2 -0
- data/lib/rubocop/cop/naming/variable_number.rb +2 -9
- data/lib/rubocop/cop/registry.rb +10 -0
- data/lib/rubocop/cop/severity.rb +3 -3
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +3 -1
- data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
- data/lib/rubocop/cop/style/collection_methods.rb +14 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +22 -5
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +49 -9
- data/lib/rubocop/cop/style/empty_literal.rb +6 -2
- data/lib/rubocop/cop/style/endless_method.rb +102 -0
- data/lib/rubocop/cop/style/eval_with_location.rb +63 -34
- data/lib/rubocop/cop/style/explicit_block_argument.rb +10 -0
- data/lib/rubocop/cop/style/float_division.rb +3 -0
- data/lib/rubocop/cop/style/for.rb +2 -0
- data/lib/rubocop/cop/style/format_string_token.rb +18 -2
- data/lib/rubocop/cop/style/hash_except.rb +95 -0
- data/lib/rubocop/cop/style/hash_like_case.rb +2 -1
- data/lib/rubocop/cop/style/if_inside_else.rb +22 -10
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +120 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +12 -2
- data/lib/rubocop/cop/style/lambda_call.rb +2 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +16 -6
- data/lib/rubocop/cop/style/method_def_parentheses.rb +7 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +26 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +3 -1
- data/lib/rubocop/cop/style/mutable_constant.rb +13 -3
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +4 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +3 -0
- data/lib/rubocop/cop/style/non_nil_check.rb +23 -13
- data/lib/rubocop/cop/style/numeric_literals.rb +6 -9
- data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +5 -2
- data/lib/rubocop/cop/style/redundant_argument.rb +7 -1
- data/lib/rubocop/cop/style/redundant_freeze.rb +8 -4
- data/lib/rubocop/cop/style/redundant_return.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +36 -2
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +29 -5
- data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +5 -4
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/while_until_modifier.rb +2 -4
- data/lib/rubocop/cop/util.rb +3 -1
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -0
- data/lib/rubocop/formatter/simple_text_formatter.rb +2 -1
- data/lib/rubocop/magic_comment.rb +30 -1
- data/lib/rubocop/options.rb +10 -10
- data/lib/rubocop/rspec/cop_helper.rb +0 -4
- data/lib/rubocop/rspec/expect_offense.rb +37 -22
- data/lib/rubocop/runner.rb +17 -1
- data/lib/rubocop/target_finder.rb +4 -2
- data/lib/rubocop/target_ruby.rb +47 -11
- data/lib/rubocop/util.rb +16 -0
- data/lib/rubocop/version.rb +8 -2
- metadata +27 -7
@@ -70,6 +70,7 @@ module RuboCop
|
|
70
70
|
return unless outermost_send.loc.end
|
71
71
|
return unless heredoc_arg.first_line != outermost_send.loc.end.line
|
72
72
|
return if subsequent_closing_parentheses_in_same_line?(outermost_send)
|
73
|
+
return if exist_argument_between_heredoc_end_and_closing_parentheses?(node)
|
73
74
|
|
74
75
|
add_offense(outermost_send.loc.end) do |corrector|
|
75
76
|
autocorrect(corrector, outermost_send)
|
@@ -215,6 +216,19 @@ module RuboCop
|
|
215
216
|
end
|
216
217
|
end
|
217
218
|
|
219
|
+
def exist_argument_between_heredoc_end_and_closing_parentheses?(node)
|
220
|
+
return false unless (heredoc_end = find_most_bottom_of_heredoc_end(node.arguments))
|
221
|
+
|
222
|
+
heredoc_end < node.loc.end.begin_pos &&
|
223
|
+
range_between(heredoc_end, node.loc.end.begin_pos).source.strip != ''
|
224
|
+
end
|
225
|
+
|
226
|
+
def find_most_bottom_of_heredoc_end(arguments)
|
227
|
+
arguments.map do |argument|
|
228
|
+
argument.loc.heredoc_end.end_pos if argument.loc.respond_to?(:heredoc_end)
|
229
|
+
end.compact.max
|
230
|
+
end
|
231
|
+
|
218
232
|
# Internal trailing comma helpers.
|
219
233
|
|
220
234
|
def remove_internal_trailing_comma(node, corrector)
|
@@ -60,12 +60,13 @@ module RuboCop
|
|
60
60
|
# }
|
61
61
|
class LineLength < Base
|
62
62
|
include CheckLineBreakable
|
63
|
-
include ConfigurableMax
|
64
63
|
include IgnoredPattern
|
65
64
|
include RangeHelp
|
66
65
|
include LineLengthHelp
|
67
66
|
extend AutoCorrector
|
68
67
|
|
68
|
+
exclude_limit 'Max'
|
69
|
+
|
69
70
|
MSG = 'Line is too long. [%<length>d/%<max>d]'
|
70
71
|
|
71
72
|
def on_block(node)
|
@@ -16,14 +16,14 @@ module RuboCop
|
|
16
16
|
# if a +
|
17
17
|
# b
|
18
18
|
# something &&
|
19
|
-
#
|
19
|
+
# something_else
|
20
20
|
# end
|
21
21
|
#
|
22
22
|
# # good
|
23
23
|
# if a +
|
24
24
|
# b
|
25
25
|
# something &&
|
26
|
-
#
|
26
|
+
# something_else
|
27
27
|
# end
|
28
28
|
#
|
29
29
|
# @example EnforcedStyle: indented
|
@@ -191,16 +191,9 @@ module RuboCop
|
|
191
191
|
end
|
192
192
|
|
193
193
|
def begin_end_alignment_style
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
# config.for_cop('Layout/BeginEndAlignment')['Enabled'] &&
|
198
|
-
# config.for_cop('Layout/BeginEndAlignment')['EnforcedStyleAlignWith']
|
199
|
-
if config.for_all_cops['NewCops'] == 'enable' ||
|
200
|
-
config.for_cop('Layout/BeginEndAlignment')['Enabled'] &&
|
201
|
-
config.for_cop('Layout/BeginEndAlignment')['Enabled'] != 'pending'
|
202
|
-
config.for_cop('Layout/BeginEndAlignment')['EnforcedStyleAlignWith']
|
203
|
-
end
|
194
|
+
begin_end_alignment_conf = config.for_cop('Layout/BeginEndAlignment')
|
195
|
+
|
196
|
+
begin_end_alignment_conf['Enabled'] && begin_end_alignment_conf['EnforcedStyleAlignWith']
|
204
197
|
end
|
205
198
|
end
|
206
199
|
end
|
@@ -106,6 +106,7 @@ module RuboCop
|
|
106
106
|
def space_missing(left_brace)
|
107
107
|
add_offense(left_brace, message: MISSING_MSG) do |corrector|
|
108
108
|
autocorrect(corrector, left_brace)
|
109
|
+
opposite_style_detected
|
109
110
|
end
|
110
111
|
end
|
111
112
|
|
@@ -114,6 +115,7 @@ module RuboCop
|
|
114
115
|
|
115
116
|
add_offense(space, message: DETECTED_MSG) do |corrector|
|
116
117
|
autocorrect(corrector, space)
|
118
|
+
opposite_style_detected
|
117
119
|
end
|
118
120
|
end
|
119
121
|
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Layout
|
6
|
+
# Checks for space between the name of a receiver and a left
|
7
|
+
# brackets.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# collection [index_or_key]
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# collection[index_or_key]
|
16
|
+
#
|
17
|
+
class SpaceBeforeBrackets < Base
|
18
|
+
include RangeHelp
|
19
|
+
extend AutoCorrector
|
20
|
+
|
21
|
+
MSG = 'Remove the space before the opening brackets.'
|
22
|
+
|
23
|
+
def on_send(node)
|
24
|
+
return unless (first_argument = node.first_argument)
|
25
|
+
|
26
|
+
begin_pos = first_argument.source_range.begin_pos
|
27
|
+
return unless (range = offense_range(node, begin_pos))
|
28
|
+
|
29
|
+
register_offense(range)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def offense_range(node, begin_pos)
|
35
|
+
if reference_variable_with_brackets?(node)
|
36
|
+
receiver_end_pos = node.receiver.source_range.end_pos
|
37
|
+
selector_begin_pos = node.loc.selector.begin_pos
|
38
|
+
return if receiver_end_pos >= selector_begin_pos
|
39
|
+
|
40
|
+
range_between(receiver_end_pos, selector_begin_pos)
|
41
|
+
elsif node.method?(:[]=)
|
42
|
+
offense_range_for_assignment(node, begin_pos)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def offense_range_for_assignment(node, begin_pos)
|
47
|
+
end_pos = node.receiver.source_range.end_pos
|
48
|
+
|
49
|
+
return if begin_pos - end_pos == 1 ||
|
50
|
+
(range = range_between(end_pos, begin_pos - 1)).source == '['
|
51
|
+
|
52
|
+
range
|
53
|
+
end
|
54
|
+
|
55
|
+
def register_offense(range)
|
56
|
+
add_offense(range) do |corrector|
|
57
|
+
corrector.remove(range)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def reference_variable_with_brackets?(node)
|
62
|
+
node.receiver&.variable? && node.method?(:[]) && node.arguments.size == 1
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -111,7 +111,8 @@ module RuboCop
|
|
111
111
|
braces_with_contents_inside(node, inner)
|
112
112
|
elsif style_for_empty_braces == :no_space
|
113
113
|
offense(range.begin_pos, range.end_pos,
|
114
|
-
'Space inside empty braces detected.'
|
114
|
+
'Space inside empty braces detected.',
|
115
|
+
'EnforcedStyleForEmptyBraces')
|
115
116
|
end
|
116
117
|
end
|
117
118
|
end
|
@@ -120,7 +121,8 @@ module RuboCop
|
|
120
121
|
return if style_for_empty_braces != :space
|
121
122
|
|
122
123
|
offense(left_brace.begin_pos, right_brace.end_pos,
|
123
|
-
'Space missing inside empty braces.'
|
124
|
+
'Space missing inside empty braces.',
|
125
|
+
'EnforcedStyleForEmptyBraces')
|
124
126
|
end
|
125
127
|
|
126
128
|
def braces_with_contents_inside(node, inner)
|
@@ -164,9 +166,9 @@ module RuboCop
|
|
164
166
|
if left_brace.end_pos == args_delimiter.begin_pos &&
|
165
167
|
cop_config['SpaceBeforeBlockParameters']
|
166
168
|
offense(left_brace.begin_pos, args_delimiter.end_pos,
|
167
|
-
'Space between { and | missing.')
|
168
|
-
|
169
|
-
|
169
|
+
'Space between { and | missing.')
|
170
|
+
else
|
171
|
+
correct_style_detected
|
170
172
|
end
|
171
173
|
else
|
172
174
|
# We indicate the position after the left brace. Otherwise it's
|
@@ -179,11 +181,11 @@ module RuboCop
|
|
179
181
|
|
180
182
|
def space_inside_left_brace(left_brace, args_delimiter)
|
181
183
|
if pipe?(args_delimiter)
|
182
|
-
|
184
|
+
if cop_config['SpaceBeforeBlockParameters']
|
185
|
+
correct_style_detected
|
186
|
+
else
|
183
187
|
offense(left_brace.end_pos, args_delimiter.begin_pos,
|
184
|
-
'Space between { and | detected.')
|
185
|
-
opposite_style_detected
|
186
|
-
end
|
188
|
+
'Space between { and | detected.')
|
187
189
|
end
|
188
190
|
else
|
189
191
|
brace_with_space = range_with_surrounding_space(range: left_brace,
|
@@ -220,7 +222,7 @@ module RuboCop
|
|
220
222
|
end
|
221
223
|
end
|
222
224
|
|
223
|
-
def offense(begin_pos, end_pos, msg)
|
225
|
+
def offense(begin_pos, end_pos, msg, style_param = 'EnforcedStyle')
|
224
226
|
range = range_between(begin_pos, end_pos)
|
225
227
|
add_offense(range, message: msg) do |corrector|
|
226
228
|
case range.source
|
@@ -229,6 +231,7 @@ module RuboCop
|
|
229
231
|
when '{|' then corrector.replace(range, '{ |')
|
230
232
|
else corrector.insert_before(range, ' ')
|
231
233
|
end
|
234
|
+
opposite_style_detected if style_param == 'EnforcedStyle'
|
232
235
|
end
|
233
236
|
end
|
234
237
|
|
@@ -112,13 +112,13 @@ module RuboCop
|
|
112
112
|
|
113
113
|
def incorrect_style_detected(token1, token2,
|
114
114
|
expect_space, is_empty_braces)
|
115
|
-
return unless ambiguous_or_unexpected_style_detected(style, token1.text == token2.text)
|
116
|
-
|
117
115
|
brace = (token1.text == '{' ? token1 : token2).pos
|
118
116
|
range = expect_space ? brace : space_range(brace)
|
117
|
+
detected_style = expect_space ? 'no_space' : 'space'
|
119
118
|
|
120
119
|
add_offense(range, message: message(brace, is_empty_braces, expect_space)) do |corrector|
|
121
120
|
autocorrect(corrector, range)
|
121
|
+
ambiguous_or_unexpected_style_detected(detected_style, token1.text == token2.text)
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks for mistyped shorthand assignments.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# x =- y
|
11
|
+
# x =+ y
|
12
|
+
# x =* y
|
13
|
+
# x =! y
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# x -= y # or x = -y
|
17
|
+
# x += y # or x = +y
|
18
|
+
# x *= y # or x = *y
|
19
|
+
# x != y # or x = !y
|
20
|
+
#
|
21
|
+
class AmbiguousAssignment < Base
|
22
|
+
include RangeHelp
|
23
|
+
|
24
|
+
MSG = 'Suspicious assignment detected. Did you mean `%<op>s`?'
|
25
|
+
|
26
|
+
SIMPLE_ASSIGNMENT_TYPES = %i[lvasgn ivasgn cvasgn gvasgn casgn].freeze
|
27
|
+
|
28
|
+
MISTAKES = {
|
29
|
+
'=-' => '-=',
|
30
|
+
'=+' => '+=',
|
31
|
+
'=*' => '*=',
|
32
|
+
'=!' => '!='
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
def on_asgn(node)
|
36
|
+
return unless (rhs = rhs(node))
|
37
|
+
|
38
|
+
range = range_between(node.loc.operator.end_pos - 1, rhs.source_range.begin_pos + 1)
|
39
|
+
source = range.source
|
40
|
+
return unless MISTAKES.key?(source)
|
41
|
+
|
42
|
+
add_offense(range, message: format(MSG, op: MISTAKES[source]))
|
43
|
+
end
|
44
|
+
|
45
|
+
SIMPLE_ASSIGNMENT_TYPES.each { |asgn_type| alias_method :"on_#{asgn_type}", :on_asgn }
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def rhs(node)
|
50
|
+
if node.casgn_type?
|
51
|
+
node.children[2]
|
52
|
+
else
|
53
|
+
node.children[1]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -17,6 +17,7 @@ module RuboCop
|
|
17
17
|
#
|
18
18
|
# @example
|
19
19
|
# # bad
|
20
|
+
# x / x
|
20
21
|
# x.top >= x.top
|
21
22
|
#
|
22
23
|
# if a.x != 0 && a.x != 0
|
@@ -27,15 +28,19 @@ module RuboCop
|
|
27
28
|
# left_child || left_child
|
28
29
|
# end
|
29
30
|
#
|
31
|
+
# # good
|
32
|
+
# x + x
|
33
|
+
# 1 << 1
|
34
|
+
#
|
30
35
|
class BinaryOperatorWithIdenticalOperands < Base
|
31
36
|
MSG = 'Binary operator `%<op>s` has identical operands.'
|
32
|
-
|
37
|
+
ALLOWED_MATH_OPERATORS = %i[+ * ** << >>].to_set.freeze
|
33
38
|
|
34
39
|
def on_send(node)
|
35
40
|
return unless node.binary_operation?
|
36
41
|
|
37
42
|
lhs, operation, rhs = *node
|
38
|
-
return if
|
43
|
+
return if ALLOWED_MATH_OPERATORS.include?(node.method_name)
|
39
44
|
|
40
45
|
add_offense(node, message: format(MSG, op: operation)) if lhs == rhs
|
41
46
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks for deprecated constants.
|
7
|
+
#
|
8
|
+
# It has `DeprecatedConstants` config. If there is an alternative method, you can set
|
9
|
+
# alternative value as `Alternative`. And you can set the deprecated version as
|
10
|
+
# `DeprecatedVersion`. These options can be omitted if they are not needed.
|
11
|
+
#
|
12
|
+
# DeprecatedConstants:
|
13
|
+
# 'DEPRECATED_CONSTANT':
|
14
|
+
# Alternative: 'alternative_value'
|
15
|
+
# DeprecatedVersion: 'deprecated_version'
|
16
|
+
#
|
17
|
+
# By default, `NIL`, `TRUE`, `FALSE` and `Random::DEFAULT` are configured.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
#
|
21
|
+
# # bad
|
22
|
+
# NIL
|
23
|
+
# TRUE
|
24
|
+
# FALSE
|
25
|
+
# Random::DEFAULT # Return value of Ruby 2 is `Random` instance, Ruby 3.0 is `Random` class.
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# nil
|
29
|
+
# true
|
30
|
+
# false
|
31
|
+
# Random.new # `::DEFAULT` has been deprecated in Ruby 3, `.new` is compatible with Ruby 2.
|
32
|
+
#
|
33
|
+
class DeprecatedConstants < Base
|
34
|
+
extend AutoCorrector
|
35
|
+
|
36
|
+
SUGGEST_GOOD_MSG = 'Use `%<good>s` instead of `%<bad>s`%<deprecated_message>s.'
|
37
|
+
DO_NOT_USE_MSG = 'Do not use `%<bad>s`%<deprecated_message>s.'
|
38
|
+
|
39
|
+
def on_const(node)
|
40
|
+
# FIXME: Workaround for "`undefined method `expression' for nil:NilClass`" when processing
|
41
|
+
# `__ENCODING__`. It is better to be able to work without this condition.
|
42
|
+
# Maybe further investigation of RuboCop AST will lead to an essential solution.
|
43
|
+
return unless node.loc
|
44
|
+
|
45
|
+
constant = node.absolute? ? consntant_name(node, node.short_name.to_s) : node.source
|
46
|
+
return unless (deprecated_constant = deprecated_constants[constant])
|
47
|
+
|
48
|
+
alternative = deprecated_constant['Alternative']
|
49
|
+
version = deprecated_constant['DeprecatedVersion']
|
50
|
+
|
51
|
+
add_offense(node, message: message(alternative, node.source, version)) do |corrector|
|
52
|
+
corrector.replace(node, alternative)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def consntant_name(node, nested_constant_name)
|
59
|
+
return nested_constant_name unless node.namespace.const_type?
|
60
|
+
|
61
|
+
consntant_name(node.namespace, "#{node.namespace.short_name}::#{nested_constant_name}")
|
62
|
+
end
|
63
|
+
|
64
|
+
def message(good, bad, deprecated_version)
|
65
|
+
deprecated_message = ", deprecated since Ruby #{deprecated_version}" if deprecated_version
|
66
|
+
|
67
|
+
if good
|
68
|
+
format(SUGGEST_GOOD_MSG, good: good, bad: bad, deprecated_message: deprecated_message)
|
69
|
+
else
|
70
|
+
format(DO_NOT_USE_MSG, bad: bad, deprecated_message: deprecated_message)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def deprecated_constants
|
75
|
+
cop_config.fetch('DeprecatedConstants', {})
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -6,6 +6,15 @@ module RuboCop
|
|
6
6
|
# This cop checks that there are no repeated bodies
|
7
7
|
# within `if/unless`, `case-when` and `rescue` constructs.
|
8
8
|
#
|
9
|
+
# With `IgnoreLiteralBranches: true`, branches are not registered
|
10
|
+
# as offenses if they return a basic literal value (string, symbol,
|
11
|
+
# integer, float, rational, complex, `true`, `false`, or `nil`), or
|
12
|
+
# return an array, hash, regexp or range that only contains one of
|
13
|
+
# the above basic literal values.
|
14
|
+
#
|
15
|
+
# With `IgnoreConstantBranches: true`, branches are not registered
|
16
|
+
# as offenses if they return a constant value.
|
17
|
+
#
|
9
18
|
# @example
|
10
19
|
# # bad
|
11
20
|
# if foo
|
@@ -56,14 +65,33 @@ module RuboCop
|
|
56
65
|
# handle_error
|
57
66
|
# end
|
58
67
|
#
|
68
|
+
# @example IgnoreLiteralBranches: true
|
69
|
+
# # good
|
70
|
+
# case size
|
71
|
+
# when "small" then 100
|
72
|
+
# when "medium" then 250
|
73
|
+
# when "large" then 1000
|
74
|
+
# else 250
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# @example IgnoreLiteralBranches: true
|
78
|
+
# # good
|
79
|
+
# case size
|
80
|
+
# when "small" then SMALL_SIZE
|
81
|
+
# when "medium" then MEDIUM_SIZE
|
82
|
+
# when "large" then LARGE_SIZE
|
83
|
+
# else MEDIUM_SIZE
|
84
|
+
# end
|
85
|
+
#
|
59
86
|
class DuplicateBranch < Base
|
60
87
|
include RescueNode
|
61
88
|
|
62
89
|
MSG = 'Duplicate branch body detected.'
|
63
90
|
|
64
91
|
def on_branching_statement(node)
|
65
|
-
branches
|
66
|
-
|
92
|
+
branches(node).each_with_object(Set.new) do |branch, previous|
|
93
|
+
next unless consider_branch?(branch)
|
94
|
+
|
67
95
|
add_offense(offense_range(branch)) unless previous.add?(branch)
|
68
96
|
end
|
69
97
|
end
|
@@ -87,6 +115,40 @@ module RuboCop
|
|
87
115
|
parent.source_range
|
88
116
|
end
|
89
117
|
end
|
118
|
+
|
119
|
+
def branches(node)
|
120
|
+
node.branches.compact
|
121
|
+
end
|
122
|
+
|
123
|
+
def consider_branch?(branch)
|
124
|
+
return false if ignore_literal_branches? && literal_branch?(branch)
|
125
|
+
return false if ignore_constant_branches? && const_branch?(branch)
|
126
|
+
|
127
|
+
true
|
128
|
+
end
|
129
|
+
|
130
|
+
def ignore_literal_branches?
|
131
|
+
cop_config.fetch('IgnoreLiteralBranches', false)
|
132
|
+
end
|
133
|
+
|
134
|
+
def ignore_constant_branches?
|
135
|
+
cop_config.fetch('IgnoreConstantBranches', false)
|
136
|
+
end
|
137
|
+
|
138
|
+
def literal_branch?(branch) # rubocop:disable Metrics/CyclomaticComplexity
|
139
|
+
return false if !branch.literal? || branch.xstr_type?
|
140
|
+
return true if branch.basic_literal?
|
141
|
+
|
142
|
+
branch.each_descendant.all? do |node|
|
143
|
+
node.basic_literal? ||
|
144
|
+
node.pair_type? || # hash keys and values are contained within a `pair` node
|
145
|
+
(node.const_type? && ignore_constant_branches?)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def const_branch?(branch)
|
150
|
+
branch.const_type?
|
151
|
+
end
|
90
152
|
end
|
91
153
|
end
|
92
154
|
end
|