rubocop 1.64.1 → 1.65.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/README.md +1 -1
- data/config/default.yml +11 -1
- data/lib/rubocop/config_loader.rb +1 -1
- data/lib/rubocop/config_loader_resolver.rb +9 -3
- data/lib/rubocop/cop/cop.rb +22 -4
- data/lib/rubocop/cop/gemspec/add_runtime_dependency.rb +38 -0
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
- data/lib/rubocop/cop/layout/assignment_indentation.rb +3 -2
- data/lib/rubocop/cop/layout/case_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/condition_position.rb +0 -4
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.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_length.rb +20 -20
- data/lib/rubocop/cop/layout/space_around_operators.rb +3 -0
- data/lib/rubocop/cop/legacy/corrector.rb +12 -2
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +0 -2
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +0 -2
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +0 -2
- data/lib/rubocop/cop/lint/boolean_symbol.rb +0 -2
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +0 -13
- data/lib/rubocop/cop/lint/debugger.rb +0 -4
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +0 -10
- data/lib/rubocop/cop/lint/duplicate_case_condition.rb +1 -5
- data/lib/rubocop/cop/lint/duplicate_hash_key.rb +0 -4
- data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -10
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +0 -4
- data/lib/rubocop/cop/lint/else_layout.rb +0 -2
- data/lib/rubocop/cop/lint/empty_ensure.rb +1 -11
- data/lib/rubocop/cop/lint/empty_interpolation.rb +0 -4
- data/lib/rubocop/cop/lint/empty_when.rb +1 -3
- data/lib/rubocop/cop/lint/ensure_return.rb +1 -6
- data/lib/rubocop/cop/lint/float_comparison.rb +3 -1
- data/lib/rubocop/cop/lint/float_out_of_range.rb +0 -4
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +0 -10
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +15 -12
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +0 -7
- data/lib/rubocop/cop/lint/interpolation_check.rb +0 -4
- data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -1
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +0 -4
- data/lib/rubocop/cop/lint/loop.rb +6 -12
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -7
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +0 -4
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +0 -5
- data/lib/rubocop/cop/lint/percent_string_array.rb +0 -4
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +0 -4
- data/lib/rubocop/cop/lint/rand_one.rb +0 -4
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +3 -1
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +0 -4
- data/lib/rubocop/cop/lint/require_parentheses.rb +0 -4
- data/lib/rubocop/cop/lint/rescue_exception.rb +0 -4
- data/lib/rubocop/cop/lint/return_in_void_context.rb +0 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +0 -4
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +6 -10
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +2 -9
- data/lib/rubocop/cop/lint/unified_integer.rb +0 -4
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +0 -5
- data/lib/rubocop/cop/lint/useless_assignment.rb +1 -5
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +0 -4
- data/lib/rubocop/cop/lint/useless_setter_call.rb +0 -4
- data/lib/rubocop/cop/lint/void.rb +5 -0
- data/lib/rubocop/cop/metrics/block_nesting.rb +19 -7
- data/lib/rubocop/cop/mixin/alignment.rb +5 -1
- data/lib/rubocop/cop/mixin/allowed_methods.rb +7 -1
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +15 -3
- data/lib/rubocop/cop/mixin/configurable_max.rb +5 -1
- data/lib/rubocop/cop/mixin/rescue_node.rb +4 -0
- data/lib/rubocop/cop/naming/predicate_name.rb +52 -26
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -1
- data/lib/rubocop/cop/style/def_with_parentheses.rb +0 -2
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +0 -1
- data/lib/rubocop/cop/style/eval_with_location.rb +12 -11
- data/lib/rubocop/cop/style/file_read.rb +2 -5
- data/lib/rubocop/cop/style/file_write.rb +2 -5
- data/lib/rubocop/cop/style/global_std_stream.rb +7 -1
- data/lib/rubocop/cop/style/hash_except.rb +8 -5
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +0 -1
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +77 -43
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +5 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/missing_else.rb +0 -4
- data/lib/rubocop/cop/style/multiline_when_then.rb +0 -4
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +0 -1
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -24
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +15 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +21 -2
- data/lib/rubocop/cop/style/super_arguments.rb +28 -10
- data/lib/rubocop/cop/style/symbol_proc.rb +8 -1
- data/lib/rubocop/cop/style/while_until_do.rb +0 -2
- data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +32 -24
- data/lib/rubocop/cop/team.rb +8 -0
- data/lib/rubocop/cop/util.rb +7 -1
- data/lib/rubocop/cop/variable_force.rb +13 -1
- data/lib/rubocop/cops_documentation_generator.rb +1 -1
- data/lib/rubocop/core_ext/string.rb +2 -6
- data/lib/rubocop/ext/regexp_node.rb +9 -31
- data/lib/rubocop/ext/regexp_parser.rb +4 -21
- data/lib/rubocop/formatter/html_formatter.rb +3 -1
- data/lib/rubocop/options.rb +3 -1
- data/lib/rubocop/rspec/shared_contexts.rb +20 -0
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/server/cache.rb +10 -0
- data/lib/rubocop/server/client_command/exec.rb +2 -2
- data/lib/rubocop/server/client_command/start.rb +1 -1
- data/lib/rubocop/server/core.rb +4 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +6 -0
- metadata +7 -6
@@ -4,6 +4,7 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# Prefer `select` or `reject` over `map { ... }.compact`.
|
7
|
+
# This cop also handles `filter_map { ... }`, similar to `map { ... }.compact`.
|
7
8
|
#
|
8
9
|
# @example
|
9
10
|
#
|
@@ -11,6 +12,9 @@ module RuboCop
|
|
11
12
|
# array.map { |e| some_condition? ? e : next }.compact
|
12
13
|
#
|
13
14
|
# # bad
|
15
|
+
# array.filter_map { |e| some_condition? ? e : next }
|
16
|
+
#
|
17
|
+
# # bad
|
14
18
|
# array.map do |e|
|
15
19
|
# if some_condition?
|
16
20
|
# e
|
@@ -40,55 +44,73 @@ module RuboCop
|
|
40
44
|
class MapCompactWithConditionalBlock < Base
|
41
45
|
extend AutoCorrector
|
42
46
|
|
43
|
-
MSG = 'Replace `
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
47
|
+
MSG = 'Replace `%<current>s` with `%<method>s`.'
|
48
|
+
RESTRICT_ON_SEND = %i[compact filter_map].freeze
|
49
|
+
|
50
|
+
# @!method conditional_block(node)
|
51
|
+
def_node_matcher :conditional_block, <<~RUBY
|
52
|
+
(block
|
53
|
+
(call _ {:map :filter_map})
|
54
|
+
(args
|
55
|
+
$(arg _))
|
56
|
+
{
|
57
|
+
(if $_ $(lvar _) {next nil?})
|
58
|
+
(if $_ {next nil?} $(lvar _))
|
59
|
+
(if $_ (next $(lvar _)) {next nil nil?})
|
60
|
+
(if $_ {next nil nil?} (next $(lvar _)))
|
61
|
+
(begin
|
62
|
+
{
|
63
|
+
(if $_ next nil?)
|
64
|
+
(if $_ nil? next)
|
65
|
+
}
|
66
|
+
$(lvar _))
|
67
|
+
(begin
|
68
|
+
{
|
69
|
+
(if $_ (next $(lvar _)) nil?)
|
70
|
+
(if $_ nil? (next $(lvar _)))
|
71
|
+
}
|
72
|
+
(nil))
|
73
|
+
})
|
70
74
|
RUBY
|
71
75
|
|
72
76
|
def on_send(node)
|
73
|
-
|
74
|
-
|
75
|
-
return
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
)
|
85
|
-
end
|
77
|
+
map_candidate = node.children.first
|
78
|
+
if (block_argument, condition, return_value = conditional_block(map_candidate))
|
79
|
+
return unless node.method?(:compact) && node.arguments.empty?
|
80
|
+
|
81
|
+
range = map_with_compact_range(node)
|
82
|
+
elsif (block_argument, condition, return_value = conditional_block(node.parent))
|
83
|
+
return unless node.method?(:filter_map)
|
84
|
+
|
85
|
+
range = filter_map_range(node)
|
86
|
+
else
|
87
|
+
return
|
86
88
|
end
|
89
|
+
|
90
|
+
inspect(node, block_argument, condition, return_value, range)
|
87
91
|
end
|
88
92
|
alias on_csend on_send
|
89
93
|
|
90
94
|
private
|
91
95
|
|
96
|
+
def inspect(node, block_argument_node, condition_node, return_value_node, range)
|
97
|
+
return unless returns_block_argument?(block_argument_node, return_value_node)
|
98
|
+
return if condition_node.parent.elsif?
|
99
|
+
|
100
|
+
method = truthy_branch?(return_value_node) ? 'select' : 'reject'
|
101
|
+
current = current(node)
|
102
|
+
|
103
|
+
add_offense(range, message: format(MSG, current: current, method: method)) do |corrector|
|
104
|
+
return if part_of_ignored_node?(node) || ignored_node?(node)
|
105
|
+
|
106
|
+
corrector.replace(
|
107
|
+
range, "#{method} { |#{block_argument_node.source}| #{condition_node.source} }"
|
108
|
+
)
|
109
|
+
|
110
|
+
ignore_node(node)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
92
114
|
def returns_block_argument?(block_argument_node, return_value_node)
|
93
115
|
block_argument_node.name == return_value_node.children.first
|
94
116
|
end
|
@@ -123,10 +145,22 @@ module RuboCop
|
|
123
145
|
end
|
124
146
|
end
|
125
147
|
|
126
|
-
def
|
127
|
-
|
148
|
+
def current(node)
|
149
|
+
if node.method?(:compact)
|
150
|
+
map_or_filter_map_method = node.children.first
|
151
|
+
|
152
|
+
"#{map_or_filter_map_method.method_name} { ... }.compact"
|
153
|
+
else
|
154
|
+
'filter_map { ... }'
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def map_with_compact_range(node)
|
159
|
+
node.receiver.send_node.loc.selector.begin.join(node.source_range.end)
|
160
|
+
end
|
128
161
|
|
129
|
-
|
162
|
+
def filter_map_range(node)
|
163
|
+
node.loc.selector.join(node.parent.source_range.end)
|
130
164
|
end
|
131
165
|
end
|
132
166
|
end
|
@@ -18,6 +18,7 @@ module RuboCop
|
|
18
18
|
return if inside_endless_method_def?(node)
|
19
19
|
return if require_parentheses_for_hash_value_omission?(node)
|
20
20
|
return if syntax_like_method_call?(node)
|
21
|
+
return if method_call_before_constant_resolution?(node)
|
21
22
|
return if super_call_without_arguments?(node)
|
22
23
|
return if legitimate_call_with_parentheses?(node)
|
23
24
|
return if allowed_camel_case_method_call?(node)
|
@@ -63,6 +64,10 @@ module RuboCop
|
|
63
64
|
node.implicit_call? || node.operator_method?
|
64
65
|
end
|
65
66
|
|
67
|
+
def method_call_before_constant_resolution?(node)
|
68
|
+
node.parent&.const_type?
|
69
|
+
end
|
70
|
+
|
66
71
|
def super_call_without_arguments?(node)
|
67
72
|
node.super_type? && node.arguments.none?
|
68
73
|
end
|
@@ -4,7 +4,7 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# Enforces the presence (default) or absence of parentheses in
|
7
|
-
# method calls containing
|
7
|
+
# method calls containing arguments.
|
8
8
|
#
|
9
9
|
# In the default style (require_parentheses), macro methods are allowed.
|
10
10
|
# Additional methods can be added to the `AllowedMethods` or
|
@@ -9,7 +9,7 @@ module RuboCop
|
|
9
9
|
#
|
10
10
|
# String interpolation is always kept in double quotes.
|
11
11
|
#
|
12
|
-
#
|
12
|
+
# NOTE: `Lint/SymbolConversion` can be used in parallel to ensure that symbols
|
13
13
|
# are not quoted that don't need to be. This cop is for configuring the quoting
|
14
14
|
# style to use for symbols that require quotes.
|
15
15
|
#
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
6
6
|
# Checks for the presence of superfluous `.rb` extension in
|
7
7
|
# the filename provided to `require` and `require_relative`.
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# NOTE: If the extension is omitted, Ruby tries adding '.rb', '.so',
|
10
10
|
# and so on to the name until found. If the file named cannot be found,
|
11
11
|
# a `LoadError` will be raised.
|
12
12
|
# There is an edge case where `foo.so` file is loaded instead of a `LoadError`
|
@@ -95,30 +95,14 @@ module RuboCop
|
|
95
95
|
delimiters.include?(char)
|
96
96
|
end
|
97
97
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
char_class_depth
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
# Please remove this `else` branch when support for regexp_parser 1.8 will be dropped.
|
111
|
-
# It's for compatibility with regexp_parser 1.8 and will never be maintained.
|
112
|
-
else
|
113
|
-
def each_escape(node)
|
114
|
-
node.parsed_tree&.traverse&.reduce(0) do |char_class_depth, (event, expr)|
|
115
|
-
yield(expr.text[1], expr.start_index, !char_class_depth.zero?) if expr.type == :escape
|
116
|
-
|
117
|
-
if expr.type == :set
|
118
|
-
char_class_depth + (event == :enter ? 1 : -1)
|
119
|
-
else
|
120
|
-
char_class_depth
|
121
|
-
end
|
98
|
+
def each_escape(node)
|
99
|
+
node.parsed_tree&.traverse&.reduce(0) do |char_class_depth, (event, expr)|
|
100
|
+
yield(expr.text[1], expr.ts, !char_class_depth.zero?) if expr.type == :escape
|
101
|
+
|
102
|
+
if expr.type == :set
|
103
|
+
char_class_depth + (event == :enter ? 1 : -1)
|
104
|
+
else
|
105
|
+
char_class_depth
|
122
106
|
end
|
123
107
|
end
|
124
108
|
end
|
@@ -7,6 +7,20 @@ module RuboCop
|
|
7
7
|
# Since the `send` method can be used to call private methods, by default,
|
8
8
|
# only the `public_send` method is detected.
|
9
9
|
#
|
10
|
+
# NOTE: Writer methods with names ending in `=` are always permitted because their
|
11
|
+
# behavior differs as follows:
|
12
|
+
#
|
13
|
+
# [source,ruby]
|
14
|
+
# ----
|
15
|
+
# def foo=(foo)
|
16
|
+
# @foo = foo
|
17
|
+
# 42
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# self.foo = 1 # => 1
|
21
|
+
# send(:foo=, 1) # => 42
|
22
|
+
# ----
|
23
|
+
#
|
10
24
|
# @safety
|
11
25
|
# This cop is not safe because it can incorrectly detect based on the receiver.
|
12
26
|
# Additionally, when `AllowSend` is set to `true`, it cannot determine whether
|
@@ -43,7 +57,7 @@ module RuboCop
|
|
43
57
|
MSG = 'Use `%<method_name>s` method call directly instead.'
|
44
58
|
RESTRICT_ON_SEND = %i[public_send send __send__].freeze
|
45
59
|
STATIC_METHOD_NAME_NODE_TYPES = %i[sym str].freeze
|
46
|
-
METHOD_NAME_PATTERN = /\A[a-zA-Z_][a-zA-Z0-9_]*[
|
60
|
+
METHOD_NAME_PATTERN = /\A[a-zA-Z_][a-zA-Z0-9_]*[!?]?\z/.freeze
|
47
61
|
RESERVED_WORDS = %i[
|
48
62
|
BEGIN END alias and begin break case class def defined? do else elsif end ensure
|
49
63
|
false for if in module next nil not or redo rescue retry return self super then true
|
@@ -159,7 +159,13 @@ module RuboCop
|
|
159
159
|
node_to_check = condition&.block_type? ? condition.send_node : condition
|
160
160
|
return unless wrap_condition?(node_to_check)
|
161
161
|
|
162
|
-
|
162
|
+
if condition.call_type?
|
163
|
+
source = parenthesized_method_arguments(condition)
|
164
|
+
|
165
|
+
corrector.replace(condition, source)
|
166
|
+
else
|
167
|
+
corrector.wrap(condition, '(', ')')
|
168
|
+
end
|
163
169
|
end
|
164
170
|
|
165
171
|
def correct_for_outer_condition_modify_form_style(corrector, node, if_branch)
|
@@ -236,7 +242,20 @@ module RuboCop
|
|
236
242
|
end
|
237
243
|
|
238
244
|
def replace_condition(condition)
|
239
|
-
|
245
|
+
return condition.source unless wrap_condition?(condition)
|
246
|
+
|
247
|
+
if condition.call_type?
|
248
|
+
parenthesized_method_arguments(condition)
|
249
|
+
else
|
250
|
+
"(#{condition.source})"
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def parenthesized_method_arguments(node)
|
255
|
+
method_call = node.source_range.begin.join(node.loc.selector.end).source
|
256
|
+
arguments = node.first_argument.source_range.begin.join(node.source_range.end).source
|
257
|
+
|
258
|
+
"#{method_call}(#{arguments})"
|
240
259
|
end
|
241
260
|
|
242
261
|
def allow_modifier?
|
@@ -3,8 +3,25 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for redundant argument forwarding when calling super
|
7
|
-
#
|
6
|
+
# Checks for redundant argument forwarding when calling super with arguments identical to
|
7
|
+
# the method definition.
|
8
|
+
#
|
9
|
+
# Using zero arity `super` within a `define_method` block results in `RuntimeError`:
|
10
|
+
#
|
11
|
+
# [source,ruby]
|
12
|
+
# ----
|
13
|
+
# def m
|
14
|
+
# define_method(:foo) { super() } # => OK
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# def m
|
18
|
+
# define_method(:foo) { super } # => RuntimeError
|
19
|
+
# end
|
20
|
+
# ----
|
21
|
+
#
|
22
|
+
# Furthermore, any arguments accompanied by a block may potentially be delegating to
|
23
|
+
# `define_method`, therefore, `super` used within these blocks will be allowed.
|
24
|
+
# This approach might result in false negatives, yet ensuring safe detection takes precedence.
|
8
25
|
#
|
9
26
|
# @example
|
10
27
|
# # bad
|
@@ -44,8 +61,10 @@ module RuboCop
|
|
44
61
|
|
45
62
|
def on_super(super_node)
|
46
63
|
def_node = super_node.ancestors.find do |node|
|
47
|
-
#
|
48
|
-
|
64
|
+
# When defining dynamic methods, implicitly calling `super` is not possible.
|
65
|
+
# Since there is a possibility of delegation to `define_method`,
|
66
|
+
# `super` used within the block is always allowed.
|
67
|
+
break if node.block_type?
|
49
68
|
|
50
69
|
break node if DEF_TYPES.include?(node.type)
|
51
70
|
end
|
@@ -127,6 +146,11 @@ module RuboCop
|
|
127
146
|
# https://bugs.ruby-lang.org/issues/20505
|
128
147
|
def block_reassigned?(def_node, block_arg_name)
|
129
148
|
def_node.each_node(*ASSIGN_TYPES).any? do |assign_node|
|
149
|
+
# TODO: Since `Symbol#name` is supported from Ruby 3.0, the inheritance check for
|
150
|
+
# `AST::Node` can be removed when requiring Ruby 3.0+.
|
151
|
+
lhs = assign_node.node_parts[0]
|
152
|
+
next if lhs.is_a?(AST::Node) && !lhs.respond_to?(:name)
|
153
|
+
|
130
154
|
assign_node.name == block_arg_name
|
131
155
|
end
|
132
156
|
end
|
@@ -135,12 +159,6 @@ module RuboCop
|
|
135
159
|
def_arg.forward_arg_type? && super_arg.forwarded_args_type?
|
136
160
|
end
|
137
161
|
|
138
|
-
def define_method?(node)
|
139
|
-
return false unless node.block_type?
|
140
|
-
|
141
|
-
node.method?(:define_method) || node.method?(:define_singleton_method)
|
142
|
-
end
|
143
|
-
|
144
162
|
def preprocess_super_args(super_args)
|
145
163
|
super_args.flat_map do |node|
|
146
164
|
if node.hash_type? && !node.braces?
|
@@ -223,7 +223,14 @@ module RuboCop
|
|
223
223
|
end
|
224
224
|
|
225
225
|
def autocorrect_without_args(corrector, node)
|
226
|
-
|
226
|
+
if node.send_node.lambda_literal?
|
227
|
+
if node.send_node.loc.selector.source == '->'
|
228
|
+
corrector.replace(node, "lambda(&:#{node.body.method_name})")
|
229
|
+
return
|
230
|
+
else
|
231
|
+
autocorrect_lambda_block(corrector, node)
|
232
|
+
end
|
233
|
+
end
|
227
234
|
|
228
235
|
corrector.replace(block_range_with_space(node), "(&:#{node.body.method_name})")
|
229
236
|
end
|
@@ -48,14 +48,19 @@ module RuboCop
|
|
48
48
|
check_nonzero_length_comparison(node)
|
49
49
|
end
|
50
50
|
|
51
|
+
def on_csend(node)
|
52
|
+
check_zero_length_predicate(node)
|
53
|
+
check_zero_length_comparison(node)
|
54
|
+
end
|
55
|
+
|
51
56
|
private
|
52
57
|
|
53
58
|
def check_zero_length_predicate(node)
|
54
|
-
return unless
|
59
|
+
return unless zero_length_predicate?(node.parent)
|
55
60
|
return if non_polymorphic_collection?(node.parent)
|
56
61
|
|
57
62
|
offense = node.loc.selector.join(node.parent.source_range.end)
|
58
|
-
message = format(ZERO_MSG, current:
|
63
|
+
message = format(ZERO_MSG, current: offense.source)
|
59
64
|
|
60
65
|
add_offense(offense, message: message) do |corrector|
|
61
66
|
corrector.replace(offense, 'empty?')
|
@@ -92,44 +97,47 @@ module RuboCop
|
|
92
97
|
end
|
93
98
|
end
|
94
99
|
|
95
|
-
# @!method zero_length_predicate(node)
|
96
|
-
def_node_matcher :zero_length_predicate
|
97
|
-
(
|
100
|
+
# @!method zero_length_predicate?(node)
|
101
|
+
def_node_matcher :zero_length_predicate?, <<~PATTERN
|
102
|
+
(call (call (...) {:length :size}) :zero?)
|
98
103
|
PATTERN
|
99
104
|
|
100
105
|
# @!method zero_length_comparison(node)
|
101
106
|
def_node_matcher :zero_length_comparison, <<~PATTERN
|
102
|
-
{(
|
103
|
-
(
|
104
|
-
(
|
105
|
-
(
|
107
|
+
{(call (call (...) ${:length :size}) $:== (int $0))
|
108
|
+
(call (int $0) $:== (call (...) ${:length :size}))
|
109
|
+
(call (call (...) ${:length :size}) $:< (int $1))
|
110
|
+
(call (int $1) $:> (call (...) ${:length :size}))}
|
106
111
|
PATTERN
|
107
112
|
|
108
113
|
# @!method nonzero_length_comparison(node)
|
109
114
|
def_node_matcher :nonzero_length_comparison, <<~PATTERN
|
110
|
-
{(
|
111
|
-
(
|
115
|
+
{(call (call (...) ${:length :size}) ${:> :!=} (int $0))
|
116
|
+
(call (int $0) ${:< :!=} (call (...) ${:length :size}))}
|
112
117
|
PATTERN
|
113
118
|
|
114
119
|
def replacement(node)
|
115
|
-
|
116
|
-
|
120
|
+
length_node = zero_length_node(node)
|
121
|
+
if length_node&.receiver
|
122
|
+
return "#{length_node.receiver.source}#{length_node.loc.dot.source}empty?"
|
123
|
+
end
|
117
124
|
|
118
|
-
|
125
|
+
other_length_node = other_length_node(node)
|
126
|
+
"!#{other_length_node.receiver.source}#{other_length_node.loc.dot.source}empty?"
|
119
127
|
end
|
120
128
|
|
121
|
-
# @!method
|
122
|
-
def_node_matcher :
|
123
|
-
{(send (
|
124
|
-
(send (int 0) :== (
|
125
|
-
(send (
|
126
|
-
(send (int 1) :> (
|
129
|
+
# @!method zero_length_node(node)
|
130
|
+
def_node_matcher :zero_length_node, <<~PATTERN
|
131
|
+
{(send $(call _ _) :== (int 0))
|
132
|
+
(send (int 0) :== $(call _ _))
|
133
|
+
(send $(call _ _) :< (int 1))
|
134
|
+
(send (int 1) :> $(call _ _))}
|
127
135
|
PATTERN
|
128
136
|
|
129
|
-
# @!method
|
130
|
-
def_node_matcher :
|
131
|
-
{(
|
132
|
-
(
|
137
|
+
# @!method other_length_node(node)
|
138
|
+
def_node_matcher :other_length_node, <<~PATTERN
|
139
|
+
{(call $(call _ _) _ _)
|
140
|
+
(call _ _ $(call _ _))}
|
133
141
|
PATTERN
|
134
142
|
|
135
143
|
# Some collection like objects in the Ruby standard library
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -74,6 +74,10 @@ module RuboCop
|
|
74
74
|
# @deprecated. Use investigate
|
75
75
|
# @return Array<offenses>
|
76
76
|
def inspect_file(processed_source)
|
77
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
78
|
+
`inspect_file` is deprecated. Use `investigate` instead.
|
79
|
+
WARNING
|
80
|
+
|
77
81
|
investigate(processed_source).offenses
|
78
82
|
end
|
79
83
|
|
@@ -108,6 +112,10 @@ module RuboCop
|
|
108
112
|
|
109
113
|
# @deprecated
|
110
114
|
def forces
|
115
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
116
|
+
`forces` is deprecated.
|
117
|
+
WARNING
|
118
|
+
|
111
119
|
@forces ||= self.class.forces_for(cops)
|
112
120
|
end
|
113
121
|
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -20,6 +20,10 @@ module RuboCop
|
|
20
20
|
|
21
21
|
# @deprecated Use `ProcessedSource#line_with_comment?`, `contains_comment?` or similar
|
22
22
|
def comment_lines?(node)
|
23
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
24
|
+
`comment_lines?` is deprecated. Use `ProcessedSource#line_with_comment?`, `contains_comment?` or similar instead.
|
25
|
+
WARNING
|
26
|
+
|
23
27
|
processed_source[line_range(node)].any? { |line| comment_line?(line) }
|
24
28
|
end
|
25
29
|
|
@@ -173,7 +177,9 @@ module RuboCop
|
|
173
177
|
def same_line?(node1, node2)
|
174
178
|
line1 = line(node1)
|
175
179
|
line2 = line(node2)
|
176
|
-
|
180
|
+
return false unless line1 && line2
|
181
|
+
|
182
|
+
line1 == line2
|
177
183
|
end
|
178
184
|
|
179
185
|
def indent(node, offset: 0)
|
@@ -27,7 +27,10 @@ module RuboCop
|
|
27
27
|
class VariableForce < Force # rubocop:disable Metrics/ClassLength
|
28
28
|
VARIABLE_ASSIGNMENT_TYPE = :lvasgn
|
29
29
|
REGEXP_NAMED_CAPTURE_TYPE = :match_with_lvasgn
|
30
|
-
|
30
|
+
PATTERN_MATCH_VARIABLE_TYPE = :match_var
|
31
|
+
VARIABLE_ASSIGNMENT_TYPES = [
|
32
|
+
VARIABLE_ASSIGNMENT_TYPE, REGEXP_NAMED_CAPTURE_TYPE, PATTERN_MATCH_VARIABLE_TYPE
|
33
|
+
].freeze
|
31
34
|
|
32
35
|
ARGUMENT_DECLARATION_TYPES = [
|
33
36
|
:arg, :optarg, :restarg,
|
@@ -112,6 +115,7 @@ module RuboCop
|
|
112
115
|
NODE_HANDLER_METHOD_NAMES = [
|
113
116
|
[VARIABLE_ASSIGNMENT_TYPE, :process_variable_assignment],
|
114
117
|
[REGEXP_NAMED_CAPTURE_TYPE, :process_regexp_named_captures],
|
118
|
+
[PATTERN_MATCH_VARIABLE_TYPE, :process_pattern_match_variable],
|
115
119
|
[MULTIPLE_ASSIGNMENT_TYPE, :process_variable_multiple_assignment],
|
116
120
|
[VARIABLE_REFERENCE_TYPE, :process_variable_referencing],
|
117
121
|
[RESCUE_TYPE, :process_rescue],
|
@@ -175,6 +179,14 @@ module RuboCop
|
|
175
179
|
skip_children!
|
176
180
|
end
|
177
181
|
|
182
|
+
def process_pattern_match_variable(node)
|
183
|
+
name = node.children.first
|
184
|
+
|
185
|
+
variable_table.declare_variable(name, node) unless variable_table.variable_exist?(name)
|
186
|
+
|
187
|
+
skip_children!
|
188
|
+
end
|
189
|
+
|
178
190
|
def regexp_captured_names(node)
|
179
191
|
regexp = node.to_regexp
|
180
192
|
|
@@ -306,7 +306,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
306
306
|
filename = "#{department_to_basename(department)}.adoc"
|
307
307
|
content = +"=== Department xref:#{filename}[#{type_title}]\n\n"
|
308
308
|
cops_of_department(department).each do |cop|
|
309
|
-
anchor = cop.cop_name.
|
309
|
+
anchor = cop.cop_name.delete('/').downcase
|
310
310
|
content << "* xref:#{filename}##{anchor}[#{cop.cop_name}]\n"
|
311
311
|
end
|
312
312
|
|
@@ -9,12 +9,8 @@ class String
|
|
9
9
|
# @return [Boolean] true is the string is blank, false otherwise
|
10
10
|
#
|
11
11
|
# @example
|
12
|
-
# ''.blank?
|
13
|
-
#
|
14
|
-
# @example
|
15
|
-
# ' '.blank? #=> true
|
16
|
-
#
|
17
|
-
# @example
|
12
|
+
# ''.blank? #=> true
|
13
|
+
# ' '.blank? #=> true
|
18
14
|
# ' test'.blank? #=> false
|
19
15
|
def blank?
|
20
16
|
empty? || lstrip.empty?
|