rubocop 1.80.1 → 1.81.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 +10 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
- data/lib/rubocop/cli.rb +1 -2
- data/lib/rubocop/config_loader.rb +3 -1
- data/lib/rubocop/config_store.rb +5 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +4 -4
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +30 -12
- data/lib/rubocop/cop/layout/line_length.rb +9 -1
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +6 -4
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +8 -0
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
- data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
- data/lib/rubocop/cop/lint/void.rb +7 -0
- data/lib/rubocop/cop/message_annotator.rb +1 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_method.rb +15 -2
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
- data/lib/rubocop/cop/style/double_negation.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
- data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +18 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +13 -10
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +6 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +16 -12
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
- data/lib/rubocop/cop/style/unless_else.rb +10 -9
- data/lib/rubocop/cop/utils/format_string.rb +10 -0
- data/lib/rubocop/lsp/diagnostic.rb +21 -20
- data/lib/rubocop/lsp/routes.rb +36 -9
- data/lib/rubocop/lsp/runtime.rb +2 -2
- data/lib/rubocop/lsp/server.rb +2 -2
- data/lib/rubocop/lsp/stdin_runner.rb +0 -16
- data/lib/rubocop/target_ruby.rb +10 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- data/lib/ruby_lsp/rubocop/addon.rb +23 -8
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
- metadata +11 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e194323f7062efb4f5777f4039ff475256dfa86b6e95dd63f42f682b3e59a55
|
4
|
+
data.tar.gz: 533b2e1fe940252958b245c2d492e0e4b39e37babd9e918fbc3ee505faf030ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4bbe12c2a1c627b8f4938a3cc52cd3e4c51ee334b8f1d3b2c373dd109c20741721c090b9152ef2e3f8a908f95c90cc7d8021ba48a1354884361219880153581
|
7
|
+
data.tar.gz: 0ee2973781e011caf6069a9072f8f6a59196d0430fe3d90af740bc2795423d4ead9fc62ddbe11bfe2be8230b769446e734eebcf461c494bb2921a3fb16135c7c
|
data/README.md
CHANGED
@@ -51,7 +51,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
51
51
|
in your `Gemfile`:
|
52
52
|
|
53
53
|
```rb
|
54
|
-
gem 'rubocop', '~> 1.
|
54
|
+
gem 'rubocop', '~> 1.81', require: false
|
55
55
|
```
|
56
56
|
|
57
57
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
data/config/default.yml
CHANGED
@@ -3341,6 +3341,12 @@ Style/ArrayIntersect:
|
|
3341
3341
|
Safe: false
|
3342
3342
|
VersionAdded: '1.40'
|
3343
3343
|
|
3344
|
+
Style/ArrayIntersectWithSingleElement:
|
3345
|
+
Description: 'Use `include?(element)` instead of `intersect?([element])`.'
|
3346
|
+
Enabled: 'pending'
|
3347
|
+
Safe: false
|
3348
|
+
VersionAdded: '1.81'
|
3349
|
+
|
3344
3350
|
Style/ArrayJoin:
|
3345
3351
|
Description: 'Use Array#join instead of Array#*.'
|
3346
3352
|
StyleGuide: '#array-join'
|
@@ -5844,10 +5850,14 @@ Style/TrailingCommaInArguments:
|
|
5844
5850
|
# parenthesized method calls where each argument is on its own line.
|
5845
5851
|
# If `consistent_comma`, the cop requires a comma after the last argument,
|
5846
5852
|
# for all parenthesized method calls with arguments.
|
5853
|
+
# If `diff_comma`, the cop requires a comma after the last argument, but only
|
5854
|
+
# when that argument is followed by an immediate newline, even if
|
5855
|
+
# there is an inline comment.
|
5847
5856
|
EnforcedStyleForMultiline: no_comma
|
5848
5857
|
SupportedStylesForMultiline:
|
5849
5858
|
- comma
|
5850
5859
|
- consistent_comma
|
5860
|
+
- diff_comma
|
5851
5861
|
- no_comma
|
5852
5862
|
|
5853
5863
|
Style/TrailingCommaInArrayLiteral:
|
@@ -83,7 +83,7 @@ module RuboCop
|
|
83
83
|
execute_runner
|
84
84
|
@options.delete(:only)
|
85
85
|
@config_store = ConfigStore.new
|
86
|
-
@config_store.
|
86
|
+
@config_store.apply_options!(@options)
|
87
87
|
# Save the todo configuration of the LineLength cop.
|
88
88
|
File.read(AUTO_GENERATED_FILE).lines.drop_while { |line| line.start_with?('#') }.join
|
89
89
|
end
|
@@ -99,7 +99,7 @@ module RuboCop
|
|
99
99
|
|
100
100
|
def reset_config_and_auto_gen_file
|
101
101
|
@config_store = ConfigStore.new
|
102
|
-
@config_store.
|
102
|
+
@config_store.apply_options!(@options)
|
103
103
|
File.open(AUTO_GENERATED_FILE, 'w') {} # create or truncate if exists
|
104
104
|
add_inheritance_from_auto_generated_file(@options[:config])
|
105
105
|
end
|
data/lib/rubocop/cli.rb
CHANGED
@@ -164,8 +164,7 @@ module RuboCop
|
|
164
164
|
set_options_to_pending_cops_reporter
|
165
165
|
handle_editor_mode
|
166
166
|
|
167
|
-
@config_store.
|
168
|
-
@config_store.force_default_config! if @options[:force_default_config]
|
167
|
+
@config_store.apply_options!(@options)
|
169
168
|
|
170
169
|
handle_exiting_options
|
171
170
|
|
@@ -75,7 +75,9 @@ module RuboCop
|
|
75
75
|
|
76
76
|
puts "configuration from #{absolute_path}" if debug?
|
77
77
|
|
78
|
-
|
78
|
+
unless hash.is_a?(Hash)
|
79
|
+
raise(ValidationError, "Malformed configuration in #{absolute_path}")
|
80
|
+
end
|
79
81
|
|
80
82
|
hash
|
81
83
|
end
|
data/lib/rubocop/config_store.rb
CHANGED
@@ -25,6 +25,11 @@ module RuboCop
|
|
25
25
|
@validated = true
|
26
26
|
end
|
27
27
|
|
28
|
+
def apply_options!(options)
|
29
|
+
self.options_config = options[:config] if options[:config]
|
30
|
+
force_default_config! if options[:force_default_config]
|
31
|
+
end
|
32
|
+
|
28
33
|
def options_config=(options_config)
|
29
34
|
loaded_config = ConfigLoader.load_file(options_config)
|
30
35
|
@options_config = ConfigLoader.merge_with_default(loaded_config, options_config)
|
@@ -35,8 +35,8 @@ module RuboCop
|
|
35
35
|
# `false` is the same as `disabled` for backward compatibility.
|
36
36
|
return false if ['disabled', false].include?(cop_config['AutoCorrect'])
|
37
37
|
|
38
|
-
# When LSP is enabled, it is considered as editing
|
39
|
-
# and autocorrection with `AutoCorrect: contextual` will not be performed.
|
38
|
+
# When LSP is enabled or the `--editor-mode` option is on, it is considered as editing
|
39
|
+
# source code, and autocorrection with `AutoCorrect: contextual` will not be performed.
|
40
40
|
return false if contextual_autocorrect? && LSP.enabled?
|
41
41
|
|
42
42
|
# :safe_autocorrect is a derived option based on several command-line
|
@@ -94,7 +94,7 @@ module RuboCop
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def surrounding_heredoc?(node)
|
97
|
-
node.
|
97
|
+
node.any_str_type? && node.heredoc?
|
98
98
|
end
|
99
99
|
|
100
100
|
def heredoc_range(node)
|
@@ -106,7 +106,7 @@ module RuboCop
|
|
106
106
|
end
|
107
107
|
|
108
108
|
def string_continuation?(node)
|
109
|
-
node.
|
109
|
+
node.any_str_type? && node.source.match?(/\\\s*$/)
|
110
110
|
end
|
111
111
|
|
112
112
|
def multiline_string?(node)
|
@@ -57,7 +57,7 @@ module RuboCop
|
|
57
57
|
def inside_string_ranges(node)
|
58
58
|
return [] unless node.is_a?(Parser::AST::Node)
|
59
59
|
|
60
|
-
node.each_node(:
|
60
|
+
node.each_node(:any_str).filter_map { |n| inside_string_range(n) }
|
61
61
|
end
|
62
62
|
|
63
63
|
def inside_string_range(node)
|
@@ -30,6 +30,8 @@ module RuboCop
|
|
30
30
|
any_block: %i[block numblock itblock],
|
31
31
|
any_def: %i[def defs],
|
32
32
|
any_match_pattern: %i[match_pattern match_pattern_p],
|
33
|
+
any_str: %i[str dstr xstr],
|
34
|
+
any_sym: %i[sym dsym],
|
33
35
|
argument: %i[arg optarg restarg kwarg kwoptarg kwrestarg blockarg forward_arg shadowarg],
|
34
36
|
boolean: %i[true false],
|
35
37
|
call: %i[send csend],
|
@@ -210,7 +212,7 @@ module RuboCop
|
|
210
212
|
# A heredoc can be a `dstr` without interpolation, but if there is interpolation
|
211
213
|
# there'll be a `begin` node, in which case, we cannot evaluate the pattern.
|
212
214
|
def acceptable_heredoc?(node)
|
213
|
-
node.
|
215
|
+
node.any_str_type? && node.heredoc? && node.each_child_node(:begin).none?
|
214
216
|
end
|
215
217
|
|
216
218
|
def process_pattern(pattern_node)
|
@@ -76,7 +76,7 @@ module RuboCop
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def on_send(node) # rubocop:disable InternalAffairs/OnSendWithoutOnCSend
|
79
|
-
new_identifier = node.first_argument
|
79
|
+
return unless (new_identifier = node.first_argument)
|
80
80
|
return unless new_identifier.basic_literal?
|
81
81
|
|
82
82
|
new_identifier = new_identifier.value
|
@@ -76,28 +76,40 @@ module RuboCop
|
|
76
76
|
# # good
|
77
77
|
# class ErrorA < BaseError; end
|
78
78
|
# class ErrorB < BaseError; end
|
79
|
-
# class ErrorC < BaseError; end
|
80
79
|
#
|
81
80
|
# # good
|
82
81
|
# class ErrorA < BaseError; end
|
83
82
|
#
|
84
83
|
# class ErrorB < BaseError; end
|
85
84
|
#
|
86
|
-
#
|
85
|
+
# # good - DefLikeMacros: [memoize]
|
86
|
+
# memoize :attribute_a
|
87
|
+
# memoize :attribute_b
|
88
|
+
#
|
89
|
+
# # good
|
90
|
+
# memoize :attribute_a
|
91
|
+
#
|
92
|
+
# memoize :attribute_b
|
87
93
|
#
|
88
94
|
# @example AllowAdjacentOneLineDefs: false
|
89
95
|
#
|
90
96
|
# # bad
|
91
97
|
# class ErrorA < BaseError; end
|
92
98
|
# class ErrorB < BaseError; end
|
93
|
-
# class ErrorC < BaseError; end
|
94
99
|
#
|
95
100
|
# # good
|
96
101
|
# class ErrorA < BaseError; end
|
97
102
|
#
|
98
103
|
# class ErrorB < BaseError; end
|
99
104
|
#
|
100
|
-
#
|
105
|
+
# # bad - DefLikeMacros: [memoize]
|
106
|
+
# memoize :attribute_a
|
107
|
+
# memoize :attribute_b
|
108
|
+
#
|
109
|
+
# # good
|
110
|
+
# memoize :attribute_a
|
111
|
+
#
|
112
|
+
# memoize :attribute_b
|
101
113
|
#
|
102
114
|
class EmptyLineBetweenDefs < Base
|
103
115
|
include RangeHelp
|
@@ -158,6 +170,8 @@ module RuboCop
|
|
158
170
|
def def_location(correction_node)
|
159
171
|
if correction_node.any_block_type?
|
160
172
|
correction_node.source_range.join(correction_node.children.first.source_range)
|
173
|
+
elsif correction_node.send_type?
|
174
|
+
correction_node.source_range
|
161
175
|
else
|
162
176
|
correction_node.loc.keyword.join(correction_node.loc.name)
|
163
177
|
end
|
@@ -175,8 +189,14 @@ module RuboCop
|
|
175
189
|
end
|
176
190
|
|
177
191
|
def macro_candidate?(node)
|
178
|
-
|
179
|
-
|
192
|
+
macro_candidate = if node.any_block_type?
|
193
|
+
node.send_node
|
194
|
+
elsif node.send_type?
|
195
|
+
node
|
196
|
+
end
|
197
|
+
return false unless macro_candidate
|
198
|
+
|
199
|
+
macro_candidate.macro? && empty_line_between_macros.include?(macro_candidate.method_name)
|
180
200
|
end
|
181
201
|
|
182
202
|
def method_candidate?(node)
|
@@ -240,7 +260,9 @@ module RuboCop
|
|
240
260
|
end
|
241
261
|
|
242
262
|
def def_start(node)
|
243
|
-
|
263
|
+
node = node.send_node if node.any_block_type?
|
264
|
+
|
265
|
+
if node.send_type?
|
244
266
|
node.source_range.line
|
245
267
|
else
|
246
268
|
node.loc.keyword.line
|
@@ -252,11 +274,7 @@ module RuboCop
|
|
252
274
|
end
|
253
275
|
|
254
276
|
def end_loc(node)
|
255
|
-
|
256
|
-
node.source_range.end
|
257
|
-
else
|
258
|
-
node.loc.end
|
259
|
-
end
|
277
|
+
node.source_range.end
|
260
278
|
end
|
261
279
|
|
262
280
|
def autocorrect_remove_lines(corrector, newline_pos, count)
|
@@ -134,6 +134,7 @@ module RuboCop
|
|
134
134
|
|
135
135
|
def check_for_breakable_block(block_node)
|
136
136
|
return unless block_node.single_line?
|
137
|
+
return if receiver_contains_heredoc?(block_node)
|
137
138
|
|
138
139
|
line_index = block_node.loc.line - 1
|
139
140
|
range = breakable_block_range(block_node)
|
@@ -321,7 +322,7 @@ module RuboCop
|
|
321
322
|
def extract_heredocs(ast)
|
322
323
|
return [] unless ast
|
323
324
|
|
324
|
-
ast.each_node(:
|
325
|
+
ast.each_node(:any_str).select(&:heredoc?).map do |node|
|
325
326
|
body = node.location.heredoc_body
|
326
327
|
delimiter = node.location.heredoc_end.source.strip
|
327
328
|
[body.first_line...body.last_line, delimiter]
|
@@ -341,6 +342,13 @@ module RuboCop
|
|
341
342
|
heredocs.any? { |range, _delimiter| range.cover?(line_number) }
|
342
343
|
end
|
343
344
|
|
345
|
+
def receiver_contains_heredoc?(node)
|
346
|
+
return false unless (receiver = node.receiver)
|
347
|
+
return true if receiver.any_str_type? && receiver.heredoc?
|
348
|
+
|
349
|
+
receiver.each_descendant(:any_str).any?(&:heredoc?)
|
350
|
+
end
|
351
|
+
|
344
352
|
def check_directive_line(line, line_index)
|
345
353
|
length_without_directive = line_length_without_directive(line)
|
346
354
|
return if length_without_directive <= max
|
@@ -102,10 +102,12 @@ module RuboCop
|
|
102
102
|
return true if begins_its_line?(assignment_rhs.source_range)
|
103
103
|
end
|
104
104
|
|
105
|
-
given_style == :aligned
|
106
|
-
|
107
|
-
|
108
|
-
|
105
|
+
return false unless given_style == :aligned
|
106
|
+
return true if kw_node_with_special_indentation(node) || assignment_node
|
107
|
+
|
108
|
+
node = argument_in_method_call(node, :with_or_without_parentheses)
|
109
|
+
|
110
|
+
node.respond_to?(:def_modifier?) && !node.def_modifier?
|
109
111
|
end
|
110
112
|
|
111
113
|
def message(node, lhs, rhs)
|
@@ -194,6 +194,14 @@ module RuboCop
|
|
194
194
|
def alignment_location(alignment_node)
|
195
195
|
if begin_end_alignment_style == 'start_of_line'
|
196
196
|
start_line_range(alignment_node)
|
197
|
+
elsif alignment_node.any_block_type?
|
198
|
+
# If the alignment node is a block, the `rescue`/`ensure` keyword should
|
199
|
+
# be aligned to the start of the block. It is possible that the block's
|
200
|
+
# `send_node` spans multiple lines, in which case it should align to the
|
201
|
+
# start of the last line.
|
202
|
+
send_node = alignment_node.send_node
|
203
|
+
range = processed_source.buffer.line_range(send_node.last_line)
|
204
|
+
range.adjust(begin_pos: range.source =~ /\S/)
|
197
205
|
else
|
198
206
|
alignment_node.source_range
|
199
207
|
end
|
@@ -118,8 +118,11 @@ module RuboCop
|
|
118
118
|
|
119
119
|
def replacement_args(node)
|
120
120
|
algorithm_constant, = algorithm_const(node)
|
121
|
-
|
121
|
+
if algorithm_constant.source == 'OpenSSL::Cipher::Cipher'
|
122
|
+
return node.first_argument.source
|
123
|
+
end
|
122
124
|
|
125
|
+
algorithm_name = algorithm_name(algorithm_constant)
|
123
126
|
if openssl_class(algorithm_constant) == 'OpenSSL::Cipher'
|
124
127
|
build_cipher_arguments(node, algorithm_name, node.arguments.empty?)
|
125
128
|
else
|
@@ -125,13 +125,13 @@ module RuboCop
|
|
125
125
|
next false if assignment_node.shorthand_asgn?
|
126
126
|
next false unless assignment_node.parent
|
127
127
|
|
128
|
-
|
129
|
-
|
128
|
+
conditional_assignment =
|
129
|
+
conditional_assignment?(assignment_node.parent, argument.scope.node)
|
130
130
|
|
131
131
|
unless uses_var?(assignment_node, argument.name)
|
132
132
|
# It's impossible to decide whether a branch or block is executed,
|
133
133
|
# so the precise reassignment location is undecidable.
|
134
|
-
next false if
|
134
|
+
next false if conditional_assignment
|
135
135
|
|
136
136
|
yield(assignment.node, location_known)
|
137
137
|
break
|
@@ -147,13 +147,13 @@ module RuboCop
|
|
147
147
|
node.source_range.begin_pos
|
148
148
|
end
|
149
149
|
|
150
|
-
# Check whether the given node is
|
150
|
+
# Check whether the given node is always executed or not
|
151
151
|
#
|
152
|
-
def
|
152
|
+
def conditional_assignment?(node, stop_search_node)
|
153
153
|
return false if node == stop_search_node
|
154
154
|
|
155
|
-
node.conditional? || node.
|
156
|
-
|
155
|
+
node.conditional? || node.type?(:block, :rescue) ||
|
156
|
+
conditional_assignment?(node.parent, stop_search_node)
|
157
157
|
end
|
158
158
|
|
159
159
|
# Get argument references without assignments' references
|
@@ -17,6 +17,7 @@ module RuboCop
|
|
17
17
|
#
|
18
18
|
# # good
|
19
19
|
# CGI.escape('http://example.com')
|
20
|
+
# URI.encode_uri_component(uri) # Since Ruby 3.1
|
20
21
|
# URI.encode_www_form([['example', 'param'], ['lang', 'en']])
|
21
22
|
# URI.encode_www_form(page: 10, locale: 'en')
|
22
23
|
# URI.encode_www_form_component('http://example.com')
|
@@ -27,6 +28,7 @@ module RuboCop
|
|
27
28
|
#
|
28
29
|
# # good
|
29
30
|
# CGI.unescape(enc_uri)
|
31
|
+
# URI.decode_uri_component(uri) # Since Ruby 3.1
|
30
32
|
# URI.decode_www_form(enc_uri)
|
31
33
|
# URI.decode_www_form_component(enc_uri)
|
32
34
|
class UriEscapeUnescape < Base
|
@@ -16,6 +16,12 @@ module RuboCop
|
|
16
16
|
# enumerator.each { |item| item >= 2 } #=> [2, 3]
|
17
17
|
# ----
|
18
18
|
#
|
19
|
+
# NOTE: Return values in assignment method definitions such as `def foo=(arg)` are
|
20
|
+
# detected because they are in a void context. However, autocorrection does not remove
|
21
|
+
# the return value, as that would change behavior. In such cases, whether to remove
|
22
|
+
# the return value or rename the method to something more appropriate should be left to
|
23
|
+
# the user.
|
24
|
+
#
|
19
25
|
# @example CheckForMethodsWithNoSideEffects: false (default)
|
20
26
|
# # bad
|
21
27
|
# def some_method
|
@@ -233,6 +239,7 @@ module RuboCop
|
|
233
239
|
|
234
240
|
def autocorrect_void_expression(corrector, node)
|
235
241
|
return if node.parent.if_type?
|
242
|
+
return if (def_node = node.each_ancestor(:any_def).first) && def_node.assignment_method?
|
236
243
|
|
237
244
|
corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
|
238
245
|
end
|
@@ -140,7 +140,7 @@ module RuboCop
|
|
140
140
|
end
|
141
141
|
|
142
142
|
def last_item_precedes_newline?(node)
|
143
|
-
after_last_item = node.children.last.source_range.end.join(node.
|
143
|
+
after_last_item = node.children.last.source_range.end.join(node.source_range.end)
|
144
144
|
|
145
145
|
after_last_item.source.start_with?(/,?\s*(#.*)?\n/)
|
146
146
|
end
|
@@ -14,7 +14,7 @@ module RuboCop
|
|
14
14
|
# method calls are assumed to return boolean values. The cop does not make an assessment
|
15
15
|
# if the return type is unknown (non-predicate method calls, variables, etc.).
|
16
16
|
#
|
17
|
-
# NOTE:
|
17
|
+
# NOTE: The `initialize` method and operator methods (`def ==`, etc.) are ignored.
|
18
18
|
#
|
19
19
|
# By default, the cop runs in `conservative` mode, which allows a method to be named
|
20
20
|
# with a question mark as long as at least one return value is boolean. In `aggressive`
|
@@ -113,6 +113,18 @@ module RuboCop
|
|
113
113
|
# true
|
114
114
|
# end
|
115
115
|
#
|
116
|
+
# @example AllowedMethods: [call] (default)
|
117
|
+
# # good
|
118
|
+
# def call
|
119
|
+
# foo == bar
|
120
|
+
# end
|
121
|
+
#
|
122
|
+
# @example AllowedPatterns: [\Afoo]
|
123
|
+
# # good
|
124
|
+
# def foo?
|
125
|
+
# 'foo'
|
126
|
+
# end
|
127
|
+
#
|
116
128
|
# @example AllowBangMethods: false (default)
|
117
129
|
# # bad
|
118
130
|
# def save!
|
@@ -149,7 +161,8 @@ module RuboCop
|
|
149
161
|
private
|
150
162
|
|
151
163
|
def allowed?(node)
|
152
|
-
|
164
|
+
node.method?(:initialize) ||
|
165
|
+
allowed_method?(node.method_name) ||
|
153
166
|
matches_allowed_pattern?(node.method_name) ||
|
154
167
|
allowed_bang_method?(node) ||
|
155
168
|
node.operator_method? ||
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Use `include?(element)` instead of `intersect?([element])`.
|
7
|
+
#
|
8
|
+
# @safety
|
9
|
+
# The receiver might not be an array.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# array.intersect?([element])
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# array.include?(element)
|
17
|
+
class ArrayIntersectWithSingleElement < Base
|
18
|
+
extend AutoCorrector
|
19
|
+
|
20
|
+
MSG = 'Use `include?(element)` instead of `intersect?([element])`.'
|
21
|
+
|
22
|
+
RESTRICT_ON_SEND = %i[intersect?].freeze
|
23
|
+
|
24
|
+
# @!method single_element(node)
|
25
|
+
def_node_matcher :single_element, <<~PATTERN
|
26
|
+
(send _ _ $(array $_))
|
27
|
+
PATTERN
|
28
|
+
|
29
|
+
def on_send(node)
|
30
|
+
array, element = single_element(node)
|
31
|
+
return unless array
|
32
|
+
|
33
|
+
add_offense(
|
34
|
+
node.source_range.with(begin_pos: node.loc.selector.begin_pos)
|
35
|
+
) do |corrector|
|
36
|
+
corrector.replace(node.loc.selector, 'include?')
|
37
|
+
corrector.replace(
|
38
|
+
array,
|
39
|
+
array.percent_literal? ? element.value.inspect : element.source
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
alias on_csend on_send
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -43,24 +43,26 @@ module RuboCop
|
|
43
43
|
# @!method nil_check?(node)
|
44
44
|
def_node_matcher :nil_check?, '(send _ :nil?)'
|
45
45
|
|
46
|
+
# rubocop:disable Metrics/AbcSize
|
46
47
|
def on_send(node)
|
47
48
|
return unless node.receiver
|
48
49
|
|
49
50
|
style_check?(node) do
|
50
51
|
add_offense(node.loc.selector) do |corrector|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
52
|
+
if prefer_comparison?
|
53
|
+
range = node.loc.dot.join(node.loc.selector.end)
|
54
|
+
corrector.replace(range, ' == nil')
|
55
|
+
else
|
56
|
+
range = node.receiver.source_range.end.join(node.source_range.end)
|
57
|
+
corrector.replace(range, '.nil?')
|
58
|
+
end
|
58
59
|
|
59
60
|
parent = node.parent
|
60
61
|
corrector.wrap(node, '(', ')') if parent.respond_to?(:method?) && parent.method?(:!)
|
61
62
|
end
|
62
63
|
end
|
63
64
|
end
|
65
|
+
# rubocop:enable Metrics/AbcSize
|
64
66
|
|
65
67
|
private
|
66
68
|
|