rubocop 0.60.0 → 0.61.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 +4 -4
- data/config/default.yml +573 -560
- data/lib/rubocop.rb +5 -0
- data/lib/rubocop/ast/node.rb +1 -1
- data/lib/rubocop/ast/sexp.rb +1 -1
- data/lib/rubocop/cli.rb +9 -14
- data/lib/rubocop/config.rb +4 -3
- data/lib/rubocop/config_loader.rb +25 -22
- data/lib/rubocop/config_loader_resolver.rb +3 -2
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +53 -0
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +73 -0
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +138 -0
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +52 -46
- data/lib/rubocop/cop/generator.rb +13 -17
- data/lib/rubocop/cop/generator/configuration_injector.rb +60 -0
- data/lib/rubocop/cop/layout/align_hash.rb +3 -0
- data/lib/rubocop/cop/layout/comment_indentation.rb +32 -2
- data/lib/rubocop/cop/layout/indent_heredoc.rb +11 -5
- data/lib/rubocop/cop/layout/indentation_width.rb +7 -1
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +11 -11
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +16 -3
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +30 -17
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +11 -0
- data/lib/rubocop/cop/lint/shadowed_exception.rb +2 -5
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -1
- data/lib/rubocop/cop/metrics/line_length.rb +2 -2
- data/lib/rubocop/cop/mixin/trailing_comma.rb +11 -15
- data/lib/rubocop/cop/offense.rb +1 -1
- data/lib/rubocop/cop/performance/open_struct.rb +46 -0
- data/lib/rubocop/cop/performance/redundant_merge.rb +18 -4
- data/lib/rubocop/cop/rails/bulk_change_table.rb +2 -2
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +15 -8
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +17 -14
- data/lib/rubocop/cop/rails/http_status.rb +4 -4
- data/lib/rubocop/cop/rails/inverse_of.rb +2 -2
- data/lib/rubocop/cop/rails/reversible_migration.rb +1 -1
- data/lib/rubocop/cop/rails/skips_model_validations.rb +1 -1
- data/lib/rubocop/cop/rails/validation.rb +4 -4
- data/lib/rubocop/cop/security/open.rb +31 -11
- data/lib/rubocop/cop/style/begin_block.rb +6 -0
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +1 -1
- data/lib/rubocop/cop/style/empty_case_condition.rb +13 -7
- data/lib/rubocop/cop/style/for.rb +9 -78
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +6 -4
- data/lib/rubocop/cop/style/global_vars.rb +1 -1
- data/lib/rubocop/cop/style/infinite_loop.rb +42 -6
- data/lib/rubocop/cop/style/lambda.rb +4 -87
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +221 -16
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/regexp_literal.rb +62 -10
- data/lib/rubocop/cop/style/unneeded_condition.rb +2 -2
- data/lib/rubocop/cop/variable_force.rb +4 -2
- data/lib/rubocop/cop/variable_force/variable.rb +2 -0
- data/lib/rubocop/magic_comment.rb +1 -1
- data/lib/rubocop/remote_config.rb +13 -4
- data/lib/rubocop/rspec/expect_offense.rb +1 -1
- data/lib/rubocop/runner.rb +15 -4
- data/lib/rubocop/version.rb +1 -1
- metadata +7 -2
@@ -3,11 +3,26 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# This cop
|
7
|
-
#
|
8
|
-
#
|
6
|
+
# This cop enforces the presence (default) or absence of parentheses in
|
7
|
+
# method calls containing parameters.
|
8
|
+
#
|
9
|
+
# In the default style (require_parentheses), macro methods are ignored.
|
10
|
+
# Additional methods can be added to the `IgnoredMethods` list. This
|
11
|
+
# option is valid only in the default style.
|
12
|
+
#
|
13
|
+
# In the alternative style (omit_parentheses), there are two additional
|
14
|
+
# options.
|
15
|
+
#
|
16
|
+
# 1. `AllowParenthesesInChaining` is `false` by default. Setting it to
|
17
|
+
# `true` allows the presence of parentheses in the last call during
|
18
|
+
# method chaining.
|
19
|
+
#
|
20
|
+
# 2. `AllowParenthesesInMultilineCall` is `false` by default. Setting it
|
21
|
+
# to `true` allows the presence of parentheses in multi-line method
|
22
|
+
# calls.
|
23
|
+
#
|
24
|
+
# @example EnforcedStyle: require_parentheses
|
9
25
|
#
|
10
|
-
# @example
|
11
26
|
#
|
12
27
|
# # bad
|
13
28
|
# array.delete e
|
@@ -39,21 +54,114 @@ module RuboCop
|
|
39
54
|
# class Foo
|
40
55
|
# bar :baz
|
41
56
|
# end
|
57
|
+
#
|
58
|
+
# @example EnforcedStyle: omit_parentheses
|
59
|
+
#
|
60
|
+
# # bad
|
61
|
+
# array.delete(e)
|
62
|
+
#
|
63
|
+
# # good
|
64
|
+
# array.delete e
|
65
|
+
#
|
66
|
+
# # bad
|
67
|
+
# foo.enforce(strict: true)
|
68
|
+
#
|
69
|
+
# # good
|
70
|
+
# foo.enforce strict: true
|
71
|
+
#
|
72
|
+
# # AllowParenthesesInMultilineCall: false (default)
|
73
|
+
#
|
74
|
+
# # bad
|
75
|
+
# foo.enforce(
|
76
|
+
# strict: true
|
77
|
+
# )
|
78
|
+
#
|
79
|
+
# # good
|
80
|
+
# foo.enforce \
|
81
|
+
# strict: true
|
82
|
+
#
|
83
|
+
# # AllowParenthesesInMultilineCall: true
|
84
|
+
#
|
85
|
+
# # good
|
86
|
+
# foo.enforce(
|
87
|
+
# strict: true
|
88
|
+
# )
|
89
|
+
#
|
90
|
+
# # good
|
91
|
+
# foo.enforce \
|
92
|
+
# strict: true
|
93
|
+
#
|
94
|
+
# # AllowParenthesesInChaining: false (default)
|
95
|
+
#
|
96
|
+
# # bad
|
97
|
+
# foo().bar(1)
|
98
|
+
#
|
99
|
+
# # good
|
100
|
+
# foo().bar 1
|
101
|
+
#
|
102
|
+
# # AllowParenthesesInChaining: true
|
103
|
+
#
|
104
|
+
# # good
|
105
|
+
# foo().bar(1)
|
106
|
+
#
|
107
|
+
# # good
|
108
|
+
# foo().bar 1
|
42
109
|
class MethodCallWithArgsParentheses < Cop
|
110
|
+
include ConfigurableEnforcedStyle
|
43
111
|
include IgnoredMethods
|
44
112
|
|
45
|
-
|
113
|
+
TRAILING_WHITESPACE_REGEX = /\s+\Z/.freeze
|
46
114
|
|
47
115
|
def on_send(node)
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
116
|
+
case style
|
117
|
+
when :require_parentheses
|
118
|
+
add_offense_for_require_parentheses(node)
|
119
|
+
when :omit_parentheses
|
120
|
+
add_offense_for_omit_parentheses(node)
|
121
|
+
end
|
52
122
|
end
|
53
123
|
alias on_super on_send
|
54
124
|
alias on_yield on_send
|
55
125
|
|
56
126
|
def autocorrect(node)
|
127
|
+
case style
|
128
|
+
when :require_parentheses
|
129
|
+
autocorrect_for_require_parentheses(node)
|
130
|
+
when :omit_parentheses
|
131
|
+
autocorrect_for_omit_parentheses(node)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def message(_node = nil)
|
136
|
+
case style
|
137
|
+
when :require_parentheses
|
138
|
+
'Use parentheses for method calls with arguments.'.freeze
|
139
|
+
when :omit_parentheses
|
140
|
+
'Omit parentheses for method calls with arguments.'.freeze
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def add_offense_for_require_parentheses(node)
|
147
|
+
return if ignored_method?(node.method_name)
|
148
|
+
return if eligible_for_parentheses_omission?(node)
|
149
|
+
return unless node.arguments? && !node.parenthesized?
|
150
|
+
|
151
|
+
add_offense(node)
|
152
|
+
end
|
153
|
+
|
154
|
+
def add_offense_for_omit_parentheses(node)
|
155
|
+
return unless node.parenthesized?
|
156
|
+
return if node.implicit_call?
|
157
|
+
return if super_call_without_arguments?(node)
|
158
|
+
return if camel_case_method_call_without_arguments?(node)
|
159
|
+
return if eligible_for_parentheses_presence?(node)
|
160
|
+
|
161
|
+
add_offense(node, location: node.loc.begin.join(node.loc.end))
|
162
|
+
end
|
163
|
+
|
164
|
+
def autocorrect_for_require_parentheses(node)
|
57
165
|
lambda do |corrector|
|
58
166
|
corrector.replace(args_begin(node), '(')
|
59
167
|
|
@@ -63,16 +171,23 @@ module RuboCop
|
|
63
171
|
end
|
64
172
|
end
|
65
173
|
|
66
|
-
|
174
|
+
def autocorrect_for_omit_parentheses(node)
|
175
|
+
lambda do |corrector|
|
176
|
+
if parentheses_at_the_end_of_multiline_call?(node)
|
177
|
+
corrector.replace(args_begin(node), ' \\')
|
178
|
+
else
|
179
|
+
corrector.replace(args_begin(node), ' ')
|
180
|
+
end
|
181
|
+
corrector.remove(node.loc.end)
|
182
|
+
end
|
183
|
+
end
|
67
184
|
|
68
|
-
def
|
69
|
-
node.operator_method? || node.setter_method? ||
|
70
|
-
ignore_macros? && node.macro? ||
|
71
|
-
super(node.method_name)
|
185
|
+
def eligible_for_parentheses_omission?(node)
|
186
|
+
node.operator_method? || node.setter_method? || ignore_macros?(node)
|
72
187
|
end
|
73
188
|
|
74
|
-
def ignore_macros?
|
75
|
-
cop_config['IgnoreMacros']
|
189
|
+
def ignore_macros?(node)
|
190
|
+
cop_config['IgnoreMacros'] && node.macro?
|
76
191
|
end
|
77
192
|
|
78
193
|
def args_begin(node)
|
@@ -94,6 +209,96 @@ module RuboCop
|
|
94
209
|
first_node = node.arguments.first
|
95
210
|
first_node.begin_type? && first_node.parenthesized_call?
|
96
211
|
end
|
212
|
+
|
213
|
+
def parentheses_at_the_end_of_multiline_call?(node)
|
214
|
+
node.multiline? &&
|
215
|
+
node.loc.begin.source_line
|
216
|
+
.gsub(TRAILING_WHITESPACE_REGEX, '')
|
217
|
+
.end_with?('(')
|
218
|
+
end
|
219
|
+
|
220
|
+
def super_call_without_arguments?(node)
|
221
|
+
node.super_type? && node.arguments.none?
|
222
|
+
end
|
223
|
+
|
224
|
+
def camel_case_method_call_without_arguments?(node)
|
225
|
+
node.camel_case_method? && node.arguments.none?
|
226
|
+
end
|
227
|
+
|
228
|
+
def eligible_for_parentheses_presence?(node)
|
229
|
+
call_in_literals?(node) ||
|
230
|
+
call_with_ambiguous_arguments?(node) ||
|
231
|
+
call_in_logical_operators?(node) ||
|
232
|
+
allowed_multiline_call_with_parentheses?(node) ||
|
233
|
+
allowed_chained_call_with_parentheses?(node)
|
234
|
+
end
|
235
|
+
|
236
|
+
def call_in_literals?(node)
|
237
|
+
node.parent &&
|
238
|
+
(node.parent.pair_type? ||
|
239
|
+
node.parent.array_type? ||
|
240
|
+
ternary_if?(node.parent))
|
241
|
+
end
|
242
|
+
|
243
|
+
def call_in_logical_operators?(node)
|
244
|
+
node.parent &&
|
245
|
+
(logical_operator?(node.parent) ||
|
246
|
+
node.parent.descendants.any?(&method(:logical_operator?)))
|
247
|
+
end
|
248
|
+
|
249
|
+
def call_with_ambiguous_arguments?(node)
|
250
|
+
call_with_braced_block?(node) ||
|
251
|
+
call_as_argument?(node) ||
|
252
|
+
hash_literal_in_arguments?(node) ||
|
253
|
+
node.descendants.any? do |n|
|
254
|
+
splat?(n) || ternary_if?(n) || logical_operator?(n)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def call_with_braced_block?(node)
|
259
|
+
node.block_node && node.block_node.braces?
|
260
|
+
end
|
261
|
+
|
262
|
+
def call_as_argument?(node)
|
263
|
+
node.parent && node.parent.send_type?
|
264
|
+
end
|
265
|
+
|
266
|
+
def hash_literal_in_arguments?(node)
|
267
|
+
node.arguments.any? do |n|
|
268
|
+
hash_literal?(n) ||
|
269
|
+
n.send_type? && node.descendants.any?(&method(:hash_literal?))
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def allowed_multiline_call_with_parentheses?(node)
|
274
|
+
cop_config['AllowParenthesesInMultilineCall'] && node.multiline?
|
275
|
+
end
|
276
|
+
|
277
|
+
def allowed_chained_call_with_parentheses?(node)
|
278
|
+
return unless cop_config['AllowParenthesesInChaining']
|
279
|
+
|
280
|
+
previous = node.descendants.first
|
281
|
+
return false unless previous && previous.send_type?
|
282
|
+
|
283
|
+
previous.parenthesized? ||
|
284
|
+
allowed_chained_call_with_parentheses?(previous)
|
285
|
+
end
|
286
|
+
|
287
|
+
def splat?(node)
|
288
|
+
node.splat_type? || node.kwsplat_type? || node.block_pass_type?
|
289
|
+
end
|
290
|
+
|
291
|
+
def ternary_if?(node)
|
292
|
+
node.if_type? && node.ternary?
|
293
|
+
end
|
294
|
+
|
295
|
+
def logical_operator?(node)
|
296
|
+
(node.and_type? || node.or_type?) && node.logical_operator?
|
297
|
+
end
|
298
|
+
|
299
|
+
def hash_literal?(node)
|
300
|
+
node.hash_type? && node.braces?
|
301
|
+
end
|
97
302
|
end
|
98
303
|
end
|
99
304
|
end
|
@@ -83,6 +83,7 @@ module RuboCop
|
|
83
83
|
# x =~ /home\//
|
84
84
|
class RegexpLiteral < Cop
|
85
85
|
include ConfigurableEnforcedStyle
|
86
|
+
include RangeHelp
|
86
87
|
|
87
88
|
MSG_USE_SLASHES = 'Use `//` around regular expression.'.freeze
|
88
89
|
MSG_USE_PERCENT_R = 'Use `%r` around regular expression.'.freeze
|
@@ -96,17 +97,9 @@ module RuboCop
|
|
96
97
|
end
|
97
98
|
|
98
99
|
def autocorrect(node)
|
99
|
-
return if contains_slash?(node)
|
100
|
-
|
101
|
-
replacement = if slash_literal?(node)
|
102
|
-
['%r', ''].zip(preferred_delimiters).map(&:join)
|
103
|
-
else
|
104
|
-
%w[/ /]
|
105
|
-
end
|
106
|
-
|
107
100
|
lambda do |corrector|
|
108
|
-
|
109
|
-
|
101
|
+
correct_delimiters(node, corrector)
|
102
|
+
correct_inner_slashes(node, corrector)
|
110
103
|
end
|
111
104
|
end
|
112
105
|
|
@@ -169,6 +162,65 @@ module RuboCop
|
|
169
162
|
config.for_cop('Style/PercentLiteralDelimiters') \
|
170
163
|
['PreferredDelimiters']['%r'].split(//)
|
171
164
|
end
|
165
|
+
|
166
|
+
def correct_delimiters(node, corrector)
|
167
|
+
replacement = calculate_replacement(node)
|
168
|
+
corrector.replace(node.loc.begin, replacement.first)
|
169
|
+
corrector.replace(node.loc.end, replacement.last)
|
170
|
+
end
|
171
|
+
|
172
|
+
def correct_inner_slashes(node, corrector)
|
173
|
+
regexp_begin = node.loc.begin.end_pos
|
174
|
+
|
175
|
+
inner_slash_indices(node).each do |index|
|
176
|
+
start = regexp_begin + index
|
177
|
+
|
178
|
+
corrector.replace(
|
179
|
+
range_between(
|
180
|
+
start,
|
181
|
+
start + inner_slash_before_correction(node).length
|
182
|
+
),
|
183
|
+
inner_slash_after_correction(node)
|
184
|
+
)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def inner_slash_indices(node)
|
189
|
+
text = node_body(node)
|
190
|
+
pattern = inner_slash_before_correction(node)
|
191
|
+
index = -1
|
192
|
+
indices = []
|
193
|
+
|
194
|
+
while (index = text.index(pattern, index + 1))
|
195
|
+
indices << index
|
196
|
+
end
|
197
|
+
|
198
|
+
indices
|
199
|
+
end
|
200
|
+
|
201
|
+
def inner_slash_before_correction(node)
|
202
|
+
inner_slash_for(node.loc.begin.source)
|
203
|
+
end
|
204
|
+
|
205
|
+
def inner_slash_after_correction(node)
|
206
|
+
inner_slash_for(calculate_replacement(node).first)
|
207
|
+
end
|
208
|
+
|
209
|
+
def inner_slash_for(opening_delimiter)
|
210
|
+
if ['/', '%r/'].include?(opening_delimiter)
|
211
|
+
'\/'
|
212
|
+
else
|
213
|
+
'/'
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def calculate_replacement(node)
|
218
|
+
if slash_literal?(node)
|
219
|
+
['%r', ''].zip(preferred_delimiters).map(&:join)
|
220
|
+
else
|
221
|
+
%w[/ /]
|
222
|
+
end
|
223
|
+
end
|
172
224
|
end
|
173
225
|
end
|
174
226
|
end
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
lambda do |corrector|
|
48
48
|
if node.ternary?
|
49
49
|
corrector.replace(range_of_offense(node), '||')
|
50
|
-
elsif node.modifier_form?
|
50
|
+
elsif node.modifier_form? || !node.else_branch
|
51
51
|
corrector.replace(node.source_range, node.if_branch.source)
|
52
52
|
else
|
53
53
|
corrected = make_ternary_form(node)
|
@@ -60,7 +60,7 @@ module RuboCop
|
|
60
60
|
private
|
61
61
|
|
62
62
|
def message(node)
|
63
|
-
if node.modifier_form?
|
63
|
+
if node.modifier_form? || !node.else_branch
|
64
64
|
UNNEEDED_CONDITION
|
65
65
|
else
|
66
66
|
MSG
|
@@ -50,8 +50,8 @@ module RuboCop
|
|
50
50
|
|
51
51
|
ZERO_ARITY_SUPER_TYPE = :zsuper
|
52
52
|
|
53
|
-
TWISTED_SCOPE_TYPES = %i[block class sclass defs].freeze
|
54
|
-
SCOPE_TYPES = (TWISTED_SCOPE_TYPES +
|
53
|
+
TWISTED_SCOPE_TYPES = %i[block class sclass defs module].freeze
|
54
|
+
SCOPE_TYPES = (TWISTED_SCOPE_TYPES + [:def]).freeze
|
55
55
|
|
56
56
|
SEND_TYPE = :send
|
57
57
|
|
@@ -196,6 +196,7 @@ module RuboCop
|
|
196
196
|
regexp.named_captures.keys
|
197
197
|
end
|
198
198
|
|
199
|
+
# rubocop:disable Metrics/AbcSize
|
199
200
|
def process_variable_operator_assignment(node)
|
200
201
|
if LOGICAL_OPERATOR_ASSIGNMENT_TYPES.include?(node.type)
|
201
202
|
asgn_node, rhs_node = *node
|
@@ -232,6 +233,7 @@ module RuboCop
|
|
232
233
|
|
233
234
|
skip_children!
|
234
235
|
end
|
236
|
+
# rubocop:enable Metrics/AbcSize
|
235
237
|
|
236
238
|
def process_variable_multiple_assignment(node)
|
237
239
|
lhs_node, rhs_node = *node
|
@@ -37,6 +37,7 @@ module RuboCop
|
|
37
37
|
!@references.empty?
|
38
38
|
end
|
39
39
|
|
40
|
+
# rubocop:disable Metrics/AbcSize
|
40
41
|
def reference!(node)
|
41
42
|
reference = Reference.new(node, @scope)
|
42
43
|
@references << reference
|
@@ -56,6 +57,7 @@ module RuboCop
|
|
56
57
|
end
|
57
58
|
end
|
58
59
|
end
|
60
|
+
# rubocop:enable Metrics/AbcSize
|
59
61
|
|
60
62
|
def capture_with_block!
|
61
63
|
@captured_by_block = true
|