rubocop 1.33.0 → 1.35.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 +1 -1
- data/config/default.yml +29 -1
- data/lib/rubocop/cli/command/suggest_extensions.rb +53 -15
- data/lib/rubocop/config_loader.rb +12 -0
- data/lib/rubocop/config_loader_resolver.rb +1 -5
- data/lib/rubocop/cop/cop.rb +1 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +58 -0
- data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +69 -0
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +61 -0
- data/lib/rubocop/cop/internal_affairs.rb +2 -0
- data/lib/rubocop/cop/layout/block_alignment.rb +2 -0
- data/lib/rubocop/cop/layout/block_end_newline.rb +4 -1
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +2 -0
- data/lib/rubocop/cop/layout/indentation_width.rb +2 -0
- data/lib/rubocop/cop/layout/line_length.rb +4 -1
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
- data/lib/rubocop/cop/legacy/corrections_proxy.rb +1 -1
- data/lib/rubocop/cop/legacy/corrector.rb +1 -1
- data/lib/rubocop/cop/lint/debugger.rb +15 -15
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +5 -0
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +9 -9
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +25 -6
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +12 -0
- data/lib/rubocop/cop/lint/redundant_with_index.rb +13 -10
- data/lib/rubocop/cop/lint/redundant_with_object.rb +12 -11
- data/lib/rubocop/cop/lint/shadowed_exception.rb +15 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +10 -1
- data/lib/rubocop/cop/lint/unreachable_loop.rb +7 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +6 -4
- data/lib/rubocop/cop/lint/void.rb +2 -0
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +76 -1
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +4 -4
- data/lib/rubocop/cop/mixin/range_help.rb +4 -5
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +2 -2
- data/lib/rubocop/cop/style/class_methods_definitions.rb +2 -1
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -1
- data/lib/rubocop/cop/style/double_negation.rb +2 -0
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/each_with_object.rb +39 -8
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/for.rb +2 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +3 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +17 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +8 -6
- data/lib/rubocop/cop/style/magic_comment_format.rb +307 -0
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +4 -1
- data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -1
- data/lib/rubocop/cop/style/next.rb +2 -0
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +16 -1
- data/lib/rubocop/cop/style/object_then.rb +2 -0
- data/lib/rubocop/cop/style/proc.rb +4 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +2 -0
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +15 -22
- data/lib/rubocop/cop/style/redundant_self.rb +2 -0
- data/lib/rubocop/cop/style/redundant_sort_by.rb +24 -8
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +14 -3
- data/lib/rubocop/cop/style/symbol_proc.rb +5 -0
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -13
- data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -1
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/ext/range.rb +15 -0
- data/lib/rubocop/feature_loader.rb +92 -0
- data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter/markdown_formatter.rb +1 -1
- data/lib/rubocop/formatter/tap_formatter.rb +1 -1
- data/lib/rubocop/server/cache.rb +4 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +4 -1
- metadata +13 -8
@@ -67,19 +67,6 @@ module RuboCop
|
|
67
67
|
class Debugger < Base
|
68
68
|
MSG = 'Remove debugger entry point `%<source>s`.'
|
69
69
|
|
70
|
-
# @!method kernel?(node)
|
71
|
-
def_node_matcher :kernel?, <<~PATTERN
|
72
|
-
(const {nil? cbase} :Kernel)
|
73
|
-
PATTERN
|
74
|
-
|
75
|
-
# @!method valid_receiver?(node, arg1)
|
76
|
-
def_node_matcher :valid_receiver?, <<~PATTERN
|
77
|
-
{
|
78
|
-
(const {nil? cbase} %1)
|
79
|
-
(send {nil? #kernel?} %1)
|
80
|
-
}
|
81
|
-
PATTERN
|
82
|
-
|
83
70
|
def on_send(node)
|
84
71
|
return unless debugger_method?(node)
|
85
72
|
|
@@ -101,7 +88,7 @@ module RuboCop
|
|
101
88
|
|
102
89
|
*receiver, method_name = v.split('.')
|
103
90
|
{
|
104
|
-
receiver: receiver.empty? ? nil : receiver.
|
91
|
+
receiver: receiver.empty? ? nil : receiver.map(&:to_sym),
|
105
92
|
method_name: method_name.to_sym
|
106
93
|
}
|
107
94
|
end.compact
|
@@ -115,10 +102,23 @@ module RuboCop
|
|
115
102
|
if method[:receiver].nil?
|
116
103
|
send_node.receiver.nil?
|
117
104
|
else
|
118
|
-
|
105
|
+
method[:receiver] == receiver_chain(send_node)
|
119
106
|
end
|
120
107
|
end
|
121
108
|
end
|
109
|
+
|
110
|
+
def receiver_chain(send_node)
|
111
|
+
receivers = []
|
112
|
+
receiver = send_node.receiver
|
113
|
+
|
114
|
+
while receiver
|
115
|
+
name = receiver.send_type? ? receiver.method_name : receiver.const_name&.to_sym
|
116
|
+
receivers.unshift(name)
|
117
|
+
receiver = receiver.receiver
|
118
|
+
end
|
119
|
+
|
120
|
+
receivers
|
121
|
+
end
|
122
122
|
end
|
123
123
|
end
|
124
124
|
end
|
@@ -63,7 +63,7 @@ module RuboCop
|
|
63
63
|
class EmptyBlock < Base
|
64
64
|
MSG = 'Empty block detected.'
|
65
65
|
|
66
|
-
def on_block(node)
|
66
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
67
67
|
return if node.body
|
68
68
|
return if allow_empty_lambdas? && lambda_or_proc?(node)
|
69
69
|
return if cop_config['AllowComments'] && allow_comment?(node)
|
@@ -7,6 +7,11 @@ module RuboCop
|
|
7
7
|
#
|
8
8
|
# NOTE: empty `else` branches are handled by `Style/EmptyElse`.
|
9
9
|
#
|
10
|
+
# @safety
|
11
|
+
# Autocorrection for this cop is not safe. The conditions for empty branches that
|
12
|
+
# the autocorrection removes may have side effects, or the logic in subsequent
|
13
|
+
# branches may change due to the removal of a previous condition.
|
14
|
+
#
|
10
15
|
# @example
|
11
16
|
# # bad
|
12
17
|
# if condition
|
@@ -6,18 +6,18 @@ module RuboCop
|
|
6
6
|
#
|
7
7
|
# This cop emulates the following Ruby warnings in Ruby 2.6.
|
8
8
|
#
|
9
|
+
# [source,console]
|
10
|
+
# ----
|
9
11
|
# % cat example.rb
|
10
12
|
# ERB.new('hi', nil, '-', '@output_buffer')
|
11
13
|
# % ruby -rerb example.rb
|
12
|
-
# example.rb:1: warning: Passing safe_level with the 2nd argument of
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
# ERB.new(str,
|
18
|
-
#
|
19
|
-
# is deprecated. Use keyword argument like ERB.new(str, eoutvar: ...)
|
20
|
-
# instead.
|
14
|
+
# example.rb:1: warning: Passing safe_level with the 2nd argument of ERB.new is
|
15
|
+
# deprecated. Do not use it, and specify other arguments as keyword arguments.
|
16
|
+
# example.rb:1: warning: Passing trim_mode with the 3rd argument of ERB.new is
|
17
|
+
# deprecated. Use keyword argument like ERB.new(str, trim_mode:...) instead.
|
18
|
+
# example.rb:1: warning: Passing eoutvar with the 4th argument of ERB.new is
|
19
|
+
# deprecated. Use keyword argument like ERB.new(str, eoutvar: ...) instead.
|
20
|
+
# ----
|
21
21
|
#
|
22
22
|
# Now non-keyword arguments other than first one are softly deprecated
|
23
23
|
# and will be removed when Ruby 2.5 becomes EOL.
|
@@ -25,13 +25,8 @@ module RuboCop
|
|
25
25
|
class NextWithoutAccumulator < Base
|
26
26
|
MSG = 'Use `next` with an accumulator argument in a `reduce`.'
|
27
27
|
|
28
|
-
# @!method on_body_of_reduce(node)
|
29
|
-
def_node_matcher :on_body_of_reduce, <<~PATTERN
|
30
|
-
(block (send _recv {:reduce :inject} !sym) _blockargs $(begin ...))
|
31
|
-
PATTERN
|
32
|
-
|
33
28
|
def on_block(node)
|
34
|
-
|
29
|
+
on_block_body_of_reduce(node) do |body|
|
35
30
|
void_next = body.each_node(:next).find do |n|
|
36
31
|
n.children.empty? && parent_block_node(n) == node
|
37
32
|
end
|
@@ -40,11 +35,35 @@ module RuboCop
|
|
40
35
|
end
|
41
36
|
end
|
42
37
|
|
38
|
+
def on_numblock(node)
|
39
|
+
on_numblock_body_of_reduce(node) do |body|
|
40
|
+
void_next = body.each_node(:next).find do |n|
|
41
|
+
n.children.empty? && parent_numblock_node(n) == node
|
42
|
+
end
|
43
|
+
|
44
|
+
add_offense(void_next) if void_next
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
43
48
|
private
|
44
49
|
|
50
|
+
# @!method on_block_body_of_reduce(node)
|
51
|
+
def_node_matcher :on_block_body_of_reduce, <<~PATTERN
|
52
|
+
(block (send _recv {:reduce :inject} !sym) _blockargs $(begin ...))
|
53
|
+
PATTERN
|
54
|
+
|
55
|
+
# @!method on_numblock_body_of_reduce(node)
|
56
|
+
def_node_matcher :on_numblock_body_of_reduce, <<~PATTERN
|
57
|
+
(numblock (send _recv {:reduce :inject} !sym) _argscount $(begin ...))
|
58
|
+
PATTERN
|
59
|
+
|
45
60
|
def parent_block_node(node)
|
46
61
|
node.each_ancestor(:block).first
|
47
62
|
end
|
63
|
+
|
64
|
+
def parent_numblock_node(node)
|
65
|
+
node.each_ancestor(:numblock).first
|
66
|
+
end
|
48
67
|
end
|
49
68
|
end
|
50
69
|
end
|
@@ -74,6 +74,18 @@ module RuboCop
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
+
def on_numblock(node)
|
78
|
+
return if target_ruby_version >= 3.0
|
79
|
+
return unless node.body
|
80
|
+
return unless unsorted_dir_loop?(node.send_node)
|
81
|
+
|
82
|
+
node.argument_list
|
83
|
+
.filter { |argument| var_is_required?(node.body, argument.name) }
|
84
|
+
.each do
|
85
|
+
add_offense(node.send_node) { |corrector| correct_block(corrector, node.send_node) }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
77
89
|
def on_block_pass(node)
|
78
90
|
return if target_ruby_version >= 3.0
|
79
91
|
return unless method_require?(node)
|
@@ -33,16 +33,6 @@ module RuboCop
|
|
33
33
|
MSG_EACH_WITH_INDEX = 'Use `each` instead of `each_with_index`.'
|
34
34
|
MSG_WITH_INDEX = 'Remove redundant `with_index`.'
|
35
35
|
|
36
|
-
# @!method redundant_with_index?(node)
|
37
|
-
def_node_matcher :redundant_with_index?, <<~PATTERN
|
38
|
-
(block
|
39
|
-
$(send
|
40
|
-
_ {:each_with_index :with_index} ...)
|
41
|
-
(args
|
42
|
-
(arg _))
|
43
|
-
...)
|
44
|
-
PATTERN
|
45
|
-
|
46
36
|
def on_block(node)
|
47
37
|
return unless (send = redundant_with_index?(node))
|
48
38
|
|
@@ -58,8 +48,21 @@ module RuboCop
|
|
58
48
|
end
|
59
49
|
end
|
60
50
|
|
51
|
+
alias on_numblock on_block
|
52
|
+
|
61
53
|
private
|
62
54
|
|
55
|
+
# @!method redundant_with_index?(node)
|
56
|
+
def_node_matcher :redundant_with_index?, <<~PATTERN
|
57
|
+
{
|
58
|
+
(block
|
59
|
+
$(send _ {:each_with_index :with_index} ...)
|
60
|
+
(args (arg _)) ...)
|
61
|
+
(numblock
|
62
|
+
$(send _ {:each_with_index :with_index} ...) 1 ...)
|
63
|
+
}
|
64
|
+
PATTERN
|
65
|
+
|
63
66
|
def message(node)
|
64
67
|
if node.method?(:each_with_index)
|
65
68
|
MSG_EACH_WITH_INDEX
|
@@ -31,19 +31,8 @@ module RuboCop
|
|
31
31
|
extend AutoCorrector
|
32
32
|
|
33
33
|
MSG_EACH_WITH_OBJECT = 'Use `each` instead of `each_with_object`.'
|
34
|
-
|
35
34
|
MSG_WITH_OBJECT = 'Remove redundant `with_object`.'
|
36
35
|
|
37
|
-
# @!method redundant_with_object?(node)
|
38
|
-
def_node_matcher :redundant_with_object?, <<~PATTERN
|
39
|
-
(block
|
40
|
-
$(send _ {:each_with_object :with_object}
|
41
|
-
_)
|
42
|
-
(args
|
43
|
-
(arg _))
|
44
|
-
...)
|
45
|
-
PATTERN
|
46
|
-
|
47
36
|
def on_block(node)
|
48
37
|
return unless (send = redundant_with_object?(node))
|
49
38
|
|
@@ -59,8 +48,20 @@ module RuboCop
|
|
59
48
|
end
|
60
49
|
end
|
61
50
|
|
51
|
+
alias on_numblock on_block
|
52
|
+
|
62
53
|
private
|
63
54
|
|
55
|
+
# @!method redundant_with_object?(node)
|
56
|
+
def_node_matcher :redundant_with_object?, <<~PATTERN
|
57
|
+
{
|
58
|
+
(block
|
59
|
+
$(send _ {:each_with_object :with_object} _) (args (arg _)) ...)
|
60
|
+
(numblock
|
61
|
+
$(send _ {:each_with_object :with_object} _) 1 ...)
|
62
|
+
}
|
63
|
+
PATTERN
|
64
|
+
|
64
65
|
def message(node)
|
65
66
|
if node.method?(:each_with_object)
|
66
67
|
MSG_EACH_WITH_OBJECT
|
@@ -7,6 +7,14 @@ module RuboCop
|
|
7
7
|
# less specific exception being rescued before a more specific
|
8
8
|
# exception is rescued.
|
9
9
|
#
|
10
|
+
# An exception is considered shadowed if it is rescued after its
|
11
|
+
# ancestor is, or if it and its ancestor are both rescued in the
|
12
|
+
# same `rescue` statement. In both cases, the more specific rescue is
|
13
|
+
# unnecessary because it is covered by rescuing the less specific
|
14
|
+
# exception. (ie. `rescue Exception, StandardError` has the same behavior
|
15
|
+
# whether `StandardError` is included or not, because all `StandardError`s
|
16
|
+
# are rescued by `rescue Exception`).
|
17
|
+
#
|
10
18
|
# @example
|
11
19
|
#
|
12
20
|
# # bad
|
@@ -19,6 +27,13 @@ module RuboCop
|
|
19
27
|
# handle_standard_error
|
20
28
|
# end
|
21
29
|
#
|
30
|
+
# # bad
|
31
|
+
# begin
|
32
|
+
# something
|
33
|
+
# rescue Exception, StandardError
|
34
|
+
# handle_error
|
35
|
+
# end
|
36
|
+
#
|
22
37
|
# # good
|
23
38
|
#
|
24
39
|
# begin
|
@@ -67,10 +67,19 @@ module RuboCop
|
|
67
67
|
variable_node = variable.scope.node.parent
|
68
68
|
return false unless variable_node.conditional?
|
69
69
|
|
70
|
-
outer_local_variable_node =
|
70
|
+
outer_local_variable_node =
|
71
|
+
find_conditional_node_from_ascendant(outer_local_variable.declaration_node)
|
72
|
+
return true unless outer_local_variable_node
|
71
73
|
|
72
74
|
outer_local_variable_node.conditional? && variable_node == outer_local_variable_node
|
73
75
|
end
|
76
|
+
|
77
|
+
def find_conditional_node_from_ascendant(node)
|
78
|
+
return unless (parent = node.parent)
|
79
|
+
return parent if parent.conditional?
|
80
|
+
|
81
|
+
find_conditional_node_from_ascendant(parent)
|
82
|
+
end
|
74
83
|
end
|
75
84
|
end
|
76
85
|
end
|
@@ -101,10 +101,14 @@ module RuboCop
|
|
101
101
|
check(node) if loop_method?(node)
|
102
102
|
end
|
103
103
|
|
104
|
+
def on_numblock(node)
|
105
|
+
check(node) if loop_method?(node)
|
106
|
+
end
|
107
|
+
|
104
108
|
private
|
105
109
|
|
106
110
|
def loop_method?(node)
|
107
|
-
return false unless node.block_type?
|
111
|
+
return false unless node.block_type? || node.numblock_type?
|
108
112
|
|
109
113
|
send_node = node.send_node
|
110
114
|
return false if matches_allowed_pattern?(send_node.source)
|
@@ -179,6 +183,8 @@ module RuboCop
|
|
179
183
|
|
180
184
|
def preceded_by_continue_statement?(break_statement)
|
181
185
|
break_statement.left_siblings.any? do |sibling|
|
186
|
+
# Numblocks have the arguments count as a number in the AST.
|
187
|
+
next if sibling.is_a?(Integer)
|
182
188
|
next if sibling.loop_keyword? || loop_method?(sibling)
|
183
189
|
|
184
190
|
sibling.each_descendant(*CONTINUE_KEYWORDS).any?
|
@@ -142,6 +142,8 @@ module RuboCop
|
|
142
142
|
check_node(node.body)
|
143
143
|
end
|
144
144
|
|
145
|
+
alias on_numblock on_block
|
146
|
+
|
145
147
|
private
|
146
148
|
|
147
149
|
def autocorrect(corrector, node)
|
@@ -157,17 +159,17 @@ module RuboCop
|
|
157
159
|
|
158
160
|
# @!method dynamic_method_definition?(node)
|
159
161
|
def_node_matcher :dynamic_method_definition?, <<~PATTERN
|
160
|
-
{(send nil? :define_method ...) (block (send nil? :define_method ...) ...)}
|
162
|
+
{(send nil? :define_method ...) ({block numblock} (send nil? :define_method ...) ...)}
|
161
163
|
PATTERN
|
162
164
|
|
163
165
|
# @!method class_or_instance_eval?(node)
|
164
166
|
def_node_matcher :class_or_instance_eval?, <<~PATTERN
|
165
|
-
(block (send _ {:class_eval :instance_eval}) ...)
|
167
|
+
({block numblock} (send _ {:class_eval :instance_eval}) ...)
|
166
168
|
PATTERN
|
167
169
|
|
168
170
|
# @!method class_or_module_or_struct_new_call?(node)
|
169
171
|
def_node_matcher :class_or_module_or_struct_new_call?, <<~PATTERN
|
170
|
-
(block (send (const {nil? cbase} {:Class :Module :Struct}) :new ...) ...)
|
172
|
+
({block numblock} (send (const {nil? cbase} {:Class :Module :Struct}) :new ...) ...)
|
171
173
|
PATTERN
|
172
174
|
|
173
175
|
def check_node(node)
|
@@ -277,7 +279,7 @@ module RuboCop
|
|
277
279
|
matcher_name = "#{m}_block?".to_sym
|
278
280
|
unless respond_to?(matcher_name)
|
279
281
|
self.class.def_node_matcher matcher_name, <<~PATTERN
|
280
|
-
(block (send {nil? const} {:#{m}} ...) ...)
|
282
|
+
({block numblock} (send {nil? const} {:#{m}} ...) ...)
|
281
283
|
PATTERN
|
282
284
|
end
|
283
285
|
|
@@ -6,7 +6,8 @@ module RuboCop
|
|
6
6
|
#
|
7
7
|
# IMPORTANT: RuboCop core depended on this module when it supported Rails department.
|
8
8
|
# Rails department has been extracted to RuboCop Rails gem.
|
9
|
-
#
|
9
|
+
#
|
10
|
+
# @deprecated This module is deprecated and will be removed by RuboCop 2.0.
|
10
11
|
# It will not be updated to `RuboCop::Cop::Base` v1 API to maintain compatibility
|
11
12
|
# with existing RuboCop Rails 2.8 or lower.
|
12
13
|
#
|
@@ -5,7 +5,22 @@ module RuboCop
|
|
5
5
|
# This module checks for Ruby 3.1's hash value omission syntax.
|
6
6
|
module HashShorthandSyntax
|
7
7
|
OMIT_HASH_VALUE_MSG = 'Omit the hash value.'
|
8
|
-
EXPLICIT_HASH_VALUE_MSG = '
|
8
|
+
EXPLICIT_HASH_VALUE_MSG = 'Include the hash value.'
|
9
|
+
DO_NOT_MIX_MSG_PREFIX = 'Do not mix explicit and implicit hash values.'
|
10
|
+
DO_NOT_MIX_OMIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{OMIT_HASH_VALUE_MSG}"
|
11
|
+
DO_NOT_MIX_EXPLICIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{EXPLICIT_HASH_VALUE_MSG}"
|
12
|
+
|
13
|
+
def on_hash_for_mixed_shorthand(hash_node)
|
14
|
+
return if ignore_mixed_hash_shorthand_syntax?(hash_node)
|
15
|
+
|
16
|
+
hash_value_type_breakdown = breakdown_value_types_of_hash(hash_node)
|
17
|
+
|
18
|
+
if hash_with_mixed_shorthand_syntax?(hash_value_type_breakdown)
|
19
|
+
mixed_shorthand_syntax_check(hash_value_type_breakdown)
|
20
|
+
else
|
21
|
+
no_mixed_shorthand_syntax_check(hash_value_type_breakdown)
|
22
|
+
end
|
23
|
+
end
|
9
24
|
|
10
25
|
def on_pair(node)
|
11
26
|
return if ignore_hash_shorthand_syntax?(node)
|
@@ -36,8 +51,14 @@ module RuboCop
|
|
36
51
|
end
|
37
52
|
end
|
38
53
|
|
54
|
+
def ignore_mixed_hash_shorthand_syntax?(hash_node)
|
55
|
+
target_ruby_version <= 3.0 || enforced_shorthand_syntax != 'consistent' ||
|
56
|
+
!hash_node.hash_type?
|
57
|
+
end
|
58
|
+
|
39
59
|
def ignore_hash_shorthand_syntax?(pair_node)
|
40
60
|
target_ruby_version <= 3.0 || enforced_shorthand_syntax == 'either' ||
|
61
|
+
enforced_shorthand_syntax == 'consistent' ||
|
41
62
|
!pair_node.parent.hash_type?
|
42
63
|
end
|
43
64
|
|
@@ -81,6 +102,60 @@ module RuboCop
|
|
81
102
|
|
82
103
|
ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized? && !!right_sibling
|
83
104
|
end
|
105
|
+
|
106
|
+
def breakdown_value_types_of_hash(hash_node)
|
107
|
+
hash_node.pairs.group_by do |pair_node|
|
108
|
+
if pair_node.value_omission?
|
109
|
+
:value_omitted
|
110
|
+
elsif require_hash_value?(pair_node.key.source, pair_node)
|
111
|
+
:value_needed
|
112
|
+
else
|
113
|
+
:value_omittable
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def hash_with_mixed_shorthand_syntax?(hash_value_type_breakdown)
|
119
|
+
hash_value_type_breakdown.keys.size > 1
|
120
|
+
end
|
121
|
+
|
122
|
+
def hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
|
123
|
+
hash_value_type_breakdown[:value_needed]&.any?
|
124
|
+
end
|
125
|
+
|
126
|
+
def each_omitted_value_pair(hash_value_type_breakdown, &block)
|
127
|
+
hash_value_type_breakdown[:value_omitted]&.each(&block)
|
128
|
+
end
|
129
|
+
|
130
|
+
def each_omittable_value_pair(hash_value_type_breakdown, &block)
|
131
|
+
hash_value_type_breakdown[:value_omittable]&.each(&block)
|
132
|
+
end
|
133
|
+
|
134
|
+
def mixed_shorthand_syntax_check(hash_value_type_breakdown)
|
135
|
+
if hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
|
136
|
+
each_omitted_value_pair(hash_value_type_breakdown) do |pair_node|
|
137
|
+
hash_key_source = pair_node.key.source
|
138
|
+
replacement = "#{hash_key_source}: #{hash_key_source}"
|
139
|
+
register_offense(pair_node, DO_NOT_MIX_EXPLICIT_VALUE_MSG, replacement)
|
140
|
+
end
|
141
|
+
else
|
142
|
+
each_omittable_value_pair(hash_value_type_breakdown) do |pair_node|
|
143
|
+
hash_key_source = pair_node.key.source
|
144
|
+
replacement = "#{hash_key_source}:"
|
145
|
+
register_offense(pair_node, DO_NOT_MIX_OMIT_VALUE_MSG, replacement)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def no_mixed_shorthand_syntax_check(hash_value_type_breakdown)
|
151
|
+
return if hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
|
152
|
+
|
153
|
+
each_omittable_value_pair(hash_value_type_breakdown) do |pair_node|
|
154
|
+
hash_key_source = pair_node.key.source
|
155
|
+
replacement = "#{hash_key_source}:"
|
156
|
+
register_offense(pair_node, OMIT_HASH_VALUE_MSG, replacement)
|
157
|
+
end
|
158
|
+
end
|
84
159
|
end
|
85
160
|
end
|
86
161
|
end
|
@@ -14,7 +14,7 @@ module RuboCop
|
|
14
14
|
{(array ...) (send _ :each_with_index) (send _ :with_index _ ?) (send _ :zip ...)}
|
15
15
|
PATTERN
|
16
16
|
|
17
|
-
def on_block(node)
|
17
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
18
18
|
on_bad_each_with_object(node) do |*match|
|
19
19
|
handle_possible_offense(node, match, 'each_with_object')
|
20
20
|
end
|
@@ -29,14 +29,14 @@ module RuboCop
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
alias on_numblock on_block
|
33
|
+
|
32
34
|
private
|
33
35
|
|
34
36
|
# @!method define_method?(node)
|
35
37
|
def_node_matcher :define_method?, <<~PATTERN
|
36
|
-
(block
|
37
|
-
(send nil? :define_method ({sym str} $_))
|
38
|
-
args
|
39
|
-
_)
|
38
|
+
({block numblock}
|
39
|
+
(send nil? :define_method ({sym str} $_)) _ _)
|
40
40
|
PATTERN
|
41
41
|
|
42
42
|
def check_complexity(node, method_name)
|
@@ -54,11 +54,11 @@ module RuboCop
|
|
54
54
|
NOT_GIVEN = Module.new
|
55
55
|
def range_with_surrounding_space(range_positional = NOT_GIVEN, # rubocop:disable Metrics/ParameterLists
|
56
56
|
range: NOT_GIVEN, side: :both, newlines: true,
|
57
|
-
whitespace: false, continuations: false
|
57
|
+
whitespace: false, continuations: false,
|
58
|
+
buffer: @processed_source.buffer)
|
58
59
|
|
59
60
|
range = range_positional unless range_positional == NOT_GIVEN
|
60
61
|
|
61
|
-
buffer = @processed_source.buffer
|
62
62
|
src = buffer.source
|
63
63
|
|
64
64
|
go_left, go_right = directions(side)
|
@@ -70,9 +70,8 @@ module RuboCop
|
|
70
70
|
Parser::Source::Range.new(buffer, begin_pos, end_pos)
|
71
71
|
end
|
72
72
|
|
73
|
-
def range_by_whole_lines(range, include_final_newline: false
|
74
|
-
|
75
|
-
|
73
|
+
def range_by_whole_lines(range, include_final_newline: false,
|
74
|
+
buffer: @processed_source.buffer)
|
76
75
|
last_line = buffer.source_line(range.last_line)
|
77
76
|
end_offset = last_line.length - range.last_column
|
78
77
|
end_offset += 1 if include_final_newline
|
@@ -73,11 +73,11 @@ module RuboCop
|
|
73
73
|
{
|
74
74
|
(send _ _
|
75
75
|
(splat (lvar %1))
|
76
|
-
(block-pass (lvar %2)))
|
76
|
+
(block-pass {(lvar %2) nil?}))
|
77
77
|
(send _ _
|
78
78
|
(splat (lvar %1))
|
79
79
|
(hash (kwsplat (lvar %3)))
|
80
|
-
(block-pass (lvar %2)))
|
80
|
+
(block-pass {(lvar %2) nil?}))
|
81
81
|
}
|
82
82
|
PATTERN
|
83
83
|
|
@@ -70,7 +70,7 @@ module RuboCop
|
|
70
70
|
|
71
71
|
def on_sclass(node)
|
72
72
|
return unless def_self_style?
|
73
|
-
return unless node.identifier.
|
73
|
+
return unless node.identifier.self_type?
|
74
74
|
return unless all_methods_public?(node)
|
75
75
|
|
76
76
|
add_offense(node, message: MSG_SCLASS) do |corrector|
|
@@ -80,6 +80,7 @@ module RuboCop
|
|
80
80
|
|
81
81
|
def on_defs(node)
|
82
82
|
return if def_self_style?
|
83
|
+
return unless node.receiver.self_type?
|
83
84
|
|
84
85
|
message = format(MSG, preferred: 'class << self')
|
85
86
|
add_offense(node, message: message)
|
@@ -66,6 +66,8 @@ module RuboCop
|
|
66
66
|
add_offense(node) if same_collection_looping?(node, node.left_sibling)
|
67
67
|
end
|
68
68
|
|
69
|
+
alias on_numblock on_block
|
70
|
+
|
69
71
|
def on_for(node)
|
70
72
|
return unless node.parent&.begin_type?
|
71
73
|
|
@@ -82,7 +84,7 @@ module RuboCop
|
|
82
84
|
end
|
83
85
|
|
84
86
|
def same_collection_looping?(node, sibling)
|
85
|
-
sibling&.block_type? &&
|
87
|
+
(sibling&.block_type? || sibling&.numblock_type?) &&
|
86
88
|
sibling.send_node.method?(node.method_name) &&
|
87
89
|
sibling.receiver == node.receiver &&
|
88
90
|
sibling.send_node.arguments == node.send_node.arguments
|
@@ -93,6 +93,8 @@ module RuboCop
|
|
93
93
|
|
94
94
|
if conditional_node
|
95
95
|
double_negative_condition_return_value?(node, last_child, conditional_node)
|
96
|
+
elsif last_child.pair_type? || last_child.hash_type? || last_child.parent.array_type?
|
97
|
+
false
|
96
98
|
else
|
97
99
|
last_child.last_line <= node.last_line
|
98
100
|
end
|
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
|
28
28
|
MSG = 'Use `Integer#times` for a simple loop which iterates a fixed number of times.'
|
29
29
|
|
30
|
-
def on_block(node)
|
30
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
31
31
|
return unless offending_each_range(node)
|
32
32
|
|
33
33
|
send_node = node.send_node
|