rubocop 0.42.0 → 0.43.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.

Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/assets/output.html.erb +21 -10
  4. data/config/default.yml +32 -2
  5. data/config/disabled.yml +8 -1
  6. data/config/enabled.yml +40 -12
  7. data/lib/rubocop.rb +14 -2
  8. data/lib/rubocop/ast_node.rb +2 -0
  9. data/lib/rubocop/cached_data.rb +13 -11
  10. data/lib/rubocop/cli.rb +5 -5
  11. data/lib/rubocop/config.rb +68 -24
  12. data/lib/rubocop/config_loader.rb +13 -11
  13. data/lib/rubocop/config_loader_resolver.rb +4 -2
  14. data/lib/rubocop/cop/cop.rb +16 -5
  15. data/lib/rubocop/cop/lint/assignment_in_condition.rb +21 -20
  16. data/lib/rubocop/cop/lint/block_alignment.rb +3 -4
  17. data/lib/rubocop/cop/lint/def_end_alignment.rb +2 -3
  18. data/lib/rubocop/cop/lint/duplicate_methods.rb +16 -6
  19. data/lib/rubocop/cop/lint/else_layout.rb +1 -1
  20. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  21. data/lib/rubocop/cop/lint/end_alignment.rb +4 -6
  22. data/lib/rubocop/cop/lint/eval.rb +1 -1
  23. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  24. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +8 -8
  25. data/lib/rubocop/cop/lint/inherit_exception.rb +22 -7
  26. data/lib/rubocop/cop/lint/literal_in_condition.rb +5 -5
  27. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +3 -5
  28. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  29. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +9 -8
  30. data/lib/rubocop/cop/lint/percent_string_array.rb +17 -6
  31. data/lib/rubocop/cop/lint/percent_symbol_array.rb +4 -4
  32. data/lib/rubocop/cop/lint/rand_one.rb +3 -3
  33. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -3
  34. data/lib/rubocop/cop/lint/shadowed_exception.rb +39 -44
  35. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +2 -2
  36. data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +1 -2
  37. data/lib/rubocop/cop/lint/unified_integer.rb +38 -0
  38. data/lib/rubocop/cop/lint/unneeded_disable.rb +51 -38
  39. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +114 -0
  40. data/lib/rubocop/cop/lint/useless_assignment.rb +25 -12
  41. data/lib/rubocop/cop/lint/useless_setter_call.rb +27 -28
  42. data/lib/rubocop/cop/lint/void.rb +2 -4
  43. data/lib/rubocop/cop/mixin/access_modifier_node.rb +5 -5
  44. data/lib/rubocop/cop/mixin/array_hash_indentation.rb +19 -17
  45. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +3 -5
  46. data/lib/rubocop/cop/mixin/configurable_naming.rb +4 -5
  47. data/lib/rubocop/cop/mixin/configurable_numbering.rb +52 -0
  48. data/lib/rubocop/cop/mixin/def_node.rb +28 -0
  49. data/lib/rubocop/cop/mixin/documentation_comment.rb +41 -0
  50. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +18 -13
  51. data/lib/rubocop/cop/mixin/if_node.rb +6 -0
  52. data/lib/rubocop/cop/mixin/match_range.rb +2 -5
  53. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
  54. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +40 -28
  55. data/lib/rubocop/cop/mixin/negative_conditional.rb +6 -6
  56. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -5
  57. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +14 -4
  58. data/lib/rubocop/cop/mixin/safe_mode.rb +23 -0
  59. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +2 -4
  60. data/lib/rubocop/cop/mixin/space_inside.rb +1 -3
  61. data/lib/rubocop/cop/mixin/statement_modifier.rb +30 -20
  62. data/lib/rubocop/cop/mixin/trailing_comma.rb +19 -17
  63. data/lib/rubocop/cop/performance/case_when_splat.rb +16 -41
  64. data/lib/rubocop/cop/performance/casecmp.rb +28 -16
  65. data/lib/rubocop/cop/performance/count.rb +58 -34
  66. data/lib/rubocop/cop/performance/detect.rb +3 -7
  67. data/lib/rubocop/cop/performance/double_start_end_with.rb +17 -13
  68. data/lib/rubocop/cop/performance/fixed_size.rb +19 -14
  69. data/lib/rubocop/cop/performance/flat_map.rb +16 -9
  70. data/lib/rubocop/cop/performance/hash_each.rb +2 -3
  71. data/lib/rubocop/cop/performance/lstrip_rstrip.rb +4 -6
  72. data/lib/rubocop/cop/performance/redundant_match.rb +4 -1
  73. data/lib/rubocop/cop/performance/redundant_merge.rb +63 -32
  74. data/lib/rubocop/cop/performance/redundant_sort_by.rb +8 -7
  75. data/lib/rubocop/cop/performance/reverse_each.rb +1 -4
  76. data/lib/rubocop/cop/performance/size.rb +21 -8
  77. data/lib/rubocop/cop/performance/sort_with_block.rb +54 -0
  78. data/lib/rubocop/cop/performance/string_replacement.rb +3 -7
  79. data/lib/rubocop/cop/rails/delegate.rb +2 -3
  80. data/lib/rubocop/cop/rails/find_by.rb +4 -8
  81. data/lib/rubocop/cop/rails/not_null_column.rb +45 -0
  82. data/lib/rubocop/cop/rails/request_referer.rb +3 -3
  83. data/lib/rubocop/cop/rails/safe_navigation.rb +89 -0
  84. data/lib/rubocop/cop/rails/save_bang.rb +78 -9
  85. data/lib/rubocop/cop/rails/scope_args.rb +3 -1
  86. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +2 -3
  87. data/lib/rubocop/cop/rails/validation.rb +1 -1
  88. data/lib/rubocop/cop/security/json_load.rb +36 -0
  89. data/lib/rubocop/cop/style/alias.rb +1 -1
  90. data/lib/rubocop/cop/style/align_hash.rb +25 -14
  91. data/lib/rubocop/cop/style/and_or.rb +13 -3
  92. data/lib/rubocop/cop/style/array_join.rb +3 -3
  93. data/lib/rubocop/cop/style/ascii_comments.rb +1 -2
  94. data/lib/rubocop/cop/style/ascii_identifiers.rb +1 -2
  95. data/lib/rubocop/cop/style/attr.rb +1 -3
  96. data/lib/rubocop/cop/style/block_comments.rb +2 -6
  97. data/lib/rubocop/cop/style/block_delimiters.rb +35 -21
  98. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +4 -4
  99. data/lib/rubocop/cop/style/case_indentation.rb +1 -3
  100. data/lib/rubocop/cop/style/class_methods.rb +3 -4
  101. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  102. data/lib/rubocop/cop/style/command_literal.rb +15 -8
  103. data/lib/rubocop/cop/style/comment_annotation.rb +1 -2
  104. data/lib/rubocop/cop/style/conditional_assignment.rb +68 -36
  105. data/lib/rubocop/cop/style/copyright.rb +1 -5
  106. data/lib/rubocop/cop/style/def_with_parentheses.rb +3 -5
  107. data/lib/rubocop/cop/style/documentation.rb +28 -56
  108. data/lib/rubocop/cop/style/documentation_method.rb +80 -0
  109. data/lib/rubocop/cop/style/each_for_simple_loop.rb +6 -5
  110. data/lib/rubocop/cop/style/each_with_object.rb +2 -2
  111. data/lib/rubocop/cop/style/else_alignment.rb +10 -9
  112. data/lib/rubocop/cop/style/empty_case_condition.rb +2 -4
  113. data/lib/rubocop/cop/style/empty_else.rb +1 -4
  114. data/lib/rubocop/cop/style/empty_line_between_defs.rb +1 -3
  115. data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +2 -5
  116. data/lib/rubocop/cop/style/encoding.rb +28 -14
  117. data/lib/rubocop/cop/style/even_odd.rb +28 -17
  118. data/lib/rubocop/cop/style/extra_spacing.rb +36 -25
  119. data/lib/rubocop/cop/style/file_name.rb +19 -10
  120. data/lib/rubocop/cop/style/first_parameter_indentation.rb +2 -3
  121. data/lib/rubocop/cop/style/for.rb +12 -8
  122. data/lib/rubocop/cop/style/format_string.rb +1 -1
  123. data/lib/rubocop/cop/style/guard_clause.rb +22 -56
  124. data/lib/rubocop/cop/style/hash_syntax.rb +72 -7
  125. data/lib/rubocop/cop/style/if_unless_modifier.rb +23 -19
  126. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +3 -3
  127. data/lib/rubocop/cop/style/indentation_width.rb +30 -16
  128. data/lib/rubocop/cop/style/infinite_loop.rb +16 -13
  129. data/lib/rubocop/cop/style/initial_indentation.rb +23 -18
  130. data/lib/rubocop/cop/style/inline_comment.rb +16 -3
  131. data/lib/rubocop/cop/style/lambda.rb +22 -10
  132. data/lib/rubocop/cop/style/leading_comment_space.rb +12 -1
  133. data/lib/rubocop/cop/style/line_end_concatenation.rb +24 -6
  134. data/lib/rubocop/cop/style/method_call_parentheses.rb +18 -9
  135. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
  136. data/lib/rubocop/cop/style/method_def_parentheses.rb +3 -4
  137. data/lib/rubocop/cop/style/method_missing.rb +10 -2
  138. data/lib/rubocop/cop/style/module_function.rb +14 -6
  139. data/lib/rubocop/cop/style/multiline_assignment_layout.rb +2 -5
  140. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -5
  141. data/lib/rubocop/cop/style/multiline_block_layout.rb +22 -15
  142. data/lib/rubocop/cop/style/multiline_method_call_brace_layout.rb +9 -0
  143. data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +41 -20
  144. data/lib/rubocop/cop/style/multiline_operation_indentation.rb +6 -6
  145. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +3 -5
  146. data/lib/rubocop/cop/style/mutable_constant.rb +21 -13
  147. data/lib/rubocop/cop/style/negated_if.rb +1 -1
  148. data/lib/rubocop/cop/style/negated_while.rb +3 -3
  149. data/lib/rubocop/cop/style/nested_modifier.rb +2 -4
  150. data/lib/rubocop/cop/style/next.rb +4 -4
  151. data/lib/rubocop/cop/style/non_nil_check.rb +18 -10
  152. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +8 -0
  153. data/lib/rubocop/cop/style/numeric_predicate.rb +9 -9
  154. data/lib/rubocop/cop/style/one_line_conditional.rb +11 -1
  155. data/lib/rubocop/cop/style/op_method.rb +1 -1
  156. data/lib/rubocop/cop/style/option_hash.rb +8 -8
  157. data/lib/rubocop/cop/style/optional_arguments.rb +21 -8
  158. data/lib/rubocop/cop/style/parallel_assignment.rb +51 -35
  159. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  160. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  161. data/lib/rubocop/cop/style/raise_args.rb +2 -2
  162. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  163. data/lib/rubocop/cop/style/redundant_parentheses.rb +26 -15
  164. data/lib/rubocop/cop/style/redundant_return.rb +5 -5
  165. data/lib/rubocop/cop/style/redundant_self.rb +20 -11
  166. data/lib/rubocop/cop/style/regexp_literal.rb +16 -10
  167. data/lib/rubocop/cop/style/rescue_ensure_alignment.rb +8 -6
  168. data/lib/rubocop/cop/style/safe_navigation.rb +125 -0
  169. data/lib/rubocop/cop/style/self_assignment.rb +2 -2
  170. data/lib/rubocop/cop/style/semicolon.rb +9 -10
  171. data/lib/rubocop/cop/style/signal_exception.rb +2 -4
  172. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  173. data/lib/rubocop/cop/style/single_line_methods.rb +18 -11
  174. data/lib/rubocop/cop/style/space_after_method_name.rb +2 -3
  175. data/lib/rubocop/cop/style/space_after_not.rb +4 -6
  176. data/lib/rubocop/cop/style/space_around_block_parameters.rb +1 -2
  177. data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +1 -3
  178. data/lib/rubocop/cop/style/space_around_operators.rb +21 -16
  179. data/lib/rubocop/cop/style/space_before_block_braces.rb +2 -12
  180. data/lib/rubocop/cop/style/space_before_first_arg.rb +1 -3
  181. data/lib/rubocop/cop/style/space_inside_array_percent_literal.rb +1 -1
  182. data/lib/rubocop/cop/style/space_inside_block_braces.rb +33 -40
  183. data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +38 -23
  184. data/lib/rubocop/cop/style/space_inside_percent_literal_delimiters.rb +1 -1
  185. data/lib/rubocop/cop/style/space_inside_string_interpolation.rb +26 -12
  186. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -4
  187. data/lib/rubocop/cop/style/symbol_array.rb +10 -10
  188. data/lib/rubocop/cop/style/symbol_proc.rb +28 -13
  189. data/lib/rubocop/cop/style/ternary_parentheses.rb +35 -5
  190. data/lib/rubocop/cop/style/trailing_blank_lines.rb +2 -4
  191. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +29 -17
  192. data/lib/rubocop/cop/style/trivial_accessors.rb +6 -6
  193. data/lib/rubocop/cop/style/unless_else.rb +2 -6
  194. data/lib/rubocop/cop/style/unneeded_capital_w.rb +8 -4
  195. data/lib/rubocop/cop/style/unneeded_interpolation.rb +4 -5
  196. data/lib/rubocop/cop/style/unneeded_percent_q.rb +13 -7
  197. data/lib/rubocop/cop/style/variable_number.rb +79 -0
  198. data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
  199. data/lib/rubocop/cop/style/word_array.rb +25 -15
  200. data/lib/rubocop/cop/style/zero_length_predicate.rb +2 -0
  201. data/lib/rubocop/cop/util.rb +23 -4
  202. data/lib/rubocop/cop/variable_force.rb +59 -25
  203. data/lib/rubocop/cop/variable_force/locatable.rb +8 -6
  204. data/lib/rubocop/cop/variable_force/variable.rb +2 -2
  205. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  206. data/lib/rubocop/formatter/disabled_config_formatter.rb +16 -11
  207. data/lib/rubocop/formatter/formatter_set.rb +12 -10
  208. data/lib/rubocop/formatter/worst_offenders_formatter.rb +4 -4
  209. data/lib/rubocop/node_pattern.rb +79 -35
  210. data/lib/rubocop/options.rb +4 -4
  211. data/lib/rubocop/processed_source.rb +9 -5
  212. data/lib/rubocop/remote_config.rb +14 -10
  213. data/lib/rubocop/result_cache.rb +14 -6
  214. data/lib/rubocop/runner.rb +55 -34
  215. data/lib/rubocop/string_util.rb +9 -5
  216. data/lib/rubocop/target_finder.rb +1 -1
  217. data/lib/rubocop/token.rb +1 -1
  218. data/lib/rubocop/version.rb +1 -1
  219. metadata +15 -4
  220. data/lib/rubocop/cop/lint/useless_array_splat.rb +0 -56
  221. data/lib/rubocop/cop/performance/push_splat.rb +0 -47
@@ -26,7 +26,7 @@ module RuboCop
26
26
 
27
27
  def on_alias(node)
28
28
  # alias_method can't be used with global variables
29
- return if node.children.any?(&:gvar_type?)
29
+ return if node.each_child_node(:gvar).any?
30
30
  # alias_method can't be used in instance_eval blocks
31
31
  scope_type = scope_type(node)
32
32
  return if scope_type == :instance_eval
@@ -189,7 +189,7 @@ module RuboCop
189
189
  end
190
190
 
191
191
  def hash?(node)
192
- node.respond_to?(:type) && node.type == :hash
192
+ node.respond_to?(:type) && node.hash_type?
193
193
  end
194
194
 
195
195
  def explicit_hash?(node)
@@ -205,25 +205,38 @@ module RuboCop
205
205
  end
206
206
 
207
207
  def autocorrect(node)
208
+ # We can't use the instance variable inside the lambda. That would
209
+ # just give each lambda the same reference and they would all get the
210
+ # last value of each. A local variable fixes the problem.
211
+ key_delta = @column_deltas[:key] || 0
212
+ key, value = *node
213
+
214
+ if value.nil?
215
+ correct_no_value(key_delta, node.source_range)
216
+ else
217
+ correct_key_value(key_delta, key.source_range, value.source_range,
218
+ node.loc.operator)
219
+ end
220
+ end
221
+
222
+ def correct_no_value(key_delta, key)
223
+ ->(corrector) { adjust(corrector, key_delta, key) }
224
+ end
225
+
226
+ def correct_key_value(key_delta, key, value, separator)
208
227
  # We can't use the instance variable inside the lambda. That would
209
228
  # just give each lambda the same reference and they would all get the
210
229
  # last value of each. Some local variables fix the problem.
211
- key_delta = @column_deltas[:key] || 0
212
230
  separator_delta = @column_deltas[:separator] || 0
213
231
  value_delta = @column_deltas[:value] || 0
214
232
 
215
- key, value = *node
216
- key_column = key.source_range.column
233
+ key_column = key.column
217
234
  key_delta = -key_column if key_delta < -key_column
218
235
 
219
236
  lambda do |corrector|
220
- if value.nil?
221
- adjust(corrector, key_delta, node.source_range)
222
- else
223
- adjust(corrector, key_delta, key.source_range)
224
- adjust(corrector, separator_delta, node.loc.operator)
225
- adjust(corrector, value_delta, value.source_range)
226
- end
237
+ adjust(corrector, key_delta, key)
238
+ adjust(corrector, separator_delta, separator)
239
+ adjust(corrector, value_delta, value)
227
240
  end
228
241
  end
229
242
 
@@ -240,9 +253,7 @@ module RuboCop
240
253
  if delta > 0
241
254
  corrector.insert_before(range, ' ' * delta)
242
255
  elsif delta < 0
243
- range = Parser::Source::Range.new(range.source_buffer,
244
- range.begin_pos - delta.abs,
245
- range.begin_pos)
256
+ range = range_between(range.begin_pos - delta.abs, range.begin_pos)
246
257
  corrector.remove(range)
247
258
  end
248
259
  end
@@ -60,7 +60,7 @@ module RuboCop
60
60
 
61
61
  def autocorrect(node)
62
62
  expr1, expr2 = *node
63
- replacement = (node.type == :and ? '&&' : '||')
63
+ replacement = (node.and_type? ? '&&' : '||')
64
64
  lambda do |corrector|
65
65
  [expr1, expr2].each do |expr|
66
66
  if expr.send_type?
@@ -78,12 +78,19 @@ module RuboCop
78
78
  def correct_send(node, corrector)
79
79
  receiver, method_name, *args = *node
80
80
  return correct_not(node, receiver, corrector) if method_name == :!
81
+ return correct_setter(node, corrector) if setter_method?(method_name)
81
82
  return unless correctable_send?(node)
82
83
 
83
84
  corrector.replace(whitespace_before_arg(node), '('.freeze)
84
85
  corrector.insert_after(args.last.source_range, ')'.freeze)
85
86
  end
86
87
 
88
+ def correct_setter(node, corrector)
89
+ receiver, _method_name, *args = *node
90
+ corrector.insert_before(receiver.source_range, '('.freeze)
91
+ corrector.insert_after(args.last.source_range, ')'.freeze)
92
+ end
93
+
87
94
  # ! is a special case:
88
95
  # 'x and !obj.method arg' can be auto-corrected if we
89
96
  # recurse down a level and add parens to 'obj.method arg'
@@ -106,6 +113,10 @@ module RuboCop
106
113
  corrector.insert_after(node.source_range, ')')
107
114
  end
108
115
 
116
+ def setter_method?(method_name)
117
+ method_name.to_s.end_with?('=')
118
+ end
119
+
109
120
  def correctable_send?(node)
110
121
  _receiver, method_name, *args = *node
111
122
  # don't clobber if we already have a starting paren
@@ -117,13 +128,12 @@ module RuboCop
117
128
  end
118
129
 
119
130
  def whitespace_before_arg(node)
120
- sb = node.source_range.source_buffer
121
131
  begin_paren = node.loc.selector.end_pos
122
132
  end_paren = begin_paren
123
133
  # Increment position of parenthesis, unless message is a predicate
124
134
  # method followed by a non-whitespace char (e.g. is_a?String).
125
135
  end_paren += 1 unless node.source =~ /\?[!\S]/
126
- Parser::Source::Range.new(sb, begin_paren, end_paren)
136
+ range_between(begin_paren, end_paren)
127
137
  end
128
138
  end
129
139
  end
@@ -14,8 +14,8 @@ module RuboCop
14
14
 
15
15
  def on_send(node)
16
16
  receiver_node, method_name, *arg_nodes = *node
17
- return unless receiver_node && receiver_node.type == :array &&
18
- method_name == :* && arg_nodes[0].type == :str
17
+ return unless receiver_node && receiver_node.array_type? &&
18
+ method_name == :* && arg_nodes.first.str_type?
19
19
 
20
20
  add_offense(node, :selector)
21
21
  end
@@ -23,7 +23,7 @@ module RuboCop
23
23
  def autocorrect(node)
24
24
  receiver_node, _method_name, *arg_nodes = *node
25
25
  array = receiver_node.source
26
- join_arg = arg_nodes[0].source
26
+ join_arg = arg_nodes.first.source
27
27
 
28
28
  lambda do |corrector|
29
29
  corrector.replace(node.source_range, "#{array}.join(#{join_arg})")
@@ -27,8 +27,7 @@ module RuboCop
27
27
  comment.text.index(first_offense)
28
28
  end_position = start_position + first_offense.length
29
29
 
30
- Parser::Source::Range.new(comment.loc.expression.source_buffer,
31
- start_position, end_position)
30
+ range_between(start_position, end_position)
32
31
  end
33
32
 
34
33
  def first_non_ascii_chars(string)
@@ -25,8 +25,7 @@ module RuboCop
25
25
  identifier.text.index(first_offense)
26
26
  end_position = start_position + first_offense.length
27
27
 
28
- Parser::Source::Range.new(identifier.pos.source_buffer,
29
- start_position, end_position)
28
+ range_between(start_position, end_position)
30
29
  end
31
30
 
32
31
  def first_non_ascii_chars(string)
@@ -20,9 +20,7 @@ module RuboCop
20
20
  attr_expr = attr_name.source_range
21
21
 
22
22
  if setter && (setter.true_type? || setter.false_type?)
23
- remove = Parser::Source::Range.new(node_expr.source_buffer,
24
- attr_expr.end_pos,
25
- node_expr.end_pos)
23
+ remove = range_between(attr_expr.end_pos, node_expr.end_pos)
26
24
  end
27
25
 
28
26
  lambda do |corrector|
@@ -37,12 +37,8 @@ module RuboCop
37
37
  def parts(comment)
38
38
  expr = comment.loc.expression
39
39
  eq_begin = expr.resize(BEGIN_LENGTH)
40
- eq_end = Parser::Source::Range.new(expr.source_buffer,
41
- expr.end_pos - END_LENGTH,
42
- expr.end_pos)
43
- contents = Parser::Source::Range.new(expr.source_buffer,
44
- eq_begin.end_pos,
45
- eq_end.begin_pos)
40
+ eq_end = range_between(expr.end_pos - END_LENGTH, expr.end_pos)
41
+ contents = range_between(eq_begin.end_pos, eq_end.begin_pos)
46
42
  [eq_begin, eq_end, contents]
47
43
  end
48
44
  end
@@ -6,7 +6,7 @@ module RuboCop
6
6
  module Style
7
7
  # Check for uses of braces or do/end around single line or
8
8
  # multi-line blocks.
9
- class BlockDelimiters < Cop # rubocop:disable Metrics/ClassLength
9
+ class BlockDelimiters < Cop
10
10
  include ConfigurableEnforcedStyle
11
11
 
12
12
  def on_send(node)
@@ -73,20 +73,34 @@ module RuboCop
73
73
  def autocorrect(node)
74
74
  return if correction_would_break_code?(node)
75
75
 
76
+ if node.loc.begin.is?('{')
77
+ replace_braces_with_do_end(node.loc)
78
+ else
79
+ replace_do_end_with_braces(node.loc)
80
+ end
81
+ end
82
+
83
+ def replace_braces_with_do_end(loc)
84
+ b = loc.begin
85
+ e = loc.end
86
+
76
87
  lambda do |corrector|
77
- b = node.loc.begin
78
- e = node.loc.end
79
- if b.is?('{')
80
- corrector.insert_before(b, ' ') unless whitespace_before?(b)
81
- corrector.insert_before(e, ' ') unless whitespace_before?(e)
82
- corrector.insert_after(b, ' ') unless whitespace_after?(b)
83
- corrector.replace(b, 'do')
84
- corrector.replace(e, 'end')
85
- else
86
- corrector.insert_after(b, ' ') unless whitespace_after?(b, 2)
87
- corrector.replace(b, '{')
88
- corrector.replace(e, '}')
89
- end
88
+ corrector.insert_before(b, ' ') unless whitespace_before?(b)
89
+ corrector.insert_before(e, ' ') unless whitespace_before?(e)
90
+ corrector.insert_after(b, ' ') unless whitespace_after?(b)
91
+ corrector.replace(b, 'do')
92
+ corrector.replace(e, 'end')
93
+ end
94
+ end
95
+
96
+ def replace_do_end_with_braces(loc)
97
+ b = loc.begin
98
+ e = loc.end
99
+
100
+ lambda do |corrector|
101
+ corrector.insert_after(b, ' ') unless whitespace_after?(b, 2)
102
+ corrector.replace(b, '{')
103
+ corrector.replace(e, '}')
90
104
  end
91
105
  end
92
106
 
@@ -160,13 +174,13 @@ module RuboCop
160
174
  end
161
175
 
162
176
  def correction_would_break_code?(node)
163
- if node.loc.begin.is?('do')
164
- # Converting `obj.method arg do |x| end` to use `{}` would cause
165
- # a syntax error.
166
- send = node.children.first
167
- _receiver, _method_name, *args = *send
168
- !args.empty? && !parentheses?(send)
169
- end
177
+ return unless node.loc.begin.is?('do')
178
+
179
+ # Converting `obj.method arg do |x| end` to use `{}` would cause
180
+ # a syntax error.
181
+ send = node.children.first
182
+ _receiver, _method_name, *args = *send
183
+ !args.empty? && !parentheses?(send)
170
184
  end
171
185
 
172
186
  def ignored_method?(method_name)
@@ -39,13 +39,13 @@ module RuboCop
39
39
  end
40
40
 
41
41
  def check_context_dependent(arg, args)
42
- braces_around_2nd_from_end = args.length > 1 && args[-2].type == :hash
42
+ braces_around_second_from_end = args.length > 1 && args[-2].hash_type?
43
43
  if braces?(arg)
44
- unless braces_around_2nd_from_end
44
+ unless braces_around_second_from_end
45
45
  add_offense(arg.parent, arg.source_range,
46
46
  format(MSG, 'Redundant'))
47
47
  end
48
- elsif braces_around_2nd_from_end
48
+ elsif braces_around_second_from_end
49
49
  add_offense(arg.parent, arg.source_range, format(MSG, 'Missing'))
50
50
  end
51
51
  end
@@ -102,7 +102,7 @@ module RuboCop
102
102
  end
103
103
 
104
104
  def non_empty_hash?(arg)
105
- arg && arg.type == :hash && arg.children.any?
105
+ arg && arg.hash_type? && !arg.children.empty?
106
106
  end
107
107
 
108
108
  def braces?(arg)
@@ -74,9 +74,7 @@ module RuboCop
74
74
  when_column = node.location.keyword.column
75
75
  begin_pos = node.loc.keyword.begin_pos
76
76
 
77
- Parser::Source::Range.new(node.source_range.source_buffer,
78
- begin_pos - when_column,
79
- begin_pos)
77
+ range_between(begin_pos - when_column, begin_pos)
80
78
  end
81
79
 
82
80
  def replacement(node)
@@ -39,11 +39,10 @@ module RuboCop
39
39
  def check(name, node)
40
40
  return unless node
41
41
 
42
- if node.type == :defs
42
+ if node.defs_type?
43
43
  check_defs(name, node)
44
- elsif node.type == :begin
45
- defs_nodes = node.children.compact.select { |n| n.type == :defs }
46
- defs_nodes.each { |n| check_defs(name, n) }
44
+ elsif node.begin_type?
45
+ node.each_child_node(:defs) { |n| check_defs(name, n) }
47
46
  end
48
47
  end
49
48
 
@@ -23,7 +23,7 @@ module RuboCop
23
23
 
24
24
  def on_send(node)
25
25
  _receiver, _method_name, *args = *node
26
- return unless args.size == 1 && args.first.type == :block_pass
26
+ return unless args.one? && args.first.block_pass_type?
27
27
 
28
28
  check_method_node(node)
29
29
  end
@@ -46,23 +46,30 @@ module RuboCop
46
46
  private
47
47
 
48
48
  def check_backtick_literal(node)
49
- return if style == :backticks && !contains_disallowed_backtick?(node)
50
- return if style == :mixed &&
51
- node.single_line? &&
52
- !contains_disallowed_backtick?(node)
49
+ return if allowed_backtick_literal?(node)
53
50
 
54
51
  add_offense(node, :expression, MSG_USE_PERCENT_X)
55
52
  end
56
53
 
57
54
  def check_percent_x_literal(node)
58
- return if style == :backticks && contains_disallowed_backtick?(node)
59
- return if style == :percent_x
60
- return if style == :mixed && node.multiline?
61
- return if style == :mixed && contains_disallowed_backtick?(node)
55
+ return if allowed_percent_x_literal?(node)
62
56
 
63
57
  add_offense(node, :expression, MSG_USE_BACKTICKS)
64
58
  end
65
59
 
60
+ def allowed_backtick_literal?(node)
61
+ style == :backticks && !contains_disallowed_backtick?(node) ||
62
+ style == :mixed && node.single_line? &&
63
+ !contains_disallowed_backtick?(node)
64
+ end
65
+
66
+ def allowed_percent_x_literal?(node)
67
+ style == :backticks && contains_disallowed_backtick?(node) ||
68
+ style == :percent_x ||
69
+ style == :mixed && node.multiline? ||
70
+ style == :mixed && contains_disallowed_backtick?(node)
71
+ end
72
+
66
73
  def contains_disallowed_backtick?(node)
67
74
  !allow_inner_backticks? && contains_backtick?(node)
68
75
  end
@@ -47,8 +47,7 @@ module RuboCop
47
47
 
48
48
  def annotation_range(comment, margin, length)
49
49
  start = comment.loc.expression.begin_pos + margin.length
50
- source_buffer = comment.loc.expression.source_buffer
51
- Parser::Source::Range.new(source_buffer, start, start + length)
50
+ range_between(start, start + length)
52
51
  end
53
52
 
54
53
  def concat_length(*args)
@@ -32,7 +32,7 @@ module RuboCop
32
32
  branch.begin_type? ? [*branch].last : branch
33
33
  end
34
34
 
35
- def lhs(node)
35
+ def lhs(node) # rubocop:disable Metrics/MethodLength
36
36
  case node.type
37
37
  when :send
38
38
  lhs_for_send(node)
@@ -77,17 +77,22 @@ module RuboCop
77
77
 
78
78
  def lhs_for_send(node)
79
79
  receiver = node.receiver.nil? ? '' : node.receiver.source
80
+ method_name = node.method_name
80
81
 
81
- if node.method_name == :[]=
82
+ if method_name == :[]=
82
83
  indices = node.children[2...-1].map(&:source).join(', ')
83
84
  "#{receiver}[#{indices}] = "
84
- elsif node.method_name.to_s.end_with?(EQUAL) &&
85
- ![:!=, :==, :===, :>=, :<=].include?(node.method_name)
86
- "#{receiver}.#{node.method_name[0...-1]} = "
85
+ elsif setter_method?(method_name)
86
+ "#{receiver}.#{method_name[0...-1]} = "
87
87
  else
88
- "#{receiver} #{node.method_name} "
88
+ "#{receiver} #{method_name} "
89
89
  end
90
90
  end
91
+
92
+ def setter_method?(method_name)
93
+ method_name.to_s.end_with?(EQUAL) &&
94
+ ![:!=, :==, :===, :>=, :<=].include?(method_name)
95
+ end
91
96
  end
92
97
 
93
98
  # Check for `if` and `case` statements where each branch is used for
@@ -277,7 +282,7 @@ module RuboCop
277
282
  def assignment_node(node)
278
283
  *_variable, assignment = *node
279
284
 
280
- if assignment.begin_type? && assignment.children.size == 1
285
+ if assignment.begin_type? && assignment.children.one?
281
286
  assignment, = *assignment
282
287
  end
283
288
 
@@ -337,18 +342,22 @@ module RuboCop
337
342
  end
338
343
 
339
344
  def check_node(node, branches)
340
- return unless branches.all?
341
- last_statements = branches.map { |branch| tail(branch) }
342
- return unless lhs_all_match?(last_statements)
343
- return if last_statements.any?(&:masgn_type?)
344
- return unless assignment_types_match?(*last_statements)
345
-
345
+ return unless allowed_statements?(branches)
346
346
  return if single_line_conditions_only? && branches.any?(&:begin_type?)
347
347
  return if correction_exceeds_line_limit?(node, branches)
348
348
 
349
349
  add_offense(node, :expression)
350
350
  end
351
351
 
352
+ def allowed_statements?(branches)
353
+ return false unless branches.all?
354
+
355
+ statements = branches.map { |branch| tail(branch) }
356
+
357
+ lhs_all_match?(statements) && !statements.any?(&:masgn_type?) &&
358
+ assignment_types_match?(*statements)
359
+ end
360
+
352
361
  # If `Metrics/LineLength` is enabled, we do not want to introduce an
353
362
  # offense by auto-correcting this cop. Find the max configured line
354
363
  # length. Find the longest line of condition. Remove the assignment
@@ -357,16 +366,26 @@ module RuboCop
357
366
  # of the longest line + the length of the corrected assignment is
358
367
  # greater than the max configured line length
359
368
  def correction_exceeds_line_limit?(node, branches)
360
- return false unless config.for_cop(LINE_LENGTH)[ENABLED]
369
+ return false unless line_length_cop_enabled?
370
+
361
371
  assignment = lhs(tail(branches[0]))
362
- max_line_length = config.for_cop(LINE_LENGTH)[MAX]
363
- indentation_width = config.for_cop(INDENTATION_WIDTH)[WIDTH] || 2
364
- return true if longest_rhs(branches) + indentation_width +
365
- assignment.length > max_line_length
366
372
 
373
+ longest_rhs_exceeds_line_limit?(branches, assignment) ||
374
+ longest_line_exceeds_line_limit?(node, assignment)
375
+ end
376
+
377
+ def longest_rhs_exceeds_line_limit?(branches, assignment)
378
+ longest_rhs_full_length(branches, assignment) > max_line_length
379
+ end
380
+
381
+ def longest_line_exceeds_line_limit?(node, assignment)
367
382
  longest_line(node, assignment).length > max_line_length
368
383
  end
369
384
 
385
+ def longest_rhs_full_length(branches, assignment)
386
+ longest_rhs(branches) + indentation_width + assignment.length
387
+ end
388
+
370
389
  def longest_line(node, assignment)
371
390
  assignment_regex = /#{Regexp.escape(assignment).gsub(' ', '\s*')}/
372
391
  lines = node.source.lines.map do |line|
@@ -380,9 +399,16 @@ module RuboCop
380
399
  branches.map { |branch| branch.children.last.source.length }.max
381
400
  end
382
401
 
383
- def lines_with_numbers(node)
384
- line_nos = node.loc.line..node.loc.last_line
385
- node.source.lines.zip(line_nos)
402
+ def line_length_cop_enabled?
403
+ config.for_cop(LINE_LENGTH)[ENABLED]
404
+ end
405
+
406
+ def max_line_length
407
+ config.for_cop(LINE_LENGTH)[MAX]
408
+ end
409
+
410
+ def indentation_width
411
+ config.for_cop(INDENTATION_WIDTH)[WIDTH] || 2
386
412
  end
387
413
 
388
414
  def single_line_conditions_only?
@@ -450,21 +476,8 @@ module RuboCop
450
476
  include ConditionalCorrectorHelper
451
477
 
452
478
  def correct(node)
453
- condition, if_branch, else_branch = *node
454
- _variable, *_operator, if_rhs = *if_branch
455
- _else_variable, *_operator, else_rhs = *else_branch
456
- condition = condition.source
457
- if_rhs = if_rhs.source
458
- else_rhs = else_rhs.source
459
-
460
- ternary = "#{condition} ? #{if_rhs} : #{else_rhs}"
461
- if if_branch.send_type? && if_branch.method_name != :[]=
462
- ternary = "(#{ternary})"
463
- end
464
- correction = "#{lhs(if_branch)}#{ternary}"
465
-
466
479
  lambda do |corrector|
467
- corrector.replace(node.source_range, correction)
480
+ corrector.replace(node.source_range, correction(node))
468
481
  end
469
482
  end
470
483
 
@@ -484,9 +497,28 @@ module RuboCop
484
497
 
485
498
  private
486
499
 
500
+ def correction(node)
501
+ condition, if_branch, else_branch = *node
502
+
503
+ "#{lhs(if_branch)}#{ternary(condition, if_branch, else_branch)}"
504
+ end
505
+
506
+ def ternary(condition, if_branch, else_branch)
507
+ _variable, *_operator, if_rhs = *if_branch
508
+ _else_variable, *_operator, else_rhs = *else_branch
509
+
510
+ expr = "#{condition.source} ? #{if_rhs.source} : #{else_rhs.source}"
511
+
512
+ element_assignment?(if_branch) ? "(#{expr})" : expr
513
+ end
514
+
515
+ def element_assignment?(node)
516
+ node.send_type? && node.method_name != :[]=
517
+ end
518
+
487
519
  def extract_branches(node)
488
520
  *_var, rhs = *node
489
- condition, = *rhs if rhs.begin_type? && rhs.children.size == 1
521
+ condition, = *rhs if rhs.begin_type? && rhs.children.one?
490
522
  _condition, if_branch, else_branch = *(condition || rhs)
491
523
 
492
524
  [if_branch, else_branch]