rubocop 1.75.1 → 1.77.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/README.md +20 -14
- data/config/default.yml +103 -25
- data/config/obsoletion.yml +6 -3
- data/lib/rubocop/config_validator.rb +6 -6
- data/lib/rubocop/cop/autocorrect_logic.rb +18 -10
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
- 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 +37 -15
- 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 +2 -0
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +6 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
- data/lib/rubocop/cop/layout/class_structure.rb +35 -0
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -2
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -3
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/leading_comment_space.rb +13 -1
- data/lib/rubocop/cop/layout/line_length.rb +26 -5
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -4
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +10 -0
- data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -38
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +12 -3
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
- data/lib/rubocop/cop/lint/ambiguous_range.rb +5 -0
- data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -5
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +86 -5
- data/lib/rubocop/cop/lint/empty_interpolation.rb +3 -1
- data/lib/rubocop/cop/lint/float_comparison.rb +31 -4
- data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
- data/lib/rubocop/cop/lint/literal_as_condition.rb +31 -25
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +2 -2
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +7 -4
- data/lib/rubocop/cop/lint/return_in_void_context.rb +7 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +4 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +25 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +5 -0
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +29 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +2 -0
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +90 -0
- data/lib/rubocop/cop/lint/useless_or.rb +98 -0
- data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +3 -3
- data/lib/rubocop/cop/lint/void.rb +2 -2
- data/lib/rubocop/cop/message_annotator.rb +7 -3
- data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +1 -1
- data/lib/rubocop/cop/mixin/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -2
- data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
- data/lib/rubocop/cop/mixin/line_length_help.rb +24 -8
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -0
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +9 -5
- data/lib/rubocop/cop/naming/file_name.rb +2 -2
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/naming/method_name.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_method.rb +281 -0
- data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +4 -4
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +32 -10
- data/lib/rubocop/cop/style/arguments_forwarding.rb +8 -5
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/class_and_module_children.rb +19 -3
- data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
- data/lib/rubocop/cop/style/collection_querying.rb +167 -0
- data/lib/rubocop/cop/style/command_literal.rb +1 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +2 -2
- data/lib/rubocop/cop/style/comparable_between.rb +5 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +18 -4
- data/lib/rubocop/cop/style/data_inheritance.rb +7 -0
- data/lib/rubocop/cop/style/def_with_parentheses.rb +18 -5
- data/lib/rubocop/cop/style/double_negation.rb +1 -1
- data/lib/rubocop/cop/style/empty_literal.rb +4 -0
- data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +100 -0
- data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
- data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
- data/lib/rubocop/cop/style/exponential_notation.rb +2 -2
- data/lib/rubocop/cop/style/fetch_env_var.rb +32 -6
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
- data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +12 -3
- data/lib/rubocop/cop/style/hash_fetch_chain.rb +0 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +3 -0
- data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
- data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +3 -3
- data/lib/rubocop/cop/style/if_unless_modifier.rb +33 -6
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -7
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
- data/lib/rubocop/cop/style/it_block_parameter.rb +33 -14
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
- data/lib/rubocop/cop/style/lambda_call.rb +7 -2
- data/lib/rubocop/cop/style/map_into_array.rb +3 -1
- data/lib/rubocop/cop/style/map_to_hash.rb +11 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -3
- data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +13 -1
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +6 -1
- data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +0 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +41 -3
- data/lib/rubocop/cop/style/redundant_self.rb +8 -5
- data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
- data/lib/rubocop/cop/style/return_nil.rb +2 -2
- data/lib/rubocop/cop/style/safe_navigation.rb +42 -14
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +6 -3
- data/lib/rubocop/cop/style/string_concatenation.rb +1 -2
- data/lib/rubocop/cop/style/struct_inheritance.rb +8 -1
- data/lib/rubocop/cop/style/super_arguments.rb +1 -2
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +7 -1
- data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +1 -1
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/variable_force/assignment.rb +7 -3
- data/lib/rubocop/cop/variable_force/variable.rb +1 -1
- data/lib/rubocop/cops_documentation_generator.rb +6 -2
- data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
- data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
- data/lib/rubocop/lsp/diagnostic.rb +4 -4
- data/lib/rubocop/magic_comment.rb +8 -0
- data/lib/rubocop/rspec/cop_helper.rb +2 -2
- data/lib/rubocop/rspec/expect_offense.rb +9 -3
- data/lib/rubocop/rspec/shared_contexts.rb +1 -2
- data/lib/rubocop/server/cache.rb +13 -10
- data/lib/rubocop/target_finder.rb +6 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +8 -1
- data/lib/ruby_lsp/rubocop/addon.rb +2 -2
- metadata +14 -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
|
@@ -78,7 +79,7 @@ module RuboCop
|
|
78
79
|
ancestor = node.ancestors.first
|
79
80
|
return false unless ancestor
|
80
81
|
|
81
|
-
!ancestor.type?(:begin, :
|
82
|
+
!ancestor.type?(:begin, :any_def, :any_block)
|
82
83
|
end
|
83
84
|
|
84
85
|
def allowed_ternary?(node)
|
@@ -98,7 +99,7 @@ module RuboCop
|
|
98
99
|
return false unless node.type?(:send, :super, :yield)
|
99
100
|
|
100
101
|
node.arguments.one? && !node.parenthesized? &&
|
101
|
-
!node.
|
102
|
+
!node.operator_method? && node.first_argument.begin_type?
|
102
103
|
end
|
103
104
|
|
104
105
|
def multiline_control_flow_statements?(node)
|
@@ -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,7 +142,9 @@ module RuboCop
|
|
134
142
|
node = begin_node.children.first
|
135
143
|
|
136
144
|
if (message = find_offense_message(begin_node, node))
|
137
|
-
|
145
|
+
if node.range_type? && !argument_of_parenthesized_method_call?(begin_node, node)
|
146
|
+
begin_node = begin_node.parent
|
147
|
+
end
|
138
148
|
|
139
149
|
return offense(begin_node, message)
|
140
150
|
end
|
@@ -154,7 +164,11 @@ module RuboCop
|
|
154
164
|
if node.lambda_or_proc? && (node.braces? || node.send_node.lambda_literal?)
|
155
165
|
return 'an expression'
|
156
166
|
end
|
167
|
+
if disallowed_one_line_pattern_matching?(begin_node, node)
|
168
|
+
return 'a one-line pattern matching'
|
169
|
+
end
|
157
170
|
return 'an interpolated expression' if interpolation?(begin_node)
|
171
|
+
return 'a method argument' if argument_of_parenthesized_method_call?(begin_node, node)
|
158
172
|
|
159
173
|
return if begin_node.chained?
|
160
174
|
|
@@ -177,6 +191,21 @@ module RuboCop
|
|
177
191
|
# @!method interpolation?(node)
|
178
192
|
def_node_matcher :interpolation?, '[^begin ^^dstr]'
|
179
193
|
|
194
|
+
def argument_of_parenthesized_method_call?(begin_node, node)
|
195
|
+
if node.basic_conditional? || node.rescue_type? || method_call_parentheses_required?(node)
|
196
|
+
return false
|
197
|
+
end
|
198
|
+
return false unless (parent = begin_node.parent)
|
199
|
+
|
200
|
+
parent.call_type? && parent.parenthesized? && parent.receiver != begin_node
|
201
|
+
end
|
202
|
+
|
203
|
+
def method_call_parentheses_required?(node)
|
204
|
+
return false unless node.call_type?
|
205
|
+
|
206
|
+
(node.receiver.nil? || node.loc.dot) && node.arguments.any?
|
207
|
+
end
|
208
|
+
|
180
209
|
def allow_in_multiline_conditions?
|
181
210
|
!!config.for_enabled_cop('Style/ParenthesesAroundCondition')['AllowInMultilineConditions']
|
182
211
|
end
|
@@ -225,6 +254,15 @@ module RuboCop
|
|
225
254
|
end
|
226
255
|
end
|
227
256
|
|
257
|
+
def disallowed_one_line_pattern_matching?(begin_node, node)
|
258
|
+
if (parent = begin_node.parent)
|
259
|
+
return false if parent.any_def_type? && parent.endless?
|
260
|
+
return false if parent.assignment?
|
261
|
+
end
|
262
|
+
|
263
|
+
node.any_match_pattern_type? && node.each_ancestor.none?(&:operator_keyword?)
|
264
|
+
end
|
265
|
+
|
228
266
|
def raised_to_power_negative_numeric?(begin_node, node)
|
229
267
|
return false unless node.numeric_type?
|
230
268
|
|
@@ -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
|
@@ -155,7 +155,7 @@ module RuboCop
|
|
155
155
|
end
|
156
156
|
|
157
157
|
def preferred_delimiters
|
158
|
-
config.for_cop('Style/PercentLiteralDelimiters')
|
158
|
+
config.for_cop('Style/PercentLiteralDelimiters')['PreferredDelimiters']['%r'].chars
|
159
159
|
end
|
160
160
|
|
161
161
|
def allowed_omit_parentheses_with_percent_r_literal?(node)
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
|
48
48
|
def on_return(node)
|
49
49
|
# Check Lint/NonLocalExitFromIterator first before this cop
|
50
|
-
node.each_ancestor(:block, :
|
50
|
+
node.each_ancestor(:block, :any_def) do |n|
|
51
51
|
break if scoped_node?(n)
|
52
52
|
|
53
53
|
send_node, args_node, _body_node = *n
|
@@ -83,7 +83,7 @@ module RuboCop
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def scoped_node?(node)
|
86
|
-
node.
|
86
|
+
node.any_def_type? || node.lambda?
|
87
87
|
end
|
88
88
|
|
89
89
|
# @!method chained_send?(node)
|
@@ -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
|
@@ -146,6 +150,7 @@ module RuboCop
|
|
146
150
|
|
147
151
|
body = extract_if_body(node)
|
148
152
|
method_call = receiver.parent
|
153
|
+
return if dotless_operator_call?(method_call) || method_call.double_colon?
|
149
154
|
|
150
155
|
removal_ranges = [begin_range(node, body), end_range(node, body)]
|
151
156
|
|
@@ -174,12 +179,19 @@ module RuboCop
|
|
174
179
|
range_with_surrounding_space(range: lhs.source_range, side: :right),
|
175
180
|
range_with_surrounding_space(range: lhs_operator_range, side: :right),
|
176
181
|
offense_range: range_between(lhs.source_range.begin_pos, rhs.source_range.end_pos)
|
177
|
-
)
|
182
|
+
) do |corrector|
|
183
|
+
corrector.replace(rhs_receiver, lhs_receiver.source)
|
184
|
+
end
|
185
|
+
ignore_node(node)
|
178
186
|
end
|
179
187
|
end
|
180
188
|
|
189
|
+
private
|
190
|
+
|
181
191
|
def report_offense(node, rhs, rhs_receiver, *removal_ranges, offense_range: node)
|
182
192
|
add_offense(offense_range) do |corrector|
|
193
|
+
next if ignored_node?(node)
|
194
|
+
|
183
195
|
# If the RHS is an `or` we cannot safely autocorrect because in order to remove
|
184
196
|
# the non-nil check we need to add safe-navs to all clauses where the receiver is used
|
185
197
|
next if and_with_rhs_or?(node)
|
@@ -193,8 +205,6 @@ module RuboCop
|
|
193
205
|
end
|
194
206
|
end
|
195
207
|
|
196
|
-
private
|
197
|
-
|
198
208
|
def find_method_chain(node)
|
199
209
|
return node unless node&.parent&.call_type?
|
200
210
|
|
@@ -227,10 +237,10 @@ module RuboCop
|
|
227
237
|
end
|
228
238
|
|
229
239
|
def offending_node?(node, lhs_receiver, rhs, rhs_receiver) # rubocop:disable Metrics/CyclomaticComplexity
|
230
|
-
return false if lhs_receiver
|
240
|
+
return false if !matching_nodes?(lhs_receiver, rhs_receiver) || rhs_receiver.nil?
|
231
241
|
return false if use_var_only_in_unless_modifier?(node, lhs_receiver)
|
232
242
|
return false if chain_length(rhs, rhs_receiver) > max_chain_length
|
233
|
-
return false if unsafe_method_used?(rhs, rhs_receiver.parent)
|
243
|
+
return false if unsafe_method_used?(node, rhs, rhs_receiver.parent)
|
234
244
|
return false if rhs.send_type? && rhs.method?(:empty?)
|
235
245
|
|
236
246
|
true
|
@@ -248,6 +258,12 @@ module RuboCop
|
|
248
258
|
end
|
249
259
|
end
|
250
260
|
|
261
|
+
def dotless_operator_call?(method_call)
|
262
|
+
return false if method_call.loc.dot
|
263
|
+
|
264
|
+
method_call.method?(:[]) || method_call.method?(:[]=) || method_call.operator_method?
|
265
|
+
end
|
266
|
+
|
251
267
|
def handle_comments(corrector, node, method_call)
|
252
268
|
comments = comments(node)
|
253
269
|
return if comments.empty?
|
@@ -306,11 +322,21 @@ module RuboCop
|
|
306
322
|
|
307
323
|
receiver = method_chain.receiver
|
308
324
|
|
309
|
-
return receiver if receiver
|
325
|
+
return receiver if matching_nodes?(receiver, checked_variable)
|
310
326
|
|
311
327
|
find_matching_receiver_invocation(receiver, checked_variable)
|
312
328
|
end
|
313
329
|
|
330
|
+
def matching_nodes?(left, right)
|
331
|
+
left == right || matching_call_nodes?(left, right)
|
332
|
+
end
|
333
|
+
|
334
|
+
def matching_call_nodes?(left, right)
|
335
|
+
return false unless left && right.respond_to?(:call_type?)
|
336
|
+
|
337
|
+
left.call_type? && right.call_type? && left.children == right.children
|
338
|
+
end
|
339
|
+
|
314
340
|
def chain_length(method_chain, method)
|
315
341
|
method.each_ancestor(:call).inject(0) do |total, ancestor|
|
316
342
|
break total + 1 if ancestor == method_chain
|
@@ -319,21 +345,24 @@ module RuboCop
|
|
319
345
|
end
|
320
346
|
end
|
321
347
|
|
322
|
-
def unsafe_method_used?(method_chain, method)
|
323
|
-
return true if unsafe_method?(method)
|
348
|
+
def unsafe_method_used?(node, method_chain, method)
|
349
|
+
return true if unsafe_method?(node, method)
|
324
350
|
|
325
351
|
method.each_ancestor(:send).any? do |ancestor|
|
326
352
|
break true unless config.cop_enabled?('Lint/SafeNavigationChain')
|
327
353
|
|
328
|
-
break true if unsafe_method?(ancestor)
|
354
|
+
break true if unsafe_method?(node, ancestor)
|
329
355
|
break true if nil_methods.include?(ancestor.method_name)
|
330
356
|
break false if ancestor == method_chain
|
331
357
|
end
|
332
358
|
end
|
333
359
|
|
334
|
-
def unsafe_method?(send_node)
|
335
|
-
negated?(send_node)
|
336
|
-
|
360
|
+
def unsafe_method?(node, send_node)
|
361
|
+
return true if negated?(send_node)
|
362
|
+
|
363
|
+
return false if node.respond_to?(:ternary?) && node.ternary?
|
364
|
+
|
365
|
+
send_node.assignment? ||
|
337
366
|
(!send_node.dot? && !send_node.safe_navigation?)
|
338
367
|
end
|
339
368
|
|
@@ -362,8 +391,7 @@ module RuboCop
|
|
362
391
|
method_chain)
|
363
392
|
start_method.each_ancestor do |ancestor|
|
364
393
|
break unless %i[send block].include?(ancestor.type)
|
365
|
-
next
|
366
|
-
next if ancestor.safe_navigation?
|
394
|
+
next if !ancestor.send_type? || ancestor.operator_method?
|
367
395
|
|
368
396
|
corrector.insert_before(ancestor.loc.dot, '&')
|
369
397
|
|
@@ -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)
|
@@ -185,8 +186,10 @@ module RuboCop
|
|
185
186
|
end
|
186
187
|
|
187
188
|
def add_parentheses?(node)
|
188
|
-
node.assignment? || (node.operator_keyword? && !node.and_type?)
|
189
|
-
|
189
|
+
return true if node.assignment? || (node.operator_keyword? && !node.and_type?)
|
190
|
+
return false unless node.call_type?
|
191
|
+
|
192
|
+
(node.arguments.any? && !node.parenthesized?) || node.prefix_not?
|
190
193
|
end
|
191
194
|
|
192
195
|
def parenthesized_method_arguments(node)
|
@@ -51,7 +51,6 @@ module RuboCop
|
|
51
51
|
# Pathname.new('/') + 'test'
|
52
52
|
#
|
53
53
|
class StringConcatenation < Base
|
54
|
-
include RangeHelp
|
55
54
|
extend AutoCorrector
|
56
55
|
|
57
56
|
MSG = 'Prefer string interpolation to string concatenation.'
|
@@ -147,7 +146,7 @@ module RuboCop
|
|
147
146
|
when :str
|
148
147
|
adjust_str(part)
|
149
148
|
when :dstr
|
150
|
-
part.children.all?(&:str_type?) ? adjust_str(part) :
|
149
|
+
part.children.all?(&:str_type?) ? adjust_str(part) : part.value
|
151
150
|
else
|
152
151
|
"\#{#{part.source}}"
|
153
152
|
end
|
@@ -3,7 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for inheritance from Struct.new.
|
6
|
+
# Checks for inheritance from `Struct.new`. Inheriting from `Struct.new`
|
7
|
+
# adds a superfluous level in inheritance tree.
|
7
8
|
#
|
8
9
|
# @safety
|
9
10
|
# Autocorrection is unsafe because it will change the inheritance
|
@@ -17,12 +18,18 @@ module RuboCop
|
|
17
18
|
# end
|
18
19
|
# end
|
19
20
|
#
|
21
|
+
# Person.ancestors
|
22
|
+
# # => [Person, #<Class:0x000000010b4e14a0>, Struct, (...)]
|
23
|
+
#
|
20
24
|
# # good
|
21
25
|
# Person = Struct.new(:first_name, :last_name) do
|
22
26
|
# def age
|
23
27
|
# 42
|
24
28
|
# end
|
25
29
|
# end
|
30
|
+
#
|
31
|
+
# Person.ancestors
|
32
|
+
# # => [Person, Struct, (...)]
|
26
33
|
class StructInheritance < Base
|
27
34
|
include RangeHelp
|
28
35
|
extend AutoCorrector
|
@@ -68,7 +68,6 @@ module RuboCop
|
|
68
68
|
class SuperArguments < Base
|
69
69
|
extend AutoCorrector
|
70
70
|
|
71
|
-
DEF_TYPES = %i[def defs].freeze
|
72
71
|
ASSIGN_TYPES = %i[or_asgn lvasgn].freeze
|
73
72
|
|
74
73
|
MSG = 'Call `super` without arguments and parentheses when the signature is identical.'
|
@@ -100,7 +99,7 @@ module RuboCop
|
|
100
99
|
# `super` used within the block is always allowed.
|
101
100
|
break if node.any_block_type? && !block_sends_to_super?(super_node, node)
|
102
101
|
|
103
|
-
break node if
|
102
|
+
break node if node.any_def_type?
|
104
103
|
end
|
105
104
|
end
|
106
105
|
|
@@ -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?
|
@@ -79,10 +79,16 @@ module RuboCop
|
|
79
79
|
# # bad
|
80
80
|
# method(1, 2,)
|
81
81
|
#
|
82
|
+
# # bad
|
83
|
+
# object[1, 2,]
|
84
|
+
#
|
82
85
|
# # good
|
83
86
|
# method(1, 2)
|
84
87
|
#
|
85
88
|
# # good
|
89
|
+
# object[1, 2]
|
90
|
+
#
|
91
|
+
# # good
|
86
92
|
# method(
|
87
93
|
# 1,
|
88
94
|
# 2
|
@@ -96,7 +102,7 @@ module RuboCop
|
|
96
102
|
end
|
97
103
|
|
98
104
|
def on_send(node)
|
99
|
-
return unless node.arguments? && node.parenthesized?
|
105
|
+
return unless node.arguments? && (node.parenthesized? || node.method?(:[]))
|
100
106
|
|
101
107
|
check(node, node.arguments, 'parameter of %<article>s method call',
|
102
108
|
node.last_argument.source_range.end_pos,
|
@@ -11,7 +11,7 @@ module RuboCop
|
|
11
11
|
# * `comma`: Requires a comma after the last item in an array, but only when each item is on
|
12
12
|
# its own line.
|
13
13
|
# * `diff_comma`: Requires a comma after the last item in an array, but only when that item is
|
14
|
-
# followed by an immediate newline.
|
14
|
+
# followed by an immediate newline, even if there is an inline comment on the same line.
|
15
15
|
# * `no_comma`: Does not require a comma after the last item in an array
|
16
16
|
#
|
17
17
|
# @example EnforcedStyleForMultiline: consistent_comma
|
@@ -11,7 +11,7 @@ module RuboCop
|
|
11
11
|
# * `comma`: Requires a comma after the last item in a hash, but only when each item is on its
|
12
12
|
# own line.
|
13
13
|
# * `diff_comma`: Requires a comma after the last item in a hash, but only when that item is
|
14
|
-
# followed by an immediate newline.
|
14
|
+
# followed by an immediate newline, even if there is an inline comment on the same line.
|
15
15
|
# * `no_comma`: Does not require a comma after the last item in a hash
|
16
16
|
#
|
17
17
|
# @example EnforcedStyleForMultiline: consistent_comma
|
data/lib/rubocop/cop/team.rb
CHANGED
data/lib/rubocop/cop/util.rb
CHANGED
@@ -110,8 +110,13 @@ module RuboCop
|
|
110
110
|
end
|
111
111
|
|
112
112
|
def multiple_assignment_node
|
113
|
-
return nil unless node.parent
|
114
|
-
|
113
|
+
return nil unless (candidate_mlhs_node = node.parent)
|
114
|
+
|
115
|
+
# In `(foo, bar), *baz`, the splat node must be traversed as well.
|
116
|
+
candidate_mlhs_node = candidate_mlhs_node.parent if candidate_mlhs_node.splat_type?
|
117
|
+
|
118
|
+
return nil unless candidate_mlhs_node.mlhs_type?
|
119
|
+
return nil unless (grandparent_node = node.parent.parent)
|
115
120
|
if (node = find_multiple_assignment_node(grandparent_node))
|
116
121
|
return node
|
117
122
|
end
|
@@ -139,7 +144,6 @@ module RuboCop
|
|
139
144
|
|
140
145
|
def find_multiple_assignment_node(grandparent_node)
|
141
146
|
return unless grandparent_node.type == MULTIPLE_LEFT_HAND_SIDE_TYPE
|
142
|
-
return if grandparent_node.children.any?(&:splat_type?)
|
143
147
|
|
144
148
|
parent = grandparent_node.parent
|
145
149
|
return parent if parent.type == MULTIPLE_ASSIGNMENT_TYPE
|
@@ -327,8 +327,12 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
327
327
|
def print_cop_with_doc(cop) # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
|
328
328
|
cop_config = config.for_cop(cop)
|
329
329
|
non_display_keys = %w[
|
330
|
-
|
331
|
-
|
330
|
+
Enabled
|
331
|
+
Description
|
332
|
+
StyleGuide
|
333
|
+
Reference References
|
334
|
+
Safe SafeAutoCorrect AutoCorrect
|
335
|
+
VersionAdded VersionChanged
|
332
336
|
]
|
333
337
|
parameters = cop_config.reject { |k| non_display_keys.include? k }
|
334
338
|
description = 'No documentation'
|
@@ -164,7 +164,7 @@ module RuboCop
|
|
164
164
|
|
165
165
|
def cop_config_params(default_cfg, cfg)
|
166
166
|
default_cfg.keys -
|
167
|
-
%w[Description StyleGuide Reference Enabled Exclude Safe
|
167
|
+
%w[Description StyleGuide Reference References Enabled Exclude Safe
|
168
168
|
SafeAutoCorrect VersionAdded VersionChanged VersionRemoved] -
|
169
169
|
cfg.keys
|
170
170
|
end
|
@@ -178,6 +178,7 @@ module RuboCop
|
|
178
178
|
next unless value.is_a?(Array)
|
179
179
|
next if value.empty?
|
180
180
|
|
181
|
+
value.map! { |v| v.nil? ? '~' : v } # Change nil back to ~ as in the YAML file.
|
181
182
|
output_buffer.puts "# #{param}: #{value.uniq.join(', ')}"
|
182
183
|
end
|
183
184
|
end
|
@@ -58,7 +58,7 @@ module RuboCop
|
|
58
58
|
return pacdots(@total_files) unless @total_files > cols
|
59
59
|
return pacdots(cols) unless (@total_files / cols).eql?(@repetitions)
|
60
60
|
|
61
|
-
pacdots(
|
61
|
+
pacdots(@total_files - (cols * @repetitions))
|
62
62
|
end
|
63
63
|
|
64
64
|
def pacdots(number)
|
@@ -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 ')
|
@@ -193,6 +193,10 @@ module RuboCop
|
|
193
193
|
SEPARATOR = ';'
|
194
194
|
OPERATOR = ':'
|
195
195
|
|
196
|
+
def new_frozen_string_literal(value)
|
197
|
+
"# -*- frozen_string_literal: #{value} -*-"
|
198
|
+
end
|
199
|
+
|
196
200
|
private
|
197
201
|
|
198
202
|
def extract_frozen_string_literal
|
@@ -275,6 +279,10 @@ module RuboCop
|
|
275
279
|
end
|
276
280
|
end
|
277
281
|
|
282
|
+
def new_frozen_string_literal(value)
|
283
|
+
"# frozen_string_literal: #{value}"
|
284
|
+
end
|
285
|
+
|
278
286
|
private
|
279
287
|
|
280
288
|
# Extract `frozen_string_literal`.
|
@@ -11,8 +11,8 @@ module CopHelper
|
|
11
11
|
ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : RuboCop::TargetRuby::DEFAULT_VERSION
|
12
12
|
end
|
13
13
|
let(:parser_engine) do
|
14
|
-
# The maximum version Parser can parse is 3.
|
15
|
-
ruby_version >= 3.
|
14
|
+
# The maximum version Parser can correctly parse is 3.3.
|
15
|
+
ruby_version >= 3.4 ? :parser_prism : ENV.fetch('PARSER_ENGINE', :parser_whitequark).to_sym
|
16
16
|
end
|
17
17
|
let(:rails_version) { false }
|
18
18
|
|