rubocop 1.69.1 → 1.70.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/config/default.yml +19 -2
- data/lib/rubocop/cli/command/execute_runner.rb +3 -3
- data/lib/rubocop/config.rb +13 -4
- data/lib/rubocop/config_loader.rb +4 -0
- data/lib/rubocop/config_loader_resolver.rb +14 -3
- data/lib/rubocop/config_validator.rb +18 -8
- data/lib/rubocop/cop/autocorrect_logic.rb +31 -34
- data/lib/rubocop/cop/base.rb +6 -0
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
- data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
- data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +4 -2
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -7
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -6
- data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -0
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +11 -2
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +24 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +3 -3
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
- data/lib/rubocop/cop/lint/constant_reassignment.rb +152 -0
- data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +11 -3
- data/lib/rubocop/cop/lint/nested_method_definition.rb +5 -1
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -2
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +6 -14
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -0
- data/lib/rubocop/cop/lint/syntax.rb +4 -1
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -4
- data/lib/rubocop/cop/lint/void.rb +3 -2
- data/lib/rubocop/cop/metrics/class_length.rb +9 -9
- data/lib/rubocop/cop/metrics/method_length.rb +8 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +7 -7
- data/lib/rubocop/cop/mixin/comments_help.rb +6 -1
- data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
- data/lib/rubocop/cop/mixin/line_length_help.rb +5 -4
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +46 -22
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +32 -1
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -4
- data/lib/rubocop/cop/style/block_delimiters.rb +8 -1
- data/lib/rubocop/cop/style/class_and_module_children.rb +5 -2
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +3 -6
- data/lib/rubocop/cop/style/empty_else.rb +4 -2
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/exact_regexp_match.rb +1 -2
- data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
- data/lib/rubocop/cop/style/file_null.rb +20 -4
- data/lib/rubocop/cop/style/float_division.rb +8 -4
- data/lib/rubocop/cop/style/hash_except.rb +54 -67
- data/lib/rubocop/cop/style/hash_syntax.rb +5 -2
- data/lib/rubocop/cop/style/if_with_semicolon.rb +6 -4
- data/lib/rubocop/cop/style/it_assignment.rb +36 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +11 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/missing_else.rb +2 -0
- data/lib/rubocop/cop/style/multiple_comparison.rb +34 -22
- data/lib/rubocop/cop/style/mutable_constant.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +13 -15
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +5 -3
- data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
- data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +12 -9
- data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -4
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +6 -5
- data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
- data/lib/rubocop/cop/style/single_line_methods.rb +2 -3
- data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
- data/lib/rubocop/cop/style/super_arguments.rb +63 -15
- data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
- data/lib/rubocop/cop/style/yoda_expression.rb +1 -0
- data/lib/rubocop/cop/util.rb +9 -2
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/lsp/diagnostic.rb +189 -0
- data/lib/rubocop/lsp/logger.rb +2 -2
- data/lib/rubocop/lsp/routes.rb +7 -23
- data/lib/rubocop/lsp/runtime.rb +15 -49
- data/lib/rubocop/lsp/stdin_runner.rb +83 -0
- data/lib/rubocop/magic_comment.rb +3 -3
- data/lib/rubocop/path_util.rb +11 -8
- data/lib/rubocop/rspec/shared_contexts.rb +4 -1
- data/lib/rubocop/runner.rb +5 -6
- data/lib/rubocop/target_ruby.rb +15 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +3 -0
- data/lib/ruby_lsp/rubocop/addon.rb +78 -0
- data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +50 -0
- metadata +16 -8
@@ -65,19 +65,23 @@ module RuboCop
|
|
65
65
|
|
66
66
|
# @!method right_coerce?(node)
|
67
67
|
def_node_matcher :right_coerce?, <<~PATTERN
|
68
|
-
(send _ :/
|
68
|
+
(send _ :/ #to_f_method?)
|
69
69
|
PATTERN
|
70
70
|
# @!method left_coerce?(node)
|
71
71
|
def_node_matcher :left_coerce?, <<~PATTERN
|
72
|
-
(send
|
72
|
+
(send #to_f_method? :/ _)
|
73
73
|
PATTERN
|
74
74
|
# @!method both_coerce?(node)
|
75
75
|
def_node_matcher :both_coerce?, <<~PATTERN
|
76
|
-
(send
|
76
|
+
(send #to_f_method? :/ #to_f_method?)
|
77
77
|
PATTERN
|
78
78
|
# @!method any_coerce?(node)
|
79
79
|
def_node_matcher :any_coerce?, <<~PATTERN
|
80
|
-
{(send _ :/
|
80
|
+
{(send _ :/ #to_f_method?) (send #to_f_method? :/ _)}
|
81
|
+
PATTERN
|
82
|
+
# @!method to_f_method?(node)
|
83
|
+
def_node_matcher :to_f_method?, <<~PATTERN
|
84
|
+
(send !nil? :to_f)
|
81
85
|
PATTERN
|
82
86
|
|
83
87
|
def on_send(node)
|
@@ -10,8 +10,10 @@ module RuboCop
|
|
10
10
|
# (`Hash#except` was added in Ruby 3.0.)
|
11
11
|
#
|
12
12
|
# For safe detection, it is limited to commonly used string and symbol comparisons
|
13
|
-
# when
|
14
|
-
#
|
13
|
+
# when using `==` or `!=`.
|
14
|
+
#
|
15
|
+
# This cop doesn't check for `Hash#delete_if` and `Hash#keep_if` because they
|
16
|
+
# modify the receiver.
|
15
17
|
#
|
16
18
|
# @safety
|
17
19
|
# This cop is unsafe because it cannot be guaranteed that the receiver
|
@@ -51,44 +53,31 @@ module RuboCop
|
|
51
53
|
MSG = 'Use `%<prefer>s` instead.'
|
52
54
|
RESTRICT_ON_SEND = %i[reject select filter].freeze
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
-
(block
|
57
|
-
(call _ _)
|
58
|
-
(args
|
59
|
-
$(arg _)
|
60
|
-
(arg _))
|
61
|
-
{
|
62
|
-
$(send
|
63
|
-
_ {:== :!= :eql? :include?} _)
|
64
|
-
(send
|
65
|
-
$(send
|
66
|
-
_ {:== :!= :eql? :include?} _) :!)
|
67
|
-
})
|
68
|
-
PATTERN
|
56
|
+
SUBSET_METHODS = %i[== != eql? include?].freeze
|
57
|
+
ACTIVE_SUPPORT_SUBSET_METHODS = (SUBSET_METHODS + %i[in? exclude?]).freeze
|
69
58
|
|
70
|
-
# @!method
|
71
|
-
def_node_matcher :
|
59
|
+
# @!method block_with_first_arg_check?(node)
|
60
|
+
def_node_matcher :block_with_first_arg_check?, <<~PATTERN
|
72
61
|
(block
|
73
|
-
(
|
62
|
+
(call _ _)
|
74
63
|
(args
|
75
|
-
$(arg
|
64
|
+
$(arg _key)
|
76
65
|
(arg _))
|
77
66
|
{
|
78
67
|
$(send
|
79
|
-
|
68
|
+
{(lvar _key) $_ _ | _ $_ (lvar _key)})
|
80
69
|
(send
|
81
70
|
$(send
|
82
|
-
|
71
|
+
{(lvar _key) $_ _ | _ $_ (lvar _key)}) :!)
|
83
72
|
})
|
84
73
|
PATTERN
|
85
74
|
|
86
75
|
def on_send(node)
|
87
76
|
block = node.parent
|
88
|
-
return unless
|
77
|
+
return unless extracts_hash_subset?(block) && semantically_except_method?(node, block)
|
89
78
|
|
90
79
|
except_key = except_key(block)
|
91
|
-
return
|
80
|
+
return unless safe_to_register_offense?(block, except_key)
|
92
81
|
|
93
82
|
range = offense_range(node)
|
94
83
|
preferred_method = "except(#{except_key_source(except_key)})"
|
@@ -101,42 +90,40 @@ module RuboCop
|
|
101
90
|
|
102
91
|
private
|
103
92
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
else
|
116
|
-
bad_method_with_poro?(block) do |key_arg, send_node|
|
117
|
-
!send_node.method?(:include?) || send_node.first_argument&.source == key_arg.source
|
93
|
+
def extracts_hash_subset?(block)
|
94
|
+
block_with_first_arg_check?(block) do |key_arg, send_node, method|
|
95
|
+
return false unless supported_subset_method?(method)
|
96
|
+
|
97
|
+
case method
|
98
|
+
when :include?, :exclude?
|
99
|
+
send_node.first_argument.source == key_arg.source
|
100
|
+
when :in?
|
101
|
+
send_node.receiver.source == key_arg.source
|
102
|
+
else
|
103
|
+
true
|
118
104
|
end
|
119
105
|
end
|
120
106
|
end
|
121
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
122
107
|
|
123
|
-
def
|
124
|
-
|
108
|
+
def supported_subset_method?(method)
|
109
|
+
if active_support_extensions_enabled?
|
110
|
+
ACTIVE_SUPPORT_SUBSET_METHODS.include?(method)
|
111
|
+
else
|
112
|
+
SUBSET_METHODS.include?(method)
|
113
|
+
end
|
114
|
+
end
|
125
115
|
|
126
|
-
|
127
|
-
body = body
|
116
|
+
def semantically_except_method?(node, block)
|
117
|
+
body, negated = extract_body_if_negated(block.body)
|
128
118
|
|
129
|
-
|
130
|
-
|
131
|
-
body.method?('==') || body.method?('eql?') || included?(negated, body)
|
132
|
-
when :select, :filter
|
133
|
-
body.method?('!=') || not_included?(negated, body)
|
119
|
+
if node.method?('reject')
|
120
|
+
body.method?('==') || body.method?('eql?') || included?(body, negated)
|
134
121
|
else
|
135
|
-
|
122
|
+
body.method?('!=') || not_included?(body, negated)
|
136
123
|
end
|
137
124
|
end
|
138
125
|
|
139
|
-
def included?(
|
126
|
+
def included?(body, negated)
|
140
127
|
if negated
|
141
128
|
body.method?('exclude?')
|
142
129
|
else
|
@@ -144,25 +131,26 @@ module RuboCop
|
|
144
131
|
end
|
145
132
|
end
|
146
133
|
|
147
|
-
def not_included?(
|
148
|
-
included?(!negated
|
134
|
+
def not_included?(body, negated)
|
135
|
+
included?(body, !negated)
|
149
136
|
end
|
150
137
|
|
151
138
|
def safe_to_register_offense?(block, except_key)
|
152
|
-
|
153
|
-
if extracted.method?('in?') || extracted.method?('include?') ||
|
154
|
-
extracted.method?('exclude?')
|
155
|
-
return true
|
156
|
-
end
|
157
|
-
return true if block.body.method?('eql?')
|
139
|
+
body = block.body
|
158
140
|
|
159
|
-
|
141
|
+
if body.method?('==') || body.method?('!=')
|
142
|
+
except_key.sym_type? || except_key.str_type?
|
143
|
+
else
|
144
|
+
true
|
145
|
+
end
|
160
146
|
end
|
161
147
|
|
162
148
|
def extract_body_if_negated(body)
|
163
|
-
|
164
|
-
|
165
|
-
|
149
|
+
if body.method?('!')
|
150
|
+
[body.receiver, true]
|
151
|
+
else
|
152
|
+
[body, false]
|
153
|
+
end
|
166
154
|
end
|
167
155
|
|
168
156
|
def except_key_source(key)
|
@@ -187,12 +175,11 @@ module RuboCop
|
|
187
175
|
end
|
188
176
|
|
189
177
|
def except_key(node)
|
190
|
-
|
191
|
-
body = extract_body_if_negated(node.body)
|
178
|
+
key_arg = node.argument_list.first.source
|
179
|
+
body, = extract_body_if_negated(node.body)
|
192
180
|
lhs, _method_name, rhs = *body
|
193
|
-
return if [lhs, rhs].map(&:source).none?(key_argument)
|
194
181
|
|
195
|
-
|
182
|
+
lhs.source == key_arg ? rhs : lhs
|
196
183
|
end
|
197
184
|
|
198
185
|
def offense_range(node)
|
@@ -137,6 +137,7 @@ module RuboCop
|
|
137
137
|
MSG_19 = 'Use the new Ruby 1.9 hash syntax.'
|
138
138
|
MSG_NO_MIXED_KEYS = "Don't mix styles in the same hash."
|
139
139
|
MSG_HASH_ROCKETS = 'Use hash rockets syntax.'
|
140
|
+
NO_MIXED_KEYS_STYLES = %i[ruby19_no_mixed_keys no_mixed_keys].freeze
|
140
141
|
|
141
142
|
def on_hash(node)
|
142
143
|
pairs = node.pairs
|
@@ -196,7 +197,7 @@ module RuboCop
|
|
196
197
|
def autocorrect(corrector, node)
|
197
198
|
if style == :hash_rockets || force_hash_rockets?(node.parent.pairs)
|
198
199
|
autocorrect_hash_rockets(corrector, node)
|
199
|
-
elsif style
|
200
|
+
elsif NO_MIXED_KEYS_STYLES.include?(style)
|
200
201
|
autocorrect_no_mixed_keys(corrector, node)
|
201
202
|
else
|
202
203
|
autocorrect_ruby19(corrector, node)
|
@@ -272,7 +273,9 @@ module RuboCop
|
|
272
273
|
end
|
273
274
|
|
274
275
|
def argument_without_space?(node)
|
275
|
-
node.argument?
|
276
|
+
return false if !node.argument? || !node.parent.loc.selector
|
277
|
+
|
278
|
+
node.source_range.begin_pos == node.parent.loc.selector.end_pos
|
276
279
|
end
|
277
280
|
|
278
281
|
def autocorrect_hash_rockets(corrector, pair_node)
|
@@ -43,7 +43,7 @@ module RuboCop
|
|
43
43
|
template = if require_newline?(node)
|
44
44
|
MSG_NEWLINE
|
45
45
|
elsif node.else_branch&.if_type? || node.else_branch&.begin_type? ||
|
46
|
-
|
46
|
+
use_masgn_or_block_in_branches?(node)
|
47
47
|
MSG_IF_ELSE
|
48
48
|
else
|
49
49
|
MSG_TERNARY
|
@@ -53,7 +53,7 @@ module RuboCop
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def autocorrect(corrector, node)
|
56
|
-
if require_newline?(node) ||
|
56
|
+
if require_newline?(node) || use_masgn_or_block_in_branches?(node)
|
57
57
|
corrector.replace(node.loc.begin, "\n")
|
58
58
|
else
|
59
59
|
corrector.replace(node, replacement(node))
|
@@ -64,8 +64,10 @@ module RuboCop
|
|
64
64
|
node.branches.compact.any?(&:begin_type?) || use_return_with_argument?(node)
|
65
65
|
end
|
66
66
|
|
67
|
-
def
|
68
|
-
node.branches.compact.any?
|
67
|
+
def use_masgn_or_block_in_branches?(node)
|
68
|
+
node.branches.compact.any? do |branch|
|
69
|
+
branch.masgn_type? || branch.block_type? || branch.numblock_type?
|
70
|
+
end
|
69
71
|
end
|
70
72
|
|
71
73
|
def use_return_with_argument?(node)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for assignments to a local `it` variable inside a block
|
7
|
+
# where `it` can refer to the first anonymous parameter as of Ruby 3.4.
|
8
|
+
#
|
9
|
+
# Although Ruby allows reassigning `it` in these cases, it could
|
10
|
+
# cause confusion if `it` is used as a block parameter elsewhere.
|
11
|
+
# For consistency, this also applies to numblocks and blocks with
|
12
|
+
# parameters, even though `it` cannot be used in those cases.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# # bad
|
16
|
+
# foo { it = 5 }
|
17
|
+
# foo { |bar| it = bar }
|
18
|
+
# foo { it = _2 }
|
19
|
+
#
|
20
|
+
# # good - use a different variable name
|
21
|
+
# foo { var = 5 }
|
22
|
+
# foo { |bar| var = bar }
|
23
|
+
# foo { bar = _2 }
|
24
|
+
class ItAssignment < Base
|
25
|
+
MSG = '`it` is the default block parameter; consider another name.'
|
26
|
+
|
27
|
+
def on_lvasgn(node)
|
28
|
+
return unless node.name == :it
|
29
|
+
return unless node.each_ancestor(:block, :numblock).any?
|
30
|
+
|
31
|
+
add_offense(node.loc.name)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -135,17 +135,20 @@ module RuboCop
|
|
135
135
|
node.parent&.class_type? && node.parent.single_line?
|
136
136
|
end
|
137
137
|
|
138
|
-
|
138
|
+
# rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
|
139
|
+
def call_with_ambiguous_arguments?(node)
|
139
140
|
call_with_braced_block?(node) ||
|
140
141
|
call_in_argument_with_block?(node) ||
|
141
142
|
call_as_argument_or_chain?(node) ||
|
142
143
|
call_in_match_pattern?(node) ||
|
143
144
|
hash_literal_in_arguments?(node) ||
|
145
|
+
ambiguous_range_argument?(node) ||
|
144
146
|
node.descendants.any? do |n|
|
145
147
|
n.forwarded_args_type? || n.block_type? || n.numblock_type? ||
|
146
148
|
ambiguous_literal?(n) || logical_operator?(n)
|
147
149
|
end
|
148
150
|
end
|
151
|
+
# rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity
|
149
152
|
|
150
153
|
def call_with_braced_block?(node)
|
151
154
|
(node.call_type? || node.super_type?) && node.block_node&.braces?
|
@@ -177,6 +180,13 @@ module RuboCop
|
|
177
180
|
end
|
178
181
|
end
|
179
182
|
|
183
|
+
def ambiguous_range_argument?(node)
|
184
|
+
return true if (first_arg = node.first_argument)&.range_type? && first_arg.begin.nil?
|
185
|
+
return true if (last_arg = node.last_argument)&.range_type? && last_arg.end.nil?
|
186
|
+
|
187
|
+
false
|
188
|
+
end
|
189
|
+
|
180
190
|
def allowed_multiline_call_with_parentheses?(node)
|
181
191
|
cop_config['AllowParenthesesInMultilineCall'] && node.multiline?
|
182
192
|
end
|
@@ -61,6 +61,8 @@ module RuboCop
|
|
61
61
|
# https://bugs.ruby-lang.org/issues/18396.
|
62
62
|
# - Parentheses are required in anonymous arguments, keyword arguments
|
63
63
|
# and block passing in Ruby 3.2.
|
64
|
+
# - Parentheses are required when the first argument is a beginless range or
|
65
|
+
# the last argument is an endless range.
|
64
66
|
#
|
65
67
|
# @example EnforcedStyle: require_parentheses (default)
|
66
68
|
#
|
@@ -107,7 +107,7 @@ module RuboCop
|
|
107
107
|
end
|
108
108
|
|
109
109
|
def variable_in_mass_assignment?(variable_name, node)
|
110
|
-
node.assignments.any? { |n| n.name == variable_name }
|
110
|
+
node.assignments.reject(&:send_type?).any? { |n| n.name == variable_name }
|
111
111
|
end
|
112
112
|
|
113
113
|
def offense_range(node)
|
@@ -55,6 +55,22 @@ module RuboCop
|
|
55
55
|
MSG = 'Avoid comparing a variable with multiple items ' \
|
56
56
|
'in a conditional, use `Array#include?` instead.'
|
57
57
|
|
58
|
+
# @!method simple_double_comparison?(node)
|
59
|
+
def_node_matcher :simple_double_comparison?, <<~PATTERN
|
60
|
+
(send lvar :== lvar)
|
61
|
+
PATTERN
|
62
|
+
|
63
|
+
# @!method simple_comparison_lhs(node)
|
64
|
+
def_node_matcher :simple_comparison_lhs, <<~PATTERN
|
65
|
+
(send ${lvar call} :== $_)
|
66
|
+
PATTERN
|
67
|
+
|
68
|
+
# @!method simple_comparison_rhs(node)
|
69
|
+
def_node_matcher :simple_comparison_rhs, <<~PATTERN
|
70
|
+
(send $_ :== ${lvar call})
|
71
|
+
PATTERN
|
72
|
+
|
73
|
+
# rubocop:disable Metrics/AbcSize
|
58
74
|
def on_or(node)
|
59
75
|
root_of_or_node = root_of_or_node(node)
|
60
76
|
return unless node == root_of_or_node
|
@@ -63,29 +79,20 @@ module RuboCop
|
|
63
79
|
return unless (variable, values = find_offending_var(node))
|
64
80
|
return if values.size < comparisons_threshold
|
65
81
|
|
66
|
-
|
82
|
+
range = offense_range(values)
|
83
|
+
|
84
|
+
add_offense(range) do |corrector|
|
67
85
|
elements = values.map(&:source).join(', ')
|
68
|
-
|
86
|
+
argument = variable.lvar_type? ? variable_name(variable) : variable.source
|
87
|
+
prefer_method = "[#{elements}].include?(#{argument})"
|
69
88
|
|
70
|
-
corrector.replace(
|
89
|
+
corrector.replace(range, prefer_method)
|
71
90
|
end
|
72
91
|
end
|
92
|
+
# rubocop:enable Metrics/AbcSize
|
73
93
|
|
74
94
|
private
|
75
95
|
|
76
|
-
# @!method simple_double_comparison?(node)
|
77
|
-
def_node_matcher :simple_double_comparison?, '(send $lvar :== $lvar)'
|
78
|
-
|
79
|
-
# @!method simple_comparison_lhs?(node)
|
80
|
-
def_node_matcher :simple_comparison_lhs?, <<~PATTERN
|
81
|
-
(send $lvar :== $_)
|
82
|
-
PATTERN
|
83
|
-
|
84
|
-
# @!method simple_comparison_rhs?(node)
|
85
|
-
def_node_matcher :simple_comparison_rhs?, <<~PATTERN
|
86
|
-
(send $_ :== $lvar)
|
87
|
-
PATTERN
|
88
|
-
|
89
96
|
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
90
97
|
def find_offending_var(node, variables = Set.new, values = [])
|
91
98
|
if node.or_type?
|
@@ -93,8 +100,8 @@ module RuboCop
|
|
93
100
|
find_offending_var(node.rhs, variables, values)
|
94
101
|
elsif simple_double_comparison?(node)
|
95
102
|
return
|
96
|
-
elsif (var, obj = simple_comparison
|
97
|
-
return if allow_method_comparison? && obj.
|
103
|
+
elsif (var, obj = simple_comparison(node))
|
104
|
+
return if allow_method_comparison? && obj.call_type?
|
98
105
|
|
99
106
|
variables << var
|
100
107
|
return if variables.size > 1
|
@@ -106,6 +113,10 @@ module RuboCop
|
|
106
113
|
end
|
107
114
|
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
108
115
|
|
116
|
+
def offense_range(values)
|
117
|
+
values.first.parent.source_range.begin.join(values.last.parent.source_range.end)
|
118
|
+
end
|
119
|
+
|
109
120
|
def variable_name(node)
|
110
121
|
node.children[0]
|
111
122
|
end
|
@@ -119,12 +130,13 @@ module RuboCop
|
|
119
130
|
end
|
120
131
|
|
121
132
|
def comparison?(node)
|
122
|
-
simple_comparison
|
133
|
+
!!simple_comparison(node) || nested_comparison?(node)
|
123
134
|
end
|
124
135
|
|
125
|
-
def simple_comparison
|
126
|
-
if (var, obj = simple_comparison_lhs
|
127
|
-
|
136
|
+
def simple_comparison(node)
|
137
|
+
if (var, obj = simple_comparison_lhs(node)) || (obj, var = simple_comparison_rhs(node))
|
138
|
+
return if var.call_type? && !allow_method_comparison?
|
139
|
+
|
128
140
|
[var, obj]
|
129
141
|
end
|
130
142
|
end
|
@@ -33,9 +33,10 @@ module RuboCop
|
|
33
33
|
RESTRICT_ON_SEND = %i[then yield_self].freeze
|
34
34
|
|
35
35
|
def on_block(node)
|
36
|
+
return unless RESTRICT_ON_SEND.include?(node.method_name)
|
37
|
+
|
36
38
|
check_method_node(node.send_node)
|
37
39
|
end
|
38
|
-
|
39
40
|
alias on_numblock on_block
|
40
41
|
|
41
42
|
def on_send(node)
|
@@ -43,29 +44,26 @@ module RuboCop
|
|
43
44
|
|
44
45
|
check_method_node(node)
|
45
46
|
end
|
47
|
+
alias on_csend on_send
|
46
48
|
|
47
49
|
private
|
48
50
|
|
49
51
|
def check_method_node(node)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
if preferred_method?(node)
|
53
|
+
correct_style_detected
|
54
|
+
else
|
55
|
+
opposite_style_detected
|
56
|
+
message = message(node)
|
57
|
+
add_offense(node.loc.selector, message: message) do |corrector|
|
58
|
+
prefer = style == :then && node.receiver.nil? ? 'self.then' : style
|
55
59
|
|
56
|
-
|
60
|
+
corrector.replace(node.loc.selector, prefer)
|
61
|
+
end
|
57
62
|
end
|
58
63
|
end
|
59
64
|
|
60
65
|
def preferred_method?(node)
|
61
|
-
|
62
|
-
when :then
|
63
|
-
node.method?(:yield_self)
|
64
|
-
when :yield_self
|
65
|
-
node.method?(:then)
|
66
|
-
else
|
67
|
-
false
|
68
|
-
end
|
66
|
+
node.method?(style)
|
69
67
|
end
|
70
68
|
|
71
69
|
def message(node)
|
@@ -98,7 +98,7 @@ module RuboCop
|
|
98
98
|
|
99
99
|
def style
|
100
100
|
return super unless super == :same_as_string_literals
|
101
|
-
return :single_quotes unless
|
101
|
+
return :single_quotes unless config.cop_enabled?('Style/StringLiterals')
|
102
102
|
|
103
103
|
string_literals_config['EnforcedStyle'].to_sym
|
104
104
|
end
|
@@ -50,6 +50,9 @@ module RuboCop
|
|
50
50
|
|
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
|
+
ACCEPTABLE_ARG_TYPES = %i[
|
54
|
+
hash forwarded_restarg splat forwarded_restarg forwarded_args
|
55
|
+
].freeze
|
53
56
|
|
54
57
|
RESTRICT_ON_SEND = %i[raise fail].freeze
|
55
58
|
|
@@ -138,9 +141,8 @@ module RuboCop
|
|
138
141
|
|
139
142
|
arg = args.first
|
140
143
|
|
141
|
-
# Allow
|
142
|
-
|
143
|
-
arg.hash_type? || arg.splat_type?
|
144
|
+
# Allow nodes that may forward more than one argument
|
145
|
+
ACCEPTABLE_ARG_TYPES.include?(arg.type)
|
144
146
|
end
|
145
147
|
|
146
148
|
def allowed_non_exploded_type?(arg)
|
@@ -36,7 +36,7 @@ module RuboCop
|
|
36
36
|
(send
|
37
37
|
{nil? (const {nil? cbase} :Random) (const {nil? cbase} :Kernel)}
|
38
38
|
:rand
|
39
|
-
{int (
|
39
|
+
{int (range int int)}))
|
40
40
|
PATTERN
|
41
41
|
|
42
42
|
# @!method rand_op_integer?(node)
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
45
45
|
(send
|
46
46
|
{nil? (const {nil? cbase} :Random) (const {nil? cbase} :Kernel)}
|
47
47
|
:rand
|
48
|
-
{int (
|
48
|
+
{int (range int int)})
|
49
49
|
{:+ :-}
|
50
50
|
int)
|
51
51
|
PATTERN
|
@@ -56,7 +56,7 @@ module RuboCop
|
|
56
56
|
(send
|
57
57
|
{nil? (const {nil? cbase} :Random) (const {nil? cbase} :Kernel)}
|
58
58
|
:rand
|
59
|
-
{int (
|
59
|
+
{int (range int int)})
|
60
60
|
{:succ :pred :next})
|
61
61
|
PATTERN
|
62
62
|
|
@@ -11,6 +11,9 @@ module RuboCop
|
|
11
11
|
# will not register an offense, because it allows the initializer to take a different
|
12
12
|
# number of arguments as its superclass potentially does.
|
13
13
|
#
|
14
|
+
# NOTE: If an initializer takes any arguments and has an empty body, RuboCop
|
15
|
+
# assumes it to *not* be redundant. This is to prevent potential `ArgumentError`.
|
16
|
+
#
|
14
17
|
# NOTE: If an initializer argument has a default value, RuboCop assumes it
|
15
18
|
# to *not* be redundant.
|
16
19
|
#
|
@@ -19,8 +22,10 @@ module RuboCop
|
|
19
22
|
# initializer.
|
20
23
|
#
|
21
24
|
# @safety
|
22
|
-
# This cop is unsafe because
|
23
|
-
#
|
25
|
+
# This cop is unsafe because removing an empty initializer may alter
|
26
|
+
# the behavior of the code, particularly if the superclass initializer
|
27
|
+
# raises an exception. In such cases, the empty initializer may act as
|
28
|
+
# a safeguard to prevent unintended errors from propagating.
|
24
29
|
#
|
25
30
|
# @example
|
26
31
|
# # bad
|
@@ -69,6 +74,10 @@ module RuboCop
|
|
69
74
|
# end
|
70
75
|
#
|
71
76
|
# # good (changes the parameter requirements)
|
77
|
+
# def initialize(_)
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
# # good (changes the parameter requirements)
|
72
81
|
# def initialize(*)
|
73
82
|
# end
|
74
83
|
#
|
@@ -111,7 +120,7 @@ module RuboCop
|
|
111
120
|
return if acceptable?(node)
|
112
121
|
|
113
122
|
if node.body.nil?
|
114
|
-
register_offense(node, MSG_EMPTY)
|
123
|
+
register_offense(node, MSG_EMPTY) if node.arguments.empty?
|
115
124
|
else
|
116
125
|
return if node.body.begin_type?
|
117
126
|
|