rubocop 0.14.1 → 0.15.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/.rubocop.yml +5 -3
- data/CHANGELOG.md +245 -198
- data/README.md +7 -0
- data/Rakefile +5 -1
- data/config/default.yml +27 -4
- data/config/enabled.yml +18 -4
- data/lib/rubocop.rb +13 -1
- data/lib/rubocop/cli.rb +83 -23
- data/lib/rubocop/config.rb +1 -1
- data/lib/rubocop/cop/cop.rb +31 -6
- data/lib/rubocop/cop/lint/block_alignment.rb +11 -8
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +21 -14
- data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
- data/lib/rubocop/cop/rails/output.rb +35 -0
- data/lib/rubocop/cop/style/{access_control.rb → access_modifier_indentation.rb} +18 -15
- data/lib/rubocop/cop/style/alias.rb +14 -2
- data/lib/rubocop/cop/style/align_hash.rb +174 -109
- data/lib/rubocop/cop/style/autocorrect_alignment.rb +38 -18
- data/lib/rubocop/cop/style/blocks.rb +4 -6
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +3 -3
- data/lib/rubocop/cop/style/cyclomatic_complexity.rb +46 -0
- data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +48 -0
- data/lib/rubocop/cop/style/empty_lines_around_body.rb +62 -0
- data/lib/rubocop/cop/style/end_of_line.rb +6 -2
- data/lib/rubocop/cop/style/favor_modifier.rb +11 -1
- data/lib/rubocop/cop/style/final_newline.rb +10 -4
- data/lib/rubocop/cop/style/hash_syntax.rb +32 -21
- data/lib/rubocop/cop/style/leading_comment_space.rb +9 -0
- data/lib/rubocop/cop/style/method_call_parentheses.rb +11 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +11 -15
- data/lib/rubocop/cop/style/redundant_return.rb +7 -4
- data/lib/rubocop/cop/style/redundant_self.rb +3 -3
- data/lib/rubocop/cop/style/signal_exception.rb +4 -2
- data/lib/rubocop/cop/style/space_after_comma_etc.rb +7 -1
- data/lib/rubocop/cop/style/space_after_control_keyword.rb +6 -0
- data/lib/rubocop/cop/style/space_after_method_name.rb +7 -1
- data/lib/rubocop/cop/style/space_after_not.rb +6 -2
- data/lib/rubocop/cop/style/space_around_block_braces.rb +149 -0
- data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +33 -0
- data/lib/rubocop/cop/style/space_around_operators.rb +169 -0
- data/lib/rubocop/cop/style/space_before_modifier_keyword.rb +6 -0
- data/lib/rubocop/cop/style/space_inside.rb +35 -0
- data/lib/rubocop/cop/style/space_inside_brackets.rb +18 -0
- data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +99 -0
- data/lib/rubocop/cop/style/space_inside_parens.rb +18 -0
- data/lib/rubocop/cop/style/special_global_vars.rb +52 -25
- data/lib/rubocop/cop/style/string_literals.rb +1 -1
- data/lib/rubocop/cop/style/surrounding_space.rb +1 -344
- data/lib/rubocop/cop/style/trailing_blank_lines.rb +17 -5
- data/lib/rubocop/cop/style/trailing_whitespace.rb +9 -5
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -2
- data/lib/rubocop/cop/style/word_array.rb +16 -1
- data/lib/rubocop/cop/team.rb +5 -5
- data/lib/rubocop/cop/util.rb +1 -0
- data/lib/rubocop/formatter/offence_count_formatter.rb +0 -1
- data/lib/rubocop/options.rb +76 -111
- data/lib/rubocop/rake_task.rb +4 -2
- data/lib/rubocop/target_finder.rb +3 -3
- data/lib/rubocop/version.rb +1 -1
- data/spec/rubocop/cli_spec.rb +123 -13
- data/spec/rubocop/config_spec.rb +2 -2
- data/spec/rubocop/cop/lint/rescue_exception_spec.rb +10 -0
- data/spec/rubocop/cop/lint/useless_setter_call_spec.rb +13 -0
- data/spec/rubocop/cop/offence_spec.rb +2 -0
- data/spec/rubocop/cop/rails/output_spec.rb +40 -0
- data/spec/rubocop/cop/style/access_modifier_indentation_spec.rb +243 -0
- data/spec/rubocop/cop/style/alias_spec.rb +8 -0
- data/spec/rubocop/cop/style/align_array_spec.rb +12 -0
- data/spec/rubocop/cop/style/align_hash_spec.rb +15 -0
- data/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb +7 -4
- data/spec/rubocop/cop/style/cyclomatic_complexity_spec.rb +203 -0
- data/spec/rubocop/cop/style/empty_lines_around_access_modifier_spec.rb +56 -0
- data/spec/rubocop/cop/style/empty_lines_around_body_spec.rb +87 -0
- data/spec/rubocop/cop/style/end_of_line_spec.rb +17 -8
- data/spec/rubocop/cop/style/favor_modifier_spec.rb +34 -0
- data/spec/rubocop/cop/style/final_newline_spec.rb +5 -0
- data/spec/rubocop/cop/style/hash_syntax_spec.rb +22 -2
- data/spec/rubocop/cop/style/leading_comment_space_spec.rb +5 -0
- data/spec/rubocop/cop/style/method_call_parentheses_spec.rb +39 -4
- data/spec/rubocop/cop/style/numeric_literals_spec.rb +5 -0
- data/spec/rubocop/cop/style/signal_exception_spec.rb +11 -0
- data/spec/rubocop/cop/style/space_after_colon_spec.rb +7 -0
- data/spec/rubocop/cop/style/space_after_comma_spec.rb +5 -0
- data/spec/rubocop/cop/style/space_after_control_keyword_spec.rb +29 -8
- data/spec/rubocop/cop/style/space_after_method_name_spec.rb +15 -0
- data/spec/rubocop/cop/style/space_after_semicolon_spec.rb +5 -0
- data/spec/rubocop/cop/style/space_around_block_braces_spec.rb +68 -0
- data/spec/rubocop/cop/style/space_around_equals_in_default_parameter_spec.rb +5 -0
- data/spec/rubocop/cop/style/space_around_operators_spec.rb +43 -0
- data/spec/rubocop/cop/style/space_before_modifier_keyword_spec.rb +23 -0
- data/spec/rubocop/cop/style/space_inside_brackets_spec.rb +7 -0
- data/spec/rubocop/cop/style/space_inside_hash_literal_braces_spec.rb +65 -23
- data/spec/rubocop/cop/style/space_inside_parens_spec.rb +7 -0
- data/spec/rubocop/cop/style/special_global_vars_spec.rb +12 -2
- data/spec/rubocop/cop/style/string_literals_spec.rb +6 -0
- data/spec/rubocop/cop/style/symbol_array_spec.rb +5 -7
- data/spec/rubocop/cop/style/trailing_blank_lines_spec.rb +26 -1
- data/spec/rubocop/cop/style/trailing_whitespace_spec.rb +7 -0
- data/spec/rubocop/cop/style/trivial_accessors_spec.rb +8 -0
- data/spec/rubocop/cop/style/word_array_spec.rb +33 -2
- data/spec/rubocop/cop/team_spec.rb +4 -4
- data/spec/rubocop/formatter/json_formatter_spec.rb +1 -1
- data/spec/rubocop/options_spec.rb +5 -96
- data/spec/rubocop/processed_source_spec.rb +3 -3
- data/spec/spec_helper.rb +28 -23
- data/spec/support/mri_syntax_checker.rb +20 -16
- metadata +24 -5
- data/spec/rubocop/cop/style/access_control_spec.rb +0 -164
@@ -9,14 +9,6 @@ module Rubocop
|
|
9
9
|
MSG = 'Separate every 3 digits in the integer portion of a number' \
|
10
10
|
'with underscores(_).'
|
11
11
|
|
12
|
-
def min_digits
|
13
|
-
cop_config['MinDigits']
|
14
|
-
end
|
15
|
-
|
16
|
-
def enough_digits?(number)
|
17
|
-
number.to_s.size >= min_digits
|
18
|
-
end
|
19
|
-
|
20
12
|
def on_int(node)
|
21
13
|
check(node)
|
22
14
|
end
|
@@ -25,15 +17,15 @@ module Rubocop
|
|
25
17
|
check(node)
|
26
18
|
end
|
27
19
|
|
28
|
-
|
29
|
-
value, = *node
|
20
|
+
private
|
30
21
|
|
31
|
-
|
32
|
-
|
22
|
+
def check(node)
|
23
|
+
int = integer_part(node)
|
33
24
|
|
34
|
-
|
35
|
-
|
25
|
+
# TODO: handle non-decimal literals as well
|
26
|
+
return if int.start_with?('0')
|
36
27
|
|
28
|
+
if int.size >= min_digits
|
37
29
|
if int =~ /\d{4}/ || int =~ /_\d{1,2}_/
|
38
30
|
convention(node, :expression)
|
39
31
|
end
|
@@ -41,7 +33,11 @@ module Rubocop
|
|
41
33
|
end
|
42
34
|
|
43
35
|
def integer_part(node)
|
44
|
-
node.loc.expression.source.split('.').first
|
36
|
+
node.loc.expression.source.sub(/^[+-]/, '').split('.').first
|
37
|
+
end
|
38
|
+
|
39
|
+
def min_digits
|
40
|
+
cop_config['MinDigits']
|
45
41
|
end
|
46
42
|
end
|
47
43
|
end
|
@@ -39,10 +39,13 @@ module Rubocop
|
|
39
39
|
|
40
40
|
def autocorrect(node)
|
41
41
|
@corrections << lambda do |corrector|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
if node.children.size > 1
|
43
|
+
kids = node.children.map { |child| child.loc.expression }
|
44
|
+
corrector.insert_before(kids.first, '[')
|
45
|
+
corrector.insert_after(kids.last, ']')
|
46
|
+
end
|
47
|
+
return_kw = range_with_surrounding_space(node.loc.keyword, :right)
|
48
|
+
corrector.remove(return_kw)
|
46
49
|
end
|
47
50
|
end
|
48
51
|
|
@@ -102,9 +102,10 @@ module Rubocop
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def autocorrect(node)
|
105
|
+
receiver, _method_name, *_args = *node
|
105
106
|
@corrections << lambda do |corrector|
|
106
|
-
corrector.
|
107
|
-
|
107
|
+
corrector.remove(receiver.loc.expression)
|
108
|
+
corrector.remove(node.loc.dot)
|
108
109
|
end
|
109
110
|
end
|
110
111
|
|
@@ -133,7 +134,6 @@ module Rubocop
|
|
133
134
|
@allowed_send_nodes << node if receiver && receiver.type == :self
|
134
135
|
end
|
135
136
|
end
|
136
|
-
|
137
137
|
end
|
138
138
|
end
|
139
139
|
end
|
@@ -69,8 +69,10 @@ module Rubocop
|
|
69
69
|
|
70
70
|
if style == :semantic
|
71
71
|
each_command(method_name, node) do |send_node|
|
72
|
-
|
73
|
-
|
72
|
+
unless ignored_node?(send_node)
|
73
|
+
convention(send_node, :selector, message(method_name))
|
74
|
+
ignore_node(send_node)
|
75
|
+
end
|
74
76
|
end
|
75
77
|
else
|
76
78
|
_receiver, selector, _args = *node
|
@@ -14,7 +14,7 @@ module Rubocop
|
|
14
14
|
processed_source.tokens.each_cons(2) do |t1, t2|
|
15
15
|
if kind(t1) && t1.pos.line == t2.pos.line &&
|
16
16
|
t2.pos.column == t1.pos.column + offset(t1)
|
17
|
-
convention(
|
17
|
+
convention(t1, t1.pos, sprintf(MSG, kind(t1)))
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -24,6 +24,12 @@ module Rubocop
|
|
24
24
|
def offset(token)
|
25
25
|
1
|
26
26
|
end
|
27
|
+
|
28
|
+
def autocorrect(token)
|
29
|
+
@corrections << lambda do |corrector|
|
30
|
+
corrector.insert_after(token.pos, ' ')
|
31
|
+
end
|
32
|
+
end
|
27
33
|
end
|
28
34
|
|
29
35
|
# Checks for comma (,) not follwed by some kind of space.
|
@@ -25,7 +25,13 @@ module Rubocop
|
|
25
25
|
expr.begin_pos - 1,
|
26
26
|
expr.begin_pos)
|
27
27
|
if pos_before_left_paren.source =~ /\s/
|
28
|
-
convention(
|
28
|
+
convention(pos_before_left_paren, pos_before_left_paren)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def autocorrect(pos_before_left_paren)
|
33
|
+
@corrections << lambda do |corrector|
|
34
|
+
corrector.remove(pos_before_left_paren)
|
29
35
|
end
|
30
36
|
end
|
31
37
|
end
|
@@ -27,8 +27,12 @@ module Rubocop
|
|
27
27
|
|
28
28
|
def autocorrect(node)
|
29
29
|
@corrections << lambda do |corrector|
|
30
|
-
|
31
|
-
|
30
|
+
receiver, _method_name, *_args = *node
|
31
|
+
space_range =
|
32
|
+
Parser::Source::Range.new(node.loc.selector.source_buffer,
|
33
|
+
node.loc.selector.end_pos,
|
34
|
+
receiver.loc.expression.begin_pos)
|
35
|
+
corrector.remove(space_range)
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# rubocop:disable SymbolName
|
4
|
+
|
5
|
+
module Rubocop
|
6
|
+
module Cop
|
7
|
+
module Style
|
8
|
+
# Checks that block braces have or don't have surrounding space depending
|
9
|
+
# on configuration. For blocks taking parameters, it checks that the left
|
10
|
+
# brace has or doesn't have trailing space depending on configuration.
|
11
|
+
class SpaceAroundBlockBraces < Cop
|
12
|
+
include SurroundingSpace
|
13
|
+
|
14
|
+
def investigate(processed_source)
|
15
|
+
return unless processed_source.ast
|
16
|
+
@processed_source = processed_source
|
17
|
+
|
18
|
+
processed_source.tokens.each_cons(2) do |t1, t2|
|
19
|
+
next if ([t1.pos, t2.pos] - positions_not_to_check).size < 2
|
20
|
+
|
21
|
+
type1, type2 = t1.type, t2.type
|
22
|
+
if [:tLCURLY, :tRCURLY].include?(type2)
|
23
|
+
check(t1, t2)
|
24
|
+
elsif type1 == :tLCURLY
|
25
|
+
if type2 == :tPIPE
|
26
|
+
check_pipe(t1, t2)
|
27
|
+
else
|
28
|
+
check(t1, t2)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def positions_not_to_check
|
35
|
+
@positions_not_to_check ||= begin
|
36
|
+
positions = []
|
37
|
+
ast = @processed_source.ast
|
38
|
+
tokens = @processed_source.tokens
|
39
|
+
|
40
|
+
on_node(:hash, ast) do |hash|
|
41
|
+
b_ix = index_of_first_token(hash)
|
42
|
+
e_ix = index_of_last_token(hash)
|
43
|
+
positions << tokens[b_ix].pos << tokens[e_ix].pos
|
44
|
+
end
|
45
|
+
|
46
|
+
# TODO: Check braces inside string/symbol/regexp/xstr
|
47
|
+
# interpolation.
|
48
|
+
on_node([:dstr, :dsym, :regexp, :xstr], ast) do |s|
|
49
|
+
b_ix = index_of_first_token(s)
|
50
|
+
e_ix = index_of_last_token(s)
|
51
|
+
tokens[b_ix..e_ix].each do |t|
|
52
|
+
positions << t.pos if t.type == :tRCURLY
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
positions
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def check(t1, t2)
|
61
|
+
if t2.text == '{'
|
62
|
+
check_space_outside_left_brace(t1, t2)
|
63
|
+
elsif t1.text == '{' && t2.text == '}'
|
64
|
+
check_empty_braces(t1, t2)
|
65
|
+
elsif cop_config['EnforcedStyle'] == 'space_inside_braces'
|
66
|
+
check_space_inside_braces(t1, t2)
|
67
|
+
else
|
68
|
+
check_no_space_inside_braces(t1, t2)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def check_empty_braces(t1, t2)
|
73
|
+
if cop_config['EnforcedStyleForEmptyBraces'] == 'space'
|
74
|
+
check_space_inside_braces(t1, t2)
|
75
|
+
else
|
76
|
+
check_no_space_inside_braces(t1, t2)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def check_space_inside_braces(t1, t2)
|
81
|
+
unless space_between?(t1, t2)
|
82
|
+
token, what = problem_details(t1, t2)
|
83
|
+
convention(token.pos, token.pos, "Space missing inside #{what}.")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def check_no_space_inside_braces(t1, t2)
|
88
|
+
if space_between?(t1, t2)
|
89
|
+
token, what = problem_details(t1, t2)
|
90
|
+
s = space_range(token)
|
91
|
+
convention(s, s, "Space inside #{what} detected.")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def problem_details(t1, t2)
|
96
|
+
if t1.text == '{'
|
97
|
+
token = t1
|
98
|
+
what = t2.text == '}' ? 'empty braces' : '{'
|
99
|
+
else
|
100
|
+
token = t2
|
101
|
+
what = '}'
|
102
|
+
end
|
103
|
+
[token, what]
|
104
|
+
end
|
105
|
+
|
106
|
+
def check_space_outside_left_brace(t1, t2)
|
107
|
+
if t2.text == '{' && !space_between?(t1, t2)
|
108
|
+
convention(t1.pos, t2.pos, 'Space missing to the left of {.')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def check_pipe(t1, t2)
|
113
|
+
if cop_config['SpaceBeforeBlockParameters']
|
114
|
+
unless space_between?(t1, t2)
|
115
|
+
convention(t2.pos, t1.pos, 'Space between { and | missing.')
|
116
|
+
end
|
117
|
+
elsif space_between?(t1, t2)
|
118
|
+
s = space_range(t1)
|
119
|
+
convention(s, s, 'Space between { and | detected.')
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def space_range(token)
|
124
|
+
src = @processed_source.buffer.source
|
125
|
+
if token.text == '{'
|
126
|
+
b = token.pos.begin_pos + 1
|
127
|
+
e = b + 1
|
128
|
+
e += 1 while src[e] =~ /\s/
|
129
|
+
else
|
130
|
+
e = token.pos.begin_pos
|
131
|
+
b = e - 1
|
132
|
+
b -= 1 while src[b - 1] =~ /\s/
|
133
|
+
end
|
134
|
+
Parser::Source::Range.new(@processed_source.buffer, b, e)
|
135
|
+
end
|
136
|
+
|
137
|
+
def autocorrect(range)
|
138
|
+
@corrections << lambda do |corrector|
|
139
|
+
case range.source
|
140
|
+
when '}', '|' then corrector.insert_before(range, ' ')
|
141
|
+
when ' ' then corrector.remove(range)
|
142
|
+
else corrector.insert_after(range, ' ')
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks that the equals signs in parameter default assignments
|
7
|
+
# have surrounding space.
|
8
|
+
class SpaceAroundEqualsInParameterDefault < Cop
|
9
|
+
include SurroundingSpace
|
10
|
+
MSG = 'Surrounding space missing in default value assignment.'
|
11
|
+
|
12
|
+
def investigate(processed_source)
|
13
|
+
return unless processed_source.ast
|
14
|
+
@processed_source = processed_source
|
15
|
+
on_node(:optarg, processed_source.ast) do |optarg|
|
16
|
+
index = index_of_first_token(optarg)
|
17
|
+
arg, equals, value = processed_source.tokens[index, 3]
|
18
|
+
unless space_between?(arg, equals) && space_between?(equals, value)
|
19
|
+
convention(equals.pos, equals.pos)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def autocorrect(range)
|
25
|
+
@corrections << lambda do |corrector|
|
26
|
+
corrector.insert_before(range, ' ')
|
27
|
+
corrector.insert_after(range, ' ')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks that operators have space around them, except for **
|
7
|
+
# which should not have surrounding space.
|
8
|
+
class SpaceAroundOperators < Cop
|
9
|
+
include SurroundingSpace
|
10
|
+
MSG_MISSING = "Surrounding space missing for operator '%s'."
|
11
|
+
MSG_DETECTED = 'Space around operator ** detected.'
|
12
|
+
|
13
|
+
# rubocop:disable SymbolName
|
14
|
+
BINARY_OPERATORS =
|
15
|
+
[:tEQL, :tAMPER2, :tPIPE, :tCARET, :tPLUS, :tMINUS, :tSTAR2,
|
16
|
+
:tDIVIDE, :tPERCENT, :tEH, :tCOLON, :tANDOP, :tOROP, :tMATCH,
|
17
|
+
:tNMATCH, :tEQ, :tNEQ, :tGT, :tRSHFT, :tGEQ, :tLT,
|
18
|
+
:tLSHFT, :tLEQ, :tASSOC, :tEQQ, :tCMP, :tOP_ASGN]
|
19
|
+
|
20
|
+
def investigate(processed_source)
|
21
|
+
return unless processed_source.ast
|
22
|
+
@processed_source = processed_source
|
23
|
+
tokens = processed_source.tokens
|
24
|
+
tokens.each_cons(3) do |token_before, token, token_after|
|
25
|
+
next if token_before.type == :kDEF # TODO: remove?
|
26
|
+
next if token_before.type == :tDOT # Called as method.
|
27
|
+
next if positions_not_to_check.include?(token.pos)
|
28
|
+
|
29
|
+
case token.type
|
30
|
+
when :tPOW, :tDSTAR
|
31
|
+
if space_on_any_side?(token_before, token, token_after)
|
32
|
+
convention(token_with_surrounding_space(token), token.pos,
|
33
|
+
MSG_DETECTED)
|
34
|
+
end
|
35
|
+
when *BINARY_OPERATORS
|
36
|
+
check_missing_space(token_before, token, token_after)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns an array of positions marking the tokens that this cop
|
42
|
+
# should not check, either because the token is not an operator
|
43
|
+
# or because another cop does the check.
|
44
|
+
def positions_not_to_check
|
45
|
+
@positions_not_to_check ||= begin
|
46
|
+
positions = []
|
47
|
+
positions.concat(do_not_check_block_arg_pipes)
|
48
|
+
positions.concat(do_not_check_param_default)
|
49
|
+
positions.concat(do_not_check_class_lshift_self)
|
50
|
+
positions.concat(do_not_check_def_things)
|
51
|
+
positions.concat(do_not_check_singleton_operator_defs)
|
52
|
+
positions
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def do_not_check_block_arg_pipes
|
57
|
+
# each { |a| }
|
58
|
+
# ^ ^
|
59
|
+
positions = []
|
60
|
+
on_node(:block, @processed_source.ast) do |b|
|
61
|
+
on_node(:args, b) do |a|
|
62
|
+
positions << a.loc.begin << a.loc.end if a.loc.begin
|
63
|
+
end
|
64
|
+
end
|
65
|
+
positions
|
66
|
+
end
|
67
|
+
|
68
|
+
def do_not_check_param_default
|
69
|
+
# func(a, b=nil)
|
70
|
+
# ^
|
71
|
+
positions = []
|
72
|
+
tokens = @processed_source.tokens
|
73
|
+
on_node(:optarg, @processed_source.ast) do |optarg|
|
74
|
+
_arg, equals, _value = tokens[index_of_first_token(optarg),
|
75
|
+
3]
|
76
|
+
positions << equals.pos
|
77
|
+
end
|
78
|
+
positions
|
79
|
+
end
|
80
|
+
|
81
|
+
def do_not_check_class_lshift_self
|
82
|
+
# class <<self
|
83
|
+
# ^
|
84
|
+
positions = []
|
85
|
+
tokens = @processed_source.tokens
|
86
|
+
on_node(:sclass, @processed_source.ast) do |sclass|
|
87
|
+
ix = index_of_first_token(sclass)
|
88
|
+
if tokens[ix, 2].map(&:type) == [:kCLASS, :tLSHFT]
|
89
|
+
positions << tokens[ix + 1].pos
|
90
|
+
end
|
91
|
+
end
|
92
|
+
positions
|
93
|
+
end
|
94
|
+
|
95
|
+
def do_not_check_def_things
|
96
|
+
# def +(other)
|
97
|
+
# ^
|
98
|
+
positions = []
|
99
|
+
tokens = @processed_source.tokens
|
100
|
+
on_node(:def, @processed_source.ast) do |def_node|
|
101
|
+
# def each &block
|
102
|
+
# ^
|
103
|
+
# def each *args
|
104
|
+
# ^
|
105
|
+
on_node([:blockarg, :restarg], def_node) do |arg_node|
|
106
|
+
positions << tokens[index_of_first_token(arg_node)].pos
|
107
|
+
end
|
108
|
+
positions << tokens[index_of_first_token(def_node) + 1].pos
|
109
|
+
end
|
110
|
+
positions
|
111
|
+
end
|
112
|
+
|
113
|
+
def do_not_check_singleton_operator_defs
|
114
|
+
# def self.===(other)
|
115
|
+
# ^
|
116
|
+
positions = []
|
117
|
+
tokens = @processed_source.tokens
|
118
|
+
on_node(:defs, @processed_source.ast) do |defs_node|
|
119
|
+
_receiver, name, _args = *defs_node
|
120
|
+
ix = index_of_first_token(defs_node)
|
121
|
+
name_token = tokens[ix..-1].find { |t| t.text == name.to_s }
|
122
|
+
positions << name_token.pos
|
123
|
+
end
|
124
|
+
positions
|
125
|
+
end
|
126
|
+
|
127
|
+
def check_missing_space(token_before, token, token_after)
|
128
|
+
unless space_on_both_sides?(token_before, token, token_after)
|
129
|
+
text = token.text.to_s + (token.type == :tOP_ASGN ? '=' : '')
|
130
|
+
convention(token_with_surrounding_space(token), token.pos,
|
131
|
+
MSG_MISSING.format(text))
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def token_with_surrounding_space(token)
|
136
|
+
src = @processed_source.buffer.source
|
137
|
+
begin_pos = token.pos.begin_pos
|
138
|
+
begin_pos -= 1 while src[begin_pos - 1] =~ /[ \t]/
|
139
|
+
end_pos = token.pos.end_pos
|
140
|
+
end_pos += 1 while src[end_pos] =~ /[ \t]/
|
141
|
+
Parser::Source::Range.new(@processed_source.buffer, begin_pos,
|
142
|
+
end_pos)
|
143
|
+
end
|
144
|
+
|
145
|
+
def space_on_both_sides?(token_before, token, token_after)
|
146
|
+
space_between?(token_before, token) && space_between?(token,
|
147
|
+
token_after)
|
148
|
+
end
|
149
|
+
|
150
|
+
def space_on_any_side?(token_before, token, token_after)
|
151
|
+
space_between?(token_before, token) || space_between?(token,
|
152
|
+
token_after)
|
153
|
+
end
|
154
|
+
|
155
|
+
def autocorrect(range)
|
156
|
+
@corrections << lambda do |corrector|
|
157
|
+
case range.source
|
158
|
+
when /\*\*/
|
159
|
+
corrector.replace(range, '**')
|
160
|
+
else
|
161
|
+
corrector.insert_before(range, ' ') unless range.source =~ /^\s/
|
162
|
+
corrector.insert_after(range, ' ') unless range.source =~ /\s$/
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|