rubocop 1.13.0 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -1
- data/config/default.yml +68 -8
- data/lib/rubocop.rb +9 -0
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -3
- data/lib/rubocop/cop/bundler/gem_version.rb +99 -0
- data/lib/rubocop/cop/internal_affairs/example_description.rb +1 -1
- data/lib/rubocop/cop/layout/argument_alignment.rb +29 -11
- data/lib/rubocop/cop/layout/case_indentation.rb +57 -9
- data/lib/rubocop/cop/layout/dot_position.rb +7 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +13 -15
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +12 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +34 -9
- data/lib/rubocop/cop/layout/indentation_width.rb +13 -2
- data/lib/rubocop/cop/layout/redundant_line_break.rb +24 -10
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +53 -0
- data/lib/rubocop/cop/layout/space_around_keyword.rb +28 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +6 -0
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +83 -39
- data/lib/rubocop/cop/lint/empty_block.rb +18 -2
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +62 -0
- data/lib/rubocop/cop/lint/literal_as_condition.rb +13 -1
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +32 -17
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +105 -74
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +5 -0
- data/lib/rubocop/cop/lint/symbol_conversion.rb +2 -12
- data/lib/rubocop/cop/lint/unreachable_loop.rb +12 -2
- data/lib/rubocop/cop/lint/unused_block_argument.rb +7 -1
- data/lib/rubocop/cop/lint/void.rb +1 -1
- data/lib/rubocop/cop/migration/department_name.rb +3 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +19 -3
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +6 -0
- data/lib/rubocop/cop/mixin/gem_declaration.rb +13 -0
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +14 -3
- data/lib/rubocop/cop/mixin/string_literals_help.rb +3 -5
- data/lib/rubocop/cop/mixin/symbol_help.rb +13 -0
- data/lib/rubocop/cop/style/class_and_module_children.rb +17 -5
- data/lib/rubocop/cop/style/empty_literal.rb +8 -1
- data/lib/rubocop/cop/style/hash_each_methods.rb +18 -1
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +58 -8
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -4
- data/lib/rubocop/cop/style/in_pattern_then.rb +56 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -1
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +62 -0
- data/lib/rubocop/cop/style/multiline_when_then.rb +2 -11
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +17 -9
- data/lib/rubocop/cop/style/nil_lambda.rb +29 -12
- data/lib/rubocop/cop/style/quoted_symbols.rb +110 -0
- data/lib/rubocop/cop/style/raise_args.rb +2 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
- data/lib/rubocop/cop/style/redundant_self.rb +24 -2
- data/lib/rubocop/cop/style/regexp_literal.rb +9 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +8 -3
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +14 -5
- data/lib/rubocop/cop/style/string_literals.rb +1 -0
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +1 -0
- data/lib/rubocop/cop/style/top_level_method_definition.rb +83 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +65 -0
- data/lib/rubocop/cop/style/when_then.rb +6 -2
- data/lib/rubocop/cop/variable_force/branch.rb +15 -0
- data/lib/rubocop/directive_comment.rb +58 -6
- data/lib/rubocop/formatter/junit_formatter.rb +21 -6
- data/lib/rubocop/options.rb +14 -20
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +10 -2
- data/lib/rubocop/rspec/shared_contexts.rb +4 -0
- data/lib/rubocop/target_finder.rb +9 -2
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +18 -9
@@ -25,11 +25,12 @@ module RuboCop
|
|
25
25
|
#
|
26
26
|
# # good
|
27
27
|
# x += 1
|
28
|
-
class RedundantCopDisableDirective < Base
|
28
|
+
class RedundantCopDisableDirective < Base # rubocop:todo Metrics/ClassLength
|
29
29
|
include RangeHelp
|
30
30
|
extend AutoCorrector
|
31
31
|
|
32
32
|
COP_NAME = 'Lint/RedundantCopDisableDirective'
|
33
|
+
DEPARTMENT_MARKER = 'DEPARTMENT'
|
33
34
|
|
34
35
|
attr_accessor :offenses_to_check
|
35
36
|
|
@@ -41,12 +42,9 @@ module RuboCop
|
|
41
42
|
def on_new_investigation
|
42
43
|
return unless offenses_to_check
|
43
44
|
|
44
|
-
cop_disabled_line_ranges = processed_source.disabled_line_ranges
|
45
|
-
|
46
45
|
redundant_cops = Hash.new { |h, k| h[k] = Set.new }
|
47
46
|
|
48
|
-
each_redundant_disable
|
49
|
-
offenses_to_check) do |comment, redundant_cop|
|
47
|
+
each_redundant_disable do |comment, redundant_cop|
|
50
48
|
redundant_cops[comment].add(redundant_cop)
|
51
49
|
end
|
52
50
|
|
@@ -56,20 +54,31 @@ module RuboCop
|
|
56
54
|
|
57
55
|
private
|
58
56
|
|
57
|
+
def cop_disabled_line_ranges
|
58
|
+
processed_source.disabled_line_ranges
|
59
|
+
end
|
60
|
+
|
61
|
+
def disabled_ranges
|
62
|
+
cop_disabled_line_ranges[COP_NAME] || [0..0]
|
63
|
+
end
|
64
|
+
|
59
65
|
def previous_line_blank?(range)
|
60
66
|
processed_source.buffer.source_line(range.line - 1).blank?
|
61
67
|
end
|
62
68
|
|
63
|
-
def comment_range_with_surrounding_space(
|
64
|
-
if previous_line_blank?(
|
65
|
-
processed_source.comment_config.comment_only_line?(
|
69
|
+
def comment_range_with_surrounding_space(directive_comment_range, line_comment_range)
|
70
|
+
if previous_line_blank?(directive_comment_range) &&
|
71
|
+
processed_source.comment_config.comment_only_line?(directive_comment_range.line) &&
|
72
|
+
directive_comment_range.begin_pos == line_comment_range.begin_pos
|
66
73
|
# When the previous line is blank, it should be retained
|
67
|
-
range_with_surrounding_space(range:
|
74
|
+
range_with_surrounding_space(range: directive_comment_range, side: :right)
|
68
75
|
else
|
69
76
|
# Eat the entire comment, the preceding space, and the preceding
|
70
77
|
# newline if there is one.
|
71
|
-
original_begin =
|
72
|
-
range = range_with_surrounding_space(
|
78
|
+
original_begin = directive_comment_range.begin_pos
|
79
|
+
range = range_with_surrounding_space(
|
80
|
+
range: directive_comment_range, side: :left, newlines: true
|
81
|
+
)
|
73
82
|
|
74
83
|
range_with_surrounding_space(range: range,
|
75
84
|
side: :right,
|
@@ -94,32 +103,34 @@ module RuboCop
|
|
94
103
|
range_with_surrounding_space(range: range, side: :right, newlines: false)
|
95
104
|
end
|
96
105
|
|
97
|
-
def each_redundant_disable(
|
98
|
-
&block)
|
99
|
-
disabled_ranges = cop_disabled_line_ranges[COP_NAME] || [0..0]
|
100
|
-
|
106
|
+
def each_redundant_disable(&block)
|
101
107
|
cop_disabled_line_ranges.each do |cop, line_ranges|
|
102
|
-
each_already_disabled(line_ranges,
|
103
|
-
|
104
|
-
each_line_range(line_ranges, disabled_ranges, offenses, cop, &block)
|
108
|
+
each_already_disabled(cop, line_ranges, &block)
|
109
|
+
each_line_range(cop, line_ranges, &block)
|
105
110
|
end
|
106
111
|
end
|
107
112
|
|
108
|
-
def each_line_range(
|
109
|
-
|
110
|
-
|
111
|
-
comment = processed_source.comment_at_line(line_range.begin)
|
112
|
-
next if ignore_offense?(disabled_ranges, line_range)
|
113
|
+
def each_line_range(cop, line_ranges)
|
114
|
+
line_ranges.each_with_index do |line_range, line_range_index|
|
115
|
+
next if ignore_offense?(line_range)
|
113
116
|
|
114
|
-
|
115
|
-
|
117
|
+
comment = processed_source.comment_at_line(line_range.begin)
|
118
|
+
redundant = if all_disabled?(comment)
|
119
|
+
find_redundant_all(line_range, line_ranges[line_range_index + 1])
|
120
|
+
elsif department_disabled?(cop, comment)
|
121
|
+
find_redundant_department(cop, line_range)
|
122
|
+
else
|
123
|
+
find_redundant_cop(cop, line_range)
|
124
|
+
end
|
125
|
+
|
126
|
+
yield comment, redundant if redundant
|
116
127
|
end
|
117
128
|
end
|
118
129
|
|
119
|
-
def each_already_disabled(
|
130
|
+
def each_already_disabled(cop, line_ranges)
|
120
131
|
line_ranges.each_cons(2) do |previous_range, range|
|
121
|
-
next if ignore_offense?(
|
122
|
-
next
|
132
|
+
next if ignore_offense?(range)
|
133
|
+
next unless followed_ranges?(previous_range, range)
|
123
134
|
|
124
135
|
# If a cop is disabled in a range that begins on the same line as
|
125
136
|
# the end of the previous range, it means that the cop was
|
@@ -130,42 +141,56 @@ module RuboCop
|
|
130
141
|
# Comments disabling all cops don't count since it's reasonable
|
131
142
|
# to disable a few select cops first and then all cops further
|
132
143
|
# down in the code.
|
133
|
-
yield comment if comment && !all_disabled?(comment)
|
144
|
+
yield comment, cop if comment && !all_disabled?(comment)
|
134
145
|
end
|
135
146
|
end
|
136
147
|
|
137
|
-
|
138
|
-
|
139
|
-
if
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
148
|
+
def find_redundant_cop(cop, range)
|
149
|
+
cop_offenses = offenses_to_check.select { |offense| offense.cop_name == cop }
|
150
|
+
cop if range_with_offense?(range, cop_offenses)
|
151
|
+
end
|
152
|
+
|
153
|
+
def find_redundant_all(range, next_range)
|
154
|
+
# If there's a disable all comment followed by a comment
|
155
|
+
# specifically disabling `cop`, we don't report the `all`
|
156
|
+
# comment. If the disable all comment is truly redundant, we will
|
157
|
+
# detect that when examining the comments of another cop, and we
|
158
|
+
# get the full line range for the disable all.
|
159
|
+
has_no_next_range = next_range.nil? || !followed_ranges?(range, next_range)
|
160
|
+
'all' if has_no_next_range && range_with_offense?(range)
|
161
|
+
end
|
162
|
+
|
163
|
+
def find_redundant_department(cop, range)
|
164
|
+
department = cop.split('/').first
|
165
|
+
offenses = offenses_to_check.select { |offense| offense.cop_name.start_with?(department) }
|
166
|
+
add_department_marker(department) if range_with_offense?(range, offenses)
|
167
|
+
end
|
168
|
+
|
169
|
+
def followed_ranges?(range, next_range)
|
170
|
+
range.end == next_range.begin
|
171
|
+
end
|
172
|
+
|
173
|
+
def range_with_offense?(range, offenses = offenses_to_check)
|
174
|
+
offenses.none? { |offense| range.cover?(offense.line) }
|
153
175
|
end
|
154
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
155
176
|
|
156
177
|
def all_disabled?(comment)
|
157
|
-
|
178
|
+
DirectiveComment.new(comment).disabled_all?
|
158
179
|
end
|
159
180
|
|
160
|
-
def ignore_offense?(
|
181
|
+
def ignore_offense?(line_range)
|
161
182
|
disabled_ranges.any? do |range|
|
162
183
|
range.cover?(line_range.min) && range.cover?(line_range.max)
|
163
184
|
end
|
164
185
|
end
|
165
186
|
|
187
|
+
def department_disabled?(cop, comment)
|
188
|
+
directive = DirectiveComment.new(comment)
|
189
|
+
directive.in_directive_department?(cop) && !directive.overridden_by_department?(cop)
|
190
|
+
end
|
191
|
+
|
166
192
|
def directive_count(comment)
|
167
|
-
|
168
|
-
cops_string.split(/,\s*/).size
|
193
|
+
DirectiveComment.new(comment).directive_count
|
169
194
|
end
|
170
195
|
|
171
196
|
def add_offenses(redundant_cops)
|
@@ -179,14 +204,11 @@ module RuboCop
|
|
179
204
|
end
|
180
205
|
|
181
206
|
def add_offense_for_entire_comment(comment, cops)
|
182
|
-
location = comment.
|
183
|
-
|
184
|
-
|
185
|
-
add_offense(
|
186
|
-
location,
|
187
|
-
message: "Unnecessary disabling of #{cop_list.join(', ')}."
|
188
|
-
) do |corrector|
|
189
|
-
range = comment_range_with_surrounding_space(location)
|
207
|
+
location = DirectiveComment.new(comment).range
|
208
|
+
cop_names = cops.sort.map { |c| describe(c) }.join(', ')
|
209
|
+
|
210
|
+
add_offense(location, message: message(cop_names)) do |corrector|
|
211
|
+
range = comment_range_with_surrounding_space(location, comment.loc.expression)
|
190
212
|
corrector.remove(range)
|
191
213
|
end
|
192
214
|
end
|
@@ -197,10 +219,8 @@ module RuboCop
|
|
197
219
|
ranges = cop_ranges.map { |_, r| r }
|
198
220
|
|
199
221
|
cop_ranges.each do |cop, range|
|
200
|
-
|
201
|
-
|
202
|
-
message: "Unnecessary disabling of #{describe(cop)}."
|
203
|
-
) do |corrector|
|
222
|
+
cop_name = describe(cop)
|
223
|
+
add_offense(range, message: message(cop_name)) do |corrector|
|
204
224
|
range = directive_range_in_list(range, ranges)
|
205
225
|
corrector.remove(range)
|
206
226
|
end
|
@@ -208,6 +228,7 @@ module RuboCop
|
|
208
228
|
end
|
209
229
|
|
210
230
|
def cop_range(comment, cop)
|
231
|
+
cop = remove_department_marker(cop)
|
211
232
|
matching_range(comment.loc.expression, cop) ||
|
212
233
|
matching_range(comment.loc.expression, Badge.parse(cop).cop_name) ||
|
213
234
|
raise("Couldn't find #{cop} in comment: #{comment.text}")
|
@@ -230,18 +251,16 @@ module RuboCop
|
|
230
251
|
end
|
231
252
|
|
232
253
|
def describe(cop)
|
233
|
-
if cop == 'all'
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
end
|
244
|
-
end
|
254
|
+
return 'all cops' if cop == 'all'
|
255
|
+
return "`#{remove_department_marker(cop)}` department" if department_marker?(cop)
|
256
|
+
return "`#{cop}`" if all_cop_names.include?(cop)
|
257
|
+
|
258
|
+
similar = NameSimilarity.find_similar_name(cop, all_cop_names)
|
259
|
+
similar ? "`#{cop}` (did you mean `#{similar}`?)" : "`#{cop}` (unknown cop)"
|
260
|
+
end
|
261
|
+
|
262
|
+
def message(cop_names)
|
263
|
+
"Unnecessary disabling of #{cop_names}."
|
245
264
|
end
|
246
265
|
|
247
266
|
def all_cop_names
|
@@ -252,6 +271,18 @@ module RuboCop
|
|
252
271
|
line = range.source_buffer.source_line(range.last_line)
|
253
272
|
(line =~ /\s*\z/) == range.last_column
|
254
273
|
end
|
274
|
+
|
275
|
+
def department_marker?(department)
|
276
|
+
department.start_with?(DEPARTMENT_MARKER)
|
277
|
+
end
|
278
|
+
|
279
|
+
def remove_department_marker(department)
|
280
|
+
department.gsub(DEPARTMENT_MARKER, '')
|
281
|
+
end
|
282
|
+
|
283
|
+
def add_department_marker(department)
|
284
|
+
DEPARTMENT_MARKER + department
|
285
|
+
end
|
255
286
|
end
|
256
287
|
end
|
257
288
|
end
|
@@ -54,6 +54,7 @@ module RuboCop
|
|
54
54
|
directive = DirectiveComment.new(comment)
|
55
55
|
|
56
56
|
cop_names.each do |name|
|
57
|
+
name = name.split('/').first if department?(directive, name)
|
57
58
|
add_offense(
|
58
59
|
range_of_offense(comment, name),
|
59
60
|
message: format(MSG, cop: all_or_name(name))
|
@@ -119,6 +120,10 @@ module RuboCop
|
|
119
120
|
def all_or_name(name)
|
120
121
|
name == 'all' ? 'all cops' : name
|
121
122
|
end
|
123
|
+
|
124
|
+
def department?(directive, name)
|
125
|
+
directive.in_directive_department?(name) && !directive.overridden_by_department?(name)
|
126
|
+
end
|
122
127
|
end
|
123
128
|
end
|
124
129
|
end
|
@@ -66,6 +66,7 @@ module RuboCop
|
|
66
66
|
class SymbolConversion < Base
|
67
67
|
extend AutoCorrector
|
68
68
|
include ConfigurableEnforcedStyle
|
69
|
+
include SymbolHelp
|
69
70
|
|
70
71
|
MSG = 'Unnecessary symbol conversion; use `%<correction>s` instead.'
|
71
72
|
MSG_CONSISTENCY = 'Symbol hash key should be quoted for consistency; ' \
|
@@ -138,10 +139,6 @@ module RuboCop
|
|
138
139
|
node.parent&.array_type? && node.parent&.percent_literal?
|
139
140
|
end
|
140
141
|
|
141
|
-
def hash_key?(node)
|
142
|
-
node.parent&.pair_type? && node == node.parent.child_nodes.first
|
143
|
-
end
|
144
|
-
|
145
142
|
def correct_hash_key(node)
|
146
143
|
# Although some operators can be converted to symbols normally
|
147
144
|
# (ie. `:==`), these are not accepted as hash keys and will
|
@@ -167,7 +164,7 @@ module RuboCop
|
|
167
164
|
next if requires_quotes?(key)
|
168
165
|
next if properly_quoted?(key.source, %("#{key.value}"))
|
169
166
|
|
170
|
-
correction = "#{
|
167
|
+
correction = %("#{key.value}")
|
171
168
|
register_offense(
|
172
169
|
key,
|
173
170
|
correction: correction,
|
@@ -175,13 +172,6 @@ module RuboCop
|
|
175
172
|
)
|
176
173
|
end
|
177
174
|
end
|
178
|
-
|
179
|
-
def quote_type
|
180
|
-
# Use the `Style/StringLiterals` configuration for quoting symbols
|
181
|
-
return '"' unless config.for_cop('Style/StringLiterals')['Enabled']
|
182
|
-
|
183
|
-
config.for_cop('Style/StringLiterals')['EnforcedStyle'] == 'single_quotes' ? "'" : '"'
|
184
|
-
end
|
185
175
|
end
|
186
176
|
end
|
187
177
|
end
|
@@ -87,6 +87,7 @@ module RuboCop
|
|
87
87
|
include IgnoredPattern
|
88
88
|
|
89
89
|
MSG = 'This loop will have at most one iteration.'
|
90
|
+
CONTINUE_KEYWORDS = %i[next redo].freeze
|
90
91
|
|
91
92
|
def on_while(node)
|
92
93
|
check(node)
|
@@ -116,7 +117,10 @@ module RuboCop
|
|
116
117
|
break_statement = statements.find { |statement| break_statement?(statement) }
|
117
118
|
return unless break_statement
|
118
119
|
|
119
|
-
|
120
|
+
unless preceded_by_continue_statement?(break_statement) ||
|
121
|
+
conditional_continue_keyword?(break_statement)
|
122
|
+
add_offense(node)
|
123
|
+
end
|
120
124
|
end
|
121
125
|
|
122
126
|
def statements(node)
|
@@ -177,9 +181,15 @@ module RuboCop
|
|
177
181
|
break_statement.left_siblings.any? do |sibling|
|
178
182
|
next if sibling.loop_keyword? || loop_method?(sibling)
|
179
183
|
|
180
|
-
sibling.each_descendant(
|
184
|
+
sibling.each_descendant(*CONTINUE_KEYWORDS).any?
|
181
185
|
end
|
182
186
|
end
|
187
|
+
|
188
|
+
def conditional_continue_keyword?(break_statement)
|
189
|
+
or_node = break_statement.each_descendant(:or).to_a.last
|
190
|
+
|
191
|
+
or_node && CONTINUE_KEYWORDS.include?(or_node.rhs.type)
|
192
|
+
end
|
183
193
|
end
|
184
194
|
end
|
185
195
|
end
|
@@ -67,11 +67,17 @@ module RuboCop
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def check_argument(variable)
|
70
|
-
return if allowed_block?(variable) ||
|
70
|
+
return if allowed_block?(variable) ||
|
71
|
+
allowed_keyword_argument?(variable) ||
|
72
|
+
used_block_local?(variable)
|
71
73
|
|
72
74
|
super
|
73
75
|
end
|
74
76
|
|
77
|
+
def used_block_local?(variable)
|
78
|
+
variable.explicit_block_local_variable? && !variable.assignments.empty?
|
79
|
+
end
|
80
|
+
|
75
81
|
def allowed_block?(variable)
|
76
82
|
!variable.block_argument? || (ignore_empty_blocks? && empty_block?(variable))
|
77
83
|
end
|
@@ -61,7 +61,9 @@ module RuboCop
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def valid_content_token?(content_token)
|
64
|
-
/\W+/.match?(content_token) ||
|
64
|
+
/\W+/.match?(content_token) ||
|
65
|
+
DISABLING_COPS_CONTENT_TOKEN.match?(content_token) ||
|
66
|
+
Registry.global.department?(content_token)
|
65
67
|
end
|
66
68
|
|
67
69
|
def contain_unexpected_character_for_department_name?(name)
|
@@ -70,17 +70,33 @@ module RuboCop
|
|
70
70
|
def extract_first_element_over_column_limit(node, elements, max)
|
71
71
|
line = node.first_line
|
72
72
|
|
73
|
-
# If
|
74
|
-
#
|
75
|
-
elements.
|
73
|
+
# If a `send` node is not parenthesized, don't move the first element, because it
|
74
|
+
# can result in changed behavior or a syntax error.
|
75
|
+
elements = elements.drop(1) if node.send_type? && !node.parenthesized?
|
76
76
|
|
77
77
|
i = 0
|
78
78
|
i += 1 while within_column_limit?(elements[i], max, line)
|
79
|
+
i = shift_elements_for_heredoc_arg(node, elements, i)
|
80
|
+
|
81
|
+
return if i.nil?
|
79
82
|
return elements.first if i.zero?
|
80
83
|
|
81
84
|
elements[i - 1]
|
82
85
|
end
|
83
86
|
|
87
|
+
# @api private
|
88
|
+
# If a send node contains a heredoc argument, splitting cannot happen
|
89
|
+
# after the heredoc or else it will cause a syntax error.
|
90
|
+
def shift_elements_for_heredoc_arg(node, elements, index)
|
91
|
+
return index unless node.send_type?
|
92
|
+
|
93
|
+
heredoc_index = elements.index { |arg| (arg.str_type? || arg.dstr_type?) && arg.heredoc? }
|
94
|
+
return index unless heredoc_index
|
95
|
+
return nil if heredoc_index.zero?
|
96
|
+
|
97
|
+
heredoc_index >= index ? index : heredoc_index + 1
|
98
|
+
end
|
99
|
+
|
84
100
|
# @api private
|
85
101
|
def within_column_limit?(element, max, line)
|
86
102
|
element && element.loc.column <= max && element.loc.line == line
|