rubocop 1.34.1 → 1.35.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +22 -0
- data/lib/rubocop/cli/command/{auto_genenerate_config.rb → auto_generate_config.rb} +0 -0
- data/lib/rubocop/config.rb +1 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +32 -2
- data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
- data/lib/rubocop/cop/generator/require_file_injector.rb +2 -2
- data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +69 -0
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/block_alignment.rb +2 -0
- data/lib/rubocop/cop/layout/block_end_newline.rb +2 -0
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +2 -0
- data/lib/rubocop/cop/layout/end_of_line.rb +4 -4
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/indentation_width.rb +2 -0
- data/lib/rubocop/cop/layout/line_length.rb +4 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +9 -9
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +4 -0
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +25 -6
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +6 -6
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +12 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +9 -3
- data/lib/rubocop/cop/lint/redundant_with_index.rb +13 -10
- data/lib/rubocop/cop/lint/redundant_with_object.rb +12 -11
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_loop.rb +7 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +6 -4
- data/lib/rubocop/cop/lint/void.rb +2 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +76 -1
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +4 -4
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/range_help.rb +2 -3
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +2 -2
- data/lib/rubocop/cop/style/arguments_forwarding.rb +2 -2
- data/lib/rubocop/cop/style/class_methods_definitions.rb +2 -1
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/each_with_object.rb +39 -8
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/for.rb +2 -0
- data/lib/rubocop/cop/style/guard_clause.rb +27 -16
- data/lib/rubocop/cop/style/hash_each_methods.rb +3 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +17 -0
- data/lib/rubocop/cop/style/inverse_methods.rb +8 -6
- data/lib/rubocop/cop/style/magic_comment_format.rb +307 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +4 -1
- data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -1
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
- data/lib/rubocop/cop/style/next.rb +3 -5
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +2 -0
- data/lib/rubocop/cop/style/proc.rb +4 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +2 -0
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
- data/lib/rubocop/cop/style/redundant_self.rb +2 -0
- data/lib/rubocop/cop/style/redundant_sort_by.rb +24 -8
- data/lib/rubocop/cop/style/safe_navigation.rb +4 -2
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +0 -2
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -1
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/feature_loader.rb +6 -2
- data/lib/rubocop/formatter/html_formatter.rb +2 -2
- data/lib/rubocop/server/cache.rb +11 -8
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +3 -2
- metadata +9 -7
@@ -7,6 +7,11 @@ module RuboCop
|
|
7
7
|
# `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`, and `equal?` methods
|
8
8
|
# are checked by default. These are customizable with `AllowedMethods` option.
|
9
9
|
#
|
10
|
+
# The `AllowedMethods` option specifies nil-safe methods,
|
11
|
+
# in other words, it is a method that is allowed to skip safe navigation.
|
12
|
+
# Note that the `AllowedMethod` option is not an option that specifies methods
|
13
|
+
# for which to suppress (allow) this cop's check.
|
14
|
+
#
|
10
15
|
# In the example below, the safe navigation operator (`&.`) is unnecessary
|
11
16
|
# because `NilClass` has methods like `respond_to?` and `is_a?`.
|
12
17
|
#
|
@@ -35,12 +40,13 @@ module RuboCop
|
|
35
40
|
# # good - without `&.` this will always return `true`
|
36
41
|
# foo&.respond_to?(:to_a)
|
37
42
|
#
|
38
|
-
# @example AllowedMethods: [
|
43
|
+
# @example AllowedMethods: [nil_safe_method]
|
39
44
|
# # bad
|
40
|
-
# do_something if attrs&.
|
45
|
+
# do_something if attrs&.nil_safe_method(:[])
|
41
46
|
#
|
42
47
|
# # good
|
43
|
-
# do_something if attrs
|
48
|
+
# do_something if attrs.nil_safe_method(:[])
|
49
|
+
# do_something if attrs&.not_nil_safe_method(:[])
|
44
50
|
#
|
45
51
|
class RedundantSafeNavigation < Base
|
46
52
|
include AllowedMethods
|
@@ -33,16 +33,6 @@ module RuboCop
|
|
33
33
|
MSG_EACH_WITH_INDEX = 'Use `each` instead of `each_with_index`.'
|
34
34
|
MSG_WITH_INDEX = 'Remove redundant `with_index`.'
|
35
35
|
|
36
|
-
# @!method redundant_with_index?(node)
|
37
|
-
def_node_matcher :redundant_with_index?, <<~PATTERN
|
38
|
-
(block
|
39
|
-
$(send
|
40
|
-
_ {:each_with_index :with_index} ...)
|
41
|
-
(args
|
42
|
-
(arg _))
|
43
|
-
...)
|
44
|
-
PATTERN
|
45
|
-
|
46
36
|
def on_block(node)
|
47
37
|
return unless (send = redundant_with_index?(node))
|
48
38
|
|
@@ -58,8 +48,21 @@ module RuboCop
|
|
58
48
|
end
|
59
49
|
end
|
60
50
|
|
51
|
+
alias on_numblock on_block
|
52
|
+
|
61
53
|
private
|
62
54
|
|
55
|
+
# @!method redundant_with_index?(node)
|
56
|
+
def_node_matcher :redundant_with_index?, <<~PATTERN
|
57
|
+
{
|
58
|
+
(block
|
59
|
+
$(send _ {:each_with_index :with_index} ...)
|
60
|
+
(args (arg _)) ...)
|
61
|
+
(numblock
|
62
|
+
$(send _ {:each_with_index :with_index} ...) 1 ...)
|
63
|
+
}
|
64
|
+
PATTERN
|
65
|
+
|
63
66
|
def message(node)
|
64
67
|
if node.method?(:each_with_index)
|
65
68
|
MSG_EACH_WITH_INDEX
|
@@ -31,19 +31,8 @@ module RuboCop
|
|
31
31
|
extend AutoCorrector
|
32
32
|
|
33
33
|
MSG_EACH_WITH_OBJECT = 'Use `each` instead of `each_with_object`.'
|
34
|
-
|
35
34
|
MSG_WITH_OBJECT = 'Remove redundant `with_object`.'
|
36
35
|
|
37
|
-
# @!method redundant_with_object?(node)
|
38
|
-
def_node_matcher :redundant_with_object?, <<~PATTERN
|
39
|
-
(block
|
40
|
-
$(send _ {:each_with_object :with_object}
|
41
|
-
_)
|
42
|
-
(args
|
43
|
-
(arg _))
|
44
|
-
...)
|
45
|
-
PATTERN
|
46
|
-
|
47
36
|
def on_block(node)
|
48
37
|
return unless (send = redundant_with_object?(node))
|
49
38
|
|
@@ -59,8 +48,20 @@ module RuboCop
|
|
59
48
|
end
|
60
49
|
end
|
61
50
|
|
51
|
+
alias on_numblock on_block
|
52
|
+
|
62
53
|
private
|
63
54
|
|
55
|
+
# @!method redundant_with_object?(node)
|
56
|
+
def_node_matcher :redundant_with_object?, <<~PATTERN
|
57
|
+
{
|
58
|
+
(block
|
59
|
+
$(send _ {:each_with_object :with_object} _) (args (arg _)) ...)
|
60
|
+
(numblock
|
61
|
+
$(send _ {:each_with_object :with_object} _) 1 ...)
|
62
|
+
}
|
63
|
+
PATTERN
|
64
|
+
|
64
65
|
def message(node)
|
65
66
|
if node.method?(:each_with_object)
|
66
67
|
MSG_EACH_WITH_OBJECT
|
@@ -69,6 +69,7 @@ module RuboCop
|
|
69
69
|
|
70
70
|
outer_local_variable_node =
|
71
71
|
find_conditional_node_from_ascendant(outer_local_variable.declaration_node)
|
72
|
+
return true unless outer_local_variable_node
|
72
73
|
|
73
74
|
outer_local_variable_node.conditional? && variable_node == outer_local_variable_node
|
74
75
|
end
|
@@ -101,10 +101,14 @@ module RuboCop
|
|
101
101
|
check(node) if loop_method?(node)
|
102
102
|
end
|
103
103
|
|
104
|
+
def on_numblock(node)
|
105
|
+
check(node) if loop_method?(node)
|
106
|
+
end
|
107
|
+
|
104
108
|
private
|
105
109
|
|
106
110
|
def loop_method?(node)
|
107
|
-
return false unless node.block_type?
|
111
|
+
return false unless node.block_type? || node.numblock_type?
|
108
112
|
|
109
113
|
send_node = node.send_node
|
110
114
|
return false if matches_allowed_pattern?(send_node.source)
|
@@ -179,6 +183,8 @@ module RuboCop
|
|
179
183
|
|
180
184
|
def preceded_by_continue_statement?(break_statement)
|
181
185
|
break_statement.left_siblings.any? do |sibling|
|
186
|
+
# Numblocks have the arguments count as a number in the AST.
|
187
|
+
next if sibling.is_a?(Integer)
|
182
188
|
next if sibling.loop_keyword? || loop_method?(sibling)
|
183
189
|
|
184
190
|
sibling.each_descendant(*CONTINUE_KEYWORDS).any?
|
@@ -142,6 +142,8 @@ module RuboCop
|
|
142
142
|
check_node(node.body)
|
143
143
|
end
|
144
144
|
|
145
|
+
alias on_numblock on_block
|
146
|
+
|
145
147
|
private
|
146
148
|
|
147
149
|
def autocorrect(corrector, node)
|
@@ -157,17 +159,17 @@ module RuboCop
|
|
157
159
|
|
158
160
|
# @!method dynamic_method_definition?(node)
|
159
161
|
def_node_matcher :dynamic_method_definition?, <<~PATTERN
|
160
|
-
{(send nil? :define_method ...) (block (send nil? :define_method ...) ...)}
|
162
|
+
{(send nil? :define_method ...) ({block numblock} (send nil? :define_method ...) ...)}
|
161
163
|
PATTERN
|
162
164
|
|
163
165
|
# @!method class_or_instance_eval?(node)
|
164
166
|
def_node_matcher :class_or_instance_eval?, <<~PATTERN
|
165
|
-
(block (send _ {:class_eval :instance_eval}) ...)
|
167
|
+
({block numblock} (send _ {:class_eval :instance_eval}) ...)
|
166
168
|
PATTERN
|
167
169
|
|
168
170
|
# @!method class_or_module_or_struct_new_call?(node)
|
169
171
|
def_node_matcher :class_or_module_or_struct_new_call?, <<~PATTERN
|
170
|
-
(block (send (const {nil? cbase} {:Class :Module :Struct}) :new ...) ...)
|
172
|
+
({block numblock} (send (const {nil? cbase} {:Class :Module :Struct}) :new ...) ...)
|
171
173
|
PATTERN
|
172
174
|
|
173
175
|
def check_node(node)
|
@@ -277,7 +279,7 @@ module RuboCop
|
|
277
279
|
matcher_name = "#{m}_block?".to_sym
|
278
280
|
unless respond_to?(matcher_name)
|
279
281
|
self.class.def_node_matcher matcher_name, <<~PATTERN
|
280
|
-
(block (send {nil? const} {:#{m}} ...) ...)
|
282
|
+
({block numblock} (send {nil? const} {:#{m}} ...) ...)
|
281
283
|
PATTERN
|
282
284
|
end
|
283
285
|
|
@@ -5,7 +5,22 @@ module RuboCop
|
|
5
5
|
# This module checks for Ruby 3.1's hash value omission syntax.
|
6
6
|
module HashShorthandSyntax
|
7
7
|
OMIT_HASH_VALUE_MSG = 'Omit the hash value.'
|
8
|
-
EXPLICIT_HASH_VALUE_MSG = '
|
8
|
+
EXPLICIT_HASH_VALUE_MSG = 'Include the hash value.'
|
9
|
+
DO_NOT_MIX_MSG_PREFIX = 'Do not mix explicit and implicit hash values.'
|
10
|
+
DO_NOT_MIX_OMIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{OMIT_HASH_VALUE_MSG}"
|
11
|
+
DO_NOT_MIX_EXPLICIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{EXPLICIT_HASH_VALUE_MSG}"
|
12
|
+
|
13
|
+
def on_hash_for_mixed_shorthand(hash_node)
|
14
|
+
return if ignore_mixed_hash_shorthand_syntax?(hash_node)
|
15
|
+
|
16
|
+
hash_value_type_breakdown = breakdown_value_types_of_hash(hash_node)
|
17
|
+
|
18
|
+
if hash_with_mixed_shorthand_syntax?(hash_value_type_breakdown)
|
19
|
+
mixed_shorthand_syntax_check(hash_value_type_breakdown)
|
20
|
+
else
|
21
|
+
no_mixed_shorthand_syntax_check(hash_value_type_breakdown)
|
22
|
+
end
|
23
|
+
end
|
9
24
|
|
10
25
|
def on_pair(node)
|
11
26
|
return if ignore_hash_shorthand_syntax?(node)
|
@@ -36,8 +51,14 @@ module RuboCop
|
|
36
51
|
end
|
37
52
|
end
|
38
53
|
|
54
|
+
def ignore_mixed_hash_shorthand_syntax?(hash_node)
|
55
|
+
target_ruby_version <= 3.0 || enforced_shorthand_syntax != 'consistent' ||
|
56
|
+
!hash_node.hash_type?
|
57
|
+
end
|
58
|
+
|
39
59
|
def ignore_hash_shorthand_syntax?(pair_node)
|
40
60
|
target_ruby_version <= 3.0 || enforced_shorthand_syntax == 'either' ||
|
61
|
+
enforced_shorthand_syntax == 'consistent' ||
|
41
62
|
!pair_node.parent.hash_type?
|
42
63
|
end
|
43
64
|
|
@@ -81,6 +102,60 @@ module RuboCop
|
|
81
102
|
|
82
103
|
ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized? && !!right_sibling
|
83
104
|
end
|
105
|
+
|
106
|
+
def breakdown_value_types_of_hash(hash_node)
|
107
|
+
hash_node.pairs.group_by do |pair_node|
|
108
|
+
if pair_node.value_omission?
|
109
|
+
:value_omitted
|
110
|
+
elsif require_hash_value?(pair_node.key.source, pair_node)
|
111
|
+
:value_needed
|
112
|
+
else
|
113
|
+
:value_omittable
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def hash_with_mixed_shorthand_syntax?(hash_value_type_breakdown)
|
119
|
+
hash_value_type_breakdown.keys.size > 1
|
120
|
+
end
|
121
|
+
|
122
|
+
def hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
|
123
|
+
hash_value_type_breakdown[:value_needed]&.any?
|
124
|
+
end
|
125
|
+
|
126
|
+
def each_omitted_value_pair(hash_value_type_breakdown, &block)
|
127
|
+
hash_value_type_breakdown[:value_omitted]&.each(&block)
|
128
|
+
end
|
129
|
+
|
130
|
+
def each_omittable_value_pair(hash_value_type_breakdown, &block)
|
131
|
+
hash_value_type_breakdown[:value_omittable]&.each(&block)
|
132
|
+
end
|
133
|
+
|
134
|
+
def mixed_shorthand_syntax_check(hash_value_type_breakdown)
|
135
|
+
if hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
|
136
|
+
each_omitted_value_pair(hash_value_type_breakdown) do |pair_node|
|
137
|
+
hash_key_source = pair_node.key.source
|
138
|
+
replacement = "#{hash_key_source}: #{hash_key_source}"
|
139
|
+
register_offense(pair_node, DO_NOT_MIX_EXPLICIT_VALUE_MSG, replacement)
|
140
|
+
end
|
141
|
+
else
|
142
|
+
each_omittable_value_pair(hash_value_type_breakdown) do |pair_node|
|
143
|
+
hash_key_source = pair_node.key.source
|
144
|
+
replacement = "#{hash_key_source}:"
|
145
|
+
register_offense(pair_node, DO_NOT_MIX_OMIT_VALUE_MSG, replacement)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def no_mixed_shorthand_syntax_check(hash_value_type_breakdown)
|
151
|
+
return if hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
|
152
|
+
|
153
|
+
each_omittable_value_pair(hash_value_type_breakdown) do |pair_node|
|
154
|
+
hash_key_source = pair_node.key.source
|
155
|
+
replacement = "#{hash_key_source}:"
|
156
|
+
register_offense(pair_node, OMIT_HASH_VALUE_MSG, replacement)
|
157
|
+
end
|
158
|
+
end
|
84
159
|
end
|
85
160
|
end
|
86
161
|
end
|
@@ -14,7 +14,7 @@ module RuboCop
|
|
14
14
|
{(array ...) (send _ :each_with_index) (send _ :with_index _ ?) (send _ :zip ...)}
|
15
15
|
PATTERN
|
16
16
|
|
17
|
-
def on_block(node)
|
17
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
18
18
|
on_bad_each_with_object(node) do |*match|
|
19
19
|
handle_possible_offense(node, match, 'each_with_object')
|
20
20
|
end
|
@@ -29,14 +29,14 @@ module RuboCop
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
alias on_numblock on_block
|
33
|
+
|
32
34
|
private
|
33
35
|
|
34
36
|
# @!method define_method?(node)
|
35
37
|
def_node_matcher :define_method?, <<~PATTERN
|
36
|
-
(block
|
37
|
-
(send nil? :define_method ({sym str} $_))
|
38
|
-
args
|
39
|
-
_)
|
38
|
+
({block numblock}
|
39
|
+
(send nil? :define_method ({sym str} $_)) _ _)
|
40
40
|
PATTERN
|
41
41
|
|
42
42
|
def check_complexity(node, method_name)
|
@@ -57,7 +57,7 @@ module RuboCop
|
|
57
57
|
end
|
58
58
|
|
59
59
|
if left_parenthesis && style == :special_inside_parentheses
|
60
|
-
return [left_parenthesis.column + 1, :
|
60
|
+
return [left_parenthesis.column + 1, :first_column_after_left_parenthesis]
|
61
61
|
end
|
62
62
|
|
63
63
|
[left_brace.source_line =~ /\S/, :start_of_line]
|
@@ -70,9 +70,8 @@ module RuboCop
|
|
70
70
|
Parser::Source::Range.new(buffer, begin_pos, end_pos)
|
71
71
|
end
|
72
72
|
|
73
|
-
def range_by_whole_lines(range, include_final_newline: false
|
74
|
-
|
75
|
-
|
73
|
+
def range_by_whole_lines(range, include_final_newline: false,
|
74
|
+
buffer: @processed_source.buffer)
|
76
75
|
last_line = buffer.source_line(range.last_line)
|
77
76
|
end_offset = last_line.length - range.last_column
|
78
77
|
end_offset += 1 if include_final_newline
|
@@ -72,10 +72,10 @@ module RuboCop
|
|
72
72
|
PATTERN
|
73
73
|
|
74
74
|
def allowed_conditional_expression_on_rhs?(node)
|
75
|
-
node&.if_type? &&
|
75
|
+
node&.if_type? && contains_constant?(node)
|
76
76
|
end
|
77
77
|
|
78
|
-
def
|
78
|
+
def contains_constant?(node)
|
79
79
|
node.branches.any?(&:const_type?)
|
80
80
|
end
|
81
81
|
end
|
@@ -73,11 +73,11 @@ module RuboCop
|
|
73
73
|
{
|
74
74
|
(send _ _
|
75
75
|
(splat (lvar %1))
|
76
|
-
(block-pass (lvar %2)))
|
76
|
+
(block-pass {(lvar %2) nil?}))
|
77
77
|
(send _ _
|
78
78
|
(splat (lvar %1))
|
79
79
|
(hash (kwsplat (lvar %3)))
|
80
|
-
(block-pass (lvar %2)))
|
80
|
+
(block-pass {(lvar %2) nil?}))
|
81
81
|
}
|
82
82
|
PATTERN
|
83
83
|
|
@@ -70,7 +70,7 @@ module RuboCop
|
|
70
70
|
|
71
71
|
def on_sclass(node)
|
72
72
|
return unless def_self_style?
|
73
|
-
return unless node.identifier.
|
73
|
+
return unless node.identifier.self_type?
|
74
74
|
return unless all_methods_public?(node)
|
75
75
|
|
76
76
|
add_offense(node, message: MSG_SCLASS) do |corrector|
|
@@ -80,6 +80,7 @@ module RuboCop
|
|
80
80
|
|
81
81
|
def on_defs(node)
|
82
82
|
return if def_self_style?
|
83
|
+
return unless node.receiver.self_type?
|
83
84
|
|
84
85
|
message = format(MSG, preferred: 'class << self')
|
85
86
|
add_offense(node, message: message)
|
@@ -66,6 +66,8 @@ module RuboCop
|
|
66
66
|
add_offense(node) if same_collection_looping?(node, node.left_sibling)
|
67
67
|
end
|
68
68
|
|
69
|
+
alias on_numblock on_block
|
70
|
+
|
69
71
|
def on_for(node)
|
70
72
|
return unless node.parent&.begin_type?
|
71
73
|
|
@@ -82,7 +84,7 @@ module RuboCop
|
|
82
84
|
end
|
83
85
|
|
84
86
|
def same_collection_looping?(node, sibling)
|
85
|
-
sibling&.block_type? &&
|
87
|
+
(sibling&.block_type? || sibling&.numblock_type?) &&
|
86
88
|
sibling.send_node.method?(node.method_name) &&
|
87
89
|
sibling.receiver == node.receiver &&
|
88
90
|
sibling.send_node.arguments == node.send_node.arguments
|
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
|
28
28
|
MSG = 'Use `Integer#times` for a simple loop which iterates a fixed number of times.'
|
29
29
|
|
30
|
-
def on_block(node)
|
30
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
31
31
|
return unless offending_each_range(node)
|
32
32
|
|
33
33
|
send_node = node.send_node
|
@@ -23,13 +23,8 @@ module RuboCop
|
|
23
23
|
MSG = 'Use `each_with_object` instead of `%<method>s`.'
|
24
24
|
METHODS = %i[inject reduce].freeze
|
25
25
|
|
26
|
-
# @!method each_with_object_candidate?(node)
|
27
|
-
def_node_matcher :each_with_object_candidate?, <<~PATTERN
|
28
|
-
(block $(send _ {:inject :reduce} _) $_ $_)
|
29
|
-
PATTERN
|
30
|
-
|
31
26
|
def on_block(node)
|
32
|
-
|
27
|
+
each_with_object_block_candidate?(node) do |method, args, body|
|
33
28
|
_, method_name, method_arg = *method
|
34
29
|
return if simple_method_arg?(method_arg)
|
35
30
|
|
@@ -40,14 +35,38 @@ module RuboCop
|
|
40
35
|
|
41
36
|
message = format(MSG, method: method_name)
|
42
37
|
add_offense(method.loc.selector, message: message) do |corrector|
|
43
|
-
|
38
|
+
autocorrect_block(corrector, node, return_value)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def on_numblock(node)
|
44
|
+
each_with_object_numblock_candidate?(node) do |method, body|
|
45
|
+
_, method_name, method_arg = *method
|
46
|
+
return if simple_method_arg?(method_arg)
|
47
|
+
|
48
|
+
return unless return_value(body)&.source == '_1'
|
49
|
+
|
50
|
+
message = format(MSG, method: method_name)
|
51
|
+
add_offense(method.loc.selector, message: message) do |corrector|
|
52
|
+
autocorrect_numblock(corrector, node)
|
44
53
|
end
|
45
54
|
end
|
46
55
|
end
|
47
56
|
|
48
57
|
private
|
49
58
|
|
50
|
-
|
59
|
+
# @!method each_with_object_block_candidate?(node)
|
60
|
+
def_node_matcher :each_with_object_block_candidate?, <<~PATTERN
|
61
|
+
(block $(send _ {:inject :reduce} _) $_ $_)
|
62
|
+
PATTERN
|
63
|
+
|
64
|
+
# @!method each_with_object_numblock_candidate?(node)
|
65
|
+
def_node_matcher :each_with_object_numblock_candidate?, <<~PATTERN
|
66
|
+
(numblock $(send _ {:inject :reduce} _) 2 $_)
|
67
|
+
PATTERN
|
68
|
+
|
69
|
+
def autocorrect_block(corrector, node, return_value)
|
51
70
|
corrector.replace(node.send_node.loc.selector, 'each_with_object')
|
52
71
|
|
53
72
|
first_arg, second_arg = *node.arguments
|
@@ -62,6 +81,18 @@ module RuboCop
|
|
62
81
|
end
|
63
82
|
end
|
64
83
|
|
84
|
+
def autocorrect_numblock(corrector, node)
|
85
|
+
corrector.replace(node.send_node.loc.selector, 'each_with_object')
|
86
|
+
|
87
|
+
# We don't remove the return value to avoid a clobbering error.
|
88
|
+
node.body.each_descendant do |var|
|
89
|
+
next unless var.lvar_type?
|
90
|
+
|
91
|
+
corrector.replace(var, '_2') if var.source == '_1'
|
92
|
+
corrector.replace(var, '_1') if var.source == '_2'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
65
96
|
def simple_method_arg?(method_arg)
|
66
97
|
method_arg&.basic_literal?
|
67
98
|
end
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
28
28
|
|
29
29
|
MSG = 'Omit pipes for the empty block parameters.'
|
30
30
|
|
31
|
-
def on_block(node)
|
31
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
32
32
|
send_node = node.send_node
|
33
33
|
check(node) unless send_node.send_type? && send_node.lambda_literal?
|
34
34
|
end
|
@@ -6,6 +6,10 @@ module RuboCop
|
|
6
6
|
# Use a guard clause instead of wrapping the code inside a conditional
|
7
7
|
# expression
|
8
8
|
#
|
9
|
+
# A condition with an `elsif` or `else` branch is allowed unless
|
10
|
+
# one of `return`, `break`, `next`, `raise`, or `fail` is used
|
11
|
+
# in the body of the conditional expression.
|
12
|
+
#
|
9
13
|
# @example
|
10
14
|
# # bad
|
11
15
|
# def test
|
@@ -50,34 +54,41 @@ module RuboCop
|
|
50
54
|
#
|
51
55
|
# @example AllowConsecutiveConditionals: false (default)
|
52
56
|
# # bad
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
57
|
+
# def test
|
58
|
+
# if foo?
|
59
|
+
# work
|
60
|
+
# end
|
56
61
|
#
|
57
|
-
#
|
58
|
-
#
|
62
|
+
# if bar? # <- reports an offense
|
63
|
+
# work
|
64
|
+
# end
|
59
65
|
# end
|
60
66
|
#
|
61
67
|
# @example AllowConsecutiveConditionals: true
|
62
68
|
# # good
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
69
|
+
# def test
|
70
|
+
# if foo?
|
71
|
+
# work
|
72
|
+
# end
|
66
73
|
#
|
67
|
-
#
|
68
|
-
#
|
74
|
+
# if bar?
|
75
|
+
# work
|
76
|
+
# end
|
69
77
|
# end
|
70
78
|
#
|
71
79
|
# # bad
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
80
|
+
# def test
|
81
|
+
# if foo?
|
82
|
+
# work
|
83
|
+
# end
|
75
84
|
#
|
76
|
-
#
|
85
|
+
# do_something
|
77
86
|
#
|
78
|
-
#
|
79
|
-
#
|
87
|
+
# if bar? # <- reports an offense
|
88
|
+
# work
|
89
|
+
# end
|
80
90
|
# end
|
91
|
+
#
|
81
92
|
class GuardClause < Base
|
82
93
|
include MinBodyLength
|
83
94
|
include StatementModifier
|
@@ -35,13 +35,15 @@ module RuboCop
|
|
35
35
|
|
36
36
|
# @!method kv_each(node)
|
37
37
|
def_node_matcher :kv_each, <<~PATTERN
|
38
|
-
(block $(send (send _ ${:keys :values}) :each) ...)
|
38
|
+
({block numblock} $(send (send _ ${:keys :values}) :each) ...)
|
39
39
|
PATTERN
|
40
40
|
|
41
41
|
def on_block(node)
|
42
42
|
register_kv_offense(node)
|
43
43
|
end
|
44
44
|
|
45
|
+
alias on_numblock on_block
|
46
|
+
|
45
47
|
private
|
46
48
|
|
47
49
|
def register_kv_offense(node)
|