rubocop 1.56.3 → 1.56.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/default.yml +1 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +42 -22
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
- data/lib/rubocop/cop/layout/dot_position.rb +1 -5
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +8 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +11 -4
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -2
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/operator_method_call.rb +6 -0
- data/lib/rubocop/cop/style/redundant_conditional.rb +1 -9
- data/lib/rubocop/cop/style/return_nil.rb +6 -2
- data/lib/rubocop/magic_comment.rb +12 -10
- data/lib/rubocop/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3088047e83f70bb0665d28875e2498dce9f6c9066be1524691b3205b155953e
|
4
|
+
data.tar.gz: 37aa8682af6da472cb469924c7a5407b0b947f15a519356dc035f45e4e82982d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d075e0720342cb33925fbbb41d13ddbfe6d060dd92df26890b839e7fb3a65ea6b78e0f0cc42ed31fb038e363e2ec57c5e068e8372ed2e39f48cba2c922bc8e9a
|
7
|
+
data.tar.gz: 7807c06a028201f01c168298f3587160d7d84d7eb8d968b01ecf33772180b8bdeba5dd1fd6a38b60ed54bb259fc306eb46d174baee5f66222986d467b38e2a85
|
data/config/default.yml
CHANGED
@@ -82,7 +82,9 @@ module RuboCop
|
|
82
82
|
node.array_type? && node.percent_literal?
|
83
83
|
end
|
84
84
|
|
85
|
-
percent_array.map(&:source_range).find
|
85
|
+
percent_array.map(&:source_range).find do |range|
|
86
|
+
offense_range.begin_pos > range.begin_pos && range.overlaps?(offense_range)
|
87
|
+
end
|
86
88
|
end
|
87
89
|
|
88
90
|
def range_of_first_line(range)
|
@@ -26,9 +26,7 @@ module RuboCop
|
|
26
26
|
# expect_no_offenses('...')
|
27
27
|
# end
|
28
28
|
class ExampleDescription < Base
|
29
|
-
|
30
|
-
attr_accessor :descriptions
|
31
|
-
end
|
29
|
+
extend AutoCorrector
|
32
30
|
|
33
31
|
MSG = 'Description does not match use of `%<method_name>s`.'
|
34
32
|
|
@@ -39,22 +37,31 @@ module RuboCop
|
|
39
37
|
expect_no_corrections
|
40
38
|
].to_set.freeze
|
41
39
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
40
|
+
EXPECT_NO_OFFENSES_DESCRIPTION_MAPPING = {
|
41
|
+
/\A(adds|registers|reports|finds) (an? )?offense/ => 'does not register an offense',
|
42
|
+
/\A(flags|handles|works)\b/ => 'does not register'
|
43
|
+
}.freeze
|
44
|
+
|
45
|
+
EXPECT_OFFENSE_DESCRIPTION_MAPPING = {
|
46
|
+
/\A(does not|doesn't) (register|find|flag|report)/ => 'registers',
|
47
|
+
/\A(does not|doesn't) add (a|an|any )?offense/ => 'registers an offense',
|
48
|
+
/\Aaccepts\b/ => 'registers'
|
49
|
+
}.freeze
|
46
50
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
/^accepts\b/
|
51
|
-
].freeze
|
51
|
+
EXPECT_NO_CORRECTIONS_DESCRIPTION_MAPPING = {
|
52
|
+
/\A(auto[- ]?)?correct/ => 'does not correct'
|
53
|
+
}.freeze
|
52
54
|
|
53
|
-
|
55
|
+
EXPECT_CORRECTION_DESCRIPTION_MAPPING = {
|
56
|
+
/\b(does not|doesn't) (auto[- ]?)?correct/ => 'autocorrects'
|
57
|
+
}.freeze
|
54
58
|
|
55
|
-
|
56
|
-
|
57
|
-
|
59
|
+
EXAMPLE_DESCRIPTION_MAPPING = {
|
60
|
+
expect_no_offenses: EXPECT_NO_OFFENSES_DESCRIPTION_MAPPING,
|
61
|
+
expect_offense: EXPECT_OFFENSE_DESCRIPTION_MAPPING,
|
62
|
+
expect_no_corrections: EXPECT_NO_CORRECTIONS_DESCRIPTION_MAPPING,
|
63
|
+
expect_correction: EXPECT_CORRECTION_DESCRIPTION_MAPPING
|
64
|
+
}.freeze
|
58
65
|
|
59
66
|
# @!method offense_example?(node)
|
60
67
|
def_node_matcher :offense_example?, <<~PATTERN
|
@@ -67,21 +74,34 @@ module RuboCop
|
|
67
74
|
|
68
75
|
def on_send(node)
|
69
76
|
parent = node.each_ancestor(:block).first
|
70
|
-
return unless parent && (
|
77
|
+
return unless parent && (current_description = offense_example?(parent))
|
71
78
|
|
72
79
|
method_name = node.method_name
|
73
80
|
message = format(MSG, method_name: method_name)
|
74
81
|
|
75
|
-
|
76
|
-
check_description(
|
82
|
+
description_map = EXAMPLE_DESCRIPTION_MAPPING[method_name]
|
83
|
+
check_description(current_description, description_map, message)
|
77
84
|
end
|
78
85
|
|
79
86
|
private
|
80
87
|
|
81
|
-
def check_description(
|
82
|
-
|
88
|
+
def check_description(current_description, description_map, message)
|
89
|
+
description_text = string_contents(current_description)
|
90
|
+
return unless (new_description = correct_description(description_text, description_map))
|
91
|
+
|
92
|
+
add_offense(current_description, message: message) do |corrector|
|
93
|
+
corrector.replace(current_description, "'#{new_description}'")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def correct_description(current_description, description_map)
|
98
|
+
description_map.each do |incorrect_description_pattern, preferred_description|
|
99
|
+
if incorrect_description_pattern.match?(current_description)
|
100
|
+
return current_description.gsub(incorrect_description_pattern, preferred_description)
|
101
|
+
end
|
102
|
+
end
|
83
103
|
|
84
|
-
|
104
|
+
nil
|
85
105
|
end
|
86
106
|
|
87
107
|
def string_contents(node)
|
@@ -32,7 +32,7 @@ module RuboCop
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def on_send(node)
|
35
|
-
return unless node.dot? ||
|
35
|
+
return unless node.dot? || node.safe_navigation?
|
36
36
|
|
37
37
|
return correct_style_detected if proper_dot_position?(node)
|
38
38
|
|
@@ -133,10 +133,6 @@ module RuboCop
|
|
133
133
|
# l.(1) has no selector, so we use the opening parenthesis instead
|
134
134
|
node.loc.selector || node.loc.begin
|
135
135
|
end
|
136
|
-
|
137
|
-
def ampersand_dot?(node)
|
138
|
-
node.loc.respond_to?(:dot) && node.loc.dot && node.loc.dot.is?('&.')
|
139
|
-
end
|
140
136
|
end
|
141
137
|
end
|
142
138
|
end
|
@@ -164,6 +164,8 @@ module RuboCop
|
|
164
164
|
|
165
165
|
if node.if_branch.and_type?
|
166
166
|
node.if_branch.children.first
|
167
|
+
elsif use_heredoc_in_condition?(node.condition)
|
168
|
+
node.condition
|
167
169
|
else
|
168
170
|
node.if_branch.children.last
|
169
171
|
end
|
@@ -180,6 +182,12 @@ module RuboCop
|
|
180
182
|
node.respond_to?(:heredoc?) && node.heredoc?
|
181
183
|
end
|
182
184
|
|
185
|
+
def use_heredoc_in_condition?(condition)
|
186
|
+
condition.descendants.any? do |descendant|
|
187
|
+
descendant.respond_to?(:heredoc?) && descendant.heredoc?
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
183
191
|
def offense_location(node)
|
184
192
|
if node.loc.respond_to?(:end) && node.loc.end
|
185
193
|
node.loc.end
|
@@ -75,7 +75,7 @@ module RuboCop
|
|
75
75
|
def right_hand_side(send_node)
|
76
76
|
dot = send_node.loc.dot
|
77
77
|
selector = send_node.loc.selector
|
78
|
-
if send_node.dot? && selector && same_line?(dot, selector)
|
78
|
+
if (send_node.dot? || send_node.safe_navigation?) && selector && same_line?(dot, selector)
|
79
79
|
dot.join(selector)
|
80
80
|
elsif selector
|
81
81
|
selector
|
@@ -179,7 +179,7 @@ module RuboCop
|
|
179
179
|
# a.b
|
180
180
|
# .c
|
181
181
|
def semantic_alignment_base(node, rhs)
|
182
|
-
return unless rhs.source.start_with?('.')
|
182
|
+
return unless rhs.source.start_with?('.', '&.')
|
183
183
|
|
184
184
|
node = semantic_alignment_node(node)
|
185
185
|
return unless node&.loc&.selector
|
@@ -82,16 +82,23 @@ module RuboCop
|
|
82
82
|
def autocorrect(corrector, offense_range:, send_node:)
|
83
83
|
corrector.replace(
|
84
84
|
offense_range,
|
85
|
-
add_safe_navigation_operator(
|
86
|
-
offense_range: offense_range,
|
87
|
-
send_node: send_node
|
88
|
-
)
|
85
|
+
add_safe_navigation_operator(offense_range: offense_range, send_node: send_node)
|
89
86
|
)
|
87
|
+
|
88
|
+
corrector.wrap(send_node, '(', ')') if require_parentheses?(send_node)
|
90
89
|
end
|
91
90
|
|
92
91
|
def brackets?(send_node)
|
93
92
|
send_node.method?(:[]) || send_node.method?(:[]=)
|
94
93
|
end
|
94
|
+
|
95
|
+
def require_parentheses?(send_node)
|
96
|
+
return false unless send_node.comparison_method?
|
97
|
+
return false unless (node = send_node.parent)
|
98
|
+
|
99
|
+
(node.respond_to?(:logical_operator?) && node.logical_operator?) ||
|
100
|
+
(node.respond_to?(:comparison_method?) && node.comparison_method?)
|
101
|
+
end
|
95
102
|
end
|
96
103
|
end
|
97
104
|
end
|
@@ -20,16 +20,17 @@ module RuboCop
|
|
20
20
|
range = offending_range(node, lhs, rhs, style)
|
21
21
|
check(range, node, lhs, rhs)
|
22
22
|
end
|
23
|
+
alias on_csend on_send
|
23
24
|
|
24
25
|
private
|
25
26
|
|
26
|
-
# In a chain of method calls, we regard the top
|
27
|
+
# In a chain of method calls, we regard the top call node as the base
|
27
28
|
# for indentation of all lines following the first. For example:
|
28
29
|
# a.
|
29
30
|
# b c { block }. <-- b is indented relative to a
|
30
31
|
# d <-- d is indented relative to a
|
31
32
|
def left_hand_side(lhs)
|
32
|
-
while lhs.parent&.
|
33
|
+
while lhs.parent&.call_type? && lhs.parent.loc.dot && !lhs.parent.assignment_method?
|
33
34
|
lhs = lhs.parent
|
34
35
|
end
|
35
36
|
lhs
|
@@ -25,6 +25,7 @@ module RuboCop
|
|
25
25
|
# # bad
|
26
26
|
# items.collect
|
27
27
|
# items.collect!
|
28
|
+
# items.collect_concat
|
28
29
|
# items.inject
|
29
30
|
# items.detect
|
30
31
|
# items.find_all
|
@@ -33,6 +34,7 @@ module RuboCop
|
|
33
34
|
# # good
|
34
35
|
# items.map
|
35
36
|
# items.map!
|
37
|
+
# items.flat_map
|
36
38
|
# items.reduce
|
37
39
|
# items.find
|
38
40
|
# items.select
|
@@ -23,6 +23,7 @@ module RuboCop
|
|
23
23
|
MSG = 'Redundant dot detected.'
|
24
24
|
RESTRICT_ON_SEND = %i[| ^ & <=> == === =~ > >= < <= << >> + - * / % ** ~ ! != !~].freeze
|
25
25
|
|
26
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
26
27
|
def on_send(node)
|
27
28
|
return unless (dot = node.loc.dot)
|
28
29
|
return if node.receiver.const_type? || !node.arguments.one?
|
@@ -33,8 +34,12 @@ module RuboCop
|
|
33
34
|
add_offense(dot) do |corrector|
|
34
35
|
wrap_in_parentheses_if_chained(corrector, node)
|
35
36
|
corrector.replace(dot, ' ')
|
37
|
+
|
38
|
+
selector = node.loc.selector
|
39
|
+
corrector.insert_after(selector, ' ') if selector.end_pos == rhs.source_range.begin_pos
|
36
40
|
end
|
37
41
|
end
|
42
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
38
43
|
|
39
44
|
private
|
40
45
|
|
@@ -54,6 +59,7 @@ module RuboCop
|
|
54
59
|
|
55
60
|
def wrap_in_parentheses_if_chained(corrector, node)
|
56
61
|
return unless node.parent&.call_type?
|
62
|
+
return if node.parent.first_argument == node
|
57
63
|
|
58
64
|
operator = node.loc.selector
|
59
65
|
|
@@ -70,19 +70,11 @@ module RuboCop
|
|
70
70
|
|
71
71
|
def replacement_condition(node)
|
72
72
|
condition = node.condition.source
|
73
|
-
expression =
|
73
|
+
expression = redundant_condition_inverted?(node) ? "!(#{condition})" : condition
|
74
74
|
|
75
75
|
node.elsif? ? indented_else_node(expression, node) : expression
|
76
76
|
end
|
77
77
|
|
78
|
-
def invert_expression?(node)
|
79
|
-
(
|
80
|
-
(node.if? || node.elsif? || node.ternary?) && redundant_condition_inverted?(node)
|
81
|
-
) || (
|
82
|
-
node.unless? && redundant_condition?(node)
|
83
|
-
)
|
84
|
-
end
|
85
|
-
|
86
78
|
def indented_else_node(expression, node)
|
87
79
|
"else\n#{indentation(node)}#{expression}"
|
88
80
|
end
|
@@ -3,9 +3,13 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Enforces consistency between
|
6
|
+
# Enforces consistency between `return nil` and `return`.
|
7
7
|
#
|
8
|
-
#
|
8
|
+
# This cop is disabled by default. Because there seems to be a perceived semantic difference
|
9
|
+
# between `return` and `return nil`. The former can be seen as just halting evaluation,
|
10
|
+
# while the latter might be used when the return value is of specific concern.
|
11
|
+
#
|
12
|
+
# Supported styles are `return` and `return_nil`.
|
9
13
|
#
|
10
14
|
# @example EnforcedStyle: return (default)
|
11
15
|
# # bad
|
@@ -7,7 +7,7 @@ module RuboCop
|
|
7
7
|
class MagicComment
|
8
8
|
# IRB's pattern for matching magic comment tokens.
|
9
9
|
# @see https://github.com/ruby/ruby/blob/b4a55c1/lib/irb/magic-file.rb#L5
|
10
|
-
TOKEN =
|
10
|
+
TOKEN = '(?<token>[[:alnum:]\-_]+)'
|
11
11
|
KEYWORDS = {
|
12
12
|
encoding: '(?:en)?coding',
|
13
13
|
frozen_string_literal: 'frozen[_-]string[_-]literal',
|
@@ -129,7 +129,7 @@ module RuboCop
|
|
129
129
|
# @return [String] if pattern matched
|
130
130
|
# @return [nil] otherwise
|
131
131
|
def extract(pattern)
|
132
|
-
@comment[pattern,
|
132
|
+
@comment[pattern, :token]
|
133
133
|
end
|
134
134
|
|
135
135
|
# Parent to Vim and Emacs magic comment handling.
|
@@ -157,10 +157,10 @@ module RuboCop
|
|
157
157
|
# @return [String] extracted value if it is found
|
158
158
|
# @return [nil] otherwise
|
159
159
|
def match(keyword)
|
160
|
-
pattern = /\A#{keyword}\s*#{self.class::OPERATOR}\s
|
160
|
+
pattern = /\A#{keyword}\s*#{self.class::OPERATOR}\s*#{TOKEN}\z/
|
161
161
|
|
162
162
|
tokens.each do |token|
|
163
|
-
next unless (value = token[pattern,
|
163
|
+
next unless (value = token[pattern, :token])
|
164
164
|
|
165
165
|
return value.downcase
|
166
166
|
end
|
@@ -188,7 +188,7 @@ module RuboCop
|
|
188
188
|
# @see https://www.gnu.org/software/emacs/manual/html_node/emacs/Specify-Coding.html
|
189
189
|
# @see https://github.com/ruby/ruby/blob/3f306dc/parse.y#L6873-L6892 Emacs handling in parse.y
|
190
190
|
class EmacsComment < EditorComment
|
191
|
-
REGEXP = /-\*-(
|
191
|
+
REGEXP = /-\*-(?<token>.+)-\*-/.freeze
|
192
192
|
FORMAT = '# -*- %s -*-'
|
193
193
|
SEPARATOR = ';'
|
194
194
|
OPERATOR = ':'
|
@@ -216,7 +216,7 @@ module RuboCop
|
|
216
216
|
#
|
217
217
|
# comment.encoding # => 'ascii-8bit'
|
218
218
|
class VimComment < EditorComment
|
219
|
-
REGEXP = /#\s*vim:\s*(
|
219
|
+
REGEXP = /#\s*vim:\s*(?<token>.+)/.freeze
|
220
220
|
FORMAT = '# vim: %s'
|
221
221
|
SEPARATOR = ', '
|
222
222
|
OPERATOR = '='
|
@@ -259,9 +259,11 @@ module RuboCop
|
|
259
259
|
# comment2.frozen_string_literal # => nil
|
260
260
|
# comment2.encoding # => 'utf-8'
|
261
261
|
class SimpleComment < MagicComment
|
262
|
+
FSTRING_LITERAL_COMMENT = 'frozen_string_literal:\s*(true|false)'
|
263
|
+
|
262
264
|
# Match `encoding` or `coding`
|
263
265
|
def encoding
|
264
|
-
extract(/\A\s
|
266
|
+
extract(/\A\s*\#\s*(#{FSTRING_LITERAL_COMMENT})?\s*#{KEYWORDS[:encoding]}: (#{TOKEN})/io)
|
265
267
|
end
|
266
268
|
|
267
269
|
# Rewrite the comment without a given token type
|
@@ -283,15 +285,15 @@ module RuboCop
|
|
283
285
|
# Case-insensitive and dashes/underscores are acceptable.
|
284
286
|
# @see https://github.com/ruby/ruby/blob/78b95b4/parse.y#L7134-L7138
|
285
287
|
def extract_frozen_string_literal
|
286
|
-
extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s
|
288
|
+
extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s*#{TOKEN}\s*\z/io)
|
287
289
|
end
|
288
290
|
|
289
291
|
def extract_shareable_constant_value
|
290
|
-
extract(/\A\s*#\s*#{KEYWORDS[:shareable_constant_value]}:\s
|
292
|
+
extract(/\A\s*#\s*#{KEYWORDS[:shareable_constant_value]}:\s*#{TOKEN}\s*\z/io)
|
291
293
|
end
|
292
294
|
|
293
295
|
def extract_typed
|
294
|
-
extract(/\A\s*#\s*#{KEYWORDS[:typed]}:\s
|
296
|
+
extract(/\A\s*#\s*#{KEYWORDS[:typed]}:\s*#{TOKEN}\s*\z/io)
|
295
297
|
end
|
296
298
|
end
|
297
299
|
end
|
data/lib/rubocop/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.56.
|
4
|
+
version: 1.56.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-09-
|
13
|
+
date: 2023-09-28 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: base64
|