rubocop 0.36.0 → 0.37.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/CHANGELOG.md +62 -2
- data/README.md +10 -1
- data/assets/output.html.erb +55 -1
- data/config/default.yml +9 -3
- data/config/disabled.yml +21 -0
- data/config/enabled.yml +11 -10
- data/lib/rubocop.rb +9 -2
- data/lib/rubocop/ast_node.rb +67 -19
- data/lib/rubocop/ast_node/builder.rb +1 -0
- data/lib/rubocop/ast_node/sexp.rb +1 -0
- data/lib/rubocop/ast_node/traversal.rb +171 -0
- data/lib/rubocop/cached_data.rb +4 -1
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/config.rb +36 -20
- data/lib/rubocop/config_loader.rb +6 -5
- data/lib/rubocop/cop/commissioner.rb +27 -18
- data/lib/rubocop/cop/cop.rb +7 -6
- data/lib/rubocop/cop/lint/duplicated_key.rb +1 -8
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +18 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +5 -1
- data/lib/rubocop/cop/lint/unneeded_disable.rb +1 -1
- data/lib/rubocop/cop/mixin/array_hash_indentation.rb +1 -0
- data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +9 -2
- data/lib/rubocop/cop/mixin/check_assignment.rb +1 -1
- data/lib/rubocop/cop/mixin/classish_length.rb +3 -4
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +8 -4
- data/lib/rubocop/cop/mixin/configurable_naming.rb +1 -1
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +2 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +35 -0
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/min_body_length.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +58 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -2
- data/lib/rubocop/cop/performance/case_when_splat.rb +7 -0
- data/lib/rubocop/cop/performance/casecmp.rb +56 -17
- data/lib/rubocop/cop/performance/redundant_block_call.rb +17 -3
- data/lib/rubocop/cop/performance/redundant_merge.rb +7 -1
- data/lib/rubocop/cop/performance/times_map.rb +3 -4
- data/lib/rubocop/cop/severity.rb +1 -1
- data/lib/rubocop/cop/style/align_hash.rb +1 -1
- data/lib/rubocop/cop/style/align_parameters.rb +1 -1
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/block_comments.rb +2 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +2 -0
- data/lib/rubocop/cop/style/copyright.rb +2 -2
- data/lib/rubocop/cop/style/documentation.rb +19 -29
- data/lib/rubocop/cop/style/each_with_object.rb +1 -1
- data/lib/rubocop/cop/style/else_alignment.rb +2 -2
- data/lib/rubocop/cop/style/encoding.rb +1 -1
- data/lib/rubocop/cop/style/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -12
- data/lib/rubocop/cop/style/guard_clause.rb +2 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -8
- data/lib/rubocop/cop/style/indent_assignment.rb +1 -1
- data/lib/rubocop/cop/style/indentation_width.rb +3 -7
- data/lib/rubocop/cop/style/method_call_parentheses.rb +2 -1
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/multiline_array_brace_layout.rb +3 -41
- data/lib/rubocop/cop/style/multiline_hash_brace_layout.rb +57 -0
- data/lib/rubocop/cop/style/multiline_method_call_brace_layout.rb +65 -0
- data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +5 -4
- data/lib/rubocop/cop/style/multiline_method_definition_brace_layout.rb +62 -0
- data/lib/rubocop/cop/style/multiline_operation_indentation.rb +9 -3
- data/lib/rubocop/cop/style/mutable_constant.rb +18 -3
- data/lib/rubocop/cop/style/nested_modifier.rb +5 -2
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -1
- data/lib/rubocop/cop/style/next.rb +32 -11
- data/lib/rubocop/cop/style/option_hash.rb +1 -1
- data/lib/rubocop/cop/style/redundant_freeze.rb +13 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +33 -7
- data/lib/rubocop/cop/style/send.rb +1 -1
- data/lib/rubocop/cop/style/space_around_keyword.rb +198 -0
- data/lib/rubocop/cop/style/space_around_operators.rb +2 -12
- data/lib/rubocop/cop/style/space_inside_block_braces.rb +1 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +4 -4
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/trailing_blank_lines.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +1 -0
- data/lib/rubocop/cop/style/trailing_comma_in_literal.rb +1 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +55 -0
- data/lib/rubocop/cop/team.rb +30 -5
- data/lib/rubocop/cop/util.rb +16 -1
- data/lib/rubocop/cop/variable_force.rb +3 -12
- data/lib/rubocop/cop/variable_force/assignment.rb +3 -3
- data/lib/rubocop/cop/variable_force/locatable.rb +25 -6
- data/lib/rubocop/cop/variable_force/reference.rb +3 -3
- data/lib/rubocop/cop/variable_force/scope.rb +8 -7
- data/lib/rubocop/cop/variable_force/variable.rb +3 -3
- data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
- data/lib/rubocop/formatter/formatter_set.rb +2 -2
- data/lib/rubocop/node_pattern.rb +1 -1
- data/lib/rubocop/options.rb +10 -10
- data/lib/rubocop/path_util.rb +5 -0
- data/lib/rubocop/processed_source.rb +8 -2
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/runner.rb +1 -1
- data/lib/rubocop/token.rb +2 -2
- data/lib/rubocop/version.rb +1 -1
- data/relnotes/v0.30.1.md +1 -0
- data/relnotes/v0.33.0.md +1 -1
- data/relnotes/v0.36.0.md +2 -1
- data/relnotes/v0.37.0.md +200 -0
- data/rubocop.gemspec +2 -1
- metadata +28 -7
- data/lib/rubocop/cop/style/space_after_control_keyword.rb +0 -35
- data/lib/rubocop/cop/style/space_before_modifier_keyword.rb +0 -38
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Style
|
7
|
+
# This cop checks that the closing brace in an a hash literal is
|
8
|
+
# symmetrical with respect to the opening brace and the hash
|
9
|
+
# elements.
|
10
|
+
#
|
11
|
+
# If a hash's opening brace is on the same line as the first element
|
12
|
+
# of the hash, then the closing brace should be on the same line as
|
13
|
+
# the last element of the hash.
|
14
|
+
#
|
15
|
+
# If a hash's opening brace is on a separate line from the first
|
16
|
+
# element of the hash, then the closing brace should be on the line
|
17
|
+
# after the last element of the hash.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
#
|
21
|
+
# # bad
|
22
|
+
# { a: 'a',
|
23
|
+
# b: 'b'
|
24
|
+
# }
|
25
|
+
#
|
26
|
+
# # bad
|
27
|
+
# {
|
28
|
+
# a: 'a',
|
29
|
+
# b: 'b' }
|
30
|
+
#
|
31
|
+
# # good
|
32
|
+
# { a: 'a',
|
33
|
+
# b: 'b' }
|
34
|
+
#
|
35
|
+
# #good
|
36
|
+
# {
|
37
|
+
# a: 'a',
|
38
|
+
# b: 'b'
|
39
|
+
# }
|
40
|
+
class MultilineHashBraceLayout < Cop
|
41
|
+
include MultilineLiteralBraceLayout
|
42
|
+
|
43
|
+
SAME_LINE_MESSAGE = 'Closing hash brace must be on the same line as ' \
|
44
|
+
'the last hash element when opening brace is on the same line as ' \
|
45
|
+
'the first hash element.'.freeze
|
46
|
+
|
47
|
+
NEW_LINE_MESSAGE = 'Closing hash brace must be on the line after ' \
|
48
|
+
'the last hash element when opening brace is on a separate line ' \
|
49
|
+
'from the first hash element.'.freeze
|
50
|
+
|
51
|
+
def on_hash(node)
|
52
|
+
check_brace_layout(node)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Style
|
7
|
+
# This cop checks that the closing brace in a method call is
|
8
|
+
# symmetrical with respect to the opening brace and the method
|
9
|
+
# arguments.
|
10
|
+
#
|
11
|
+
# If a method call's opening brace is on the same line as the
|
12
|
+
# first argument of the call, then the closing brace should be
|
13
|
+
# on the same line as the last argument of the call.
|
14
|
+
#
|
15
|
+
# If a method call's opening brace is on a separate line from
|
16
|
+
# the first argument of the call, then the closing brace should
|
17
|
+
# be on the line after the last argument of the call.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
#
|
21
|
+
# # bad
|
22
|
+
# foo(a,
|
23
|
+
# b
|
24
|
+
# )
|
25
|
+
#
|
26
|
+
# # bad
|
27
|
+
# foo(
|
28
|
+
# a,
|
29
|
+
# b)
|
30
|
+
#
|
31
|
+
# # good
|
32
|
+
# foo(a,
|
33
|
+
# b)
|
34
|
+
#
|
35
|
+
# #good
|
36
|
+
# foo(
|
37
|
+
# a,
|
38
|
+
# b
|
39
|
+
# )
|
40
|
+
class MultilineMethodCallBraceLayout < Cop
|
41
|
+
include MultilineLiteralBraceLayout
|
42
|
+
|
43
|
+
SAME_LINE_MESSAGE = 'Closing method call brace must be on the ' \
|
44
|
+
'same line as the last argument when opening brace is on the same ' \
|
45
|
+
'line as the first argument.'.freeze
|
46
|
+
|
47
|
+
NEW_LINE_MESSAGE = 'Closing method call brace must be on the ' \
|
48
|
+
'line after the last argument when opening brace is on a separate ' \
|
49
|
+
'line from the first argument.'.freeze
|
50
|
+
|
51
|
+
def on_send(node)
|
52
|
+
check_brace_layout(node)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def children(node)
|
58
|
+
_receiver, _method_name, *args = *node
|
59
|
+
|
60
|
+
args
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -37,10 +37,11 @@ module RuboCop
|
|
37
37
|
|
38
38
|
def validate_config
|
39
39
|
if style == :aligned && cop_config['IndentationWidth']
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
raise ValidationError,
|
41
|
+
'The `Style/MultilineMethodCallIndentation`' \
|
42
|
+
' cop only accepts an `IndentationWidth` ' \
|
43
|
+
'configuration parameter when ' \
|
44
|
+
'`EnforcedStyle` is `indented`.'
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Style
|
7
|
+
# This cop checks that the closing brace in a method definition is
|
8
|
+
# symmetrical with respect to the opening brace and the method
|
9
|
+
# parameters.
|
10
|
+
#
|
11
|
+
# If a method definition's opening brace is on the same line as the
|
12
|
+
# first parameter of the definition, then the closing brace should be
|
13
|
+
# on the same line as the last parameter of the definition.
|
14
|
+
#
|
15
|
+
# If a method definition's opening brace is on a separate line from
|
16
|
+
# the first parameter of the definition, then the closing brace should
|
17
|
+
# be on the line after the last parameter of the definition.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
#
|
21
|
+
# # bad
|
22
|
+
# def foo(a,
|
23
|
+
# b
|
24
|
+
# )
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# # bad
|
28
|
+
# def foo(
|
29
|
+
# a,
|
30
|
+
# b)
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# # good
|
34
|
+
# def foo(a,
|
35
|
+
# b)
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# #good
|
39
|
+
# def foo(
|
40
|
+
# a,
|
41
|
+
# b
|
42
|
+
# )
|
43
|
+
# end
|
44
|
+
class MultilineMethodDefinitionBraceLayout < Cop
|
45
|
+
include OnMethodDef
|
46
|
+
include MultilineLiteralBraceLayout
|
47
|
+
|
48
|
+
SAME_LINE_MESSAGE = 'Closing method definition brace must be on the ' \
|
49
|
+
'same line as the last parameter when opening brace is on the same ' \
|
50
|
+
'line as the first parameter.'.freeze
|
51
|
+
|
52
|
+
NEW_LINE_MESSAGE = 'Closing method definition brace must be on the ' \
|
53
|
+
'line after the last parameter when opening brace is on a separate ' \
|
54
|
+
'line from the first parameter.'.freeze
|
55
|
+
|
56
|
+
def on_method_def(_node, _method_name, args, _body)
|
57
|
+
check_brace_layout(args)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
28
28
|
|
29
29
|
def validate_config
|
30
30
|
if style == :aligned && cop_config['IndentationWidth']
|
31
|
-
|
31
|
+
raise ValidationError, 'The `Style/MultilineOperationIndentation`' \
|
32
32
|
' cop only accepts an `IndentationWidth` ' \
|
33
33
|
'configuration parameter when ' \
|
34
34
|
'`EnforcedStyle` is `indented`.'
|
@@ -53,7 +53,7 @@ module RuboCop
|
|
53
53
|
return false if not_for_this_cop?(node)
|
54
54
|
|
55
55
|
correct_column = if should_align?(node, rhs, given_style)
|
56
|
-
|
56
|
+
node.loc.column
|
57
57
|
else
|
58
58
|
indentation(lhs) + correct_indentation(node)
|
59
59
|
end
|
@@ -62,8 +62,14 @@ module RuboCop
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def should_align?(node, rhs, given_style)
|
65
|
+
assignment_node = part_of_assignment_rhs(node, rhs)
|
66
|
+
if assignment_node
|
67
|
+
assignment_rhs = CheckAssignment.extract_rhs(assignment_node)
|
68
|
+
return true if begins_its_line?(assignment_rhs.source_range)
|
69
|
+
end
|
70
|
+
|
65
71
|
given_style == :aligned && (kw_node_with_special_indentation(node) ||
|
66
|
-
|
72
|
+
assignment_node ||
|
67
73
|
argument_in_method_call(node))
|
68
74
|
end
|
69
75
|
|
@@ -16,18 +16,33 @@ module RuboCop
|
|
16
16
|
class MutableConstant < Cop
|
17
17
|
MSG = 'Freeze mutable objects assigned to constants.'.freeze
|
18
18
|
|
19
|
+
include FrozenStringLiteral
|
20
|
+
|
19
21
|
def on_casgn(node)
|
20
22
|
_scope, _const_name, value = *node
|
23
|
+
on_assignment(value)
|
24
|
+
end
|
21
25
|
|
22
|
-
|
23
|
-
|
24
|
-
|
26
|
+
def on_or_asgn(node)
|
27
|
+
lhs, value = *node
|
28
|
+
on_assignment(value) if lhs && lhs.type == :casgn
|
25
29
|
end
|
26
30
|
|
27
31
|
def autocorrect(node)
|
28
32
|
expr = node.source_range
|
29
33
|
->(corrector) { corrector.replace(expr, "#{expr.source}.freeze") }
|
30
34
|
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def on_assignment(value)
|
39
|
+
return unless value
|
40
|
+
return unless value.mutable_literal?
|
41
|
+
return if FROZEN_STRING_LITERAL_TYPES.include?(value.type) &&
|
42
|
+
frozen_string_literals_enabled?(processed_source)
|
43
|
+
|
44
|
+
add_offense(value, :expression)
|
45
|
+
end
|
31
46
|
end
|
32
47
|
end
|
33
48
|
end
|
@@ -83,14 +83,17 @@ module RuboCop
|
|
83
83
|
outer_keyword = outer_node.loc.keyword.source
|
84
84
|
inner_keyword = inner_node.loc.keyword.source
|
85
85
|
|
86
|
-
operator = outer_keyword == 'if' ? '&&' : '||'
|
86
|
+
operator = outer_keyword == 'if'.freeze ? '&&'.freeze : '||'.freeze
|
87
87
|
|
88
|
+
outer_expr = outer_cond.source
|
89
|
+
outer_expr = "(#{outer_expr})" if outer_cond.or_type? &&
|
90
|
+
operator == '&&'.freeze
|
88
91
|
inner_expr = inner_cond.source
|
89
92
|
inner_expr = "(#{inner_expr})" if inner_cond.or_type?
|
90
93
|
inner_expr = "!#{inner_expr}" unless outer_keyword == inner_keyword
|
91
94
|
|
92
95
|
"#{outer_node.loc.keyword.source} " \
|
93
|
-
"#{
|
96
|
+
"#{outer_expr} #{operator} #{inner_expr}"
|
94
97
|
end
|
95
98
|
end
|
96
99
|
end
|
@@ -26,7 +26,8 @@ module RuboCop
|
|
26
26
|
next if nested.method_args.empty? ||
|
27
27
|
parenthesized_call?(nested) ||
|
28
28
|
operator?(nested.method_name) ||
|
29
|
-
rspec_matcher?(node, nested)
|
29
|
+
rspec_matcher?(node, nested) ||
|
30
|
+
nested.asgn_method_call?
|
30
31
|
add_offense(nested, nested.source_range, format(MSG, nested.source))
|
31
32
|
end
|
32
33
|
end
|
@@ -108,20 +108,41 @@ module RuboCop
|
|
108
108
|
|
109
109
|
def autocorrect(node)
|
110
110
|
lambda do |corrector|
|
111
|
-
|
111
|
+
if modifier_if?(node)
|
112
|
+
autocorrect_modifier(corrector, node)
|
113
|
+
else
|
114
|
+
autocorrect_block(corrector, node)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
112
118
|
|
113
|
-
|
114
|
-
|
115
|
-
|
119
|
+
def autocorrect_modifier(corrector, node)
|
120
|
+
cond, if_body, else_body = *node
|
121
|
+
body = if_body || else_body
|
116
122
|
|
117
|
-
|
118
|
-
|
123
|
+
replacement = "next #{opposite_kw(if_body)} #{cond.source}\n" \
|
124
|
+
"#{' ' * node.source_range.column}#{body.source}"
|
119
125
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
126
|
+
corrector.replace(node.source_range, replacement)
|
127
|
+
end
|
128
|
+
|
129
|
+
def autocorrect_block(corrector, node)
|
130
|
+
cond, if_body, = *node
|
131
|
+
|
132
|
+
next_code = "next #{opposite_kw(if_body)} #{cond.source}"
|
133
|
+
corrector.insert_before(node.source_range, next_code)
|
134
|
+
|
135
|
+
corrector.remove(cond_range(node, cond))
|
136
|
+
corrector.remove(end_range(node))
|
137
|
+
|
138
|
+
# end_range starts with the final newline of the if body
|
139
|
+
reindent_lines = (node.source_range.line + 1)...node.loc.end.line
|
140
|
+
reindent_lines = reindent_lines.to_a - heredoc_lines(node)
|
141
|
+
reindent(reindent_lines, cond, corrector)
|
142
|
+
end
|
143
|
+
|
144
|
+
def opposite_kw(if_body)
|
145
|
+
if_body.nil? ? 'if' : 'unless'
|
125
146
|
end
|
126
147
|
|
127
148
|
def cond_range(node, cond)
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
49
49
|
|
50
50
|
def validate_config
|
51
51
|
if target_ruby_version < 2.0
|
52
|
-
|
52
|
+
raise ValidationError, 'The `Style/OptionHash` cop is only ' \
|
53
53
|
'compatible with Ruby 2.0 and up, but the ' \
|
54
54
|
'target Ruby version for your project is ' \
|
55
55
|
"1.9.\nPlease disable this cop or adjust " \
|
@@ -13,15 +13,16 @@ module RuboCop
|
|
13
13
|
# # good
|
14
14
|
# CONST = 1
|
15
15
|
class RedundantFreeze < Cop
|
16
|
+
include FrozenStringLiteral
|
17
|
+
|
16
18
|
MSG = 'Freezing immutable objects is pointless.'.freeze
|
17
19
|
|
18
20
|
def on_send(node)
|
19
21
|
receiver, method_name, *args = *node
|
20
22
|
|
21
|
-
return unless
|
22
|
-
method_name == :freeze &&
|
23
|
+
return unless method_name == :freeze &&
|
23
24
|
args.empty? &&
|
24
|
-
|
25
|
+
immutable_literal?(receiver)
|
25
26
|
|
26
27
|
add_offense(node, :expression)
|
27
28
|
end
|
@@ -32,6 +33,15 @@ module RuboCop
|
|
32
33
|
corrector.remove(node.loc.selector)
|
33
34
|
end
|
34
35
|
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def immutable_literal?(node)
|
40
|
+
return false unless node
|
41
|
+
return true if node.immutable_literal?
|
42
|
+
FROZEN_STRING_LITERAL_TYPES.include?(node.type) &&
|
43
|
+
frozen_string_literals_enabled?(processed_source)
|
44
|
+
end
|
35
45
|
end
|
36
46
|
end
|
37
47
|
end
|
@@ -28,16 +28,30 @@ module RuboCop
|
|
28
28
|
|
29
29
|
child_node = node.children.first
|
30
30
|
return if keyword_ancestor?(node) && parens_required?(node)
|
31
|
+
return if child_node.hash_type? && first_argument?(node) &&
|
32
|
+
!parentheses?(node.parent)
|
31
33
|
|
32
|
-
if
|
33
|
-
|
34
|
+
return if rescue?(node)
|
35
|
+
check(node, child_node)
|
36
|
+
end
|
37
|
+
|
38
|
+
def check(begin_node, node)
|
39
|
+
if keyword_with_redundant_parentheses?(node)
|
40
|
+
return offense(begin_node, 'a keyword')
|
34
41
|
end
|
35
|
-
return offense(
|
36
|
-
return offense(
|
37
|
-
return offense(
|
38
|
-
|
42
|
+
return offense(begin_node, 'a literal') if disallowed_literal?(node)
|
43
|
+
return offense(begin_node, 'a variable') if node.variable?
|
44
|
+
return offense(begin_node, 'a constant') if node.const_type?
|
45
|
+
check_send(begin_node, node) if node.send_type?
|
46
|
+
end
|
39
47
|
|
40
|
-
|
48
|
+
def check_send(begin_node, node)
|
49
|
+
if node.unary_operation?
|
50
|
+
offense(begin_node, 'an unary operation') unless begin_node.chained?
|
51
|
+
else
|
52
|
+
return unless method_call_with_redundant_parentheses?(node)
|
53
|
+
offense(begin_node, 'a method call')
|
54
|
+
end
|
41
55
|
end
|
42
56
|
|
43
57
|
def offense(node, msg)
|
@@ -74,6 +88,18 @@ module RuboCop
|
|
74
88
|
|
75
89
|
args.empty? || parentheses?(send_node) || square_brackets?(send_node)
|
76
90
|
end
|
91
|
+
|
92
|
+
def first_argument?(node)
|
93
|
+
send_node = node.parent
|
94
|
+
return false unless send_node && send_node.send_type?
|
95
|
+
|
96
|
+
_receiver, _method_name, *args = *send_node
|
97
|
+
node == args.first
|
98
|
+
end
|
99
|
+
|
100
|
+
def rescue?(node)
|
101
|
+
node.parent && node.parent.array_type?
|
102
|
+
end
|
77
103
|
end
|
78
104
|
end
|
79
105
|
end
|