rubocop 1.56.3 → 1.57.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 +12 -0
- data/lib/rubocop/cli.rb +1 -1
- 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/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
- data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
- data/lib/rubocop/cop/lint/debugger.rb +10 -1
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +0 -1
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +20 -4
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +11 -4
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +2 -2
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -2
- data/lib/rubocop/cop/style/class_equality_comparison.rb +5 -0
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/format_string.rb +24 -3
- data/lib/rubocop/cop/style/guard_clause.rb +26 -0
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +17 -3
- data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
- data/lib/rubocop/cop/style/operator_method_call.rb +6 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +9 -1
- data/lib/rubocop/cop/style/redundant_conditional.rb +1 -9
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +86 -5
- data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +18 -2
- data/lib/rubocop/cop/style/redundant_parentheses.rb +21 -5
- data/lib/rubocop/cop/style/return_nil.rb +6 -2
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +65 -0
- data/lib/rubocop/magic_comment.rb +12 -10
- data/lib/rubocop/server/cache.rb +1 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- metadata +10 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d38c0bf9376bd86de4bdf5561b74b11e895bc90ac263a8c29520afec2fb7d0b0
|
4
|
+
data.tar.gz: 5e624dd813953b2058306d07986c19d55fa170fa8f3960844c4d62f2f87b3277
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dee188b376a118be4c08956361312fc91bf4e55cdadfa8129611f8a3b19fef80fb8241658778a5f6fb042336ba4137c6c64d2a65189ad00567730934e3dcde74
|
7
|
+
data.tar.gz: 4dbf33a643a4f945d3564426b49338d463a55e734812d8c3113df04aa430577c2142b7685990bdd12915e537a1add4b181dd96488632dd89a544a33c5f712944
|
data/README.md
CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
53
53
|
in your `Gemfile`:
|
54
54
|
|
55
55
|
```rb
|
56
|
-
gem 'rubocop', '~> 1.
|
56
|
+
gem 'rubocop', '~> 1.57', require: false
|
57
57
|
```
|
58
58
|
|
59
59
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
data/config/default.yml
CHANGED
@@ -2170,7 +2170,9 @@ Lint/RedundantRegexpQuantifiers:
|
|
2170
2170
|
Lint/RedundantRequireStatement:
|
2171
2171
|
Description: 'Checks for unnecessary `require` statement.'
|
2172
2172
|
Enabled: true
|
2173
|
+
SafeAutoCorrect: false
|
2173
2174
|
VersionAdded: '0.76'
|
2175
|
+
VersionChanged: '1.57'
|
2174
2176
|
|
2175
2177
|
Lint/RedundantSafeNavigation:
|
2176
2178
|
Description: 'Checks for redundant safe navigation calls.'
|
@@ -3354,7 +3356,9 @@ Style/ClassEqualityComparison:
|
|
3354
3356
|
Description: 'Enforces the use of `Object#instance_of?` instead of class comparison for equality.'
|
3355
3357
|
StyleGuide: '#instance-of-vs-class-comparison'
|
3356
3358
|
Enabled: true
|
3359
|
+
SafeAutoCorrect: false
|
3357
3360
|
VersionAdded: '0.93'
|
3361
|
+
VersionChanged: '1.57'
|
3358
3362
|
AllowedMethods:
|
3359
3363
|
- ==
|
3360
3364
|
- equal?
|
@@ -3409,6 +3413,7 @@ Style/CollectionMethods:
|
|
3409
3413
|
PreferredMethods:
|
3410
3414
|
collect: 'map'
|
3411
3415
|
collect!: 'map!'
|
3416
|
+
collect_concat: 'flat_map'
|
3412
3417
|
inject: 'reduce'
|
3413
3418
|
detect: 'find'
|
3414
3419
|
find_all: 'select'
|
@@ -4919,7 +4924,9 @@ Style/RedundantFilterChain:
|
|
4919
4924
|
Identifies usages of `any?`, `empty?`, `none?` or `one?` predicate methods chained to
|
4920
4925
|
`select`/`filter`/`find_all` and change them to use predicate method instead.
|
4921
4926
|
Enabled: pending
|
4927
|
+
SafeAutoCorrect: false
|
4922
4928
|
VersionAdded: '1.52'
|
4929
|
+
VersionChanged: '1.57'
|
4923
4930
|
|
4924
4931
|
Style/RedundantFreeze:
|
4925
4932
|
Description: "Checks usages of Object#freeze on immutable objects."
|
@@ -5181,6 +5188,11 @@ Style/SingleLineBlockParams:
|
|
5181
5188
|
- acc
|
5182
5189
|
- elem
|
5183
5190
|
|
5191
|
+
Style/SingleLineDoEndBlock:
|
5192
|
+
Description: 'Checks for single-line `do`...`end` blocks.'
|
5193
|
+
Enabled: pending
|
5194
|
+
VersionAdded: '1.57'
|
5195
|
+
|
5184
5196
|
Style/SingleLineMethods:
|
5185
5197
|
Description: 'Avoid single-line methods.'
|
5186
5198
|
StyleGuide: '#no-single-line-methods'
|
data/lib/rubocop/cli.rb
CHANGED
@@ -11,7 +11,7 @@ module RuboCop
|
|
11
11
|
STATUS_ERROR = 2
|
12
12
|
STATUS_INTERRUPTED = Signal.list['INT'] + 128
|
13
13
|
DEFAULT_PARALLEL_OPTIONS = %i[
|
14
|
-
color debug display_style_guide display_time display_only_fail_level_offenses
|
14
|
+
color config debug display_style_guide display_time display_only_fail_level_offenses
|
15
15
|
display_only_failed except extra_details fail_level fix_layout format
|
16
16
|
ignore_disable_comments lint only only_guide_cops require safe
|
17
17
|
autocorrect safe_autocorrect autocorrect_all
|
@@ -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
|
@@ -354,7 +354,7 @@ module RuboCop
|
|
354
354
|
# Don't check indentation if the line doesn't start with the body.
|
355
355
|
# For example, lines like "else do_something".
|
356
356
|
first_char_pos_on_line = body_node.source_range.source_line =~ /\S/
|
357
|
-
|
357
|
+
body_node.loc.column != first_char_pos_on_line
|
358
358
|
end
|
359
359
|
|
360
360
|
def offending_range(body_node, indentation)
|
@@ -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,10 +179,10 @@ 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
|
-
return unless node&.loc&.selector
|
185
|
+
return unless node&.loc&.selector && node.loc.dot
|
186
186
|
|
187
187
|
node.loc.dot.join(node.loc.selector)
|
188
188
|
end
|
@@ -204,6 +204,10 @@ module RuboCop
|
|
204
204
|
dot_right_above = get_dot_right_above(node)
|
205
205
|
return dot_right_above if dot_right_above
|
206
206
|
|
207
|
+
if (multiline_block_chain_node = find_multiline_block_chain_node(node))
|
208
|
+
return multiline_block_chain_node
|
209
|
+
end
|
210
|
+
|
207
211
|
node = first_call_has_a_dot(node)
|
208
212
|
return if node.loc.dot.line != node.first_line
|
209
213
|
|
@@ -219,6 +223,17 @@ module RuboCop
|
|
219
223
|
end
|
220
224
|
end
|
221
225
|
|
226
|
+
def find_multiline_block_chain_node(node)
|
227
|
+
return unless (block_node = node.each_descendant(:block, :numblock).first)
|
228
|
+
return unless block_node.multiline? && block_node.parent.call_type?
|
229
|
+
|
230
|
+
if node.receiver.call_type?
|
231
|
+
node.receiver
|
232
|
+
else
|
233
|
+
block_node.parent
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
222
237
|
def first_call_has_a_dot(node)
|
223
238
|
# descend to root of method chain
|
224
239
|
node = node.receiver while node.receiver
|
@@ -168,7 +168,7 @@ module RuboCop
|
|
168
168
|
# follows, and that the rules for space inside don't apply.
|
169
169
|
return true if token2.comment?
|
170
170
|
|
171
|
-
|
171
|
+
!same_line?(token1, token2) || token1.space_after?
|
172
172
|
end
|
173
173
|
end
|
174
174
|
end
|
@@ -95,8 +95,11 @@ module RuboCop
|
|
95
95
|
def assumed_usage_context?(node)
|
96
96
|
# Basically, debugger methods are not used as a method argument without arguments.
|
97
97
|
return false unless node.arguments.empty? && node.each_ancestor(:send, :csend).any?
|
98
|
+
return true if assumed_argument?(node)
|
98
99
|
|
99
|
-
node.each_ancestor.none?
|
100
|
+
node.each_ancestor.none? do |ancestor|
|
101
|
+
ancestor.block_type? || ancestor.numblock_type? || ancestor.lambda_or_proc?
|
102
|
+
end
|
100
103
|
end
|
101
104
|
|
102
105
|
def chained_method_name(send_node)
|
@@ -109,6 +112,12 @@ module RuboCop
|
|
109
112
|
end
|
110
113
|
chained_method_name
|
111
114
|
end
|
115
|
+
|
116
|
+
def assumed_argument?(node)
|
117
|
+
parent = node.parent
|
118
|
+
|
119
|
+
parent.call_type? || parent.literal? || parent.pair_type?
|
120
|
+
end
|
112
121
|
end
|
113
122
|
end
|
114
123
|
end
|
@@ -5,7 +5,7 @@ module RuboCop
|
|
5
5
|
module Lint
|
6
6
|
# Checks for blocks without a body.
|
7
7
|
# Such empty blocks are typically an oversight or we should provide a comment
|
8
|
-
#
|
8
|
+
# to clarify what we're aiming for.
|
9
9
|
#
|
10
10
|
# Empty lambdas and procs are ignored by default.
|
11
11
|
#
|
@@ -34,7 +34,7 @@ module RuboCop
|
|
34
34
|
# interpolation should not be removed if the expanded value
|
35
35
|
# contains a space character.
|
36
36
|
expanded_value = autocorrected_value(final_node)
|
37
|
-
return if in_array_percent_literal?(begin_node) && /\s/.match?(expanded_value)
|
37
|
+
return if in_array_percent_literal?(begin_node) && /\s|\A\z/.match?(expanded_value)
|
38
38
|
|
39
39
|
add_offense(final_node) do |corrector|
|
40
40
|
return if final_node.dstr_type? # nested, fixed in next iteration
|
@@ -24,6 +24,10 @@ module RuboCop
|
|
24
24
|
#
|
25
25
|
# This cop target those features.
|
26
26
|
#
|
27
|
+
# @safety
|
28
|
+
# This cop's autocorrection is unsafe because if `require 'pp'` is removed from one file,
|
29
|
+
# `NameError` can be encountered when another file uses `PP.pp`.
|
30
|
+
#
|
27
31
|
# @example
|
28
32
|
# # bad
|
29
33
|
# require 'unloaded_feature'
|
@@ -4,8 +4,12 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Lint
|
6
6
|
# Checks for redundant safe navigation calls.
|
7
|
-
#
|
8
|
-
#
|
7
|
+
# Use cases where a constant, named in camel case for classes and modules is `nil` are rare,
|
8
|
+
# and an offense is not detected when the receiver is a snake case constant.
|
9
|
+
#
|
10
|
+
# For all receivers, the `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`,
|
11
|
+
# and `equal?` methods are checked by default.
|
12
|
+
# These are customizable with `AllowedMethods` option.
|
9
13
|
#
|
10
14
|
# The `AllowedMethods` option specifies nil-safe methods,
|
11
15
|
# in other words, it is a method that is allowed to skip safe navigation.
|
@@ -22,6 +26,9 @@ module RuboCop
|
|
22
26
|
#
|
23
27
|
# @example
|
24
28
|
# # bad
|
29
|
+
# CamelCaseConst&.do_something
|
30
|
+
#
|
31
|
+
# # bad
|
25
32
|
# do_something if attrs&.respond_to?(:[])
|
26
33
|
#
|
27
34
|
# # good
|
@@ -33,6 +40,9 @@ module RuboCop
|
|
33
40
|
# end
|
34
41
|
#
|
35
42
|
# # good
|
43
|
+
# CamelCaseConst.do_something
|
44
|
+
#
|
45
|
+
# # good
|
36
46
|
# while node.is_a?(BeginNode)
|
37
47
|
# node = node.parent
|
38
48
|
# end
|
@@ -57,18 +67,24 @@ module RuboCop
|
|
57
67
|
|
58
68
|
NIL_SPECIFIC_METHODS = (nil.methods - Object.new.methods).to_set.freeze
|
59
69
|
|
70
|
+
SNAKE_CASE = /\A[[:digit:][:upper:]_]+\z/.freeze
|
71
|
+
|
60
72
|
# @!method respond_to_nil_specific_method?(node)
|
61
73
|
def_node_matcher :respond_to_nil_specific_method?, <<~PATTERN
|
62
74
|
(csend _ :respond_to? (sym %NIL_SPECIFIC_METHODS))
|
63
75
|
PATTERN
|
64
76
|
|
77
|
+
# rubocop:disable Metrics/AbcSize
|
65
78
|
def on_csend(node)
|
66
|
-
|
67
|
-
|
79
|
+
unless node.receiver.const_type? && !node.receiver.source.match?(SNAKE_CASE)
|
80
|
+
return unless check?(node) && allowed_method?(node.method_name)
|
81
|
+
return if respond_to_nil_specific_method?(node)
|
82
|
+
end
|
68
83
|
|
69
84
|
range = range_between(node.loc.dot.begin_pos, node.source_range.end_pos)
|
70
85
|
add_offense(range) { |corrector| corrector.replace(node.loc.dot, '.') }
|
71
86
|
end
|
87
|
+
# rubocop:enable Metrics/AbcSize
|
72
88
|
|
73
89
|
private
|
74
90
|
|
@@ -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
|
@@ -12,6 +12,7 @@ module RuboCop
|
|
12
12
|
# Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
|
13
13
|
# will be counted as one line regardless of its actual size.
|
14
14
|
#
|
15
|
+
# NOTE: This cop does not apply for `Struct` definitions.
|
15
16
|
#
|
16
17
|
# NOTE: The `ExcludedMethods` configuration is deprecated and only kept
|
17
18
|
# for backwards compatibility. Please use `AllowedMethods` and `AllowedPatterns`
|
@@ -40,7 +41,6 @@ module RuboCop
|
|
40
41
|
# )
|
41
42
|
# end # 6 points
|
42
43
|
#
|
43
|
-
# NOTE: This cop does not apply for `Struct` definitions.
|
44
44
|
class BlockLength < Base
|
45
45
|
include CodeLength
|
46
46
|
include AllowedMethods
|
@@ -11,6 +11,8 @@ module RuboCop
|
|
11
11
|
# Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
|
12
12
|
# will be counted as one line regardless of its actual size.
|
13
13
|
#
|
14
|
+
# NOTE: This cop also applies for `Struct` definitions.
|
15
|
+
#
|
14
16
|
# @example CountAsOne: ['array', 'heredoc', 'method_call']
|
15
17
|
#
|
16
18
|
# class Foo
|
@@ -34,8 +36,6 @@ module RuboCop
|
|
34
36
|
# )
|
35
37
|
# end # 6 points
|
36
38
|
#
|
37
|
-
#
|
38
|
-
# NOTE: This cop also applies for `Struct` definitions.
|
39
39
|
class ClassLength < Base
|
40
40
|
include CodeLength
|
41
41
|
|
@@ -10,7 +10,7 @@ module RuboCop
|
|
10
10
|
include Util
|
11
11
|
|
12
12
|
FOLDABLE_TYPES = %i[array hash heredoc send csend].freeze
|
13
|
-
CLASSLIKE_TYPES = %i[class module
|
13
|
+
CLASSLIKE_TYPES = %i[class module].freeze
|
14
14
|
private_constant :FOLDABLE_TYPES, :CLASSLIKE_TYPES
|
15
15
|
|
16
16
|
def initialize(node, processed_source, count_comments: false, foldable_types: [])
|
@@ -145,7 +145,7 @@ module RuboCop
|
|
145
145
|
|
146
146
|
def extract_body(node)
|
147
147
|
case node.type
|
148
|
-
when :class, :module, :block, :numblock, :def, :defs
|
148
|
+
when :class, :module, :sclass, :block, :numblock, :def, :defs
|
149
149
|
node.body
|
150
150
|
when :casgn
|
151
151
|
_scope, _name, value = *node
|
@@ -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
|
@@ -8,6 +8,11 @@ module RuboCop
|
|
8
8
|
# `==`, `equal?`, and `eql?` custom method definitions are allowed by default.
|
9
9
|
# These are customizable with `AllowedMethods` option.
|
10
10
|
#
|
11
|
+
# @safety
|
12
|
+
# This cop's autocorrection is unsafe because there is no guarantee that
|
13
|
+
# the constant `Foo` exists when autocorrecting `var.class.name == 'Foo'` to
|
14
|
+
# `var.instance_of?(Foo)`.
|
15
|
+
#
|
11
16
|
# @example
|
12
17
|
# # bad
|
13
18
|
# var.class == Date
|
@@ -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
|
@@ -4,13 +4,25 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# Enforces the use of a single string formatting utility.
|
7
|
-
# Valid options include Kernel#format
|
7
|
+
# Valid options include `Kernel#format`, `Kernel#sprintf`, and `String#%`.
|
8
8
|
#
|
9
|
-
# The detection of String
|
9
|
+
# The detection of `String#%` cannot be implemented in a reliable
|
10
10
|
# manner for all cases, so only two scenarios are considered -
|
11
11
|
# if the first argument is a string literal and if the second
|
12
12
|
# argument is an array literal.
|
13
13
|
#
|
14
|
+
# Autocorrection will be applied when using argument is a literal or known built-in conversion
|
15
|
+
# methods such as `to_d`, `to_f`, `to_h`, `to_i`, `to_r`, `to_s`, and `to_sym` on variables,
|
16
|
+
# provided that their return value is not an array. For example, when using `to_s`,
|
17
|
+
# `'%s' % [1, 2, 3].to_s` can be autocorrected without any incompatibility:
|
18
|
+
#
|
19
|
+
# [source,ruby]
|
20
|
+
# ----
|
21
|
+
# '%s' % [1, 2, 3] #=> '1'
|
22
|
+
# format('%s', [1, 2, 3]) #=> '[1, 2, 3]'
|
23
|
+
# '%s' % [1, 2, 3].to_s #=> '[1, 2, 3]'
|
24
|
+
# ----
|
25
|
+
#
|
14
26
|
# @example EnforcedStyle: format (default)
|
15
27
|
# # bad
|
16
28
|
# puts sprintf('%10s', 'hoge')
|
@@ -42,6 +54,9 @@ module RuboCop
|
|
42
54
|
MSG = 'Favor `%<prefer>s` over `%<current>s`.'
|
43
55
|
RESTRICT_ON_SEND = %i[format sprintf %].freeze
|
44
56
|
|
57
|
+
# Known conversion methods whose return value is not an array.
|
58
|
+
AUTOCORRECTABLE_METHODS = %i[to_d to_f to_h to_i to_r to_s to_sym].freeze
|
59
|
+
|
45
60
|
# @!method formatter(node)
|
46
61
|
def_node_matcher :formatter, <<~PATTERN
|
47
62
|
{
|
@@ -53,7 +68,7 @@ module RuboCop
|
|
53
68
|
|
54
69
|
# @!method variable_argument?(node)
|
55
70
|
def_node_matcher :variable_argument?, <<~PATTERN
|
56
|
-
(send {str dstr} :%
|
71
|
+
(send {str dstr} :% #autocorrectable?)
|
57
72
|
PATTERN
|
58
73
|
|
59
74
|
def on_send(node)
|
@@ -70,6 +85,12 @@ module RuboCop
|
|
70
85
|
|
71
86
|
private
|
72
87
|
|
88
|
+
def autocorrectable?(node)
|
89
|
+
return true if node.lvar_type?
|
90
|
+
|
91
|
+
node.send_type? && !AUTOCORRECTABLE_METHODS.include?(node.method_name)
|
92
|
+
end
|
93
|
+
|
73
94
|
def message(detected_style)
|
74
95
|
format(MSG, prefer: method_name(style), current: method_name(detected_style))
|
75
96
|
end
|