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,198 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Style
|
7
|
+
# Checks the spacing around the keywords.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# something 'test'do|x|
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# while(something)
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# something = 123if test
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# something 'test' do |x|
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# while (something)
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# something = 123 if test
|
28
|
+
class SpaceAroundKeyword < Cop
|
29
|
+
MSG_BEFORE = 'Space before keyword `%s` is missing.'.freeze
|
30
|
+
MSG_AFTER = 'Space after keyword `%s` is missing.'.freeze
|
31
|
+
|
32
|
+
DO = 'do'.freeze
|
33
|
+
ACCEPT_LEFT_PAREN = %w(break next not return super yield).freeze
|
34
|
+
|
35
|
+
def on_and(node)
|
36
|
+
check(node, [:operator].freeze) if node.keyword?
|
37
|
+
end
|
38
|
+
|
39
|
+
def on_block(node)
|
40
|
+
check(node, [:begin, :end].freeze)
|
41
|
+
end
|
42
|
+
|
43
|
+
def on_break(node)
|
44
|
+
check(node, [:keyword].freeze)
|
45
|
+
end
|
46
|
+
|
47
|
+
def on_case(node)
|
48
|
+
check(node, [:keyword, :else].freeze)
|
49
|
+
end
|
50
|
+
|
51
|
+
def on_ensure(node)
|
52
|
+
check(node, [:keyword].freeze)
|
53
|
+
end
|
54
|
+
|
55
|
+
def on_for(node)
|
56
|
+
check(node, [:begin, :end].freeze)
|
57
|
+
end
|
58
|
+
|
59
|
+
def on_if(node)
|
60
|
+
check(node, [:keyword, :else, :begin, :end].freeze, 'then'.freeze)
|
61
|
+
end
|
62
|
+
|
63
|
+
def on_kwbegin(node)
|
64
|
+
check(node, [:begin, :end].freeze, nil)
|
65
|
+
end
|
66
|
+
|
67
|
+
def on_next(node)
|
68
|
+
check(node, [:keyword].freeze)
|
69
|
+
end
|
70
|
+
|
71
|
+
def on_or(node)
|
72
|
+
check(node, [:operator].freeze) if node.keyword?
|
73
|
+
end
|
74
|
+
|
75
|
+
def on_postexe(node)
|
76
|
+
check(node, [:keyword].freeze)
|
77
|
+
end
|
78
|
+
|
79
|
+
def on_preexe(node)
|
80
|
+
check(node, [:keyword].freeze)
|
81
|
+
end
|
82
|
+
|
83
|
+
def on_resbody(node)
|
84
|
+
check(node, [:keyword].freeze)
|
85
|
+
end
|
86
|
+
|
87
|
+
def on_rescue(node)
|
88
|
+
check(node, [:else].freeze)
|
89
|
+
end
|
90
|
+
|
91
|
+
def on_return(node)
|
92
|
+
check(node, [:keyword].freeze)
|
93
|
+
end
|
94
|
+
|
95
|
+
def on_send(node)
|
96
|
+
check(node, [:selector].freeze) if node.keyword_not?
|
97
|
+
end
|
98
|
+
|
99
|
+
def on_super(node)
|
100
|
+
check(node, [:keyword].freeze)
|
101
|
+
end
|
102
|
+
|
103
|
+
def on_until(node)
|
104
|
+
check(node, [:begin, :end, :keyword].freeze)
|
105
|
+
end
|
106
|
+
|
107
|
+
def on_when(node)
|
108
|
+
check(node, [:keyword].freeze)
|
109
|
+
end
|
110
|
+
|
111
|
+
def on_while(node)
|
112
|
+
check(node, [:begin, :end, :keyword].freeze)
|
113
|
+
end
|
114
|
+
|
115
|
+
def on_yield(node)
|
116
|
+
check(node, [:keyword].freeze)
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def check(node, locations, begin_keyword = DO)
|
122
|
+
locations.each do |loc|
|
123
|
+
next unless node.loc.respond_to?(loc)
|
124
|
+
range = node.loc.public_send(loc)
|
125
|
+
next unless range
|
126
|
+
|
127
|
+
case loc
|
128
|
+
when :begin then check_begin(node, range, begin_keyword)
|
129
|
+
when :end then check_end(node, range, begin_keyword)
|
130
|
+
else check_keyword(node, range)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def check_begin(node, range, begin_keyword)
|
136
|
+
return if begin_keyword && !range.is?(begin_keyword)
|
137
|
+
|
138
|
+
check_keyword(node, range)
|
139
|
+
end
|
140
|
+
|
141
|
+
def check_end(node, range, begin_keyword)
|
142
|
+
return if begin_keyword == DO && !do?(node)
|
143
|
+
|
144
|
+
offense(range, MSG_BEFORE) if space_before_missing?(range)
|
145
|
+
end
|
146
|
+
|
147
|
+
def do?(node)
|
148
|
+
node.loc.begin && node.loc.begin.is?(DO)
|
149
|
+
end
|
150
|
+
|
151
|
+
def check_keyword(node, range)
|
152
|
+
offense(range, MSG_BEFORE) if space_before_missing?(range) &&
|
153
|
+
!preceded_by_operator?(node, range)
|
154
|
+
offense(range, MSG_AFTER) if space_after_missing?(range)
|
155
|
+
end
|
156
|
+
|
157
|
+
def offense(range, msg)
|
158
|
+
add_offense(range, range, msg % range.source)
|
159
|
+
end
|
160
|
+
|
161
|
+
def space_before_missing?(range)
|
162
|
+
pos = range.begin_pos - 1
|
163
|
+
return false if pos < 0
|
164
|
+
range.source_buffer.source[pos] !~ /[\s\(\|\{\[;,\*\=]/
|
165
|
+
end
|
166
|
+
|
167
|
+
def space_after_missing?(range)
|
168
|
+
pos = range.end_pos
|
169
|
+
char = range.source_buffer.source[pos]
|
170
|
+
return false unless range.source_buffer.source[pos]
|
171
|
+
return false if accept_left_parenthesis?(range) && char == '('.freeze
|
172
|
+
|
173
|
+
char !~ /[\s;,#\\\)\}\]]/
|
174
|
+
end
|
175
|
+
|
176
|
+
def accept_left_parenthesis?(range)
|
177
|
+
ACCEPT_LEFT_PAREN.include?(range.source)
|
178
|
+
end
|
179
|
+
|
180
|
+
def preceded_by_operator?(node, _range)
|
181
|
+
ancestor = node.ancestors.first
|
182
|
+
return false unless ancestor
|
183
|
+
return true if ancestor.and_type? || ancestor.or_type?
|
184
|
+
return false unless ancestor.send_type?
|
185
|
+
operator?(ancestor.loc.selector.source.to_sym)
|
186
|
+
end
|
187
|
+
|
188
|
+
def autocorrect(range)
|
189
|
+
if space_before_missing?(range)
|
190
|
+
->(corrector) { corrector.insert_before(range, ' '.freeze) }
|
191
|
+
else
|
192
|
+
->(corrector) { corrector.insert_after(range, ' '.freeze) }
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
@@ -39,9 +39,9 @@ module RuboCop
|
|
39
39
|
def on_send(node)
|
40
40
|
if node.loc.operator # aref assignment, attribute assignment
|
41
41
|
on_special_asgn(node)
|
42
|
-
elsif !unary_operation?
|
42
|
+
elsif !node.unary_operation? && !called_with_dot?(node)
|
43
43
|
op = node.loc.selector
|
44
|
-
if operator?(op)
|
44
|
+
if operator?(op.source.to_sym)
|
45
45
|
_, _, right, = *node
|
46
46
|
check_operator(node.loc.selector, right.source_range)
|
47
47
|
end
|
@@ -75,16 +75,6 @@ module RuboCop
|
|
75
75
|
|
76
76
|
private
|
77
77
|
|
78
|
-
def operator?(range)
|
79
|
-
range.source !~ /^\[|\w/
|
80
|
-
end
|
81
|
-
|
82
|
-
def unary_operation?(node)
|
83
|
-
return unless (selector = node.loc.selector)
|
84
|
-
operator?(selector) &&
|
85
|
-
node.source_range.begin_pos == selector.begin_pos
|
86
|
-
end
|
87
|
-
|
88
78
|
def called_with_dot?(node)
|
89
79
|
node.loc.dot
|
90
80
|
end
|
@@ -146,7 +146,7 @@ module RuboCop
|
|
146
146
|
case cop_config['EnforcedStyleForEmptyBraces']
|
147
147
|
when 'space' then :space
|
148
148
|
when 'no_space' then :no_space
|
149
|
-
else
|
149
|
+
else raise 'Unknown EnforcedStyleForEmptyBraces selected!'
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
@@ -82,14 +82,14 @@ module RuboCop
|
|
82
82
|
regular_msg = regular.join('` or `')
|
83
83
|
english_msg = english.join('` or `')
|
84
84
|
|
85
|
-
if regular.
|
85
|
+
if !regular.empty? && !english.empty?
|
86
86
|
format(MSG_BOTH, english_msg, regular_msg, global_var)
|
87
|
-
elsif regular.
|
87
|
+
elsif !regular.empty?
|
88
88
|
format(MSG_REGULAR, regular_msg, global_var)
|
89
|
-
elsif english.
|
89
|
+
elsif !english.empty?
|
90
90
|
format(MSG_ENGLISH, english_msg, global_var)
|
91
91
|
else
|
92
|
-
|
92
|
+
raise 'Bug in SpecialGlobalVars - global var w/o preferred vars!'
|
93
93
|
end
|
94
94
|
else
|
95
95
|
format(MSG_REGULAR, preferred_names(global_var).first, global_var)
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
|
32
32
|
def validate_config
|
33
33
|
if style == :percent && target_ruby_version < 2.0
|
34
|
-
|
34
|
+
raise ValidationError, 'The default `percent` style for the ' \
|
35
35
|
'`Style/SymbolArray` cop is only compatible' \
|
36
36
|
' with Ruby 2.0 and up, but the target Ruby' \
|
37
37
|
" version for your project is 1.9.\nPlease " \
|
@@ -36,7 +36,7 @@ module RuboCop
|
|
36
36
|
begin_pos = sb.source.length - whitespace_at_end.length
|
37
37
|
autocorrect_range = Parser::Source::Range.new(sb, begin_pos,
|
38
38
|
sb.source.length)
|
39
|
-
begin_pos += 1 unless whitespace_at_end.
|
39
|
+
begin_pos += 1 unless whitespace_at_end.empty?
|
40
40
|
report_range = Parser::Source::Range.new(sb, begin_pos,
|
41
41
|
sb.source.length)
|
42
42
|
add_offense(autocorrect_range, report_range,
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Style
|
7
|
+
# This cop checks for receiver.length == 0 predicates and the
|
8
|
+
# negated versions receiver.length > 0 and receiver.length != 0.
|
9
|
+
# These can be replaced with receiver.empty? and
|
10
|
+
# !receiver.empty? respectively.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
#
|
14
|
+
# @bad
|
15
|
+
# [1, 2, 3].length == 0
|
16
|
+
# 0 == "foobar".length
|
17
|
+
# hash.size > 0
|
18
|
+
#
|
19
|
+
# @good
|
20
|
+
# [1, 2, 3].empty?
|
21
|
+
# "foobar".empty?
|
22
|
+
# !hash.empty?
|
23
|
+
class ZeroLengthPredicate < Cop
|
24
|
+
ZERO_MSG = 'Use `empty?` instead of `%s == 0`.'.freeze
|
25
|
+
NONZERO_MSG = 'Use `!empty?` instead of `%s %s %s`.'.freeze
|
26
|
+
|
27
|
+
def on_send(node)
|
28
|
+
zero_length_predicate = zero_length_predicate(node)
|
29
|
+
|
30
|
+
if zero_length_predicate
|
31
|
+
add_offense(node, :expression,
|
32
|
+
format(ZERO_MSG, *zero_length_predicate))
|
33
|
+
end
|
34
|
+
|
35
|
+
nonzero_length_predicate = nonzero_length_predicate(node)
|
36
|
+
|
37
|
+
if nonzero_length_predicate
|
38
|
+
add_offense(node, :expression,
|
39
|
+
format(NONZERO_MSG, *nonzero_length_predicate))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def_node_matcher :zero_length_predicate, <<-END
|
44
|
+
{(send (send _ ${:length :size}) :== (int 0))
|
45
|
+
(send (int 0) :== (send _ ${:length :size}))}
|
46
|
+
END
|
47
|
+
|
48
|
+
def_node_matcher :nonzero_length_predicate, <<-END
|
49
|
+
{(send (send _ ${:length :size}) ${:> :!=} (int $0))
|
50
|
+
(send (int $0) ${:< :!=} (send _ ${:length :size}))}
|
51
|
+
END
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -33,10 +33,31 @@ module RuboCop
|
|
33
33
|
return Lint::Syntax.offenses_from_processed_source(processed_source)
|
34
34
|
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
# The autocorrection process may have to be repeated multiple times
|
37
|
+
# until there are no corrections left to perform
|
38
|
+
# To speed things up, run auto-correcting cops by themselves, and only
|
39
|
+
# run the other cops when no corrections are left
|
40
|
+
autocorrect_cops, other_cops = cops.partition(&:autocorrect?)
|
41
|
+
offenses = []
|
42
|
+
errors = {}
|
43
|
+
|
44
|
+
if autocorrect_cops.any?
|
45
|
+
commissioner = Commissioner.new(autocorrect_cops,
|
46
|
+
forces_for(autocorrect_cops))
|
47
|
+
offenses = commissioner.investigate(processed_source)
|
48
|
+
if autocorrect(processed_source.buffer, autocorrect_cops)
|
49
|
+
# We corrected some errors. Another round of inspection will be
|
50
|
+
# done, and any other offenses will be caught then, so we don't
|
51
|
+
# need to continue.
|
52
|
+
return offenses
|
53
|
+
end
|
54
|
+
errors = commissioner.errors
|
55
|
+
end
|
56
|
+
|
57
|
+
commissioner = Commissioner.new(other_cops, forces_for(other_cops))
|
58
|
+
offenses.concat(commissioner.investigate(processed_source))
|
59
|
+
errors.merge!(commissioner.errors)
|
60
|
+
process_commissioner_errors(processed_source.path, errors)
|
40
61
|
offenses
|
41
62
|
end
|
42
63
|
|
@@ -47,7 +68,11 @@ module RuboCop
|
|
47
68
|
end
|
48
69
|
|
49
70
|
def forces
|
50
|
-
@forces ||=
|
71
|
+
@forces ||= forces_for(cops)
|
72
|
+
end
|
73
|
+
|
74
|
+
def forces_for(cops)
|
75
|
+
Force.all.each_with_object([]) do |force_class, forces|
|
51
76
|
joining_cops = cops.select { |cop| cop.join_force?(force_class) }
|
52
77
|
next if joining_cops.empty?
|
53
78
|
forces << force_class.new(joining_cops)
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -9,6 +9,8 @@ module RuboCop
|
|
9
9
|
include PathUtil
|
10
10
|
extend RuboCop::Sexp
|
11
11
|
|
12
|
+
BYTE_ORDER_MARK = 0xfeff # The Unicode codepoint
|
13
|
+
|
12
14
|
EQUALS_ASGN_NODES = [:lvasgn, :ivasgn, :cvasgn, :gvasgn,
|
13
15
|
:casgn, :masgn].freeze
|
14
16
|
SHORTHAND_ASGN_NODES = [:op_asgn, :or_asgn, :and_asgn].freeze
|
@@ -71,7 +73,7 @@ module RuboCop
|
|
71
73
|
when Parser::AST::Node
|
72
74
|
arg.source_range
|
73
75
|
else
|
74
|
-
|
76
|
+
raise ArgumentError, "Invalid argument #{arg}"
|
75
77
|
end
|
76
78
|
|
77
79
|
source_range.begin.line..source_range.end.line
|
@@ -114,6 +116,19 @@ module RuboCop
|
|
114
116
|
Parser::Source::Range.new(source_buffer, begin_pos, end_pos)
|
115
117
|
end
|
116
118
|
|
119
|
+
# Returns the column attribute of the range, except if the range is on
|
120
|
+
# the first line and there's a byte order mark at the beginning of that
|
121
|
+
# line, in which case 1 is subtracted from the column value. This gives
|
122
|
+
# the column as it appears when viewing the file in an editor.
|
123
|
+
def effective_column(range)
|
124
|
+
if range.line == 1 &&
|
125
|
+
@processed_source.raw_source.codepoints.first == BYTE_ORDER_MARK
|
126
|
+
range.column - 1
|
127
|
+
else
|
128
|
+
range.column
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
117
132
|
def range_with_surrounding_comma(range, side = :both, buffer = nil)
|
118
133
|
buffer ||= @processed_source.buffer
|
119
134
|
src = buffer.source
|