rubocop 1.57.2 → 1.59.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 +2 -2
- data/config/default.yml +43 -2
- data/lib/rubocop/config_obsoletion.rb +11 -8
- data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
- 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/extra_spacing.rb +4 -10
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +6 -6
- 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/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/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 +2 -1
- data/lib/rubocop/cop/lint/duplicate_methods.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 +78 -0
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
- 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_safe_navigation.rb +43 -0
- 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/symbol_conversion.rb +7 -2
- 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 +14 -1
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- 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 +2 -2
- 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/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 +68 -6
- 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/collection_compact.rb +7 -6
- 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 +1 -1
- data/lib/rubocop/cop/style/date_time.rb +5 -4
- 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 -3
- 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/hash_each_methods.rb +83 -10
- data/lib/rubocop/cop/style/hash_except.rb +2 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +6 -5
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +3 -2
- data/lib/rubocop/cop/style/map_to_hash.rb +10 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
- 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/next.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +2 -2
- data/lib/rubocop/cop/style/redundant_argument.rb +3 -2
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +3 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +3 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +2 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +15 -8
- 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 +5 -2
- data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
- 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/unpack_first.rb +11 -14
- data/lib/rubocop/formatter/html_formatter.rb +1 -2
- data/lib/rubocop/result_cache.rb +0 -1
- data/lib/rubocop/runner.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +4 -0
- metadata +14 -9
@@ -49,12 +49,12 @@ module RuboCop
|
|
49
49
|
class DateTime < Base
|
50
50
|
extend AutoCorrector
|
51
51
|
|
52
|
-
CLASS_MSG = 'Prefer Time over DateTime
|
53
|
-
COERCION_MSG = 'Do not use
|
52
|
+
CLASS_MSG = 'Prefer `Time` over `DateTime`.'
|
53
|
+
COERCION_MSG = 'Do not use `#to_datetime`.'
|
54
54
|
|
55
55
|
# @!method date_time?(node)
|
56
56
|
def_node_matcher :date_time?, <<~PATTERN
|
57
|
-
(
|
57
|
+
(call (const {nil? (cbase)} :DateTime) ...)
|
58
58
|
PATTERN
|
59
59
|
|
60
60
|
# @!method historic_date?(node)
|
@@ -64,7 +64,7 @@ module RuboCop
|
|
64
64
|
|
65
65
|
# @!method to_datetime?(node)
|
66
66
|
def_node_matcher :to_datetime?, <<~PATTERN
|
67
|
-
(
|
67
|
+
(call _ :to_datetime)
|
68
68
|
PATTERN
|
69
69
|
|
70
70
|
def on_send(node)
|
@@ -75,6 +75,7 @@ module RuboCop
|
|
75
75
|
|
76
76
|
add_offense(node, message: message) { |corrector| autocorrect(corrector, node) }
|
77
77
|
end
|
78
|
+
alias on_csend on_send
|
78
79
|
|
79
80
|
private
|
80
81
|
|
@@ -58,12 +58,12 @@ module RuboCop
|
|
58
58
|
|
59
59
|
# @!method each_with_object_block_candidate?(node)
|
60
60
|
def_node_matcher :each_with_object_block_candidate?, <<~PATTERN
|
61
|
-
(block $(
|
61
|
+
(block $(call _ {:inject :reduce} _) $_ $_)
|
62
62
|
PATTERN
|
63
63
|
|
64
64
|
# @!method each_with_object_numblock_candidate?(node)
|
65
65
|
def_node_matcher :each_with_object_numblock_candidate?, <<~PATTERN
|
66
|
-
(numblock $(
|
66
|
+
(numblock $(call _ {:inject :reduce} _) 2 $_)
|
67
67
|
PATTERN
|
68
68
|
|
69
69
|
def autocorrect_block(corrector, node, return_value)
|
@@ -83,7 +83,7 @@ module RuboCop
|
|
83
83
|
parent = node.parent
|
84
84
|
return false unless parent && %i[send super zsuper].include?(parent.type)
|
85
85
|
|
86
|
-
node.equal?(parent.
|
86
|
+
node.equal?(parent.first_argument) && !parentheses?(node.parent)
|
87
87
|
end
|
88
88
|
|
89
89
|
def replacement_range(node)
|
@@ -84,7 +84,7 @@ module RuboCop
|
|
84
84
|
# are considered.
|
85
85
|
return if node.method?(:eval) && !valid_eval_receiver?(node.receiver)
|
86
86
|
|
87
|
-
code = node.
|
87
|
+
code = node.first_argument
|
88
88
|
return unless code && (code.str_type? || code.dstr_type?)
|
89
89
|
|
90
90
|
check_location(node, code)
|
@@ -165,7 +165,7 @@ module RuboCop
|
|
165
165
|
end
|
166
166
|
|
167
167
|
def check_line(node, code)
|
168
|
-
line_node = node.
|
168
|
+
line_node = node.last_argument
|
169
169
|
line_diff = line_difference(line_node, code)
|
170
170
|
if line_diff.zero?
|
171
171
|
add_offense_for_same_line(node, line_node)
|
@@ -227,7 +227,7 @@ module RuboCop
|
|
227
227
|
end
|
228
228
|
|
229
229
|
def missing_line(node, code)
|
230
|
-
line_diff = line_difference(node.
|
230
|
+
line_diff = line_difference(node.last_argument, code)
|
231
231
|
sign = line_diff.positive? ? :+ : :-
|
232
232
|
expected_line(sign, line_diff)
|
233
233
|
end
|
@@ -30,7 +30,7 @@ module RuboCop
|
|
30
30
|
|
31
31
|
# @!method exact_regexp_match(node)
|
32
32
|
def_node_matcher :exact_regexp_match, <<~PATTERN
|
33
|
-
(
|
33
|
+
(call
|
34
34
|
_ {:=~ :=== :!~ :match :match?}
|
35
35
|
(regexp
|
36
36
|
(str $_)
|
@@ -49,6 +49,7 @@ module RuboCop
|
|
49
49
|
corrector.replace(node, prefer)
|
50
50
|
end
|
51
51
|
end
|
52
|
+
alias on_csend on_send
|
52
53
|
|
53
54
|
private
|
54
55
|
|
@@ -86,7 +86,7 @@ module RuboCop
|
|
86
86
|
|
87
87
|
def extract_block_name(def_node)
|
88
88
|
if def_node.block_argument?
|
89
|
-
def_node.
|
89
|
+
def_node.last_argument.name
|
90
90
|
else
|
91
91
|
'block'
|
92
92
|
end
|
@@ -127,7 +127,7 @@ module RuboCop
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def insert_argument(node, corrector, block_name)
|
130
|
-
last_arg = node.
|
130
|
+
last_arg = node.last_argument
|
131
131
|
arg_range = range_with_surrounding_comma(last_arg.source_range, :right)
|
132
132
|
replacement = " &#{block_name}"
|
133
133
|
replacement = ",#{replacement}" unless arg_range.source.end_with?(',')
|
@@ -17,10 +17,16 @@ module RuboCop
|
|
17
17
|
# @example
|
18
18
|
# # bad
|
19
19
|
# hash.keys.each { |k| p k }
|
20
|
-
# hash.
|
20
|
+
# hash.each { |k, unused_value| p k }
|
21
21
|
#
|
22
22
|
# # good
|
23
23
|
# hash.each_key { |k| p k }
|
24
|
+
#
|
25
|
+
# # bad
|
26
|
+
# hash.values.each { |v| p v }
|
27
|
+
# hash.each { |unused_key, v| p v }
|
28
|
+
#
|
29
|
+
# # good
|
24
30
|
# hash.each_value { |v| p v }
|
25
31
|
#
|
26
32
|
# @example AllowedReceivers: ['execute']
|
@@ -33,22 +39,46 @@ module RuboCop
|
|
33
39
|
extend AutoCorrector
|
34
40
|
|
35
41
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
42
|
+
UNUSED_BLOCK_ARG_MSG = "#{MSG.chop} and remove the unused `%<unused_code>s` block argument."
|
36
43
|
|
37
44
|
# @!method kv_each(node)
|
38
45
|
def_node_matcher :kv_each, <<~PATTERN
|
39
|
-
({block numblock} $(
|
46
|
+
({block numblock} $(call (call _ ${:keys :values}) :each) ...)
|
47
|
+
PATTERN
|
48
|
+
|
49
|
+
# @!method each_arguments(node)
|
50
|
+
def_node_matcher :each_arguments, <<~PATTERN
|
51
|
+
(block (call _ :each)(args $_key $_value) ...)
|
40
52
|
PATTERN
|
41
53
|
|
42
54
|
# @!method kv_each_with_block_pass(node)
|
43
55
|
def_node_matcher :kv_each_with_block_pass, <<~PATTERN
|
44
|
-
(
|
56
|
+
(call $(call _ ${:keys :values}) :each (block_pass (sym _)))
|
45
57
|
PATTERN
|
46
58
|
|
59
|
+
# rubocop:disable Metrics/AbcSize
|
47
60
|
def on_block(node)
|
61
|
+
return unless handleable?(node)
|
62
|
+
|
48
63
|
kv_each(node) do |target, method|
|
49
|
-
register_kv_offense(target, method)
|
64
|
+
register_kv_offense(target, method) and return
|
65
|
+
end
|
66
|
+
|
67
|
+
return unless (key, value = each_arguments(node))
|
68
|
+
|
69
|
+
if unused_block_arg_exist?(node, value)
|
70
|
+
message = message('each_key', node.method_name, value.source)
|
71
|
+
unused_range = key.source_range.end.join(value.source_range.end)
|
72
|
+
|
73
|
+
register_each_args_offense(node, message, 'each_key', unused_range)
|
74
|
+
elsif unused_block_arg_exist?(node, key)
|
75
|
+
message = message('each_value', node.method_name, key.source)
|
76
|
+
unused_range = key.source_range.begin.join(value.source_range.begin)
|
77
|
+
|
78
|
+
register_each_args_offense(node, message, 'each_value', unused_range)
|
50
79
|
end
|
51
80
|
end
|
81
|
+
# rubocop:enable Metrics/AbcSize
|
52
82
|
|
53
83
|
alias on_numblock on_block
|
54
84
|
|
@@ -60,27 +90,70 @@ module RuboCop
|
|
60
90
|
|
61
91
|
private
|
62
92
|
|
93
|
+
def handleable?(node)
|
94
|
+
return false unless (root_receiver = root_receiver(node))
|
95
|
+
|
96
|
+
!root_receiver.literal? || root_receiver.hash_type?
|
97
|
+
end
|
98
|
+
|
63
99
|
def register_kv_offense(target, method)
|
64
100
|
return unless (parent_receiver = target.receiver.receiver)
|
65
101
|
return if allowed_receiver?(parent_receiver)
|
66
102
|
|
67
|
-
|
103
|
+
current = target.receiver.loc.selector.join(target.source_range.end).source
|
104
|
+
|
105
|
+
add_offense(kv_range(target), message: format_message(method, current)) do |corrector|
|
68
106
|
correct_key_value_each(target, corrector)
|
69
107
|
end
|
70
108
|
end
|
71
109
|
|
110
|
+
def unused_block_arg_exist?(node, block_arg)
|
111
|
+
lvar_sources = node.body.each_descendant(:lvar).map(&:source)
|
112
|
+
|
113
|
+
if block_arg.mlhs_type?
|
114
|
+
block_arg.each_descendant(:arg).all? do |block_arg|
|
115
|
+
lvar_sources.none?(block_arg.source)
|
116
|
+
end
|
117
|
+
else
|
118
|
+
lvar_sources.none?(block_arg.source)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def message(prefer, method_name, unused_code)
|
123
|
+
format(
|
124
|
+
UNUSED_BLOCK_ARG_MSG, prefer: prefer, current: method_name, unused_code: unused_code
|
125
|
+
)
|
126
|
+
end
|
127
|
+
|
128
|
+
def register_each_args_offense(node, message, prefer, unused_range)
|
129
|
+
add_offense(node, message: message) do |corrector|
|
130
|
+
corrector.replace(node.send_node.loc.selector, prefer)
|
131
|
+
corrector.remove(unused_range)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
72
135
|
def register_kv_with_block_pass_offense(node, target, method)
|
73
136
|
return unless (parent_receiver = node.parent.receiver.receiver)
|
74
137
|
return if allowed_receiver?(parent_receiver)
|
75
138
|
|
76
|
-
range = target.loc.selector.
|
77
|
-
|
139
|
+
range = target.loc.selector.join(node.parent.loc.selector.end)
|
140
|
+
|
141
|
+
add_offense(range, message: format_message(method, range.source)) do |corrector|
|
78
142
|
corrector.replace(range, "each_#{method[0..-2]}")
|
79
143
|
end
|
80
144
|
end
|
81
145
|
|
82
|
-
def
|
83
|
-
|
146
|
+
def root_receiver(node)
|
147
|
+
receiver = node.receiver
|
148
|
+
if receiver&.receiver
|
149
|
+
root_receiver(receiver)
|
150
|
+
else
|
151
|
+
receiver
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def format_message(method_name, current)
|
156
|
+
format(MSG, prefer: "each_#{method_name[0..-2]}", current: current)
|
84
157
|
end
|
85
158
|
|
86
159
|
def check_argument(variable)
|
@@ -103,7 +176,7 @@ module RuboCop
|
|
103
176
|
name = "each_#{node.receiver.method_name.to_s.chop}"
|
104
177
|
return correct_implicit(node, corrector, name) unless receiver
|
105
178
|
|
106
|
-
new_source = receiver.source + "
|
179
|
+
new_source = receiver.source + "#{node.loc.dot.source}#{name}"
|
107
180
|
corrector.replace(node, new_source)
|
108
181
|
end
|
109
182
|
|
@@ -43,7 +43,7 @@ module RuboCop
|
|
43
43
|
# @!method bad_method_with_poro?(node)
|
44
44
|
def_node_matcher :bad_method_with_poro?, <<~PATTERN
|
45
45
|
(block
|
46
|
-
(
|
46
|
+
(call _ _)
|
47
47
|
(args
|
48
48
|
$(arg _)
|
49
49
|
(arg _))
|
@@ -86,6 +86,7 @@ module RuboCop
|
|
86
86
|
corrector.replace(range, preferred_method)
|
87
87
|
end
|
88
88
|
end
|
89
|
+
alias on_csend on_send
|
89
90
|
|
90
91
|
private
|
91
92
|
|
@@ -60,17 +60,17 @@ module RuboCop
|
|
60
60
|
# @!method inverse_candidate?(node)
|
61
61
|
def_node_matcher :inverse_candidate?, <<~PATTERN
|
62
62
|
{
|
63
|
-
(send $(
|
64
|
-
(send ({block numblock} $(
|
65
|
-
(send (begin $(
|
63
|
+
(send $(call $(...) $_ $...) :!)
|
64
|
+
(send ({block numblock} $(call $(...) $_) $...) :!)
|
65
|
+
(send (begin $(call $(...) $_ $...)) :!)
|
66
66
|
}
|
67
67
|
PATTERN
|
68
68
|
|
69
69
|
# @!method inverse_block?(node)
|
70
70
|
def_node_matcher :inverse_block?, <<~PATTERN
|
71
|
-
({block numblock} $(
|
71
|
+
({block numblock} $(call (...) $_) ... { $(call ... :!)
|
72
72
|
$(send (...) {:!= :!~} ...)
|
73
|
-
(begin ... $(
|
73
|
+
(begin ... $(call ... :!))
|
74
74
|
(begin ... $(send (...) {:!= :!~} ...))
|
75
75
|
})
|
76
76
|
PATTERN
|
@@ -87,6 +87,7 @@ module RuboCop
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
90
|
+
alias on_csend on_send
|
90
91
|
|
91
92
|
def on_block(node)
|
92
93
|
inverse_block?(node) do |_method_call, method, block|
|
@@ -44,9 +44,9 @@ module RuboCop
|
|
44
44
|
|
45
45
|
# @!method map_and_compact?(node)
|
46
46
|
def_node_matcher :map_and_compact?, <<~RUBY
|
47
|
-
(
|
47
|
+
(call
|
48
48
|
(block
|
49
|
-
(
|
49
|
+
(call _ :map)
|
50
50
|
(args
|
51
51
|
$(arg _))
|
52
52
|
{
|
@@ -85,6 +85,7 @@ module RuboCop
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
88
|
+
alias on_csend on_send
|
88
89
|
|
89
90
|
private
|
90
91
|
|
@@ -34,21 +34,25 @@ module RuboCop
|
|
34
34
|
|
35
35
|
minimum_target_ruby_version 2.6
|
36
36
|
|
37
|
-
MSG = 'Pass a block to `to_h` instead of calling `%<method>s
|
37
|
+
MSG = 'Pass a block to `to_h` instead of calling `%<method>s%<dot>sto_h`.'
|
38
38
|
RESTRICT_ON_SEND = %i[to_h].freeze
|
39
39
|
|
40
40
|
# @!method map_to_h?(node)
|
41
41
|
def_node_matcher :map_to_h?, <<~PATTERN
|
42
42
|
{
|
43
|
-
$(
|
44
|
-
$(
|
43
|
+
$(call ({block numblock} $(call _ {:map :collect}) ...) :to_h)
|
44
|
+
$(call $(call _ {:map :collect} (block_pass sym)) :to_h)
|
45
45
|
}
|
46
46
|
PATTERN
|
47
47
|
|
48
|
+
def self.autocorrect_incompatible_with
|
49
|
+
[Layout::SingleLineBlockChain]
|
50
|
+
end
|
51
|
+
|
48
52
|
def on_send(node)
|
49
53
|
return unless (to_h_node, map_node = map_to_h?(node))
|
50
54
|
|
51
|
-
message = format(MSG, method: map_node.loc.selector.source)
|
55
|
+
message = format(MSG, method: map_node.loc.selector.source, dot: map_node.loc.dot.source)
|
52
56
|
add_offense(map_node.loc.selector, message: message) do |corrector|
|
53
57
|
# If the `to_h` call already has a block, do not autocorrect.
|
54
58
|
next if to_h_node.block_node
|
@@ -56,6 +60,7 @@ module RuboCop
|
|
56
60
|
autocorrect(corrector, to_h_node, map_node)
|
57
61
|
end
|
58
62
|
end
|
63
|
+
alias on_csend on_send
|
59
64
|
|
60
65
|
private
|
61
66
|
|
@@ -63,6 +68,7 @@ module RuboCop
|
|
63
68
|
removal_range = range_between(to_h.loc.dot.begin_pos, to_h.loc.selector.end_pos)
|
64
69
|
|
65
70
|
corrector.remove(range_with_surrounding_space(removal_range, side: :left))
|
71
|
+
corrector.replace(map.loc.dot, '.') if to_h.dot?
|
66
72
|
corrector.replace(map.loc.selector, 'to_h')
|
67
73
|
end
|
68
74
|
end
|
@@ -86,6 +86,7 @@ module RuboCop
|
|
86
86
|
|
87
87
|
def legitimate_call_with_parentheses?(node) # rubocop:disable Metrics/PerceivedComplexity
|
88
88
|
call_in_literals?(node) ||
|
89
|
+
node.parent&.when_type? ||
|
89
90
|
call_with_ambiguous_arguments?(node) ||
|
90
91
|
call_in_logical_operators?(node) ||
|
91
92
|
call_in_optional_arguments?(node) ||
|
@@ -8,6 +8,9 @@ module RuboCop
|
|
8
8
|
# This cop can be customized allowed methods with `AllowedMethods`.
|
9
9
|
# By default, there are no methods to allowed.
|
10
10
|
#
|
11
|
+
# NOTE: This cop allows the use of `it()` without arguments in blocks,
|
12
|
+
# as in `0.times { it() }`, following `Lint/ItWithoutArgumentsInBlock` cop.
|
13
|
+
#
|
11
14
|
# @example
|
12
15
|
# # bad
|
13
16
|
# object.some_method()
|
@@ -30,15 +33,18 @@ module RuboCop
|
|
30
33
|
|
31
34
|
MSG = 'Do not use parentheses for method calls with no arguments.'
|
32
35
|
|
36
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
33
37
|
def on_send(node)
|
34
38
|
return unless !node.arguments? && node.parenthesized?
|
35
39
|
return if ineligible_node?(node)
|
36
40
|
return if default_argument?(node)
|
37
41
|
return if allowed_method_name?(node.method_name)
|
38
42
|
return if same_name_assignment?(node)
|
43
|
+
return if parenthesized_it_method_in_block?(node)
|
39
44
|
|
40
45
|
register_offense(node)
|
41
46
|
end
|
47
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
42
48
|
|
43
49
|
private
|
44
50
|
|
@@ -71,6 +77,20 @@ module RuboCop
|
|
71
77
|
end
|
72
78
|
end
|
73
79
|
|
80
|
+
# Respects `Lint/ItWithoutArgumentsInBlock` cop and the following Ruby 3.3's warning:
|
81
|
+
#
|
82
|
+
# $ ruby -e '0.times { begin; it; end }'
|
83
|
+
# -e:1: warning: `it` calls without arguments will refer to the first block param in
|
84
|
+
# Ruby 3.4; use it() or self.it
|
85
|
+
#
|
86
|
+
def parenthesized_it_method_in_block?(node)
|
87
|
+
return false unless node.method?(:it)
|
88
|
+
return false unless (block_node = node.each_ancestor(:block).first)
|
89
|
+
return false unless block_node.arguments.empty_and_without_delimiters?
|
90
|
+
|
91
|
+
!node.receiver && node.arguments.empty? && !node.block_literal?
|
92
|
+
end
|
93
|
+
|
74
94
|
def any_assignment?(node)
|
75
95
|
node.each_ancestor(*AST::Node::ASSIGNMENTS).any? do |asgn_node|
|
76
96
|
# `obj.method = value` parses as (send ... :method= ...), and will
|
@@ -170,7 +170,7 @@ module RuboCop
|
|
170
170
|
return true if node.arguments.any? do |arg|
|
171
171
|
arg.forward_arg_type? || arg.restarg_type? || arg.kwrestarg_type?
|
172
172
|
end
|
173
|
-
return false unless (last_argument = node.
|
173
|
+
return false unless (last_argument = node.last_argument)
|
174
174
|
|
175
175
|
last_argument.blockarg_type? && last_argument.name.nil?
|
176
176
|
end
|
@@ -4,8 +4,8 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# Checks for redundant dot before operator method call.
|
7
|
-
# The target operator methods are `|`, `^`, `&`,
|
8
|
-
#
|
7
|
+
# The target operator methods are `|`, `^`, `&`, ``<=>``, `==`, `===`, `=~`, `>`, `>=`, `<`,
|
8
|
+
# ``<=``, `<<`, `>>`, `+`, `-`, `*`, `/`, `%`, `**`, `~`, `!`, `!=`, and `!~`.
|
9
9
|
#
|
10
10
|
# @example
|
11
11
|
#
|
@@ -67,12 +67,13 @@ module RuboCop
|
|
67
67
|
return unless redundant_argument?(node)
|
68
68
|
|
69
69
|
offense_range = argument_range(node)
|
70
|
-
message = format(MSG, arg: node.
|
70
|
+
message = format(MSG, arg: node.first_argument.source)
|
71
71
|
|
72
72
|
add_offense(offense_range, message: message) do |corrector|
|
73
73
|
corrector.remove(offense_range)
|
74
74
|
end
|
75
75
|
end
|
76
|
+
alias on_csend on_send
|
76
77
|
|
77
78
|
private
|
78
79
|
|
@@ -80,7 +81,7 @@ module RuboCop
|
|
80
81
|
redundant_argument = redundant_arg_for_method(node.method_name.to_s)
|
81
82
|
return false if redundant_argument.nil?
|
82
83
|
|
83
|
-
node.
|
84
|
+
node.first_argument == redundant_argument
|
84
85
|
end
|
85
86
|
|
86
87
|
def redundant_arg_for_method(method_name)
|
@@ -25,20 +25,20 @@ module RuboCop
|
|
25
25
|
MSG = 'Remove the redundant double splat and braces, use keyword arguments directly.'
|
26
26
|
MERGE_METHODS = %i[merge merge!].freeze
|
27
27
|
|
28
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
28
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
29
29
|
def on_hash(node)
|
30
30
|
return if node.pairs.empty? || node.pairs.any?(&:hash_rocket?)
|
31
31
|
return unless (parent = node.parent)
|
32
32
|
return unless parent.call_type? || parent.kwsplat_type?
|
33
33
|
return unless mergeable?(parent)
|
34
34
|
return unless (kwsplat = node.each_ancestor(:kwsplat).first)
|
35
|
-
return if allowed_double_splat_receiver?(kwsplat)
|
35
|
+
return if !node.braces? || allowed_double_splat_receiver?(kwsplat)
|
36
36
|
|
37
37
|
add_offense(kwsplat) do |corrector|
|
38
38
|
autocorrect(corrector, node, kwsplat)
|
39
39
|
end
|
40
40
|
end
|
41
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
41
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
42
42
|
|
43
43
|
private
|
44
44
|
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
# @!method redundant_fetch_block_candidate?(node)
|
48
48
|
def_node_matcher :redundant_fetch_block_candidate?, <<~PATTERN
|
49
49
|
(block
|
50
|
-
$(
|
50
|
+
$(call _ :fetch _)
|
51
51
|
(args)
|
52
52
|
${nil? #basic_literal? #const_type?})
|
53
53
|
PATTERN
|
@@ -61,10 +61,10 @@ module RuboCop
|
|
61
61
|
bad = build_bad_method(send, body)
|
62
62
|
|
63
63
|
add_offense(range, message: format(MSG, good: good, bad: bad)) do |corrector|
|
64
|
-
|
64
|
+
_, _, key = send.children
|
65
65
|
default_value = body ? body.source : 'nil'
|
66
66
|
|
67
|
-
corrector.replace(
|
67
|
+
corrector.replace(range, "fetch(#{key.source}, #{default_value})")
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
@@ -107,6 +107,8 @@ module RuboCop
|
|
107
107
|
|
108
108
|
def inside_string_literal_or_method_with_argument?(range)
|
109
109
|
processed_source.tokens.each_cons(2).any? do |token, next_token|
|
110
|
+
next if token.line == next_token.line
|
111
|
+
|
110
112
|
inside_string_literal?(range, token) || method_with_argument?(token, next_token)
|
111
113
|
end
|
112
114
|
end
|