rubocop 1.75.8 → 1.80.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/README.md +20 -16
- data/config/default.yml +107 -26
- data/config/obsoletion.yml +6 -3
- data/exe/rubocop +1 -8
- data/lib/rubocop/cli.rb +17 -1
- data/lib/rubocop/config_loader.rb +1 -38
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +6 -3
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +5 -2
- data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +0 -22
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
- data/lib/rubocop/cop/gemspec/require_mfa.rb +15 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +4 -4
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +3 -2
- data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +26 -5
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -0
- data/lib/rubocop/cop/layout/space_around_keyword.rb +6 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +8 -0
- data/lib/rubocop/cop/layout/space_before_brackets.rb +2 -9
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +7 -2
- data/lib/rubocop/cop/lint/ambiguous_range.rb +5 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +25 -4
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
- data/lib/rubocop/cop/lint/empty_interpolation.rb +3 -1
- data/lib/rubocop/cop/lint/float_comparison.rb +4 -4
- data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
- data/lib/rubocop/cop/lint/literal_as_condition.rb +34 -28
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -2
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +1 -0
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +101 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +4 -4
- data/lib/rubocop/cop/lint/require_range_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +4 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +30 -4
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +5 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +29 -4
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +90 -0
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +1 -0
- data/lib/rubocop/cop/lint/useless_or.rb +98 -0
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +3 -3
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +121 -0
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
- data/lib/rubocop/cop/mixin/line_length_help.rb +24 -8
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/naming/file_name.rb +2 -2
- data/lib/rubocop/cop/naming/method_name.rb +127 -13
- data/lib/rubocop/cop/naming/predicate_method.rb +306 -0
- data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +4 -4
- data/lib/rubocop/cop/security/eval.rb +2 -1
- data/lib/rubocop/cop/security/open.rb +1 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -1
- data/lib/rubocop/cop/style/accessor_grouping.rb +13 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +11 -17
- data/lib/rubocop/cop/style/array_intersect.rb +98 -34
- data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/collection_querying.rb +167 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +4 -2
- data/lib/rubocop/cop/style/dig_chain.rb +1 -1
- data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +100 -0
- data/lib/rubocop/cop/style/exponential_notation.rb +3 -2
- data/lib/rubocop/cop/style/fetch_env_var.rb +32 -6
- data/lib/rubocop/cop/style/hash_conversion.rb +16 -8
- data/lib/rubocop/cop/style/if_unless_modifier.rb +13 -6
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +1 -1
- data/lib/rubocop/cop/style/it_assignment.rb +69 -12
- data/lib/rubocop/cop/style/it_block_parameter.rb +36 -15
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -3
- data/lib/rubocop/cop/style/map_to_set.rb +1 -3
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +4 -6
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +16 -0
- data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
- data/lib/rubocop/cop/style/parallel_assignment.rb +32 -20
- data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +34 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -9
- data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
- data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +1 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +42 -6
- data/lib/rubocop/cop/style/redundant_self.rb +8 -5
- data/lib/rubocop/cop/style/safe_navigation.rb +38 -12
- data/lib/rubocop/cop/style/single_line_methods.rb +7 -4
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +32 -2
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +25 -8
- data/lib/rubocop/cops_documentation_generator.rb +1 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +18 -5
- data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/pacman_formatter.rb +1 -0
- data/lib/rubocop/lsp/diagnostic.rb +4 -4
- data/lib/rubocop/lsp/routes.rb +35 -6
- data/lib/rubocop/pending_cops_reporter.rb +56 -0
- data/lib/rubocop/result_cache.rb +14 -12
- data/lib/rubocop/rspec/expect_offense.rb +9 -3
- data/lib/rubocop/runner.rb +6 -4
- data/lib/rubocop/server/cache.rb +4 -2
- data/lib/rubocop/server/client_command/base.rb +10 -0
- data/lib/rubocop/server/client_command/exec.rb +2 -1
- data/lib/rubocop/server/client_command/start.rb +11 -1
- data/lib/rubocop/target_finder.rb +9 -9
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +11 -1
- data/lib/ruby_lsp/rubocop/addon.rb +2 -2
- metadata +17 -7
@@ -49,6 +49,7 @@ module RuboCop
|
|
49
49
|
empty_parentheses?(node) ||
|
50
50
|
first_arg_begins_with_hash_literal?(node) ||
|
51
51
|
rescue?(node) ||
|
52
|
+
in_pattern_matching_in_method_argument?(node) ||
|
52
53
|
allowed_pin_operator?(node) ||
|
53
54
|
allowed_expression?(node)
|
54
55
|
end
|
@@ -122,6 +123,13 @@ module RuboCop
|
|
122
123
|
hash_literal && first_argument?(node) && !parentheses?(hash_literal) && !parenthesized
|
123
124
|
end
|
124
125
|
|
126
|
+
def in_pattern_matching_in_method_argument?(begin_node)
|
127
|
+
return false unless begin_node.parent&.call_type?
|
128
|
+
return false unless (node = begin_node.children.first)
|
129
|
+
|
130
|
+
target_ruby_version <= 2.7 ? node.match_pattern_type? : node.match_pattern_p_type?
|
131
|
+
end
|
132
|
+
|
125
133
|
def method_chain_begins_with_hash_literal(node)
|
126
134
|
return if node.nil?
|
127
135
|
return node if node.hash_type?
|
@@ -134,14 +142,14 @@ module RuboCop
|
|
134
142
|
node = begin_node.children.first
|
135
143
|
|
136
144
|
if (message = find_offense_message(begin_node, node))
|
137
|
-
if node.range_type? && !argument_of_parenthesized_method_call?(begin_node)
|
145
|
+
if node.range_type? && !argument_of_parenthesized_method_call?(begin_node, node)
|
138
146
|
begin_node = begin_node.parent
|
139
147
|
end
|
140
148
|
|
141
149
|
return offense(begin_node, message)
|
142
150
|
end
|
143
151
|
|
144
|
-
check_send(begin_node, node) if node
|
152
|
+
check_send(begin_node, node) if call_node?(node)
|
145
153
|
end
|
146
154
|
|
147
155
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
@@ -156,8 +164,12 @@ module RuboCop
|
|
156
164
|
if node.lambda_or_proc? && (node.braces? || node.send_node.lambda_literal?)
|
157
165
|
return 'an expression'
|
158
166
|
end
|
167
|
+
if disallowed_one_line_pattern_matching?(begin_node, node)
|
168
|
+
return 'a one-line pattern matching'
|
169
|
+
end
|
159
170
|
return 'an interpolated expression' if interpolation?(begin_node)
|
160
|
-
return 'a method argument' if argument_of_parenthesized_method_call?(begin_node)
|
171
|
+
return 'a method argument' if argument_of_parenthesized_method_call?(begin_node, node)
|
172
|
+
return 'a one-line rescue' if oneline_rescue_parentheses_required?(begin_node, node)
|
161
173
|
|
162
174
|
return if begin_node.chained?
|
163
175
|
|
@@ -180,14 +192,23 @@ module RuboCop
|
|
180
192
|
# @!method interpolation?(node)
|
181
193
|
def_node_matcher :interpolation?, '[^begin ^^dstr]'
|
182
194
|
|
183
|
-
def argument_of_parenthesized_method_call?(begin_node)
|
184
|
-
node
|
185
|
-
|
195
|
+
def argument_of_parenthesized_method_call?(begin_node, node)
|
196
|
+
if node.basic_conditional? || node.rescue_type? || method_call_parentheses_required?(node)
|
197
|
+
return false
|
198
|
+
end
|
186
199
|
return false unless (parent = begin_node.parent)
|
187
200
|
|
188
201
|
parent.call_type? && parent.parenthesized? && parent.receiver != begin_node
|
189
202
|
end
|
190
203
|
|
204
|
+
def oneline_rescue_parentheses_required?(begin_node, node)
|
205
|
+
return false unless node.rescue_type?
|
206
|
+
return false unless (parent = begin_node.parent)
|
207
|
+
return false if parent.if_type? && parent.ternary?
|
208
|
+
|
209
|
+
!parent.type?(:call, :array, :pair)
|
210
|
+
end
|
211
|
+
|
191
212
|
def method_call_parentheses_required?(node)
|
192
213
|
return false unless node.call_type?
|
193
214
|
|
@@ -198,7 +219,13 @@ module RuboCop
|
|
198
219
|
!!config.for_enabled_cop('Style/ParenthesesAroundCondition')['AllowInMultilineConditions']
|
199
220
|
end
|
200
221
|
|
222
|
+
def call_node?(node)
|
223
|
+
node.call_type? || (node.any_block_type? && node.braces? && !node.lambda_or_proc?)
|
224
|
+
end
|
225
|
+
|
201
226
|
def check_send(begin_node, node)
|
227
|
+
node = node.send_node if node.any_block_type?
|
228
|
+
|
202
229
|
return check_unary(begin_node, node) if node.unary_operation?
|
203
230
|
|
204
231
|
return unless method_call_with_redundant_parentheses?(node)
|
@@ -242,6 +269,15 @@ module RuboCop
|
|
242
269
|
end
|
243
270
|
end
|
244
271
|
|
272
|
+
def disallowed_one_line_pattern_matching?(begin_node, node)
|
273
|
+
if (parent = begin_node.parent)
|
274
|
+
return false if parent.any_def_type? && parent.endless?
|
275
|
+
return false if parent.assignment?
|
276
|
+
end
|
277
|
+
|
278
|
+
node.any_match_pattern_type? && node.each_ancestor.none?(&:operator_keyword?)
|
279
|
+
end
|
280
|
+
|
245
281
|
def raised_to_power_negative_numeric?(begin_node, node)
|
246
282
|
return false unless node.numeric_type?
|
247
283
|
|
@@ -67,6 +67,9 @@ module RuboCop
|
|
67
67
|
|
68
68
|
def on_or_asgn(node)
|
69
69
|
allow_self(node.lhs)
|
70
|
+
|
71
|
+
lhs_name = node.lhs.lvasgn_type? ? node.lhs.name : node.lhs
|
72
|
+
add_lhs_to_local_variables_scopes(node.rhs, lhs_name)
|
70
73
|
end
|
71
74
|
alias on_and_asgn on_or_asgn
|
72
75
|
|
@@ -123,11 +126,11 @@ module RuboCop
|
|
123
126
|
def on_if(node)
|
124
127
|
# Allow conditional nodes to use `self` in the condition if that variable
|
125
128
|
# name is used in an `lvasgn` or `masgn` within the `if`.
|
126
|
-
node.
|
127
|
-
if
|
128
|
-
add_lhs_to_local_variables_scopes(node.condition,
|
129
|
-
|
130
|
-
add_masgn_lhs_variables(node.condition,
|
129
|
+
node.each_descendant(:lvasgn, :masgn) do |descendant_node|
|
130
|
+
if descendant_node.lvasgn_type?
|
131
|
+
add_lhs_to_local_variables_scopes(node.condition, descendant_node.lhs)
|
132
|
+
else
|
133
|
+
add_masgn_lhs_variables(node.condition, descendant_node.lhs)
|
131
134
|
end
|
132
135
|
end
|
133
136
|
end
|
@@ -86,6 +86,10 @@ module RuboCop
|
|
86
86
|
# foo.baz = bar if foo
|
87
87
|
# foo.baz + bar if foo
|
88
88
|
# foo.bar > 2 if foo
|
89
|
+
#
|
90
|
+
# foo ? foo[index] : nil # Ignored `foo&.[](index)` due to unclear readability benefit.
|
91
|
+
# foo ? foo[idx] = v : nil # Ignored `foo&.[]=(idx, v)` due to unclear readability benefit.
|
92
|
+
# foo ? foo * 42 : nil # Ignored `foo&.*(42)` due to unclear readability benefit.
|
89
93
|
class SafeNavigation < Base # rubocop:disable Metrics/ClassLength
|
90
94
|
include NilMethods
|
91
95
|
include RangeHelp
|
@@ -138,6 +142,7 @@ module RuboCop
|
|
138
142
|
# @!method strip_begin(node)
|
139
143
|
def_node_matcher :strip_begin, '{ (begin $!begin) $!(begin) }'
|
140
144
|
|
145
|
+
# rubocop:disable Metrics/AbcSize
|
141
146
|
def on_if(node)
|
142
147
|
return if allowed_if_condition?(node)
|
143
148
|
|
@@ -146,13 +151,16 @@ module RuboCop
|
|
146
151
|
|
147
152
|
body = extract_if_body(node)
|
148
153
|
method_call = receiver.parent
|
154
|
+
return if dotless_operator_call?(method_call) || method_call.double_colon?
|
149
155
|
|
150
156
|
removal_ranges = [begin_range(node, body), end_range(node, body)]
|
151
157
|
|
152
158
|
report_offense(node, method_chain, method_call, *removal_ranges) do |corrector|
|
159
|
+
corrector.replace(receiver, checked_variable.source) if checked_variable.csend_type?
|
153
160
|
corrector.insert_before(method_call.loc.dot, '&') unless method_call.safe_navigation?
|
154
161
|
end
|
155
162
|
end
|
163
|
+
# rubocop:enable Metrics/AbcSize
|
156
164
|
|
157
165
|
def on_and(node) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
158
166
|
collect_and_clauses(node).each do |(lhs, lhs_operator_range), (rhs, _rhs_operator_range)|
|
@@ -181,6 +189,8 @@ module RuboCop
|
|
181
189
|
end
|
182
190
|
end
|
183
191
|
|
192
|
+
private
|
193
|
+
|
184
194
|
def report_offense(node, rhs, rhs_receiver, *removal_ranges, offense_range: node)
|
185
195
|
add_offense(offense_range) do |corrector|
|
186
196
|
next if ignored_node?(node)
|
@@ -198,8 +208,6 @@ module RuboCop
|
|
198
208
|
end
|
199
209
|
end
|
200
210
|
|
201
|
-
private
|
202
|
-
|
203
211
|
def find_method_chain(node)
|
204
212
|
return node unless node&.parent&.call_type?
|
205
213
|
|
@@ -235,7 +243,7 @@ module RuboCop
|
|
235
243
|
return false if !matching_nodes?(lhs_receiver, rhs_receiver) || rhs_receiver.nil?
|
236
244
|
return false if use_var_only_in_unless_modifier?(node, lhs_receiver)
|
237
245
|
return false if chain_length(rhs, rhs_receiver) > max_chain_length
|
238
|
-
return false if unsafe_method_used?(rhs, rhs_receiver.parent)
|
246
|
+
return false if unsafe_method_used?(node, rhs, rhs_receiver.parent)
|
239
247
|
return false if rhs.send_type? && rhs.method?(:empty?)
|
240
248
|
|
241
249
|
true
|
@@ -253,6 +261,14 @@ module RuboCop
|
|
253
261
|
end
|
254
262
|
end
|
255
263
|
|
264
|
+
def dotless_operator_call?(method_call)
|
265
|
+
method_call = method_call.parent while method_call.parent.send_type?
|
266
|
+
|
267
|
+
return false if method_call.loc.dot
|
268
|
+
|
269
|
+
method_call.method?(:[]) || method_call.method?(:[]=) || method_call.operator_method?
|
270
|
+
end
|
271
|
+
|
256
272
|
def handle_comments(corrector, node, method_call)
|
257
273
|
comments = comments(node)
|
258
274
|
return if comments.empty?
|
@@ -322,8 +338,16 @@ module RuboCop
|
|
322
338
|
|
323
339
|
def matching_call_nodes?(left, right)
|
324
340
|
return false unless left && right.respond_to?(:call_type?)
|
341
|
+
return false unless left.call_type? && right.call_type?
|
325
342
|
|
326
|
-
|
343
|
+
# Compare receiver and method name, but ignore the difference between
|
344
|
+
# safe navigation method call (`&.`) and dot method call (`.`).
|
345
|
+
left_receiver, left_method, *left_args = left.children
|
346
|
+
right_receiver, right_method, *right_args = right.children
|
347
|
+
|
348
|
+
left_method == right_method &&
|
349
|
+
matching_nodes?(left_receiver, right_receiver) &&
|
350
|
+
left_args == right_args
|
327
351
|
end
|
328
352
|
|
329
353
|
def chain_length(method_chain, method)
|
@@ -334,21 +358,24 @@ module RuboCop
|
|
334
358
|
end
|
335
359
|
end
|
336
360
|
|
337
|
-
def unsafe_method_used?(method_chain, method)
|
338
|
-
return true if unsafe_method?(method)
|
361
|
+
def unsafe_method_used?(node, method_chain, method)
|
362
|
+
return true if unsafe_method?(node, method)
|
339
363
|
|
340
364
|
method.each_ancestor(:send).any? do |ancestor|
|
341
365
|
break true unless config.cop_enabled?('Lint/SafeNavigationChain')
|
342
366
|
|
343
|
-
break true if unsafe_method?(ancestor)
|
367
|
+
break true if unsafe_method?(node, ancestor)
|
344
368
|
break true if nil_methods.include?(ancestor.method_name)
|
345
369
|
break false if ancestor == method_chain
|
346
370
|
end
|
347
371
|
end
|
348
372
|
|
349
|
-
def unsafe_method?(send_node)
|
350
|
-
negated?(send_node)
|
351
|
-
|
373
|
+
def unsafe_method?(node, send_node)
|
374
|
+
return true if negated?(send_node)
|
375
|
+
|
376
|
+
return false if node.respond_to?(:ternary?) && node.ternary?
|
377
|
+
|
378
|
+
send_node.assignment? ||
|
352
379
|
(!send_node.dot? && !send_node.safe_navigation?)
|
353
380
|
end
|
354
381
|
|
@@ -377,8 +404,7 @@ module RuboCop
|
|
377
404
|
method_chain)
|
378
405
|
start_method.each_ancestor do |ancestor|
|
379
406
|
break unless %i[send block].include?(ancestor.type)
|
380
|
-
next
|
381
|
-
next if ancestor.safe_navigation?
|
407
|
+
next if !ancestor.send_type? || ancestor.operator_method?
|
382
408
|
|
383
409
|
corrector.insert_before(ancestor.loc.dot, '&')
|
384
410
|
|
@@ -65,7 +65,7 @@ module RuboCop
|
|
65
65
|
return false if target_ruby_version < 3.0
|
66
66
|
return false if disallow_endless_method_style?
|
67
67
|
return false unless body_node
|
68
|
-
return false if body_node.parent.assignment_method? ||
|
68
|
+
return false if body_node.basic_conditional? || body_node.parent.assignment_method? ||
|
69
69
|
NOT_SUPPORTED_ENDLESS_METHOD_BODY_TYPES.include?(body_node.type)
|
70
70
|
|
71
71
|
!body_node.type?(:begin, :kwbegin)
|
@@ -86,10 +86,10 @@ module RuboCop
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def correct_to_endless(corrector, node)
|
89
|
-
|
89
|
+
receiver = "#{node.receiver.source}." if node.receiver
|
90
90
|
arguments = node.arguments.any? ? node.arguments.source : '()'
|
91
91
|
body_source = method_body_source(node.body)
|
92
|
-
replacement = "def #{
|
92
|
+
replacement = "def #{receiver}#{node.method_name}#{arguments} = #{body_source}"
|
93
93
|
|
94
94
|
corrector.replace(node, replacement)
|
95
95
|
end
|
@@ -130,7 +130,10 @@ module RuboCop
|
|
130
130
|
end
|
131
131
|
|
132
132
|
def require_parentheses?(method_body)
|
133
|
-
|
133
|
+
return false unless method_body.send_type?
|
134
|
+
return false if method_body.arithmetic_operation?
|
135
|
+
|
136
|
+
!method_body.arguments.empty? && !method_body.comparison_method?
|
134
137
|
end
|
135
138
|
|
136
139
|
def disallow_endless_method_style?
|
@@ -115,8 +115,9 @@ module RuboCop
|
|
115
115
|
end
|
116
116
|
|
117
117
|
def correct_node(corrector, node)
|
118
|
-
corrector.replace(node.loc.keyword, 'if') if node.unless?
|
118
|
+
corrector.replace(node.loc.keyword, 'if') if node.unless? && !part_of_ignored_node?(node)
|
119
119
|
corrector.replace(node.condition, chainable_condition(node))
|
120
|
+
ignore_node(node)
|
120
121
|
end
|
121
122
|
|
122
123
|
def correct_for_guard_condition_style(corrector, node, if_branch)
|
@@ -174,6 +175,8 @@ module RuboCop
|
|
174
175
|
|
175
176
|
if parenthesize_method?(condition)
|
176
177
|
parenthesized_method_arguments(condition)
|
178
|
+
elsif condition.and_type?
|
179
|
+
parenthesized_and(condition)
|
177
180
|
else
|
178
181
|
"(#{condition.source})"
|
179
182
|
end
|
@@ -185,12 +188,19 @@ module RuboCop
|
|
185
188
|
end
|
186
189
|
|
187
190
|
def add_parentheses?(node)
|
188
|
-
return true if node.assignment? ||
|
191
|
+
return true if node.assignment? || node.or_type?
|
192
|
+
return true if assignment_in_and?(node)
|
189
193
|
return false unless node.call_type?
|
190
194
|
|
191
195
|
(node.arguments.any? && !node.parenthesized?) || node.prefix_not?
|
192
196
|
end
|
193
197
|
|
198
|
+
def assignment_in_and?(node)
|
199
|
+
return false unless node.and_type?
|
200
|
+
|
201
|
+
node.each_descendant.any?(&:assignment?)
|
202
|
+
end
|
203
|
+
|
194
204
|
def parenthesized_method_arguments(node)
|
195
205
|
method_call = node.source_range.begin.join(node.loc.selector.end).source
|
196
206
|
arguments = node.first_argument.source_range.begin.join(node.source_range.end).source
|
@@ -198,6 +208,26 @@ module RuboCop
|
|
198
208
|
"#{method_call}(#{arguments})"
|
199
209
|
end
|
200
210
|
|
211
|
+
def parenthesized_and(node)
|
212
|
+
# We only need to add parentheses around the last clause if it's an assignment,
|
213
|
+
# because other clauses will be unchanged by merging conditionals.
|
214
|
+
lhs = node.lhs.source
|
215
|
+
rhs = parenthesized_and_clause(node.rhs)
|
216
|
+
operator = range_with_surrounding_space(node.loc.operator, whitespace: true).source
|
217
|
+
|
218
|
+
"#{lhs}#{operator}#{rhs}"
|
219
|
+
end
|
220
|
+
|
221
|
+
def parenthesized_and_clause(node)
|
222
|
+
if node.and_type?
|
223
|
+
parenthesized_and(node)
|
224
|
+
elsif node.assignment?
|
225
|
+
"(#{node.source})"
|
226
|
+
else
|
227
|
+
node.source
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
201
231
|
def allow_modifier?
|
202
232
|
cop_config['AllowModifier']
|
203
233
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
#
|
6
|
+
# Checks for parentheses around stabby lambda arguments.
|
7
7
|
# There are two different styles. Defaults to `require_parentheses`.
|
8
8
|
#
|
9
9
|
# @example EnforcedStyle: require_parentheses (default)
|
@@ -81,7 +81,7 @@ module RuboCop
|
|
81
81
|
|
82
82
|
content = *sym
|
83
83
|
content = content.map { |c| c.is_a?(AST::Node) ? c.source : c }.join
|
84
|
-
content_without_delimiter_pairs = content.gsub(/(\[[^\s\[\]]*\])|(\([^\s
|
84
|
+
content_without_delimiter_pairs = content.gsub(/(\[[^\s\[\]]*\])|(\([^\s()]*\))/, '')
|
85
85
|
|
86
86
|
content.include?(' ') || DELIMITERS.any? do |delimiter|
|
87
87
|
content_without_delimiter_pairs.include?(delimiter)
|
@@ -270,7 +270,7 @@ module RuboCop
|
|
270
270
|
end
|
271
271
|
|
272
272
|
def allow_if_method_has_argument?(send_node)
|
273
|
-
!!cop_config.fetch('AllowMethodsWithArguments', false) &&
|
273
|
+
!!cop_config.fetch('AllowMethodsWithArguments', false) && send_node.arguments.any?
|
274
274
|
end
|
275
275
|
|
276
276
|
def allow_comments?
|
@@ -71,6 +71,8 @@ module RuboCop
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
BRANCH_NODES = %i[if case case_match rescue].freeze
|
75
|
+
|
74
76
|
def variable_table
|
75
77
|
@variable_table ||= VariableTable.new(self)
|
76
78
|
end
|
@@ -236,11 +238,16 @@ module RuboCop
|
|
236
238
|
end
|
237
239
|
|
238
240
|
def process_loop(node)
|
239
|
-
if
|
241
|
+
if node.post_condition_loop?
|
240
242
|
# See the comment at the end of file for this behavior.
|
241
243
|
condition_node, body_node = *node
|
242
244
|
process_node(body_node)
|
243
245
|
process_node(condition_node)
|
246
|
+
elsif node.for_type?
|
247
|
+
# In `for item in items` the rightmost expression is evaluated first.
|
248
|
+
process_node(node.collection)
|
249
|
+
process_node(node.variable)
|
250
|
+
process_node(node.body) if node.body
|
244
251
|
else
|
245
252
|
process_children(node)
|
246
253
|
end
|
@@ -296,7 +303,7 @@ module RuboCop
|
|
296
303
|
variable_table.accessible_variables.each { |variable| variable.reference!(node) }
|
297
304
|
end
|
298
305
|
|
299
|
-
# Mark
|
306
|
+
# Mark last assignments which are referenced in the same loop
|
300
307
|
# as referenced by ignoring AST order since they would be referenced
|
301
308
|
# in next iteration.
|
302
309
|
def mark_assignments_as_referenced_in_loop(node)
|
@@ -308,13 +315,12 @@ module RuboCop
|
|
308
315
|
# would be skipped here.
|
309
316
|
next unless variable
|
310
317
|
|
311
|
-
variable.assignments.
|
312
|
-
|
313
|
-
assignment_node.equal?(assignment.node)
|
314
|
-
end
|
315
|
-
|
316
|
-
assignment.reference!(node)
|
318
|
+
loop_assignments = variable.assignments.select do |assignment|
|
319
|
+
assignment_nodes_in_loop.include?(assignment.node)
|
317
320
|
end
|
321
|
+
next unless loop_assignments.any?
|
322
|
+
|
323
|
+
reference_assignments(loop_assignments, node)
|
318
324
|
end
|
319
325
|
end
|
320
326
|
|
@@ -354,6 +360,17 @@ module RuboCop
|
|
354
360
|
end
|
355
361
|
end
|
356
362
|
|
363
|
+
def reference_assignments(loop_assignments, loop_node)
|
364
|
+
# If inside a branching statement, mark all as referenced.
|
365
|
+
# Otherwise, mark only the last assignment as referenced.
|
366
|
+
# Note that `rescue` must be considered as branching because of
|
367
|
+
# the `retry` keyword.
|
368
|
+
loop_assignments.each do |assignment|
|
369
|
+
assignment.reference!(loop_node) if assignment.node.each_ancestor(*BRANCH_NODES).any?
|
370
|
+
end
|
371
|
+
loop_assignments.last&.reference!(loop_node)
|
372
|
+
end
|
373
|
+
|
357
374
|
def scanned_node?(node)
|
358
375
|
scanned_nodes.include?(node)
|
359
376
|
end
|
@@ -7,6 +7,7 @@ require 'yard'
|
|
7
7
|
# @api private
|
8
8
|
class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
9
9
|
include ::RuboCop::Cop::Documentation
|
10
|
+
|
10
11
|
CopData = Struct.new(
|
11
12
|
:cop, :description, :example_objects, :safety_objects, :see_objects, :config, keyword_init: true
|
12
13
|
)
|
@@ -4,7 +4,7 @@ module RuboCop
|
|
4
4
|
module Formatter
|
5
5
|
# This formatter displays a YAML configuration file where all cops that
|
6
6
|
# detected any offenses are configured to not detect the offense.
|
7
|
-
class DisabledConfigFormatter < BaseFormatter
|
7
|
+
class DisabledConfigFormatter < BaseFormatter # rubocop:disable Metrics/ClassLength
|
8
8
|
include PathUtil
|
9
9
|
|
10
10
|
HEADING = <<~COMMENTS
|
@@ -17,6 +17,22 @@ module RuboCop
|
|
17
17
|
# versions of RuboCop, may require this file to be generated again.
|
18
18
|
COMMENTS
|
19
19
|
|
20
|
+
EXCLUDED_CONFIG_KEYS = %w[
|
21
|
+
AutoCorrect
|
22
|
+
Description
|
23
|
+
Enabled
|
24
|
+
Exclude
|
25
|
+
Include
|
26
|
+
Reference
|
27
|
+
References
|
28
|
+
Safe
|
29
|
+
SafeAutoCorrect
|
30
|
+
StyleGuide
|
31
|
+
VersionAdded
|
32
|
+
VersionChanged
|
33
|
+
VersionRemoved
|
34
|
+
].freeze
|
35
|
+
|
20
36
|
@config_to_allow_offenses = {}
|
21
37
|
@detected_styles = {}
|
22
38
|
|
@@ -163,10 +179,7 @@ module RuboCop
|
|
163
179
|
end
|
164
180
|
|
165
181
|
def cop_config_params(default_cfg, cfg)
|
166
|
-
default_cfg.keys -
|
167
|
-
%w[Description StyleGuide Reference References Enabled Exclude Safe
|
168
|
-
SafeAutoCorrect VersionAdded VersionChanged VersionRemoved] -
|
169
|
-
cfg.keys
|
182
|
+
default_cfg.keys - EXCLUDED_CONFIG_KEYS - cfg.keys
|
170
183
|
end
|
171
184
|
|
172
185
|
def output_cop_param_comments(output_buffer, params, default_cfg)
|
@@ -79,7 +79,7 @@ module RuboCop
|
|
79
79
|
LanguageServer::Protocol::Interface::CodeDescription.new(href: doc_url)
|
80
80
|
end
|
81
81
|
|
82
|
-
# rubocop:disable
|
82
|
+
# rubocop:disable Metrics/MethodLength
|
83
83
|
def autocorrect_action
|
84
84
|
LanguageServer::Protocol::Interface::CodeAction.new(
|
85
85
|
title: "Autocorrect #{@offense.cop_name}",
|
@@ -98,7 +98,7 @@ module RuboCop
|
|
98
98
|
is_preferred: true
|
99
99
|
)
|
100
100
|
end
|
101
|
-
# rubocop:enable
|
101
|
+
# rubocop:enable Metrics/MethodLength
|
102
102
|
|
103
103
|
# rubocop:disable Metrics/MethodLength
|
104
104
|
def offense_replacements
|
@@ -120,7 +120,7 @@ module RuboCop
|
|
120
120
|
end
|
121
121
|
# rubocop:enable Metrics/MethodLength
|
122
122
|
|
123
|
-
# rubocop:disable
|
123
|
+
# rubocop:disable Metrics/MethodLength
|
124
124
|
def disable_line_action
|
125
125
|
LanguageServer::Protocol::Interface::CodeAction.new(
|
126
126
|
title: "Disable #{@offense.cop_name} for this line",
|
@@ -138,7 +138,7 @@ module RuboCop
|
|
138
138
|
)
|
139
139
|
)
|
140
140
|
end
|
141
|
-
# rubocop:enable
|
141
|
+
# rubocop:enable Metrics/MethodLength
|
142
142
|
|
143
143
|
def line_disable_comment
|
144
144
|
new_text = if @offense.source_line.include?(' # rubocop:disable ')
|