rubocop 0.40.0 → 0.41.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +7 -1014
- data/config/default.yml +61 -5
- data/config/disabled.yml +6 -0
- data/config/enabled.yml +63 -4
- data/lib/rubocop.rb +17 -1
- data/lib/rubocop/ast_node.rb +56 -42
- data/lib/rubocop/ast_node/traversal.rb +3 -3
- data/lib/rubocop/cli.rb +14 -9
- data/lib/rubocop/comment_config.rb +85 -32
- data/lib/rubocop/config.rb +29 -8
- data/lib/rubocop/config_loader.rb +1 -1
- data/lib/rubocop/cop/cop.rb +1 -1
- data/lib/rubocop/cop/corrector.rb +13 -0
- data/lib/rubocop/cop/lint/block_alignment.rb +25 -11
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +5 -2
- data/lib/rubocop/cop/lint/inherit_exception.rb +69 -0
- data/lib/rubocop/cop/lint/percent_string_array.rb +60 -0
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +57 -0
- data/lib/rubocop/cop/lint/shadowed_exception.rb +95 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +28 -13
- data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +25 -19
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +16 -8
- data/lib/rubocop/cop/mixin/if_node.rb +1 -2
- data/lib/rubocop/cop/mixin/integer_node.rb +13 -0
- data/lib/rubocop/cop/mixin/match_range.rb +26 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +16 -7
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +18 -1
- data/lib/rubocop/cop/mixin/negative_conditional.rb +6 -4
- data/lib/rubocop/cop/mixin/percent_literal.rb +10 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +24 -6
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +20 -7
- data/lib/rubocop/cop/mixin/string_literals_help.rb +2 -2
- data/lib/rubocop/cop/mixin/trailing_comma.rb +34 -20
- data/lib/rubocop/cop/performance/flat_map.rb +23 -10
- data/lib/rubocop/cop/performance/push_splat.rb +47 -0
- data/lib/rubocop/cop/performance/redundant_block_call.rb +24 -1
- data/lib/rubocop/cop/performance/redundant_merge.rb +3 -5
- data/lib/rubocop/cop/performance/sample.rb +15 -11
- data/lib/rubocop/cop/rails/exit.rb +62 -0
- data/lib/rubocop/cop/rails/output_safety.rb +45 -0
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +12 -4
- data/lib/rubocop/cop/rails/request_referer.rb +40 -0
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +63 -28
- data/lib/rubocop/cop/rails/validation.rb +37 -23
- data/lib/rubocop/cop/style/alias.rb +10 -6
- data/lib/rubocop/cop/style/bare_percent_literals.rb +18 -7
- data/lib/rubocop/cop/style/block_delimiters.rb +15 -22
- data/lib/rubocop/cop/style/closing_parenthesis_indentation.rb +19 -8
- data/lib/rubocop/cop/style/comment_indentation.rb +13 -5
- data/lib/rubocop/cop/style/conditional_assignment.rb +111 -59
- data/lib/rubocop/cop/style/documentation.rb +7 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +43 -0
- data/lib/rubocop/cop/style/each_with_object.rb +25 -14
- data/lib/rubocop/cop/style/empty_else.rb +6 -10
- data/lib/rubocop/cop/style/extra_spacing.rb +20 -3
- data/lib/rubocop/cop/style/file_name.rb +16 -4
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +9 -2
- data/lib/rubocop/cop/style/if_unless_modifier.rb +20 -13
- data/lib/rubocop/cop/style/implicit_runtime_error.rb +32 -0
- data/lib/rubocop/cop/style/infinite_loop.rb +42 -5
- data/lib/rubocop/cop/style/lambda.rb +22 -0
- data/lib/rubocop/cop/style/method_def_parentheses.rb +12 -4
- data/lib/rubocop/cop/style/module_function.rb +28 -6
- data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +49 -12
- data/lib/rubocop/cop/style/mutable_constant.rb +8 -1
- data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
- data/lib/rubocop/cop/style/next.rb +43 -31
- data/lib/rubocop/cop/style/not.rb +33 -13
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +92 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +1 -4
- data/lib/rubocop/cop/style/parallel_assignment.rb +26 -8
- data/lib/rubocop/cop/style/{deprecated_hash_methods.rb → preferred_hash_methods.rb} +8 -8
- data/lib/rubocop/cop/style/redundant_parentheses.rb +29 -19
- data/lib/rubocop/cop/style/redundant_self.rb +13 -6
- data/lib/rubocop/cop/style/space_after_not.rb +7 -5
- data/lib/rubocop/cop/style/space_around_keyword.rb +6 -0
- data/lib/rubocop/cop/style/space_around_operators.rb +5 -1
- data/lib/rubocop/cop/style/space_before_first_arg.rb +21 -9
- data/lib/rubocop/cop/style/space_inside_array_percent_literal.rb +53 -0
- data/lib/rubocop/cop/style/space_inside_block_braces.rb +2 -2
- data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +26 -6
- data/lib/rubocop/cop/style/space_inside_percent_literal_delimiters.rb +64 -0
- data/lib/rubocop/cop/style/string_literals.rb +37 -8
- data/lib/rubocop/cop/style/symbol_array.rb +21 -12
- data/lib/rubocop/cop/style/symbol_proc.rb +26 -19
- data/lib/rubocop/cop/style/word_array.rb +1 -5
- data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -6
- data/lib/rubocop/cop/team.rb +40 -27
- data/lib/rubocop/cop/util.rb +13 -42
- data/lib/rubocop/formatter/disabled_config_formatter.rb +37 -14
- data/lib/rubocop/formatter/html_formatter.rb +3 -7
- data/lib/rubocop/result_cache.rb +18 -4
- data/{spec/support → lib/rubocop/rspec}/cop_helper.rb +3 -0
- data/lib/rubocop/rspec/host_environment_simulation_helper.rb +33 -0
- data/lib/rubocop/rspec/shared_contexts.rb +75 -0
- data/lib/rubocop/rspec/shared_examples.rb +101 -0
- data/lib/rubocop/rspec/support.rb +9 -0
- data/lib/rubocop/runner.rb +2 -2
- data/lib/rubocop/string_interpreter.rb +58 -0
- data/lib/rubocop/version.rb +1 -1
- metadata +27 -7
@@ -30,7 +30,14 @@ module RuboCop
|
|
30
30
|
|
31
31
|
def autocorrect(node)
|
32
32
|
expr = node.source_range
|
33
|
-
|
33
|
+
lambda do |corrector|
|
34
|
+
if node.array_type? && node.loc.begin.nil? && node.loc.end.nil?
|
35
|
+
corrector.insert_before(expr, '[')
|
36
|
+
corrector.insert_after(expr, '].freeze')
|
37
|
+
else
|
38
|
+
corrector.insert_after(expr, '.freeze')
|
39
|
+
end
|
40
|
+
end
|
34
41
|
end
|
35
42
|
|
36
43
|
private
|
@@ -81,18 +81,22 @@ module RuboCop
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def simple_if_without_break?(node)
|
84
|
-
return false unless node
|
85
|
-
return false if ternary?(node)
|
86
|
-
return false if if_else?(node)
|
84
|
+
return false unless if_without_else?(node)
|
87
85
|
return false if style == :skip_modifier_ifs && modifier_if?(node)
|
88
86
|
return false if !modifier_if?(node) && !min_body_length?(node)
|
89
87
|
|
90
|
-
|
91
|
-
|
88
|
+
!exit_body_type?(node)
|
89
|
+
end
|
90
|
+
|
91
|
+
def if_without_else?(node)
|
92
|
+
node.if_type? && !ternary?(node) && !if_else?(node)
|
93
|
+
end
|
94
|
+
|
95
|
+
def exit_body_type?(node)
|
92
96
|
_conditional, if_body, _else_body = *node
|
93
|
-
return
|
97
|
+
return false unless if_body
|
94
98
|
|
95
|
-
|
99
|
+
EXIT_TYPES.include?(if_body.type)
|
96
100
|
end
|
97
101
|
|
98
102
|
def offense_node(body)
|
@@ -135,10 +139,10 @@ module RuboCop
|
|
135
139
|
corrector.remove(cond_range(node, cond))
|
136
140
|
corrector.remove(end_range(node))
|
137
141
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
reindent(
|
142
|
+
lines = reindentable_lines(node)
|
143
|
+
return if lines.empty?
|
144
|
+
|
145
|
+
reindent(lines, cond, corrector)
|
142
146
|
end
|
143
147
|
|
144
148
|
def opposite_kw(if_body)
|
@@ -170,42 +174,50 @@ module RuboCop
|
|
170
174
|
source_buffer.source[end_pos..-1] =~ /\A\s*$/
|
171
175
|
end
|
172
176
|
|
177
|
+
def reindentable_lines(node)
|
178
|
+
buffer = node.source_range.source_buffer
|
179
|
+
|
180
|
+
# end_range starts with the final newline of the if body
|
181
|
+
lines = (node.source_range.line + 1)...node.loc.end.line
|
182
|
+
lines = lines.to_a - heredoc_lines(node)
|
183
|
+
# Skip blank lines
|
184
|
+
lines.reject { |lineno| buffer.source_line(lineno) =~ /\A\s*\z/ }
|
185
|
+
end
|
186
|
+
|
173
187
|
# Adjust indentation of `lines` to match `node`
|
174
188
|
def reindent(lines, node, corrector)
|
175
189
|
range = node.source_range
|
176
190
|
buffer = range.source_buffer
|
177
191
|
|
178
192
|
target_indent = range.source_line =~ /\S/
|
179
|
-
|
180
|
-
# Skip blank lines
|
181
|
-
lines.reject! { |lineno| buffer.source_line(lineno) =~ /\A\s*\z/ }
|
182
|
-
return if lines.empty?
|
183
|
-
|
184
|
-
actual_indent = lines.map do |lineno|
|
185
|
-
buffer.source_line(lineno) =~ /\S/
|
186
|
-
end.min
|
187
|
-
|
188
|
-
delta = actual_indent - target_indent
|
193
|
+
delta = actual_indent(lines, buffer) - target_indent
|
189
194
|
lines.each do |lineno|
|
190
|
-
|
191
|
-
adjustment += @reindented_lines[lineno]
|
192
|
-
@reindented_lines[lineno] = adjustment
|
193
|
-
|
194
|
-
if adjustment > 0
|
195
|
-
corrector.remove_leading(buffer.line_range(lineno), adjustment)
|
196
|
-
elsif adjustment < 0
|
197
|
-
corrector.insert_before(buffer.line_range(lineno),
|
198
|
-
' ' * -adjustment)
|
199
|
-
end
|
195
|
+
reindent_line(corrector, lineno, delta, buffer)
|
200
196
|
end
|
201
197
|
end
|
202
198
|
|
199
|
+
def actual_indent(lines, buffer)
|
200
|
+
lines.map { |lineno| buffer.source_line(lineno) =~ /\S/ }.min
|
201
|
+
end
|
202
|
+
|
203
203
|
def heredoc_lines(node)
|
204
204
|
node.each_node(:dstr)
|
205
205
|
.select { |n| n.loc.respond_to?(:heredoc_body) }
|
206
206
|
.map { |n| n.loc.heredoc_body }
|
207
207
|
.flat_map { |b| (b.line...b.last_line).to_a }
|
208
208
|
end
|
209
|
+
|
210
|
+
def reindent_line(corrector, lineno, delta, buffer)
|
211
|
+
adjustment = delta + @reindented_lines[lineno]
|
212
|
+
@reindented_lines[lineno] = adjustment
|
213
|
+
|
214
|
+
if adjustment > 0
|
215
|
+
corrector.remove_leading(buffer.line_range(lineno), adjustment)
|
216
|
+
elsif adjustment < 0
|
217
|
+
corrector.insert_before(buffer.line_range(lineno),
|
218
|
+
' ' * -adjustment)
|
219
|
+
end
|
220
|
+
end
|
209
221
|
end
|
210
222
|
end
|
211
223
|
end
|
@@ -31,22 +31,42 @@ module RuboCop
|
|
31
31
|
range = range_with_surrounding_space(node.loc.selector, :right)
|
32
32
|
child = node.children.first
|
33
33
|
|
34
|
-
if
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
OPPOSITE_METHODS[child.method_name].to_s)
|
39
|
-
end
|
40
|
-
elsif child.and_type? || child.or_type? || child.binary_operation? ||
|
41
|
-
ternary?(child)
|
42
|
-
lambda do |corrector|
|
43
|
-
corrector.replace(range, '!(')
|
44
|
-
corrector.insert_after(node.source_range, ')')
|
45
|
-
end
|
34
|
+
if opposite_method?(child)
|
35
|
+
correct_opposite_method(range, child)
|
36
|
+
elsif requires_parens?(child)
|
37
|
+
correct_with_parens(range, node)
|
46
38
|
else
|
47
|
-
|
39
|
+
correct_without_parens(range)
|
48
40
|
end
|
49
41
|
end
|
42
|
+
|
43
|
+
def opposite_method?(child)
|
44
|
+
child.send_type? && OPPOSITE_METHODS.key?(child.method_name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def requires_parens?(child)
|
48
|
+
child.and_type? || child.or_type? || child.binary_operation? ||
|
49
|
+
ternary?(child)
|
50
|
+
end
|
51
|
+
|
52
|
+
def correct_opposite_method(range, child)
|
53
|
+
lambda do |corrector|
|
54
|
+
corrector.remove(range)
|
55
|
+
corrector.replace(child.loc.selector,
|
56
|
+
OPPOSITE_METHODS[child.method_name].to_s)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def correct_with_parens(range, node)
|
61
|
+
lambda do |corrector|
|
62
|
+
corrector.replace(range, '!(')
|
63
|
+
corrector.insert_after(node.source_range, ')')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def correct_without_parens(range)
|
68
|
+
->(corrector) { corrector.replace(range, '!') }
|
69
|
+
end
|
50
70
|
end
|
51
71
|
end
|
52
72
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Style
|
7
|
+
# This cop checks for octal, hex, binary and decimal literals using
|
8
|
+
# uppercase prefixes and corrects them to lowercase prefix
|
9
|
+
# or no prefix (in case of decimals).
|
10
|
+
# eg. for octal use `0o` instead of `0` or `0O`.
|
11
|
+
#
|
12
|
+
# Can be configured to use `0` only for octal literals using
|
13
|
+
# `EnforcedOctalStyle` => `zero_only`
|
14
|
+
class NumericLiteralPrefix < Cop
|
15
|
+
include IntegerNode
|
16
|
+
|
17
|
+
OCTAL_ZERO_ONLY_REGEX = /^0[Oo][0-7]+$/
|
18
|
+
OCTAL_REGEX = /^0O?[0-7]+$/
|
19
|
+
HEX_REGEX = /^0X[0-9A-F]+$/
|
20
|
+
BINARY_REGEX = /^0B[01]+$/
|
21
|
+
DECIMAL_REGEX = /^0[dD][0-9]+$/
|
22
|
+
|
23
|
+
OCTAL_ZERO_ONLY_MSG = 'Use 0 for octal literals.'.freeze
|
24
|
+
OCTAL_MSG = 'Use 0o for octal literals.'.freeze
|
25
|
+
HEX_MSG = 'Use 0x for hexadecimal literals.'.freeze
|
26
|
+
BINARY_MSG = 'Use 0b for binary literals.'.freeze
|
27
|
+
DECIMAL_MSG = 'Do not use prefixes for decimal literals.'.freeze
|
28
|
+
|
29
|
+
def on_int(node)
|
30
|
+
type = literal_type(node)
|
31
|
+
return unless type
|
32
|
+
|
33
|
+
msg = self.class.const_get("#{type.upcase}_MSG")
|
34
|
+
add_offense(node, :expression, msg)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def autocorrect(node)
|
40
|
+
lambda do |corrector|
|
41
|
+
type = literal_type(node)
|
42
|
+
corrector.replace(node.source_range,
|
43
|
+
send(:"format_#{type}", node.source))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def literal_type(node)
|
48
|
+
literal = integer_part(node)
|
49
|
+
|
50
|
+
if literal =~ OCTAL_ZERO_ONLY_REGEX && octal_zero_only?
|
51
|
+
return :octal_zero_only
|
52
|
+
elsif literal =~ OCTAL_REGEX && !octal_zero_only?
|
53
|
+
return :octal
|
54
|
+
end
|
55
|
+
|
56
|
+
case literal
|
57
|
+
when HEX_REGEX
|
58
|
+
:hex
|
59
|
+
when BINARY_REGEX
|
60
|
+
:binary
|
61
|
+
when DECIMAL_REGEX
|
62
|
+
:decimal
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def octal_zero_only?
|
67
|
+
cop_config['EnforcedOctalStyle'] == 'zero_only'
|
68
|
+
end
|
69
|
+
|
70
|
+
def format_octal(source)
|
71
|
+
source.sub(/^0O?/, '0o')
|
72
|
+
end
|
73
|
+
|
74
|
+
def format_octal_zero_only(source)
|
75
|
+
source.sub(/^0[Oo]?/, '0')
|
76
|
+
end
|
77
|
+
|
78
|
+
def format_hex(source)
|
79
|
+
source.sub(/^0X/, '0x')
|
80
|
+
end
|
81
|
+
|
82
|
+
def format_binary(source)
|
83
|
+
source.sub(/^0B/, '0b')
|
84
|
+
end
|
85
|
+
|
86
|
+
def format_decimal(source)
|
87
|
+
source.sub(/^0[dD]/, '')
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -11,6 +11,7 @@ module RuboCop
|
|
11
11
|
# digits for which an offense can be registered), but essentially it's
|
12
12
|
# a Max parameter (the maximum number of something that's allowed).
|
13
13
|
include ConfigurableMax
|
14
|
+
include IntegerNode
|
14
15
|
|
15
16
|
MSG = 'Separate every 3 digits in the integer portion of a number ' \
|
16
17
|
'with underscores(_).'.freeze
|
@@ -70,10 +71,6 @@ module RuboCop
|
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
73
|
-
def integer_part(node)
|
74
|
-
node.source.sub(/^[+-]/, '').split('.').first
|
75
|
-
end
|
76
|
-
|
77
74
|
def min_digits
|
78
75
|
cop_config['MinDigits']
|
79
76
|
end
|
@@ -147,13 +147,13 @@ module RuboCop
|
|
147
147
|
def modifier_while?(node)
|
148
148
|
node.loc.respond_to?(:keyword) &&
|
149
149
|
%w(while until).include?(node.loc.keyword.source) &&
|
150
|
-
node.
|
150
|
+
node.modifier_form?
|
151
151
|
end
|
152
152
|
|
153
153
|
def rescue_modifier?(node)
|
154
|
-
node &&
|
155
|
-
node.
|
156
|
-
|
154
|
+
node && node.rescue_type? &&
|
155
|
+
(node.parent.nil? || !(node.parent.kwbegin_type? ||
|
156
|
+
node.parent.ensure_type?))
|
157
157
|
end
|
158
158
|
|
159
159
|
# An internal class for correcting parallel assignment
|
@@ -202,6 +202,28 @@ module RuboCop
|
|
202
202
|
_node, rescue_clause = *node.parent
|
203
203
|
_, _, rescue_result = *rescue_clause
|
204
204
|
|
205
|
+
# If the parallel assignment uses a rescue modifier and it is the
|
206
|
+
# only contents of a method, then we want to make use of the
|
207
|
+
# implicit begin
|
208
|
+
if node.parent.parent && node.parent.parent.def_type?
|
209
|
+
super + def_correction(rescue_result)
|
210
|
+
else
|
211
|
+
begin_correction(rescue_result)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def correction_range
|
216
|
+
node.parent.source_range
|
217
|
+
end
|
218
|
+
|
219
|
+
private
|
220
|
+
|
221
|
+
def def_correction(rescue_result)
|
222
|
+
"\nrescue" \
|
223
|
+
"\n#{offset(node)}#{rescue_result.source}"
|
224
|
+
end
|
225
|
+
|
226
|
+
def begin_correction(rescue_result)
|
205
227
|
"begin\n" \
|
206
228
|
"#{indentation(node)}" \
|
207
229
|
"#{assignment.join("\n#{indentation(node)}")}" \
|
@@ -209,10 +231,6 @@ module RuboCop
|
|
209
231
|
"#{indentation(node)}#{rescue_result.source}" \
|
210
232
|
"\n#{offset(node)}end"
|
211
233
|
end
|
212
|
-
|
213
|
-
def correction_range
|
214
|
-
node.parent.source_range
|
215
|
-
end
|
216
234
|
end
|
217
235
|
|
218
236
|
# An internal class for correcting parallel assignment
|
@@ -4,22 +4,22 @@
|
|
4
4
|
module RuboCop
|
5
5
|
module Cop
|
6
6
|
module Style
|
7
|
-
# This cop checks for uses of
|
8
|
-
# and Hash#
|
9
|
-
class
|
10
|
-
MSG = '`Hash#%s`
|
7
|
+
# This cop checks for uses of methods Hash#has_key? and Hash#has_value?
|
8
|
+
# Prefer to use Hash#key? and Hash#value? instead
|
9
|
+
class PreferredHashMethods < Cop
|
10
|
+
MSG = 'Use `Hash#%s` instead of `Hash#%s`.'.freeze
|
11
11
|
|
12
|
-
|
12
|
+
PREFERRED_METHODS = [:has_key?, :has_value?].freeze
|
13
13
|
|
14
14
|
def on_send(node)
|
15
15
|
_receiver, method_name, *args = *node
|
16
16
|
return unless args.size == 1 &&
|
17
|
-
|
17
|
+
PREFERRED_METHODS.include?(method_name)
|
18
18
|
|
19
19
|
add_offense(node, :selector,
|
20
20
|
format(MSG,
|
21
|
-
method_name,
|
22
|
-
|
21
|
+
proper_method_name(method_name),
|
22
|
+
method_name))
|
23
23
|
end
|
24
24
|
|
25
25
|
def autocorrect(node)
|
@@ -32,17 +32,16 @@ module RuboCop
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def parens_allowed?(node)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
(keyword_ancestor?(node) && parens_required?(node)) ||
|
35
|
+
# don't flag `()`
|
36
|
+
empty_parentheses?(node) ||
|
37
|
+
# don't flag `break(1)`, etc
|
38
|
+
(keyword_ancestor?(node) && parens_required?(node)) ||
|
40
39
|
# don't flag `method ({key: value})`
|
41
|
-
|
40
|
+
hash_literal_as_first_arg?(node) ||
|
42
41
|
# don't flag `rescue(ExceptionClass)`
|
43
42
|
rescue?(node) ||
|
44
43
|
# don't flag `method (arg) { }`
|
45
|
-
(arg_in_call_with_block?(node) && !parentheses?(parent)) ||
|
44
|
+
(arg_in_call_with_block?(node) && !parentheses?(node.parent)) ||
|
46
45
|
# don't flag
|
47
46
|
# ```
|
48
47
|
# { a: (1
|
@@ -51,6 +50,15 @@ module RuboCop
|
|
51
50
|
allowed_array_or_hash_element?(node)
|
52
51
|
end
|
53
52
|
|
53
|
+
def empty_parentheses?(node)
|
54
|
+
node.children.empty?
|
55
|
+
end
|
56
|
+
|
57
|
+
def hash_literal_as_first_arg?(node)
|
58
|
+
child = node.children.first
|
59
|
+
child.hash_type? && first_arg?(node) && !parentheses?(node.parent)
|
60
|
+
end
|
61
|
+
|
54
62
|
def check(begin_node)
|
55
63
|
node = begin_node.children.first
|
56
64
|
if keyword_with_redundant_parentheses?(node)
|
@@ -63,22 +71,24 @@ module RuboCop
|
|
63
71
|
end
|
64
72
|
|
65
73
|
def check_send(begin_node, node)
|
66
|
-
if node.unary_operation?
|
67
|
-
return if begin_node.chained?
|
74
|
+
return check_unary(begin_node, node) if node.unary_operation?
|
68
75
|
|
69
|
-
|
70
|
-
|
71
|
-
if node.send_type?
|
72
|
-
return unless method_call_with_redundant_parentheses?(node)
|
73
|
-
end
|
76
|
+
return unless method_call_with_redundant_parentheses?(node)
|
77
|
+
return if call_chain_starts_with_int?(begin_node, node)
|
74
78
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
+
offense(begin_node, 'a method call')
|
80
|
+
end
|
81
|
+
|
82
|
+
def check_unary(begin_node, node)
|
83
|
+
return if begin_node.chained?
|
79
84
|
|
80
|
-
|
85
|
+
# parens are not redundant in `(!recv.method arg)`
|
86
|
+
node = node.children.first while node.unary_operation?
|
87
|
+
if node.send_type?
|
88
|
+
return unless method_call_with_redundant_parentheses?(node)
|
81
89
|
end
|
90
|
+
|
91
|
+
offense(begin_node, 'an unary operation')
|
82
92
|
end
|
83
93
|
|
84
94
|
def offense(node, msg)
|