rubocop 1.56.4 → 1.60.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/LICENSE.txt +1 -1
- data/README.md +4 -4
- data/config/default.yml +57 -3
- data/lib/rubocop/cli/command/auto_generate_config.rb +10 -5
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/config.rb +0 -2
- data/lib/rubocop/config_loader.rb +0 -1
- data/lib/rubocop/config_obsoletion.rb +11 -8
- data/lib/rubocop/config_validator.rb +0 -2
- data/lib/rubocop/cop/base.rb +6 -0
- data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
- data/lib/rubocop/cop/exclude_limit.rb +1 -1
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
- data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
- data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -2
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +12 -2
- data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +22 -7
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +16 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +2 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +50 -20
- data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -4
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/debugger.rb +11 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -3
- data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
- data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +85 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +0 -1
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
- data/lib/rubocop/cop/lint/number_conversion.rb +9 -4
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +63 -4
- data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
- data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
- data/lib/rubocop/cop/lint/symbol_conversion.rb +7 -2
- data/lib/rubocop/cop/lint/syntax.rb +6 -3
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/lint/useless_times.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +43 -12
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +8 -3
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +16 -12
- data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -0
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +14 -11
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +12 -4
- data/lib/rubocop/cop/naming/constant_name.rb +1 -2
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/security/open.rb +2 -2
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +120 -17
- data/lib/rubocop/cop/style/array_first_last.rb +64 -0
- data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
- data/lib/rubocop/cop/style/case_like_if.rb +4 -4
- data/lib/rubocop/cop/style/class_check.rb +1 -0
- data/lib/rubocop/cop/style/class_equality_comparison.rb +5 -0
- data/lib/rubocop/cop/style/collection_compact.rb +18 -8
- data/lib/rubocop/cop/style/combinable_loops.rb +13 -7
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
- data/lib/rubocop/cop/style/date_time.rb +5 -4
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +7 -7
- data/lib/rubocop/cop/style/each_with_object.rb +2 -2
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/eval_with_location.rb +3 -14
- data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
- data/lib/rubocop/cop/style/format_string.rb +24 -3
- data/lib/rubocop/cop/style/guard_clause.rb +26 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +83 -10
- data/lib/rubocop/cop/style/hash_except.rb +2 -1
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +28 -3
- data/lib/rubocop/cop/style/inverse_methods.rb +6 -5
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +39 -2
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +3 -2
- data/lib/rubocop/cop/style/map_to_hash.rb +17 -7
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +14 -5
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -4
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
- data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -3
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
- data/lib/rubocop/cop/style/next.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +2 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +2 -2
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -0
- data/lib/rubocop/cop/style/redundant_argument.rb +3 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +9 -1
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +93 -5
- data/lib/rubocop/cop/style/redundant_each.rb +7 -4
- data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +3 -3
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +22 -5
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +10 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +68 -21
- data/lib/rubocop/cop/style/redundant_return.rb +1 -1
- data/lib/rubocop/cop/style/redundant_self.rb +17 -2
- data/lib/rubocop/cop/style/redundant_sort.rb +9 -8
- data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
- data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -1
- data/lib/rubocop/cop/style/sample.rb +2 -1
- data/lib/rubocop/cop/style/select_by_regexp.rb +7 -6
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +8 -0
- data/lib/rubocop/cop/style/single_argument_dig.rb +7 -3
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
- data/lib/rubocop/cop/style/slicing_with_range.rb +76 -10
- data/lib/rubocop/cop/style/string_chars.rb +1 -0
- data/lib/rubocop/cop/style/strip.rb +7 -4
- data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +36 -0
- data/lib/rubocop/cop/style/unpack_first.rb +11 -14
- data/lib/rubocop/cops_documentation_generator.rb +11 -1
- data/lib/rubocop/ext/regexp_node.rb +9 -4
- data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
- data/lib/rubocop/formatter/html_formatter.rb +5 -4
- data/lib/rubocop/formatter/json_formatter.rb +0 -1
- data/lib/rubocop/formatter.rb +1 -1
- data/lib/rubocop/lsp/routes.rb +1 -1
- data/lib/rubocop/options.rb +0 -8
- data/lib/rubocop/result_cache.rb +0 -1
- data/lib/rubocop/rspec/shared_contexts.rb +6 -0
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/runner.rb +1 -1
- data/lib/rubocop/server/cache.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +5 -0
- metadata +16 -24
- /data/lib/rubocop/formatter/{git_hub_actions_formatter.rb → github_actions_formatter.rb} +0 -0
@@ -72,7 +72,7 @@ module RuboCop
|
|
72
72
|
return if ignored_node?(def_node)
|
73
73
|
|
74
74
|
left_parenthesis = def_node.arguments.loc.begin
|
75
|
-
first_elem = def_node.
|
75
|
+
first_elem = def_node.first_argument
|
76
76
|
return unless first_elem
|
77
77
|
return if same_line?(first_elem, left_parenthesis)
|
78
78
|
|
@@ -182,7 +182,7 @@ module RuboCop
|
|
182
182
|
end
|
183
183
|
|
184
184
|
def add_correct_closing_paren(node, corrector)
|
185
|
-
corrector.insert_after(node.
|
185
|
+
corrector.insert_after(node.last_argument, ')')
|
186
186
|
end
|
187
187
|
|
188
188
|
def remove_incorrect_closing_paren(node, corrector)
|
@@ -271,7 +271,7 @@ module RuboCop
|
|
271
271
|
def add_correct_external_trailing_comma(node, corrector)
|
272
272
|
return unless external_trailing_comma?(node)
|
273
273
|
|
274
|
-
corrector.insert_after(node.
|
274
|
+
corrector.insert_after(node.last_argument, ',')
|
275
275
|
end
|
276
276
|
|
277
277
|
def remove_incorrect_external_trailing_comma(node, corrector)
|
@@ -8,7 +8,7 @@ module RuboCop
|
|
8
8
|
#
|
9
9
|
# Note: When ``Layout/LineLength``'s `AllowHeredoc` is false (not default),
|
10
10
|
# this cop does not add any offenses for long here documents to
|
11
|
-
# avoid
|
11
|
+
# avoid ``Layout/LineLength``'s offenses.
|
12
12
|
#
|
13
13
|
# @example
|
14
14
|
# # bad
|
@@ -354,7 +354,7 @@ module RuboCop
|
|
354
354
|
# Don't check indentation if the line doesn't start with the body.
|
355
355
|
# For example, lines like "else do_something".
|
356
356
|
first_char_pos_on_line = body_node.source_range.source_line =~ /\S/
|
357
|
-
|
357
|
+
body_node.loc.column != first_char_pos_on_line
|
358
358
|
end
|
359
359
|
|
360
360
|
def offending_range(body_node, indentation)
|
@@ -107,7 +107,7 @@ module RuboCop
|
|
107
107
|
return false unless line.end_with?("\\\n")
|
108
108
|
|
109
109
|
# Ensure backslash isn't part of a token spanning to the next line.
|
110
|
-
node.children.none? { |c| c.first_line
|
110
|
+
node.children.none? { |c| (c.first_line...c.last_line).cover?(line_num) && c.multiline? }
|
111
111
|
end
|
112
112
|
|
113
113
|
def autocorrect(corrector, offense_range, insert_pos, spaces)
|
@@ -182,7 +182,7 @@ module RuboCop
|
|
182
182
|
return unless rhs.source.start_with?('.', '&.')
|
183
183
|
|
184
184
|
node = semantic_alignment_node(node)
|
185
|
-
return unless node&.loc&.selector
|
185
|
+
return unless node&.loc&.selector && node.loc.dot
|
186
186
|
|
187
187
|
node.loc.dot.join(node.loc.selector)
|
188
188
|
end
|
@@ -204,6 +204,10 @@ module RuboCop
|
|
204
204
|
dot_right_above = get_dot_right_above(node)
|
205
205
|
return dot_right_above if dot_right_above
|
206
206
|
|
207
|
+
if (multiline_block_chain_node = find_multiline_block_chain_node(node))
|
208
|
+
return multiline_block_chain_node
|
209
|
+
end
|
210
|
+
|
207
211
|
node = first_call_has_a_dot(node)
|
208
212
|
return if node.loc.dot.line != node.first_line
|
209
213
|
|
@@ -219,6 +223,17 @@ module RuboCop
|
|
219
223
|
end
|
220
224
|
end
|
221
225
|
|
226
|
+
def find_multiline_block_chain_node(node)
|
227
|
+
return unless (block_node = node.each_descendant(:block, :numblock).first)
|
228
|
+
return unless block_node.multiline? && block_node.parent.call_type?
|
229
|
+
|
230
|
+
if node.receiver.call_type?
|
231
|
+
node.receiver
|
232
|
+
else
|
233
|
+
block_node.parent
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
222
237
|
def first_call_has_a_dot(node)
|
223
238
|
# descend to root of method chain
|
224
239
|
node = node.receiver while node.receiver
|
@@ -62,6 +62,7 @@ module RuboCop
|
|
62
62
|
|
63
63
|
register_offense(node)
|
64
64
|
end
|
65
|
+
alias on_csend on_send
|
65
66
|
|
66
67
|
private
|
67
68
|
|
@@ -135,7 +136,7 @@ module RuboCop
|
|
135
136
|
.gsub(/" *\\\n\s*'/, %q(" + ')) # Double quote, backslash, and then single quote
|
136
137
|
.gsub(/' *\\\n\s*"/, %q(' + ")) # Single quote, backslash, and then double quote
|
137
138
|
.gsub(/(["']) *\\\n\s*\1/, '') # Double or single quote, backslash, then same quote
|
138
|
-
.gsub(/\n\s*(
|
139
|
+
.gsub(/\n\s*(?=(&)?\.\w)/, '') # Extra space within method chaining which includes `&.`
|
139
140
|
.gsub(/\s*\\?\n\s*/, ' ') # Any other line break, with or without backslash
|
140
141
|
end
|
141
142
|
|
@@ -29,7 +29,7 @@ module RuboCop
|
|
29
29
|
MSG = '`%<kw_loc>s` at %<kw_loc_line>d, %<kw_loc_column>d is not ' \
|
30
30
|
'aligned with `%<beginning>s` at ' \
|
31
31
|
'%<begin_loc_line>d, %<begin_loc_column>d.'
|
32
|
-
ANCESTOR_TYPES = %i[kwbegin def defs class module block].freeze
|
32
|
+
ANCESTOR_TYPES = %i[kwbegin def defs class module block numblock].freeze
|
33
33
|
ANCESTOR_TYPES_WITH_ACCESS_MODIFIERS = %i[def defs].freeze
|
34
34
|
ALTERNATIVE_ACCESS_MODIFIERS = %i[public_class_method private_class_method].freeze
|
35
35
|
|
@@ -95,7 +95,7 @@ module RuboCop
|
|
95
95
|
def alignment_source(node, starting_loc)
|
96
96
|
ending_loc =
|
97
97
|
case node.type
|
98
|
-
when :block, :kwbegin
|
98
|
+
when :block, :numblock, :kwbegin
|
99
99
|
node.loc.begin
|
100
100
|
when :def, :defs, :class, :module,
|
101
101
|
:lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn
|
@@ -104,8 +104,8 @@ module RuboCop
|
|
104
104
|
mlhs_node, = *node
|
105
105
|
mlhs_node.source_range
|
106
106
|
else
|
107
|
-
# It is a wrapper with access modifier.
|
108
|
-
node.child_nodes.first.loc.name
|
107
|
+
# It is a wrapper with receiver of object attribute or access modifier.
|
108
|
+
node.receiver&.source_range || node.child_nodes.first.loc.name
|
109
109
|
end
|
110
110
|
|
111
111
|
range_between(starting_loc.begin_pos, ending_loc.end_pos).source
|
@@ -25,10 +25,15 @@ module RuboCop
|
|
25
25
|
|
26
26
|
MSG = 'Put method call on a separate line if chained to a single line block.'
|
27
27
|
|
28
|
+
def self.autocorrect_incompatible_with
|
29
|
+
[Style::MapToHash]
|
30
|
+
end
|
31
|
+
|
28
32
|
def on_send(node)
|
29
33
|
range = offending_range(node)
|
30
34
|
add_offense(range) { |corrector| corrector.insert_before(range, "\n") } if range
|
31
35
|
end
|
36
|
+
alias on_csend on_send
|
32
37
|
|
33
38
|
private
|
34
39
|
|
@@ -50,6 +50,20 @@ module RuboCop
|
|
50
50
|
#
|
51
51
|
# # good
|
52
52
|
# a ** b
|
53
|
+
#
|
54
|
+
# @example EnforcedStyleForRationalLiterals: no_space (default)
|
55
|
+
# # bad
|
56
|
+
# 1 / 48r
|
57
|
+
#
|
58
|
+
# # good
|
59
|
+
# 1/48r
|
60
|
+
#
|
61
|
+
# @example EnforcedStyleForRationalLiterals: space
|
62
|
+
# # bad
|
63
|
+
# 1/48r
|
64
|
+
#
|
65
|
+
# # good
|
66
|
+
# 1 / 48r
|
53
67
|
class SpaceAroundOperators < Base
|
54
68
|
include PrecedingFollowingAlignment
|
55
69
|
include RangeHelp
|
@@ -64,7 +78,7 @@ module RuboCop
|
|
64
78
|
end
|
65
79
|
|
66
80
|
def on_sclass(node)
|
67
|
-
check_operator(:sclass, node.loc.operator, node
|
81
|
+
check_operator(:sclass, node.loc.operator, node)
|
68
82
|
end
|
69
83
|
|
70
84
|
def on_pair(node)
|
@@ -72,14 +86,14 @@ module RuboCop
|
|
72
86
|
|
73
87
|
return if hash_table_style? && !node.parent.pairs_on_same_line?
|
74
88
|
|
75
|
-
check_operator(:pair, node.loc.operator, node
|
89
|
+
check_operator(:pair, node.loc.operator, node)
|
76
90
|
end
|
77
91
|
|
78
92
|
def on_if(node)
|
79
93
|
return unless node.ternary?
|
80
94
|
|
81
|
-
check_operator(:if, node.loc.question, node.if_branch
|
82
|
-
check_operator(:if, node.loc.colon, node.else_branch
|
95
|
+
check_operator(:if, node.loc.question, node.if_branch)
|
96
|
+
check_operator(:if, node.loc.colon, node.else_branch)
|
83
97
|
end
|
84
98
|
|
85
99
|
def on_resbody(node)
|
@@ -87,7 +101,7 @@ module RuboCop
|
|
87
101
|
|
88
102
|
_, variable, = *node
|
89
103
|
|
90
|
-
check_operator(:resbody, node.loc.assoc, variable
|
104
|
+
check_operator(:resbody, node.loc.assoc, variable)
|
91
105
|
end
|
92
106
|
|
93
107
|
def on_send(node)
|
@@ -96,7 +110,7 @@ module RuboCop
|
|
96
110
|
if node.setter_method?
|
97
111
|
on_special_asgn(node)
|
98
112
|
elsif regular_operator?(node)
|
99
|
-
check_operator(:send, node.loc.selector, node.first_argument
|
113
|
+
check_operator(:send, node.loc.selector, node.first_argument)
|
100
114
|
end
|
101
115
|
end
|
102
116
|
|
@@ -105,7 +119,7 @@ module RuboCop
|
|
105
119
|
|
106
120
|
return unless rhs
|
107
121
|
|
108
|
-
check_operator(:assignment, node.loc.operator, rhs
|
122
|
+
check_operator(:assignment, node.loc.operator, rhs)
|
109
123
|
end
|
110
124
|
|
111
125
|
def on_casgn(node)
|
@@ -113,7 +127,7 @@ module RuboCop
|
|
113
127
|
|
114
128
|
return unless right
|
115
129
|
|
116
|
-
check_operator(:assignment, node.loc.operator, right
|
130
|
+
check_operator(:assignment, node.loc.operator, right)
|
117
131
|
end
|
118
132
|
|
119
133
|
def on_binary(node)
|
@@ -121,7 +135,7 @@ module RuboCop
|
|
121
135
|
|
122
136
|
return unless rhs
|
123
137
|
|
124
|
-
check_operator(:binary, node.loc.operator, rhs
|
138
|
+
check_operator(:binary, node.loc.operator, rhs)
|
125
139
|
end
|
126
140
|
|
127
141
|
def on_special_asgn(node)
|
@@ -129,13 +143,13 @@ module RuboCop
|
|
129
143
|
|
130
144
|
return unless right
|
131
145
|
|
132
|
-
check_operator(:special_asgn, node.loc.operator, right
|
146
|
+
check_operator(:special_asgn, node.loc.operator, right)
|
133
147
|
end
|
134
148
|
|
135
149
|
def on_match_pattern(node)
|
136
150
|
return if target_ruby_version < 3.0
|
137
151
|
|
138
|
-
check_operator(:match_pattern, node.loc.operator, node
|
152
|
+
check_operator(:match_pattern, node.loc.operator, node)
|
139
153
|
end
|
140
154
|
|
141
155
|
alias on_or on_binary
|
@@ -168,7 +182,7 @@ module RuboCop
|
|
168
182
|
|
169
183
|
offense(type, operator, with_space, right_operand) do |msg|
|
170
184
|
add_offense(operator, message: msg) do |corrector|
|
171
|
-
autocorrect(corrector, with_space)
|
185
|
+
autocorrect(corrector, with_space, right_operand)
|
172
186
|
end
|
173
187
|
end
|
174
188
|
end
|
@@ -178,11 +192,15 @@ module RuboCop
|
|
178
192
|
yield msg if msg
|
179
193
|
end
|
180
194
|
|
181
|
-
def autocorrect(corrector, range)
|
182
|
-
|
195
|
+
def autocorrect(corrector, range, right_operand)
|
196
|
+
range_source = range.source
|
197
|
+
|
198
|
+
if range_source.include?('**') && !space_around_exponent_operator?
|
183
199
|
corrector.replace(range, '**')
|
184
|
-
elsif
|
185
|
-
corrector.replace(range,
|
200
|
+
elsif range_source.include?('/') && !space_around_slash_operator?(right_operand)
|
201
|
+
corrector.replace(range, '/')
|
202
|
+
elsif range_source.end_with?("\n")
|
203
|
+
corrector.replace(range, " #{range_source.strip}\n")
|
186
204
|
else
|
187
205
|
enclose_operator_with_space(corrector, range)
|
188
206
|
end
|
@@ -202,14 +220,14 @@ module RuboCop
|
|
202
220
|
end
|
203
221
|
|
204
222
|
def offense_message(type, operator, with_space, right_operand)
|
205
|
-
if should_not_have_surrounding_space?(operator)
|
223
|
+
if should_not_have_surrounding_space?(operator, right_operand)
|
206
224
|
return if with_space.is?(operator.source)
|
207
225
|
|
208
226
|
"Space around operator `#{operator.source}` detected."
|
209
227
|
elsif !/^\s.*\s$/.match?(with_space.source)
|
210
228
|
"Surrounding space missing for operator `#{operator.source}`."
|
211
229
|
elsif excess_leading_space?(type, operator, with_space) ||
|
212
|
-
excess_trailing_space?(right_operand, with_space)
|
230
|
+
excess_trailing_space?(right_operand.source_range, with_space)
|
213
231
|
"Operator `#{operator.source}` should be surrounded " \
|
214
232
|
'by a single space.'
|
215
233
|
end
|
@@ -247,12 +265,24 @@ module RuboCop
|
|
247
265
|
cop_config['EnforcedStyleForExponentOperator'] == 'space'
|
248
266
|
end
|
249
267
|
|
268
|
+
def space_around_slash_operator?(right_operand)
|
269
|
+
return true unless right_operand.rational_type?
|
270
|
+
|
271
|
+
cop_config['EnforcedStyleForRationalLiterals'] == 'space'
|
272
|
+
end
|
273
|
+
|
250
274
|
def force_equal_sign_alignment?
|
251
275
|
config.for_cop('Layout/ExtraSpacing')['ForceEqualSignAlignment']
|
252
276
|
end
|
253
277
|
|
254
|
-
def should_not_have_surrounding_space?(operator)
|
255
|
-
operator.is?('**')
|
278
|
+
def should_not_have_surrounding_space?(operator, right_operand)
|
279
|
+
if operator.is?('**')
|
280
|
+
!space_around_exponent_operator?
|
281
|
+
elsif operator.is?('/')
|
282
|
+
!space_around_slash_operator?(right_operand)
|
283
|
+
else
|
284
|
+
false
|
285
|
+
end
|
256
286
|
end
|
257
287
|
end
|
258
288
|
end
|
@@ -168,7 +168,7 @@ module RuboCop
|
|
168
168
|
# follows, and that the rules for space inside don't apply.
|
169
169
|
return true if token2.comment?
|
170
170
|
|
171
|
-
|
171
|
+
!same_line?(token1, token2) || token1.space_after?
|
172
172
|
end
|
173
173
|
end
|
174
174
|
end
|
@@ -17,24 +17,24 @@ module RuboCop
|
|
17
17
|
#
|
18
18
|
# @example
|
19
19
|
# # bad
|
20
|
-
# if some_var =
|
20
|
+
# if some_var = value
|
21
21
|
# do_something
|
22
22
|
# end
|
23
23
|
#
|
24
24
|
# # good
|
25
|
-
# if some_var ==
|
25
|
+
# if some_var == value
|
26
26
|
# do_something
|
27
27
|
# end
|
28
28
|
#
|
29
29
|
# @example AllowSafeAssignment: true (default)
|
30
30
|
# # good
|
31
|
-
# if (some_var =
|
31
|
+
# if (some_var = value)
|
32
32
|
# do_something
|
33
33
|
# end
|
34
34
|
#
|
35
35
|
# @example AllowSafeAssignment: false
|
36
36
|
# # bad
|
37
|
-
# if (some_var =
|
37
|
+
# if (some_var = value)
|
38
38
|
# do_something
|
39
39
|
# end
|
40
40
|
#
|
@@ -6,10 +6,10 @@ module RuboCop
|
|
6
6
|
# Checks for places where binary operator has identical operands.
|
7
7
|
#
|
8
8
|
# It covers arithmetic operators: `-`, `/`, `%`;
|
9
|
-
# comparison operators: `==`, `===`, `=~`, `>`, `>=`, `<`,
|
9
|
+
# comparison operators: `==`, `===`, `=~`, `>`, `>=`, `<`, ``<=``;
|
10
10
|
# bitwise operators: `|`, `^`, `&`;
|
11
11
|
# boolean operators: `&&`, `||`
|
12
|
-
# and "spaceship" operator -
|
12
|
+
# and "spaceship" operator - ``<=>``.
|
13
13
|
#
|
14
14
|
# Simple arithmetic operations are allowed by this cop: `+`, `*`, `**`, `<<` and `>>`.
|
15
15
|
# Although these can be rewritten in a different way, it should not be necessary to
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Lint
|
6
|
-
# Checks for overwriting an exception with an exception result by use
|
6
|
+
# Checks for overwriting an exception with an exception result by use ``rescue =>``.
|
7
7
|
#
|
8
8
|
# You intended to write as `rescue StandardError`.
|
9
9
|
# However, you have written `rescue => StandardError`.
|
@@ -66,6 +66,7 @@ module RuboCop
|
|
66
66
|
# end
|
67
67
|
class Debugger < Base
|
68
68
|
MSG = 'Remove debugger entry point `%<source>s`.'
|
69
|
+
BLOCK_TYPES = %i[block numblock kwbegin].freeze
|
69
70
|
|
70
71
|
def on_send(node)
|
71
72
|
return if !debugger_method?(node) || assumed_usage_context?(node)
|
@@ -95,8 +96,11 @@ module RuboCop
|
|
95
96
|
def assumed_usage_context?(node)
|
96
97
|
# Basically, debugger methods are not used as a method argument without arguments.
|
97
98
|
return false unless node.arguments.empty? && node.each_ancestor(:send, :csend).any?
|
99
|
+
return true if assumed_argument?(node)
|
98
100
|
|
99
|
-
node.each_ancestor.none?
|
101
|
+
node.each_ancestor.none? do |ancestor|
|
102
|
+
BLOCK_TYPES.include?(ancestor.type) || ancestor.lambda_or_proc?
|
103
|
+
end
|
100
104
|
end
|
101
105
|
|
102
106
|
def chained_method_name(send_node)
|
@@ -109,6 +113,12 @@ module RuboCop
|
|
109
113
|
end
|
110
114
|
chained_method_name
|
111
115
|
end
|
116
|
+
|
117
|
+
def assumed_argument?(node)
|
118
|
+
parent = node.parent
|
119
|
+
|
120
|
+
parent.call_type? || parent.literal? || parent.pair_type?
|
121
|
+
end
|
112
122
|
end
|
113
123
|
end
|
114
124
|
end
|
@@ -253,7 +253,7 @@ module RuboCop
|
|
253
253
|
# Assume that if a method definition is inside any block call which
|
254
254
|
# we can't identify, it could be a DSL
|
255
255
|
node.each_ancestor(:block).any? do |ancestor|
|
256
|
-
ancestor.
|
256
|
+
!ancestor.method?(:class_eval) && !ancestor.class_constructor?
|
257
257
|
end
|
258
258
|
end
|
259
259
|
|
@@ -5,7 +5,7 @@ module RuboCop
|
|
5
5
|
module Lint
|
6
6
|
# Checks for blocks without a body.
|
7
7
|
# Such empty blocks are typically an oversight or we should provide a comment
|
8
|
-
#
|
8
|
+
# to clarify what we're aiming for.
|
9
9
|
#
|
10
10
|
# Empty lambdas and procs are ignored by default.
|
11
11
|
#
|
@@ -106,7 +106,7 @@ module RuboCop
|
|
106
106
|
private
|
107
107
|
|
108
108
|
def autocorrect(corrector, node)
|
109
|
-
str_arg = node.
|
109
|
+
str_arg = node.first_argument.source
|
110
110
|
|
111
111
|
kwargs = build_kwargs(node)
|
112
112
|
overridden_kwargs = override_by_legacy_args(kwargs, node)
|
@@ -121,11 +121,11 @@ module RuboCop
|
|
121
121
|
end
|
122
122
|
|
123
123
|
def build_kwargs(node)
|
124
|
-
return [nil, nil] unless node.
|
124
|
+
return [nil, nil] unless node.last_argument.hash_type?
|
125
125
|
|
126
126
|
trim_mode_arg, eoutvar_arg = nil
|
127
127
|
|
128
|
-
node.
|
128
|
+
node.last_argument.pairs.each do |pair|
|
129
129
|
case pair.key.source
|
130
130
|
when 'trim_mode'
|
131
131
|
trim_mode_arg = "trim_mode: #{pair.value.source}"
|
@@ -18,6 +18,10 @@ module RuboCop
|
|
18
18
|
# # good - using BigDecimal
|
19
19
|
# x.to_d == 0.1.to_d
|
20
20
|
#
|
21
|
+
# # good - comparing against zero
|
22
|
+
# x == 0.0
|
23
|
+
# x != 0.0
|
24
|
+
#
|
21
25
|
# # good
|
22
26
|
# (x - 0.1).abs < Float::EPSILON
|
23
27
|
#
|
@@ -39,6 +43,8 @@ module RuboCop
|
|
39
43
|
|
40
44
|
def on_send(node)
|
41
45
|
lhs, _method, rhs = *node
|
46
|
+
return if literal_zero?(lhs) || literal_zero?(rhs)
|
47
|
+
|
42
48
|
add_offense(node) if float?(lhs) || float?(rhs)
|
43
49
|
end
|
44
50
|
|
@@ -59,6 +65,10 @@ module RuboCop
|
|
59
65
|
end
|
60
66
|
end
|
61
67
|
|
68
|
+
def literal_zero?(node)
|
69
|
+
node&.numeric_type? && node.value.zero?
|
70
|
+
end
|
71
|
+
|
62
72
|
# rubocop:disable Metrics/PerceivedComplexity
|
63
73
|
def check_send(node)
|
64
74
|
if node.arithmetic_operation?
|
@@ -35,12 +35,13 @@ module RuboCop
|
|
35
35
|
|
36
36
|
# @!method id_as_hash_key?(node)
|
37
37
|
def_node_matcher :id_as_hash_key?, <<~PATTERN
|
38
|
-
(
|
38
|
+
(call _ {:key? :has_key? :fetch :[] :[]=} (send _ :object_id) ...)
|
39
39
|
PATTERN
|
40
40
|
|
41
41
|
def on_send(node)
|
42
42
|
add_offense(node) if id_as_hash_key?(node)
|
43
43
|
end
|
44
|
+
alias on_csend on_send
|
44
45
|
end
|
45
46
|
end
|
46
47
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# Emulates the following Ruby warning in Ruby 3.3.
|
7
|
+
#
|
8
|
+
# [source,ruby]
|
9
|
+
# ----
|
10
|
+
# $ ruby -e '0.times { it }'
|
11
|
+
# -e:1: warning: `it` calls without arguments will refer to the first block param in Ruby 3.4;
|
12
|
+
# use it() or self.it
|
13
|
+
# ----
|
14
|
+
#
|
15
|
+
# `it` calls without arguments will refer to the first block param in Ruby 3.4.
|
16
|
+
# So use `it()` or `self.it` to ensure compatibility.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
#
|
20
|
+
# # bad
|
21
|
+
# do_something { it }
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# do_something { it() }
|
25
|
+
# do_something { self.it }
|
26
|
+
#
|
27
|
+
class ItWithoutArgumentsInBlock < Base
|
28
|
+
include NodePattern::Macros
|
29
|
+
|
30
|
+
MSG = '`it` calls without arguments will refer to the first block param in Ruby 3.4; ' \
|
31
|
+
'use `it()` or `self.it`.'
|
32
|
+
|
33
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
34
|
+
return unless (body = node.body)
|
35
|
+
return unless node.arguments.empty_and_without_delimiters?
|
36
|
+
|
37
|
+
if body.send_type? && deprecated_it_method?(body)
|
38
|
+
add_offense(body)
|
39
|
+
else
|
40
|
+
body.each_descendant(:send).each do |send_node|
|
41
|
+
next unless deprecated_it_method?(send_node)
|
42
|
+
|
43
|
+
add_offense(send_node)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def deprecated_it_method?(node)
|
49
|
+
return false unless node.method?(:it)
|
50
|
+
|
51
|
+
!node.receiver && node.arguments.empty? && !node.parenthesized? && !node.block_literal?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# Checks for literal assignments in the conditions of `if`, `while`, and `until`.
|
7
|
+
# It emulates the following Ruby warning:
|
8
|
+
#
|
9
|
+
# [source,console]
|
10
|
+
# ----
|
11
|
+
# $ ruby -we 'if x = true; end'
|
12
|
+
# -e:1: warning: found `= literal' in conditional, should be ==
|
13
|
+
# ----
|
14
|
+
#
|
15
|
+
# As a lint cop, it cannot be determined if `==` is appropriate as intended,
|
16
|
+
# therefore this cop does not provide autocorrection.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
#
|
20
|
+
# # bad
|
21
|
+
# if x = 42
|
22
|
+
# do_something
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# if x == 42
|
27
|
+
# do_something
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# # good
|
31
|
+
# if x = y
|
32
|
+
# do_something
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
class LiteralAssignmentInCondition < Base
|
36
|
+
MSG = "Don't use literal assignment `= %<literal>s` in conditional, " \
|
37
|
+
'should be `==` or non-literal operand.'
|
38
|
+
|
39
|
+
def on_if(node)
|
40
|
+
traverse_node(node.condition) do |asgn_node|
|
41
|
+
next unless asgn_node.loc.operator
|
42
|
+
|
43
|
+
rhs = asgn_node.to_a.last
|
44
|
+
next if !all_literals?(rhs) || parallel_assignment_with_splat_operator?(rhs)
|
45
|
+
|
46
|
+
range = offense_range(asgn_node, rhs)
|
47
|
+
|
48
|
+
add_offense(range, message: format(MSG, literal: rhs.source))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
alias on_while on_if
|
52
|
+
alias on_until on_if
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def traverse_node(node, &block)
|
57
|
+
yield node if AST::Node::EQUALS_ASSIGNMENTS.include?(node.type)
|
58
|
+
|
59
|
+
node.each_child_node { |child| traverse_node(child, &block) }
|
60
|
+
end
|
61
|
+
|
62
|
+
def all_literals?(node)
|
63
|
+
case node.type
|
64
|
+
when :dstr, :xstr
|
65
|
+
false
|
66
|
+
when :array
|
67
|
+
node.values.all? { |value| all_literals?(value) }
|
68
|
+
when :hash
|
69
|
+
(node.values + node.keys).all? { |item| all_literals?(item) }
|
70
|
+
else
|
71
|
+
node.respond_to?(:literal?) && node.literal?
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def parallel_assignment_with_splat_operator?(node)
|
76
|
+
node.array_type? && node.values.first&.splat_type?
|
77
|
+
end
|
78
|
+
|
79
|
+
def offense_range(asgn_node, rhs)
|
80
|
+
asgn_node.loc.operator.join(rhs.source_range.end)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|