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
@@ -93,12 +93,10 @@ module RuboCop
|
|
93
93
|
|
94
94
|
def on_send(node)
|
95
95
|
receiver, method_name, *_args = *node
|
96
|
-
return unless receiver && receiver.
|
97
|
-
return
|
98
|
-
|
99
|
-
|
100
|
-
node.asgn_method_call? ||
|
101
|
-
@allowed_send_nodes.include?(node) ||
|
96
|
+
return unless receiver && receiver.self_type?
|
97
|
+
return unless regular_method_call?(node)
|
98
|
+
|
99
|
+
return if @allowed_send_nodes.include?(node) ||
|
102
100
|
@local_variables.include?(method_name)
|
103
101
|
|
104
102
|
add_offense(node, :expression)
|
@@ -114,6 +112,15 @@ module RuboCop
|
|
114
112
|
|
115
113
|
private
|
116
114
|
|
115
|
+
def regular_method_call?(node)
|
116
|
+
_receiver, method_name, *_args = *node
|
117
|
+
|
118
|
+
!(operator?(method_name) ||
|
119
|
+
keyword?(method_name) ||
|
120
|
+
constant_name?(method_name) ||
|
121
|
+
node.asgn_method_call?)
|
122
|
+
end
|
123
|
+
|
117
124
|
def on_argument(node)
|
118
125
|
name, = *node
|
119
126
|
@local_variables << name
|
@@ -16,12 +16,14 @@ module RuboCop
|
|
16
16
|
MSG = 'Do not leave space between `!` and its argument.'.freeze
|
17
17
|
|
18
18
|
def on_send(node)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
if node.keyword_bang? && whitespace_after_bang_op?(node)
|
20
|
+
add_offense(node, :expression)
|
21
|
+
end
|
22
|
+
end
|
23
23
|
|
24
|
-
|
24
|
+
def whitespace_after_bang_op?(node)
|
25
|
+
receiver, _method_name, *_args = *node
|
26
|
+
receiver.loc.column - node.loc.column > 1
|
25
27
|
end
|
26
28
|
|
27
29
|
def autocorrect(node)
|
@@ -30,6 +30,7 @@ module RuboCop
|
|
30
30
|
MSG_AFTER = 'Space after keyword `%s` is missing.'.freeze
|
31
31
|
|
32
32
|
DO = 'do'.freeze
|
33
|
+
SAFE_NAVIGATION = '&.'.freeze
|
33
34
|
ACCEPT_LEFT_PAREN =
|
34
35
|
%w(break defined? next not rescue return super yield).freeze
|
35
36
|
ACCEPT_LEFT_SQUARE_BRACKET =
|
@@ -183,6 +184,7 @@ module RuboCop
|
|
183
184
|
char == '('.freeze
|
184
185
|
return false if accept_left_square_bracket?(range) &&
|
185
186
|
char == '['.freeze
|
187
|
+
return false if safe_navigation_call?(range, pos)
|
186
188
|
|
187
189
|
char !~ /[\s;,#\\\)\}\]\.]/
|
188
190
|
end
|
@@ -195,6 +197,10 @@ module RuboCop
|
|
195
197
|
ACCEPT_LEFT_SQUARE_BRACKET.include?(range.source)
|
196
198
|
end
|
197
199
|
|
200
|
+
def safe_navigation_call?(range, pos)
|
201
|
+
range.source_buffer.source[pos, 2].start_with?(SAFE_NAVIGATION)
|
202
|
+
end
|
203
|
+
|
198
204
|
def preceded_by_operator?(node, _range)
|
199
205
|
# regular dotted method calls bind more tightly than operators
|
200
206
|
# so we need to climb up the AST past them
|
@@ -42,7 +42,7 @@ module RuboCop
|
|
42
42
|
on_special_asgn(node)
|
43
43
|
elsif !node.unary_operation? && !called_with_dot?(node)
|
44
44
|
op = node.method_name
|
45
|
-
if
|
45
|
+
if operator_with_regular_syntax?(op)
|
46
46
|
_, _, right, = *node
|
47
47
|
check_operator(node.loc.selector, right.source_range)
|
48
48
|
end
|
@@ -80,6 +80,10 @@ module RuboCop
|
|
80
80
|
node.loc.dot
|
81
81
|
end
|
82
82
|
|
83
|
+
def operator_with_regular_syntax?(op)
|
84
|
+
![:[], :!, :[]=].include?(op) && operator?(op)
|
85
|
+
end
|
86
|
+
|
83
87
|
def check_operator(op, right_operand)
|
84
88
|
with_space = range_with_surrounding_space(op)
|
85
89
|
return if with_space.source.start_with?("\n")
|
@@ -23,17 +23,11 @@ module RuboCop
|
|
23
23
|
'the first argument.'.freeze
|
24
24
|
|
25
25
|
def on_send(node)
|
26
|
-
return
|
27
|
-
|
28
|
-
_receiver, method_name, *args = *node
|
29
|
-
return if args.empty?
|
30
|
-
return if operator?(method_name)
|
31
|
-
return if node.asgn_method_call?
|
26
|
+
return unless regular_method_call_with_params?(node)
|
27
|
+
return unless expect_params_after_method_name?(node)
|
32
28
|
|
29
|
+
_receiver, _method_name, *args = *node
|
33
30
|
arg1 = args.first.source_range
|
34
|
-
return if arg1.line > node.loc.line
|
35
|
-
return if allow_for_alignment? && aligned_with_something?(arg1)
|
36
|
-
|
37
31
|
arg1_with_space = range_with_surrounding_space(arg1, :left)
|
38
32
|
space = Parser::Source::Range.new(arg1.source_buffer,
|
39
33
|
arg1_with_space.begin_pos,
|
@@ -44,6 +38,24 @@ module RuboCop
|
|
44
38
|
def autocorrect(range)
|
45
39
|
->(corrector) { corrector.replace(range, ' ') }
|
46
40
|
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def regular_method_call_with_params?(node)
|
45
|
+
_receiver, method_name, *args = *node
|
46
|
+
|
47
|
+
!(args.empty? || operator?(method_name) || node.asgn_method_call?)
|
48
|
+
end
|
49
|
+
|
50
|
+
def expect_params_after_method_name?(node)
|
51
|
+
return false if parentheses?(node)
|
52
|
+
|
53
|
+
_receiver, _method_name, *args = *node
|
54
|
+
arg1 = args.first.source_range
|
55
|
+
|
56
|
+
arg1.line == node.loc.line &&
|
57
|
+
!(allow_for_alignment? && aligned_with_something?(arg1))
|
58
|
+
end
|
47
59
|
end
|
48
60
|
end
|
49
61
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Style
|
7
|
+
# Checks for unnecessary additional spaces inside array percent literals
|
8
|
+
# (i.e. %i/%w).
|
9
|
+
#
|
10
|
+
# @good
|
11
|
+
# %i(foo bar baz)
|
12
|
+
#
|
13
|
+
# @bad
|
14
|
+
# %w(foo bar baz)
|
15
|
+
class SpaceInsideArrayPercentLiteral < Cop
|
16
|
+
include MatchRange
|
17
|
+
include PercentLiteral
|
18
|
+
|
19
|
+
MSG = 'Use only a single space inside array percent literal.'.freeze
|
20
|
+
MULTIPLE_SPACES_BETWEEN_ITEMS_REGEX =
|
21
|
+
/(?:[\S&&[^\\]](?:\\ )*)( {2,})(?=\S)/
|
22
|
+
|
23
|
+
def on_array(node)
|
24
|
+
process(node, *%w(%i %I %w %W))
|
25
|
+
end
|
26
|
+
|
27
|
+
def on_percent_literal(node)
|
28
|
+
each_unnecessary_space_match(node) do |range|
|
29
|
+
add_offense(node, range, MSG)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def autocorrect(node)
|
34
|
+
lambda do |corrector|
|
35
|
+
each_unnecessary_space_match(node) do |range|
|
36
|
+
corrector.replace(range, ' ')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def each_unnecessary_space_match(node, &blk)
|
44
|
+
each_match_range(
|
45
|
+
contents_range(node),
|
46
|
+
MULTIPLE_SPACES_BETWEEN_ITEMS_REGEX,
|
47
|
+
&blk
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -37,7 +37,7 @@ module RuboCop
|
|
37
37
|
|
38
38
|
if left_brace.end_pos == right_brace.begin_pos
|
39
39
|
adjacent_braces(sb, left_brace, right_brace)
|
40
|
-
|
40
|
+
else
|
41
41
|
range = Parser::Source::Range.new(sb, left_brace.end_pos,
|
42
42
|
right_brace.begin_pos)
|
43
43
|
inner = range.source
|
@@ -70,7 +70,7 @@ module RuboCop
|
|
70
70
|
space_inside_left_brace(left_brace, args_delimiter, sb)
|
71
71
|
end
|
72
72
|
|
73
|
-
if inner =~ /\S$/
|
73
|
+
if inner =~ /\S$/ && block_length(node) == 0
|
74
74
|
no_space(sb, right_brace.begin_pos, right_brace.end_pos,
|
75
75
|
'Space missing inside }.')
|
76
76
|
else
|
@@ -34,11 +34,8 @@ module RuboCop
|
|
34
34
|
return if t2.type == :tCOMMENT # Also indicates there's a line break.
|
35
35
|
|
36
36
|
is_empty_braces = t1.text == '{' && t2.text == '}'
|
37
|
-
expect_space
|
38
|
-
|
39
|
-
else
|
40
|
-
style == :space
|
41
|
-
end
|
37
|
+
expect_space = expect_space?(t1, t2)
|
38
|
+
|
42
39
|
if offense?(t1, t2, expect_space)
|
43
40
|
incorrect_style_detected(t1, t2, expect_space, is_empty_braces)
|
44
41
|
else
|
@@ -46,12 +43,35 @@ module RuboCop
|
|
46
43
|
end
|
47
44
|
end
|
48
45
|
|
46
|
+
def expect_space?(t1, t2)
|
47
|
+
is_same_braces = t1.text == t2.text
|
48
|
+
is_empty_braces = t1.text == '{' && t2.text == '}'
|
49
|
+
|
50
|
+
if is_same_braces && style == :compact
|
51
|
+
false
|
52
|
+
elsif is_empty_braces
|
53
|
+
cop_config['EnforcedStyleForEmptyBraces'] != 'no_space'
|
54
|
+
else
|
55
|
+
style != :no_space
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
49
59
|
def incorrect_style_detected(t1, t2, expect_space, is_empty_braces)
|
50
60
|
brace = (t1.text == '{' ? t1 : t2).pos
|
51
61
|
range = expect_space ? brace : space_range(brace)
|
52
62
|
add_offense(range, range,
|
53
63
|
message(brace, is_empty_braces, expect_space)) do
|
54
|
-
|
64
|
+
if expect_space
|
65
|
+
if t1.text == t2.text
|
66
|
+
ambiguous_style_detected(:no_space, :compact)
|
67
|
+
else
|
68
|
+
unexpected_style_detected(:no_space)
|
69
|
+
end
|
70
|
+
elsif t1.text == t2.text
|
71
|
+
unexpected_style_detected(:space)
|
72
|
+
else
|
73
|
+
ambiguous_style_detected(:space, :compact)
|
74
|
+
end
|
55
75
|
end
|
56
76
|
end
|
57
77
|
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Style
|
7
|
+
# Checks for unnecessary additional spaces inside the delimiters of
|
8
|
+
# %i/%w/%x literals.
|
9
|
+
#
|
10
|
+
# @good
|
11
|
+
# %i(foo bar baz)
|
12
|
+
#
|
13
|
+
# @bad
|
14
|
+
# %w( foo bar baz )
|
15
|
+
#
|
16
|
+
# @bad
|
17
|
+
# %x( ls -l )
|
18
|
+
class SpaceInsidePercentLiteralDelimiters < Cop
|
19
|
+
include MatchRange
|
20
|
+
include PercentLiteral
|
21
|
+
|
22
|
+
MSG = 'Do not use spaces inside percent literal delimiters.'.freeze
|
23
|
+
BEGIN_REGEX = /\A( +)/
|
24
|
+
END_REGEX = /(?<!\\)( +)\z/
|
25
|
+
|
26
|
+
def on_array(node)
|
27
|
+
process(node, *%w(%i %I %w %W))
|
28
|
+
end
|
29
|
+
|
30
|
+
def on_percent_literal(node)
|
31
|
+
add_offenses_for_unnecessary_spaces(node)
|
32
|
+
end
|
33
|
+
|
34
|
+
def on_xstr(node)
|
35
|
+
add_offenses_for_unnecessary_spaces(node)
|
36
|
+
end
|
37
|
+
|
38
|
+
def autocorrect(node)
|
39
|
+
lambda do |corrector|
|
40
|
+
regex_matches(node) do |match_range|
|
41
|
+
corrector.remove(match_range)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def add_offenses_for_unnecessary_spaces(node)
|
49
|
+
return unless node.single_line?
|
50
|
+
|
51
|
+
regex_matches(node) do |match_range|
|
52
|
+
add_offense(node, match_range, MSG)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def regex_matches(node, &blk)
|
57
|
+
[BEGIN_REGEX, END_REGEX].each do |regex|
|
58
|
+
each_match_range(contents_range(node), regex, &blk)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -20,9 +20,10 @@ module RuboCop
|
|
20
20
|
return if node.loc.is_a?(Parser::Source::Map::Heredoc)
|
21
21
|
|
22
22
|
children = node.children
|
23
|
-
return unless children
|
23
|
+
return unless all_string_literals?(children)
|
24
|
+
|
25
|
+
quote_styles = detect_quote_styles(node)
|
24
26
|
|
25
|
-
quote_styles = children.map { |c| c.loc.begin.source }.uniq
|
26
27
|
if quote_styles.size > 1
|
27
28
|
add_offense(node, :expression, MSG_INCONSISTENT)
|
28
29
|
else
|
@@ -34,6 +35,22 @@ module RuboCop
|
|
34
35
|
|
35
36
|
private
|
36
37
|
|
38
|
+
def all_string_literals?(nodes)
|
39
|
+
nodes.all? { |n| n.str_type? || n.dstr_type? }
|
40
|
+
end
|
41
|
+
|
42
|
+
def detect_quote_styles(node)
|
43
|
+
styles = node.children.map { |c| c.loc.begin }
|
44
|
+
|
45
|
+
# For multi-line strings that only have quote marks
|
46
|
+
# at the beginning of the first line and the end of
|
47
|
+
# the last, the begin and end region of each child
|
48
|
+
# is nil. The quote marks are in the parent node.
|
49
|
+
return [node.loc.begin.source] if styles.all?(&:nil?)
|
50
|
+
|
51
|
+
styles.map(&:source).uniq
|
52
|
+
end
|
53
|
+
|
37
54
|
def message(*)
|
38
55
|
if style == :single_quotes
|
39
56
|
"Prefer single-quoted strings when you don't need string " \
|
@@ -59,13 +76,25 @@ module RuboCop
|
|
59
76
|
def check_multiline_quote_style(node, quote)
|
60
77
|
range = node.source_range
|
61
78
|
children = node.children
|
62
|
-
if quote
|
79
|
+
if unexpected_single_quotes?(quote)
|
63
80
|
add_offense(node, range) if children.all? { |c| wrong_quotes?(c) }
|
64
|
-
elsif quote
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
81
|
+
elsif unexpected_double_quotes?(quote) &&
|
82
|
+
!accept_child_double_quotes?(children)
|
83
|
+
add_offense(node, range)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def unexpected_single_quotes?(quote)
|
88
|
+
quote == "'" && style == :double_quotes
|
89
|
+
end
|
90
|
+
|
91
|
+
def unexpected_double_quotes?(quote)
|
92
|
+
quote == '"' && style == :single_quotes
|
93
|
+
end
|
94
|
+
|
95
|
+
def accept_child_double_quotes?(nodes)
|
96
|
+
nodes.any? do |n|
|
97
|
+
n.dstr_type? || double_quotes_acceptable?(n.str_content)
|
69
98
|
end
|
70
99
|
end
|
71
100
|
end
|
@@ -19,13 +19,9 @@ module RuboCop
|
|
19
19
|
|
20
20
|
def on_array(node)
|
21
21
|
if bracketed_array_of?(:sym, node)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
add_offense(node, :expression, PERCENT_MSG) if style == :percent
|
26
|
-
elsif node.loc.begin && node.loc.begin.source =~ /\A%[iI]/
|
27
|
-
style_detected(:percent)
|
28
|
-
add_offense(node, :expression, ARRAY_MSG) if style == :brackets
|
22
|
+
check_bracketed_array(node)
|
23
|
+
elsif percent_array?(node)
|
24
|
+
check_percent_array(node)
|
29
25
|
end
|
30
26
|
end
|
31
27
|
|
@@ -44,6 +40,23 @@ module RuboCop
|
|
44
40
|
|
45
41
|
private
|
46
42
|
|
43
|
+
def percent_array?(node)
|
44
|
+
node.loc.begin && node.loc.begin.source =~ /\A%[iI]/
|
45
|
+
end
|
46
|
+
|
47
|
+
def check_bracketed_array(node)
|
48
|
+
return if comments_in_array?(node)
|
49
|
+
return if symbols_contain_spaces?(node)
|
50
|
+
|
51
|
+
style_detected(:brackets)
|
52
|
+
add_offense(node, :expression, PERCENT_MSG) if style == :percent
|
53
|
+
end
|
54
|
+
|
55
|
+
def check_percent_array(node)
|
56
|
+
style_detected(:percent)
|
57
|
+
add_offense(node, :expression, ARRAY_MSG) if style == :brackets
|
58
|
+
end
|
59
|
+
|
47
60
|
def comments_in_array?(node)
|
48
61
|
comments = processed_source.comments
|
49
62
|
array_range = node.source_range.to_a
|
@@ -63,7 +76,7 @@ module RuboCop
|
|
63
76
|
def autocorrect(node)
|
64
77
|
syms = node.children.map { |c| c.children[0].to_s }
|
65
78
|
corrected = if style == :percent
|
66
|
-
escape = syms.any? { |s|
|
79
|
+
escape = syms.any? { |s| needs_escaping?(s) }
|
67
80
|
syms = syms.map { |s| escape_string(s) } if escape
|
68
81
|
syms = syms.map { |s| s.gsub(/\)/, '\\)') }
|
69
82
|
if escape
|
@@ -80,10 +93,6 @@ module RuboCop
|
|
80
93
|
corrector.replace(node.source_range, corrected)
|
81
94
|
end
|
82
95
|
end
|
83
|
-
|
84
|
-
def escape_string(string)
|
85
|
-
string.inspect[1..-2].tap { |s| s.gsub!(/\\"/, '"') }
|
86
|
-
end
|
87
96
|
end
|
88
97
|
end
|
89
98
|
end
|