rubocop 1.85.1 → 1.86.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/config/default.yml +9 -12
- data/lib/rubocop/cache_config.rb +1 -1
- data/lib/rubocop/cli/command/auto_generate_config.rb +1 -1
- data/lib/rubocop/cli/command/show_cops.rb +2 -2
- data/lib/rubocop/cli/command/show_docs_url.rb +1 -1
- data/lib/rubocop/config.rb +14 -10
- data/lib/rubocop/config_finder.rb +1 -1
- data/lib/rubocop/config_loader_resolver.rb +2 -1
- data/lib/rubocop/config_store.rb +1 -1
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/documentation.rb +2 -3
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +9 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +6 -3
- data/lib/rubocop/cop/layout/line_length.rb +5 -3
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +28 -3
- data/lib/rubocop/cop/layout/space_around_keyword.rb +3 -1
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +1 -0
- data/lib/rubocop/cop/lint/constant_reassignment.rb +59 -9
- data/lib/rubocop/cop/lint/duplicate_methods.rb +55 -8
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +6 -1
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
- data/lib/rubocop/cop/lint/empty_when.rb +8 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +16 -0
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -0
- data/lib/rubocop/cop/lint/syntax.rb +25 -1
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +4 -4
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +2 -0
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +22 -7
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +1 -1
- data/lib/rubocop/cop/registry.rb +20 -13
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +14 -2
- data/lib/rubocop/cop/style/and_or.rb +1 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +25 -7
- data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +23 -31
- data/lib/rubocop/cop/style/collection_compact.rb +36 -16
- data/lib/rubocop/cop/style/concat_array_literals.rb +2 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +0 -4
- data/lib/rubocop/cop/style/empty_class_definition.rb +24 -2
- data/lib/rubocop/cop/style/file_open.rb +1 -1
- data/lib/rubocop/cop/style/global_vars.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +9 -6
- data/lib/rubocop/cop/style/hash_lookup_method.rb +7 -0
- data/lib/rubocop/cop/style/if_inside_else.rb +1 -5
- data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -5
- data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
- data/lib/rubocop/cop/style/magic_comment_format.rb +2 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -3
- data/lib/rubocop/cop/style/module_member_existence_check.rb +1 -11
- data/lib/rubocop/cop/style/mutable_constant.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +5 -11
- data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
- data/lib/rubocop/cop/style/one_class_per_file.rb +24 -4
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/redundant_each.rb +3 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +16 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +22 -20
- data/lib/rubocop/cop/style/redundant_percent_q.rb +4 -1
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
- data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +10 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +7 -7
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +4 -3
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
- data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/lsp/routes.rb +10 -3
- data/lib/rubocop/mcp/server.rb +27 -1
- data/lib/rubocop/path_util.rb +14 -2
- data/lib/rubocop/plugin/loader.rb +1 -1
- data/lib/rubocop/result_cache.rb +10 -1
- data/lib/rubocop/rspec/cop_helper.rb +8 -0
- data/lib/rubocop/rspec/shared_contexts.rb +11 -2
- data/lib/rubocop/runner.rb +8 -3
- data/lib/rubocop/server/core.rb +2 -0
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/version.rb +2 -2
- metadata +5 -19
|
@@ -232,9 +232,7 @@ module RuboCop
|
|
|
232
232
|
end
|
|
233
233
|
|
|
234
234
|
def semantic_message(node)
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if block_begin == '{'
|
|
235
|
+
if node.braces?
|
|
238
236
|
'Prefer `do...end` over `{...}` for procedural blocks.'
|
|
239
237
|
else
|
|
240
238
|
'Prefer `{...}` over `do...end` for functional blocks.'
|
|
@@ -372,17 +370,22 @@ module RuboCop
|
|
|
372
370
|
end
|
|
373
371
|
# rubocop:enable Metrics/CyclomaticComplexity
|
|
374
372
|
|
|
373
|
+
# rubocop:disable Metrics/CyclomaticComplexity -- inlined special_method checks to avoid double evaluation
|
|
375
374
|
def proper_block_style?(node)
|
|
376
375
|
return true if require_do_end?(node)
|
|
377
|
-
|
|
376
|
+
|
|
377
|
+
method_name = node.method_name
|
|
378
|
+
return true if allowed_method?(method_name) || matches_allowed_pattern?(method_name)
|
|
379
|
+
return node.braces? if braces_required_method?(method_name)
|
|
378
380
|
|
|
379
381
|
case style
|
|
380
382
|
when :line_count_based then line_count_based_block_style?(node)
|
|
381
383
|
when :semantic then semantic_block_style?(node)
|
|
382
384
|
when :braces_for_chaining then braces_for_chaining_style?(node)
|
|
383
|
-
when :always_braces then
|
|
385
|
+
when :always_braces then node.braces?
|
|
384
386
|
end
|
|
385
387
|
end
|
|
388
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
386
389
|
|
|
387
390
|
def require_do_end?(node)
|
|
388
391
|
return false if node.braces? || node.multiline?
|
|
@@ -391,19 +394,6 @@ module RuboCop
|
|
|
391
394
|
resbody.children.first&.array_type?
|
|
392
395
|
end
|
|
393
396
|
|
|
394
|
-
def special_method?(method_name)
|
|
395
|
-
allowed_method?(method_name) ||
|
|
396
|
-
matches_allowed_pattern?(method_name) ||
|
|
397
|
-
braces_required_method?(method_name)
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
def special_method_proper_block_style?(node)
|
|
401
|
-
method_name = node.method_name
|
|
402
|
-
return true if allowed_method?(method_name) || matches_allowed_pattern?(method_name)
|
|
403
|
-
|
|
404
|
-
node.braces? if braces_required_method?(method_name)
|
|
405
|
-
end
|
|
406
|
-
|
|
407
397
|
def braces_required_method?(method_name)
|
|
408
398
|
braces_required_methods.include?(method_name.to_s)
|
|
409
399
|
end
|
|
@@ -428,17 +418,11 @@ module RuboCop
|
|
|
428
418
|
end
|
|
429
419
|
|
|
430
420
|
def braces_for_chaining_style?(node)
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
'{'
|
|
437
|
-
end
|
|
438
|
-
end
|
|
439
|
-
|
|
440
|
-
def braces_style?(node)
|
|
441
|
-
node.loc.begin.source == '{'
|
|
421
|
+
if node.multiline?
|
|
422
|
+
node.chained? ? node.braces? : !node.braces?
|
|
423
|
+
else
|
|
424
|
+
node.braces?
|
|
425
|
+
end
|
|
442
426
|
end
|
|
443
427
|
|
|
444
428
|
def correction_would_break_code?(node)
|
|
@@ -448,7 +432,11 @@ module RuboCop
|
|
|
448
432
|
end
|
|
449
433
|
|
|
450
434
|
def functional_method?(method_name)
|
|
451
|
-
|
|
435
|
+
functional_methods.include?(method_name)
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
def functional_methods
|
|
439
|
+
@functional_methods ||= cop_config['FunctionalMethods'].to_set(&:to_sym).freeze
|
|
452
440
|
end
|
|
453
441
|
|
|
454
442
|
def functional_block?(node)
|
|
@@ -460,7 +448,11 @@ module RuboCop
|
|
|
460
448
|
end
|
|
461
449
|
|
|
462
450
|
def procedural_method?(method_name)
|
|
463
|
-
|
|
451
|
+
procedural_methods.include?(method_name)
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
def procedural_methods
|
|
455
|
+
@procedural_methods ||= cop_config['ProceduralMethods'].to_set(&:to_sym).freeze
|
|
464
456
|
end
|
|
465
457
|
|
|
466
458
|
def return_value_used?(node)
|
|
@@ -64,22 +64,34 @@ module RuboCop
|
|
|
64
64
|
# @!method reject_method?(node)
|
|
65
65
|
def_node_matcher :reject_method?, <<~PATTERN
|
|
66
66
|
(block
|
|
67
|
-
(call
|
|
68
|
-
!nil? {:reject :reject!})
|
|
67
|
+
(call !nil? {:reject :reject!})
|
|
69
68
|
$(args ...)
|
|
70
|
-
(call
|
|
71
|
-
|
|
69
|
+
(call $(lvar _) :nil?))
|
|
70
|
+
PATTERN
|
|
71
|
+
|
|
72
|
+
# @!method reject_method_for_numblock_or_itblock?(node)
|
|
73
|
+
def_node_matcher :reject_method_for_numblock_or_itblock?, <<~PATTERN
|
|
74
|
+
{
|
|
75
|
+
(numblock (call !nil? {:reject :reject!}) _ (call (lvar :_1) :nil?))
|
|
76
|
+
(itblock (call !nil? {:reject :reject!}) _ (call (lvar :it) :nil?))
|
|
77
|
+
}
|
|
72
78
|
PATTERN
|
|
73
79
|
|
|
74
80
|
# @!method select_method?(node)
|
|
75
81
|
def_node_matcher :select_method?, <<~PATTERN
|
|
76
82
|
(block
|
|
77
|
-
(call
|
|
78
|
-
!nil? {:select :select! :filter :filter!})
|
|
83
|
+
(call !nil? {:select :select! :filter :filter!})
|
|
79
84
|
$(args ...)
|
|
80
85
|
(call
|
|
81
|
-
(call
|
|
82
|
-
|
|
86
|
+
(call $(lvar _) :nil?) :!))
|
|
87
|
+
PATTERN
|
|
88
|
+
|
|
89
|
+
# @!method select_method_for_numblock_or_itblock?(node)
|
|
90
|
+
def_node_matcher :select_method_for_numblock_or_itblock?, <<~PATTERN
|
|
91
|
+
{
|
|
92
|
+
(numblock (call !nil? {:select :select! :filter :filter!}) _ (call (call (lvar :_1) :nil?) :!))
|
|
93
|
+
(itblock (call !nil? {:select :select! :filter :filter!}) _ (call (call (lvar :it) :nil?) :!))
|
|
94
|
+
}
|
|
83
95
|
PATTERN
|
|
84
96
|
|
|
85
97
|
# @!method grep_v_with_nil?(node)
|
|
@@ -102,26 +114,34 @@ module RuboCop
|
|
|
102
114
|
|
|
103
115
|
private
|
|
104
116
|
|
|
105
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
106
117
|
def offense_range(node)
|
|
107
118
|
if reject_method_with_block_pass?(node) || grep_v_with_nil?(node)
|
|
108
119
|
range(node, node)
|
|
109
120
|
else
|
|
110
121
|
block_node = node.parent
|
|
111
122
|
|
|
112
|
-
return unless block_node&.
|
|
113
|
-
unless
|
|
114
|
-
return
|
|
115
|
-
end
|
|
116
|
-
return unless args.last.source == receiver.source
|
|
123
|
+
return unless block_node&.any_block_type?
|
|
124
|
+
return unless match_block_method?(block_node)
|
|
117
125
|
|
|
118
126
|
range(node, block_node)
|
|
119
127
|
end
|
|
120
128
|
end
|
|
121
|
-
|
|
129
|
+
|
|
130
|
+
def match_block_method?(block_node)
|
|
131
|
+
if block_node.block_type?
|
|
132
|
+
result = reject_method?(block_node) || select_method?(block_node)
|
|
133
|
+
return false unless result
|
|
134
|
+
|
|
135
|
+
args, receiver = result
|
|
136
|
+
args.last.source == receiver.source
|
|
137
|
+
else
|
|
138
|
+
reject_method_for_numblock_or_itblock?(block_node) ||
|
|
139
|
+
select_method_for_numblock_or_itblock?(block_node)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
122
142
|
|
|
123
143
|
def to_enum_method?(node)
|
|
124
|
-
return false unless node.receiver.
|
|
144
|
+
return false unless node.receiver.call_type?
|
|
125
145
|
|
|
126
146
|
TO_ENUM_METHODS.include?(node.receiver.method_name)
|
|
127
147
|
end
|
|
@@ -99,10 +99,6 @@ module RuboCop
|
|
|
99
99
|
end
|
|
100
100
|
end
|
|
101
101
|
|
|
102
|
-
def setter_method?(method_name)
|
|
103
|
-
method_name.to_s.end_with?(EQUAL) && !%i[!= == === >= <=].include?(method_name)
|
|
104
|
-
end
|
|
105
|
-
|
|
106
102
|
def assignment_rhs_exist?(node)
|
|
107
103
|
parent = node.parent
|
|
108
104
|
return true unless parent
|
|
@@ -10,16 +10,20 @@ module RuboCop
|
|
|
10
10
|
#
|
|
11
11
|
# The supported styles are:
|
|
12
12
|
#
|
|
13
|
-
# *
|
|
13
|
+
# * class_keyword (default) - prefer standard class definition over `Class.new`
|
|
14
14
|
# * class_new - prefer `Class.new` over class definition
|
|
15
15
|
#
|
|
16
16
|
# One difference between the two styles is that the `Class.new` form does not make
|
|
17
17
|
# the subclass name available to the base class's `inherited` callback.
|
|
18
|
-
# For this reason, `EnforcedStyle:
|
|
18
|
+
# For this reason, `EnforcedStyle: class_keyword` is set as the default style.
|
|
19
19
|
# Class definitions without a superclass, which are not involved in inheritance,
|
|
20
20
|
# are not detected. This ensures safe detection regardless of the applied style.
|
|
21
21
|
# This avoids overlapping responsibilities with the `Lint/EmptyClass` cop.
|
|
22
22
|
#
|
|
23
|
+
# Use `AllowedParentClasses` to permit both styles for specific parent classes.
|
|
24
|
+
# For example, adding `StandardError` allows both `Error = Class.new(StandardError)`
|
|
25
|
+
# and `class Error < StandardError; end` regardless of the enforced style.
|
|
26
|
+
#
|
|
23
27
|
# @example EnforcedStyle: class_keyword (default)
|
|
24
28
|
# # bad
|
|
25
29
|
# FooError = Class.new(StandardError)
|
|
@@ -42,6 +46,14 @@ module RuboCop
|
|
|
42
46
|
# # good
|
|
43
47
|
# FooError = Class.new(StandardError)
|
|
44
48
|
#
|
|
49
|
+
# @example AllowedParentClasses: ['StandardError']
|
|
50
|
+
# # good - allowed regardless of EnforcedStyle
|
|
51
|
+
# FooError = Class.new(StandardError)
|
|
52
|
+
#
|
|
53
|
+
# # good - allowed regardless of EnforcedStyle
|
|
54
|
+
# class FooError < StandardError
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
45
57
|
class EmptyClassDefinition < Base
|
|
46
58
|
include ConfigurableEnforcedStyle
|
|
47
59
|
extend AutoCorrector
|
|
@@ -59,6 +71,7 @@ module RuboCop
|
|
|
59
71
|
return unless %i[class_keyword class_definition].include?(style)
|
|
60
72
|
return unless (class_new_node = class_new_assignment(node))
|
|
61
73
|
return if (arg = class_new_node.first_argument) && !arg.const_type?
|
|
74
|
+
return if allowed_parent_class?(class_new_node.first_argument.source)
|
|
62
75
|
|
|
63
76
|
add_offense(node, message: MSG_CLASS_KEYWORD) do |corrector|
|
|
64
77
|
autocorrect_class_new(corrector, node, class_new_node)
|
|
@@ -69,6 +82,7 @@ module RuboCop
|
|
|
69
82
|
return unless style == :class_new
|
|
70
83
|
return unless node.parent_class
|
|
71
84
|
return if (body = node.body) && !body.children.empty?
|
|
85
|
+
return if allowed_parent_class?(node.parent_class.source)
|
|
72
86
|
|
|
73
87
|
add_offense(node, message: MSG_CLASS_NEW) do |corrector|
|
|
74
88
|
autocorrect_class_definition(corrector, node)
|
|
@@ -77,6 +91,14 @@ module RuboCop
|
|
|
77
91
|
|
|
78
92
|
private
|
|
79
93
|
|
|
94
|
+
def allowed_parent_class?(parent_class_name)
|
|
95
|
+
allowed_parent_classes.include?(parent_class_name)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def allowed_parent_classes
|
|
99
|
+
cop_config.fetch('AllowedParentClasses', [])
|
|
100
|
+
end
|
|
101
|
+
|
|
80
102
|
def autocorrect_class_new(corrector, node, class_new_node)
|
|
81
103
|
indent = ' ' * node.loc.column
|
|
82
104
|
class_name = node.name
|
|
@@ -72,7 +72,7 @@ module RuboCop
|
|
|
72
72
|
def offensive_usage?(node)
|
|
73
73
|
return true unless node.value_used?
|
|
74
74
|
|
|
75
|
-
node.parent.
|
|
75
|
+
node.parent.lvasgn_type? || receiver_of_chained_call?(node)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
def receiver_of_chained_call?(node)
|
|
@@ -224,15 +224,18 @@ module RuboCop
|
|
|
224
224
|
end
|
|
225
225
|
|
|
226
226
|
def find_heredoc_argument(node)
|
|
227
|
-
return unless node
|
|
227
|
+
return unless node
|
|
228
228
|
|
|
229
|
-
|
|
229
|
+
node = node.children.first while node.begin_type?
|
|
230
|
+
return node if heredoc?(node)
|
|
231
|
+
return unless node.call_type?
|
|
230
232
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
find_heredoc_argument(last_arg)
|
|
233
|
+
node.arguments.reverse_each do |argument|
|
|
234
|
+
heredoc_argument = find_heredoc_argument(argument)
|
|
235
|
+
return heredoc_argument if heredoc_argument
|
|
235
236
|
end
|
|
237
|
+
|
|
238
|
+
find_heredoc_argument(node.receiver)
|
|
236
239
|
end
|
|
237
240
|
|
|
238
241
|
def autocorrect_heredoc_argument(corrector, node, heredoc_node, leave_branch, guard)
|
|
@@ -41,8 +41,13 @@ module RuboCop
|
|
|
41
41
|
# # good
|
|
42
42
|
# hash.fetch(key)
|
|
43
43
|
#
|
|
44
|
+
# @example AllowedReceivers: ['Rails.cache']
|
|
45
|
+
# # good
|
|
46
|
+
# Rails.cache.fetch(name, options) { block }
|
|
47
|
+
#
|
|
44
48
|
class HashLookupMethod < Base
|
|
45
49
|
include ConfigurableEnforcedStyle
|
|
50
|
+
include AllowedReceivers
|
|
46
51
|
extend AutoCorrector
|
|
47
52
|
|
|
48
53
|
BRACKET_MSG = 'Use `Hash#[]` instead of `Hash#fetch`.'
|
|
@@ -51,6 +56,8 @@ module RuboCop
|
|
|
51
56
|
RESTRICT_ON_SEND = %i[[] fetch].freeze
|
|
52
57
|
|
|
53
58
|
def on_send(node)
|
|
59
|
+
return if (receiver = node.receiver) && allowed_receiver?(receiver)
|
|
60
|
+
|
|
54
61
|
if offense_for_brackets?(node)
|
|
55
62
|
add_offense(node.loc.selector, message: BRACKET_MSG) do |corrector|
|
|
56
63
|
correct_fetch_to_brackets(corrector, node)
|
|
@@ -85,7 +85,7 @@ module RuboCop
|
|
|
85
85
|
private
|
|
86
86
|
|
|
87
87
|
def autocorrect(corrector, node)
|
|
88
|
-
if then?
|
|
88
|
+
if node.then?
|
|
89
89
|
# If the nested `if` is a then node, correct it first,
|
|
90
90
|
# then the next pass will use `correct_to_elsif_from_if_inside_else_form`
|
|
91
91
|
IfThenCorrector.new(node, indentation: 0).call(corrector)
|
|
@@ -124,10 +124,6 @@ module RuboCop
|
|
|
124
124
|
corrector.remove(range_by_whole_lines(find_end_range(node), include_final_newline: true))
|
|
125
125
|
end
|
|
126
126
|
|
|
127
|
-
def then?(node)
|
|
128
|
-
node.loc.begin&.source == 'then'
|
|
129
|
-
end
|
|
130
|
-
|
|
131
127
|
def find_end_range(node)
|
|
132
128
|
end_range = node.loc.end
|
|
133
129
|
return end_range if end_range
|
|
@@ -101,6 +101,7 @@ module RuboCop
|
|
|
101
101
|
|
|
102
102
|
add_offense(node.loc.keyword, message: format(msg, keyword: node.keyword)) do |corrector|
|
|
103
103
|
next if part_of_ignored_node?(node)
|
|
104
|
+
next if another_modifier_if_on_same_line?(node)
|
|
104
105
|
|
|
105
106
|
autocorrect(corrector, node)
|
|
106
107
|
ignore_node(node)
|
|
@@ -280,6 +281,16 @@ module RuboCop
|
|
|
280
281
|
node.parent if node&.type?(:pair)
|
|
281
282
|
end
|
|
282
283
|
|
|
284
|
+
def another_modifier_if_on_same_line?(node)
|
|
285
|
+
collection = find_containing_collection(node)
|
|
286
|
+
return false unless collection
|
|
287
|
+
|
|
288
|
+
line = node.source_range.line
|
|
289
|
+
collection.each_descendant(:if).any? do |sibling|
|
|
290
|
+
sibling != node && sibling.modifier_form? && sibling.source_range.line == line
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
283
294
|
def non_simple_if_unless?(node)
|
|
284
295
|
node.ternary? || node.elsif? || node.else?
|
|
285
296
|
end
|
|
@@ -17,9 +17,9 @@ module RuboCop
|
|
|
17
17
|
include OnNormalIfUnless
|
|
18
18
|
extend AutoCorrector
|
|
19
19
|
|
|
20
|
-
MSG_IF_ELSE = 'Do not use
|
|
21
|
-
MSG_NEWLINE = 'Do not use
|
|
22
|
-
MSG_TERNARY = 'Do not use
|
|
20
|
+
MSG_IF_ELSE = 'Do not use `%<keyword>s %<expr>s;` - use `if/else` instead.'
|
|
21
|
+
MSG_NEWLINE = 'Do not use `%<keyword>s %<expr>s;` - use a newline instead.'
|
|
22
|
+
MSG_TERNARY = 'Do not use `%<keyword>s %<expr>s;` - use a ternary operator instead.'
|
|
23
23
|
|
|
24
24
|
def on_normal_if_unless(node)
|
|
25
25
|
return if node.parent&.if_type?
|
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
|
49
49
|
MSG_TERNARY
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
format(template, expr: node.condition.source)
|
|
52
|
+
format(template, keyword: node.keyword, expr: node.condition.source)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def autocorrect(corrector, node)
|
|
@@ -71,7 +71,7 @@ module RuboCop
|
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def use_return_with_argument?(node)
|
|
74
|
-
node.
|
|
74
|
+
node.branches.compact.any? { |branch| branch.return_type? && branch.arguments.any? }
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
def replacement(node)
|
|
@@ -80,6 +80,8 @@ module RuboCop
|
|
|
80
80
|
then_code = node.if_branch ? build_expression(node.if_branch) : 'nil'
|
|
81
81
|
else_code = node.else_branch ? build_expression(node.else_branch) : 'nil'
|
|
82
82
|
|
|
83
|
+
then_code, else_code = else_code, then_code if node.unless?
|
|
84
|
+
|
|
83
85
|
"#{node.condition.source} ? #{then_code} : #{else_code}"
|
|
84
86
|
end
|
|
85
87
|
|
|
@@ -48,8 +48,7 @@ module RuboCop
|
|
|
48
48
|
private
|
|
49
49
|
|
|
50
50
|
def allowed_addresses
|
|
51
|
-
allowed_addresses
|
|
52
|
-
Array(allowed_addresses).map(&:downcase)
|
|
51
|
+
@allowed_addresses ||= Array(cop_config['AllowedAddresses']).map(&:downcase).freeze
|
|
53
52
|
end
|
|
54
53
|
|
|
55
54
|
def potential_ip?(str)
|
|
@@ -176,7 +176,7 @@ module RuboCop
|
|
|
176
176
|
if first_non_comment_token
|
|
177
177
|
0...first_non_comment_token.line
|
|
178
178
|
else
|
|
179
|
-
|
|
179
|
+
0..
|
|
180
180
|
end
|
|
181
181
|
end
|
|
182
182
|
|
|
@@ -299,7 +299,7 @@ module RuboCop
|
|
|
299
299
|
end
|
|
300
300
|
|
|
301
301
|
def supported_capitalizations
|
|
302
|
-
cop_config['SupportedCapitalizations'].map(&:to_sym)
|
|
302
|
+
@supported_capitalizations ||= cop_config['SupportedCapitalizations'].map(&:to_sym).freeze
|
|
303
303
|
end
|
|
304
304
|
end
|
|
305
305
|
end
|
|
@@ -33,16 +33,18 @@ module RuboCop
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def included_macros_list
|
|
36
|
-
cop_config.fetch('IncludedMacros', []).map(&:to_sym)
|
|
36
|
+
@included_macros_list ||= cop_config.fetch('IncludedMacros', []).map(&:to_sym).freeze
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def included_macro_patterns
|
|
40
|
-
|
|
40
|
+
@included_macro_patterns ||=
|
|
41
|
+
cop_config.fetch('IncludedMacroPatterns', [])
|
|
42
|
+
.map { |pattern| Regexp.new(pattern) }.freeze
|
|
41
43
|
end
|
|
42
44
|
|
|
43
45
|
def matches_included_macro_pattern?(method_name)
|
|
44
46
|
included_macro_patterns.any? do |pattern|
|
|
45
|
-
|
|
47
|
+
pattern.match?(method_name.to_s)
|
|
46
48
|
end
|
|
47
49
|
end
|
|
48
50
|
|
|
@@ -32,7 +32,6 @@ module RuboCop
|
|
|
32
32
|
# Array.private_instance_methods.include?(:foo)
|
|
33
33
|
# Array.protected_instance_methods.include?(:foo)
|
|
34
34
|
# Array.public_instance_methods.include?(:foo)
|
|
35
|
-
# Array.included_modules.include?(:foo)
|
|
36
35
|
#
|
|
37
36
|
# # good
|
|
38
37
|
# Array.class_variable_defined?(:foo)
|
|
@@ -40,15 +39,8 @@ module RuboCop
|
|
|
40
39
|
# Array.private_method_defined?(:foo)
|
|
41
40
|
# Array.protected_method_defined?(:foo)
|
|
42
41
|
# Array.public_method_defined?(:foo)
|
|
43
|
-
# Array.include?(:foo)
|
|
44
|
-
#
|
|
45
|
-
# @example AllowedMethods: [included_modules]
|
|
46
|
-
#
|
|
47
|
-
# # good
|
|
48
|
-
# Array.included_modules.include?(:foo)
|
|
49
42
|
#
|
|
50
43
|
class ModuleMemberExistenceCheck < Base
|
|
51
|
-
include AllowedMethods
|
|
52
44
|
extend AutoCorrector
|
|
53
45
|
|
|
54
46
|
MSG = 'Use `%<replacement>s` instead.'
|
|
@@ -64,14 +56,13 @@ module RuboCop
|
|
|
64
56
|
METHOD_REPLACEMENTS = {
|
|
65
57
|
class_variables: :class_variable_defined?,
|
|
66
58
|
constants: :const_defined?,
|
|
67
|
-
included_modules: :include?,
|
|
68
59
|
instance_methods: :method_defined?,
|
|
69
60
|
private_instance_methods: :private_method_defined?,
|
|
70
61
|
protected_instance_methods: :protected_method_defined?,
|
|
71
62
|
public_instance_methods: :public_method_defined?
|
|
72
63
|
}.freeze
|
|
73
64
|
|
|
74
|
-
METHODS_WITHOUT_INHERIT_PARAM = Set[:class_variables
|
|
65
|
+
METHODS_WITHOUT_INHERIT_PARAM = Set[:class_variables].freeze
|
|
75
66
|
METHODS_WITH_INHERIT_PARAM =
|
|
76
67
|
(METHOD_REPLACEMENTS.keys.to_set - METHODS_WITHOUT_INHERIT_PARAM).freeze
|
|
77
68
|
|
|
@@ -81,7 +72,6 @@ module RuboCop
|
|
|
81
72
|
return unless (parent = node.parent)
|
|
82
73
|
return unless module_member_inclusion?(parent)
|
|
83
74
|
return unless simple_method_argument?(node) && simple_method_argument?(parent)
|
|
84
|
-
return if allowed_method?(node.method_name)
|
|
85
75
|
|
|
86
76
|
offense_range = node.location.selector.join(parent.source_range.end)
|
|
87
77
|
replacement = replacement_for(node, parent)
|
|
@@ -125,7 +125,7 @@ module RuboCop
|
|
|
125
125
|
MSG = 'Freeze mutable objects assigned to constants.'
|
|
126
126
|
|
|
127
127
|
def on_casgn(node)
|
|
128
|
-
if node.expression.nil? # This is only the case for `CONST += ...` or
|
|
128
|
+
if node.expression.nil? # This is only the case for `CONST += ...` or similar
|
|
129
129
|
parent = node.parent
|
|
130
130
|
return unless parent.or_asgn_type? # We only care about `CONST ||= ...`
|
|
131
131
|
|
|
@@ -121,17 +121,11 @@ module RuboCop
|
|
|
121
121
|
end
|
|
122
122
|
|
|
123
123
|
def autocorrect_comparison(corrector, node)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
expr.sub(/^(\S*)\s*!=\s*nil/, '!\1.nil?')
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
return if expr == new_code
|
|
133
|
-
|
|
134
|
-
corrector.replace(node, new_code)
|
|
124
|
+
if include_semantic_changes?
|
|
125
|
+
corrector.replace(node, node.receiver.source)
|
|
126
|
+
else
|
|
127
|
+
corrector.replace(node, "!#{node.receiver.source}.nil?")
|
|
128
|
+
end
|
|
135
129
|
end
|
|
136
130
|
|
|
137
131
|
def autocorrect_non_nil(corrector, node, inner_node)
|
|
@@ -13,30 +13,50 @@ module RuboCop
|
|
|
13
13
|
# classes that logically belong with the main class.
|
|
14
14
|
#
|
|
15
15
|
# @example
|
|
16
|
-
# # bad
|
|
16
|
+
# # bad - Multiple top-level classes
|
|
17
17
|
# class Foo
|
|
18
18
|
# end
|
|
19
19
|
#
|
|
20
20
|
# class Bar
|
|
21
21
|
# end
|
|
22
22
|
#
|
|
23
|
-
# # bad
|
|
23
|
+
# # bad - Multiple top-level modules
|
|
24
|
+
# module Foo
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
# module Bar
|
|
28
|
+
# end
|
|
29
|
+
#
|
|
30
|
+
# # bad - A top-level class and a top-level module
|
|
24
31
|
# class Foo
|
|
25
32
|
# end
|
|
26
33
|
#
|
|
27
34
|
# module Bar
|
|
28
35
|
# end
|
|
29
36
|
#
|
|
30
|
-
# # good
|
|
37
|
+
# # good - A single top-level class
|
|
31
38
|
# class Foo
|
|
32
39
|
# end
|
|
33
40
|
#
|
|
34
|
-
# # good
|
|
41
|
+
# # good - A single top-level module
|
|
42
|
+
# module Foo
|
|
43
|
+
# end
|
|
44
|
+
#
|
|
45
|
+
# # good - Nested classes within a single top-level class
|
|
35
46
|
# class Foo
|
|
36
47
|
# class Bar
|
|
37
48
|
# end
|
|
38
49
|
# end
|
|
39
50
|
#
|
|
51
|
+
# # good - Multiple classes within a single top-level module
|
|
52
|
+
# module Foo
|
|
53
|
+
# class Bar
|
|
54
|
+
# end
|
|
55
|
+
#
|
|
56
|
+
# class Baz
|
|
57
|
+
# end
|
|
58
|
+
# end
|
|
59
|
+
#
|
|
40
60
|
# @example AllowedClasses: ['AllowedClass']
|
|
41
61
|
# # good
|
|
42
62
|
# class Foo
|
|
@@ -51,7 +51,7 @@ module RuboCop
|
|
|
51
51
|
EXPLODED_MSG = 'Provide an exception class and message as arguments to `%<method>s`.'
|
|
52
52
|
COMPACT_MSG = 'Provide an exception object as an argument to `%<method>s`.'
|
|
53
53
|
ACCEPTABLE_ARG_TYPES = %i[
|
|
54
|
-
hash forwarded_restarg splat
|
|
54
|
+
hash forwarded_restarg splat forwarded_kwrestarg forwarded_args
|
|
55
55
|
].freeze
|
|
56
56
|
|
|
57
57
|
RESTRICT_ON_SEND = %i[raise fail].freeze
|
|
@@ -64,7 +64,7 @@ module RuboCop
|
|
|
64
64
|
def redundant_each_method(node)
|
|
65
65
|
return if node.last_argument&.block_pass_type?
|
|
66
66
|
|
|
67
|
-
if node.method?(:each) && !node.parent&.
|
|
67
|
+
if node.method?(:each) && !node.parent&.any_block_type?
|
|
68
68
|
ancestor_node = node.each_ancestor(:call).detect do |ancestor|
|
|
69
69
|
ancestor.receiver == node &&
|
|
70
70
|
(RESTRICT_ON_SEND.include?(ancestor.method_name) || ancestor.method?(:reverse_each))
|
|
@@ -74,8 +74,8 @@ module RuboCop
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
return unless (prev_method = node.children.first)
|
|
77
|
-
return if !prev_method.
|
|
78
|
-
prev_method.
|
|
77
|
+
return if !prev_method.call_type? || prev_method.parent.any_block_type? ||
|
|
78
|
+
prev_method.last_argument&.block_pass_type?
|
|
79
79
|
|
|
80
80
|
detected = prev_method.method_name.to_s.start_with?('each_') unless node.method?(:each)
|
|
81
81
|
|