rubocop 0.35.1 → 0.36.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 (385) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +164 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +72 -21
  5. data/bin/rubocop +1 -0
  6. data/config/default.yml +167 -18
  7. data/config/disabled.yml +19 -6
  8. data/config/enabled.yml +159 -14
  9. data/lib/rubocop.rb +67 -26
  10. data/lib/rubocop/ast_node.rb +488 -14
  11. data/lib/rubocop/ast_node/builder.rb +24 -0
  12. data/lib/rubocop/ast_node/sexp.rb +13 -0
  13. data/lib/rubocop/cached_data.rb +58 -0
  14. data/lib/rubocop/cli.rb +47 -10
  15. data/lib/rubocop/comment_config.rb +9 -2
  16. data/lib/rubocop/config.rb +99 -31
  17. data/lib/rubocop/config_loader.rb +23 -14
  18. data/lib/rubocop/config_store.rb +1 -0
  19. data/lib/rubocop/cop/autocorrect_logic.rb +2 -1
  20. data/lib/rubocop/cop/commissioner.rb +3 -5
  21. data/lib/rubocop/cop/cop.rb +23 -17
  22. data/lib/rubocop/cop/corrector.rb +25 -0
  23. data/lib/rubocop/cop/force.rb +1 -0
  24. data/lib/rubocop/cop/ignored_node.rb +3 -2
  25. data/lib/rubocop/cop/lint/ambiguous_operator.rb +2 -1
  26. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +2 -1
  27. data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -3
  28. data/lib/rubocop/cop/lint/block_alignment.rb +29 -91
  29. data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -1
  30. data/lib/rubocop/cop/lint/condition_position.rb +2 -1
  31. data/lib/rubocop/cop/lint/debugger.rb +29 -12
  32. data/lib/rubocop/cop/lint/def_end_alignment.rb +16 -18
  33. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +6 -6
  34. data/lib/rubocop/cop/lint/duplicate_methods.rb +98 -74
  35. data/lib/rubocop/cop/lint/duplicated_key.rb +3 -2
  36. data/lib/rubocop/cop/lint/each_with_object_argument.rb +3 -2
  37. data/lib/rubocop/cop/lint/else_layout.rb +2 -1
  38. data/lib/rubocop/cop/lint/empty_ensure.rb +2 -1
  39. data/lib/rubocop/cop/lint/empty_interpolation.rb +2 -1
  40. data/lib/rubocop/cop/lint/end_alignment.rb +77 -39
  41. data/lib/rubocop/cop/lint/end_in_method.rb +2 -1
  42. data/lib/rubocop/cop/lint/ensure_return.rb +2 -1
  43. data/lib/rubocop/cop/lint/eval.rb +2 -1
  44. data/lib/rubocop/cop/lint/float_out_of_range.rb +31 -0
  45. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +14 -30
  46. data/lib/rubocop/cop/lint/handle_exceptions.rb +2 -1
  47. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +85 -0
  48. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +120 -0
  49. data/lib/rubocop/cop/lint/invalid_character_literal.rb +3 -1
  50. data/lib/rubocop/cop/lint/literal_in_condition.rb +6 -9
  51. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +6 -9
  52. data/lib/rubocop/cop/lint/loop.rb +2 -1
  53. data/lib/rubocop/cop/lint/nested_method_definition.rb +19 -3
  54. data/lib/rubocop/cop/lint/next_without_accumulator.rb +38 -0
  55. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +5 -8
  56. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +8 -6
  57. data/lib/rubocop/cop/lint/rand_one.rb +36 -0
  58. data/lib/rubocop/cop/lint/require_parentheses.rb +6 -5
  59. data/lib/rubocop/cop/lint/rescue_exception.rb +3 -2
  60. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +2 -1
  61. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +6 -4
  62. data/lib/rubocop/cop/lint/syntax.rb +9 -5
  63. data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +3 -2
  64. data/lib/rubocop/cop/lint/unneeded_disable.rb +121 -18
  65. data/lib/rubocop/cop/lint/unreachable_code.rb +5 -4
  66. data/lib/rubocop/cop/lint/unused_block_argument.rb +9 -7
  67. data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -1
  68. data/lib/rubocop/cop/lint/useless_access_modifier.rb +56 -29
  69. data/lib/rubocop/cop/lint/useless_assignment.rb +4 -16
  70. data/lib/rubocop/cop/lint/useless_comparison.rb +3 -2
  71. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +2 -1
  72. data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -20
  73. data/lib/rubocop/cop/lint/void.rb +10 -11
  74. data/lib/rubocop/cop/metrics/abc_size.rb +3 -1
  75. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -1
  76. data/lib/rubocop/cop/metrics/class_length.rb +1 -0
  77. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +4 -2
  78. data/lib/rubocop/cop/metrics/line_length.rb +35 -13
  79. data/lib/rubocop/cop/metrics/method_length.rb +2 -1
  80. data/lib/rubocop/cop/metrics/module_length.rb +1 -0
  81. data/lib/rubocop/cop/metrics/parameter_lists.rb +2 -1
  82. data/lib/rubocop/cop/metrics/perceived_complexity.rb +4 -2
  83. data/lib/rubocop/cop/mixin/access_modifier_node.rb +3 -10
  84. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -0
  85. data/lib/rubocop/cop/mixin/array_hash_indentation.rb +80 -0
  86. data/lib/rubocop/cop/mixin/array_syntax.rb +2 -1
  87. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +14 -20
  88. data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +5 -4
  89. data/lib/rubocop/cop/mixin/check_assignment.rb +20 -15
  90. data/lib/rubocop/cop/mixin/classish_length.rb +1 -0
  91. data/lib/rubocop/cop/mixin/code_length.rb +1 -0
  92. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +17 -15
  93. data/lib/rubocop/cop/mixin/configurable_max.rb +1 -0
  94. data/lib/rubocop/cop/mixin/configurable_naming.rb +4 -0
  95. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +9 -4
  96. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +24 -16
  97. data/lib/rubocop/cop/mixin/first_element_line_break.rb +3 -2
  98. data/lib/rubocop/cop/mixin/hash_node.rb +15 -0
  99. data/lib/rubocop/cop/mixin/if_node.rb +1 -0
  100. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -0
  101. data/lib/rubocop/cop/mixin/method_preference.rb +1 -0
  102. data/lib/rubocop/cop/mixin/min_body_length.rb +1 -0
  103. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +177 -0
  104. data/lib/rubocop/cop/mixin/negative_conditional.rb +1 -0
  105. data/lib/rubocop/cop/mixin/on_method_def.rb +6 -5
  106. data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +1 -0
  107. data/lib/rubocop/cop/mixin/parentheses.rb +22 -0
  108. data/lib/rubocop/cop/mixin/parser_diagnostic.rb +1 -0
  109. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -0
  110. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +79 -0
  111. data/lib/rubocop/cop/mixin/safe_assignment.rb +1 -0
  112. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +2 -1
  113. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +2 -1
  114. data/lib/rubocop/cop/mixin/space_inside.rb +2 -1
  115. data/lib/rubocop/cop/mixin/statement_modifier.rb +6 -5
  116. data/lib/rubocop/cop/mixin/string_help.rb +2 -9
  117. data/lib/rubocop/cop/mixin/string_literals_help.rb +13 -7
  118. data/lib/rubocop/cop/mixin/surrounding_space.rb +3 -2
  119. data/lib/rubocop/cop/mixin/trailing_comma.rb +134 -0
  120. data/lib/rubocop/cop/mixin/unused_argument.rb +1 -0
  121. data/lib/rubocop/cop/offense.rb +19 -14
  122. data/lib/rubocop/cop/performance/case_when_splat.rb +8 -8
  123. data/lib/rubocop/cop/performance/casecmp.rb +54 -0
  124. data/lib/rubocop/cop/performance/count.rb +10 -9
  125. data/lib/rubocop/cop/performance/detect.rb +6 -5
  126. data/lib/rubocop/cop/performance/double_start_end_with.rb +65 -0
  127. data/lib/rubocop/cop/performance/end_with.rb +55 -0
  128. data/lib/rubocop/cop/performance/fixed_size.rb +1 -0
  129. data/lib/rubocop/cop/performance/flat_map.rb +9 -8
  130. data/lib/rubocop/cop/performance/hash_each.rb +86 -0
  131. data/lib/rubocop/cop/performance/lstrip_rstrip.rb +44 -0
  132. data/lib/rubocop/cop/performance/range_include.rb +40 -0
  133. data/lib/rubocop/cop/performance/redundant_block_call.rb +57 -0
  134. data/lib/rubocop/cop/performance/redundant_match.rb +51 -0
  135. data/lib/rubocop/cop/performance/redundant_merge.rb +85 -0
  136. data/lib/rubocop/cop/performance/redundant_sort_by.rb +45 -0
  137. data/lib/rubocop/cop/performance/reverse_each.rb +3 -2
  138. data/lib/rubocop/cop/performance/sample.rb +6 -5
  139. data/lib/rubocop/cop/performance/size.rb +2 -1
  140. data/lib/rubocop/cop/performance/start_with.rb +58 -0
  141. data/lib/rubocop/cop/performance/string_replacement.rb +18 -23
  142. data/lib/rubocop/cop/performance/times_map.rb +49 -0
  143. data/lib/rubocop/cop/rails/action_filter.rb +4 -3
  144. data/lib/rubocop/cop/rails/date.rb +5 -4
  145. data/lib/rubocop/cop/rails/delegate.rb +3 -2
  146. data/lib/rubocop/cop/rails/find_by.rb +20 -14
  147. data/lib/rubocop/cop/rails/find_each.rb +23 -2
  148. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +3 -2
  149. data/lib/rubocop/cop/rails/output.rb +4 -2
  150. data/lib/rubocop/cop/rails/pluralization_grammar.rb +3 -2
  151. data/lib/rubocop/cop/rails/read_write_attribute.rb +5 -7
  152. data/lib/rubocop/cop/rails/scope_args.rb +3 -2
  153. data/lib/rubocop/cop/rails/time_zone.rb +14 -10
  154. data/lib/rubocop/cop/rails/validation.rb +4 -3
  155. data/lib/rubocop/cop/severity.rb +8 -7
  156. data/lib/rubocop/cop/style/access_modifier_indentation.rb +5 -4
  157. data/lib/rubocop/cop/style/accessor_method_name.rb +1 -0
  158. data/lib/rubocop/cop/style/alias.rb +84 -24
  159. data/lib/rubocop/cop/style/align_array.rb +2 -1
  160. data/lib/rubocop/cop/style/align_hash.rb +13 -14
  161. data/lib/rubocop/cop/style/align_parameters.rb +3 -2
  162. data/lib/rubocop/cop/style/and_or.rb +9 -7
  163. data/lib/rubocop/cop/style/array_join.rb +5 -5
  164. data/lib/rubocop/cop/style/ascii_comments.rb +2 -1
  165. data/lib/rubocop/cop/style/ascii_identifiers.rb +2 -1
  166. data/lib/rubocop/cop/style/attr.rb +30 -5
  167. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +3 -3
  168. data/lib/rubocop/cop/style/bare_percent_literals.rb +2 -1
  169. data/lib/rubocop/cop/style/begin_block.rb +2 -1
  170. data/lib/rubocop/cop/style/block_comments.rb +2 -1
  171. data/lib/rubocop/cop/style/block_delimiters.rb +10 -9
  172. data/lib/rubocop/cop/style/block_end_newline.rb +3 -2
  173. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +9 -8
  174. data/lib/rubocop/cop/style/case_equality.rb +2 -1
  175. data/lib/rubocop/cop/style/case_indentation.rb +2 -1
  176. data/lib/rubocop/cop/style/character_literal.rb +11 -7
  177. data/lib/rubocop/cop/style/class_and_module_camel_case.rb +2 -1
  178. data/lib/rubocop/cop/style/class_and_module_children.rb +3 -2
  179. data/lib/rubocop/cop/style/class_check.rb +2 -1
  180. data/lib/rubocop/cop/style/class_methods.rb +2 -1
  181. data/lib/rubocop/cop/style/class_vars.rb +2 -1
  182. data/lib/rubocop/cop/style/closing_parenthesis_indentation.rb +3 -2
  183. data/lib/rubocop/cop/style/collection_methods.rb +2 -1
  184. data/lib/rubocop/cop/style/colon_method_call.rb +3 -2
  185. data/lib/rubocop/cop/style/command_literal.rb +8 -7
  186. data/lib/rubocop/cop/style/comment_annotation.rb +3 -2
  187. data/lib/rubocop/cop/style/comment_indentation.rb +4 -6
  188. data/lib/rubocop/cop/style/conditional_assignment.rb +362 -0
  189. data/lib/rubocop/cop/style/constant_name.rb +2 -1
  190. data/lib/rubocop/cop/style/copyright.rb +7 -6
  191. data/lib/rubocop/cop/style/def_with_parentheses.rb +2 -1
  192. data/lib/rubocop/cop/style/deprecated_hash_methods.rb +3 -2
  193. data/lib/rubocop/cop/style/documentation.rb +7 -11
  194. data/lib/rubocop/cop/style/dot_position.rb +3 -2
  195. data/lib/rubocop/cop/style/double_negation.rb +2 -1
  196. data/lib/rubocop/cop/style/each_with_object.rb +4 -3
  197. data/lib/rubocop/cop/style/else_alignment.rb +3 -2
  198. data/lib/rubocop/cop/style/empty_else.rb +4 -3
  199. data/lib/rubocop/cop/style/empty_line_between_defs.rb +2 -1
  200. data/lib/rubocop/cop/style/empty_lines.rb +10 -4
  201. data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +13 -5
  202. data/lib/rubocop/cop/style/empty_lines_around_block_body.rb +7 -3
  203. data/lib/rubocop/cop/style/empty_lines_around_class_body.rb +6 -3
  204. data/lib/rubocop/cop/style/empty_lines_around_method_body.rb +4 -3
  205. data/lib/rubocop/cop/style/empty_lines_around_module_body.rb +4 -2
  206. data/lib/rubocop/cop/style/empty_literal.rb +20 -5
  207. data/lib/rubocop/cop/style/encoding.rb +8 -11
  208. data/lib/rubocop/cop/style/end_block.rb +3 -1
  209. data/lib/rubocop/cop/style/end_of_line.rb +2 -1
  210. data/lib/rubocop/cop/style/even_odd.rb +4 -3
  211. data/lib/rubocop/cop/style/extra_spacing.rb +110 -74
  212. data/lib/rubocop/cop/style/file_name.rb +103 -6
  213. data/lib/rubocop/cop/style/first_array_element_line_break.rb +3 -2
  214. data/lib/rubocop/cop/style/first_hash_element_line_break.rb +5 -6
  215. data/lib/rubocop/cop/style/first_method_argument_line_break.rb +14 -1
  216. data/lib/rubocop/cop/style/first_method_parameter_line_break.rb +2 -1
  217. data/lib/rubocop/cop/style/first_parameter_indentation.rb +6 -4
  218. data/lib/rubocop/cop/style/flip_flop.rb +2 -1
  219. data/lib/rubocop/cop/style/for.rb +2 -1
  220. data/lib/rubocop/cop/style/format_string.rb +1 -0
  221. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +89 -0
  222. data/lib/rubocop/cop/style/global_vars.rb +2 -1
  223. data/lib/rubocop/cop/style/guard_clause.rb +63 -11
  224. data/lib/rubocop/cop/style/hash_syntax.rb +10 -10
  225. data/lib/rubocop/cop/style/identical_conditional_branches.rb +93 -0
  226. data/lib/rubocop/cop/style/if_inside_else.rb +49 -0
  227. data/lib/rubocop/cop/style/if_unless_modifier.rb +6 -5
  228. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -1
  229. data/lib/rubocop/cop/style/indent_array.rb +89 -38
  230. data/lib/rubocop/cop/style/indent_assignment.rb +43 -0
  231. data/lib/rubocop/cop/style/indent_hash.rb +16 -77
  232. data/lib/rubocop/cop/style/indentation_consistency.rb +2 -1
  233. data/lib/rubocop/cop/style/indentation_width.rb +11 -11
  234. data/lib/rubocop/cop/style/infinite_loop.rb +5 -9
  235. data/lib/rubocop/cop/style/initial_indentation.rb +2 -1
  236. data/lib/rubocop/cop/style/inline_comment.rb +2 -1
  237. data/lib/rubocop/cop/style/lambda.rb +14 -11
  238. data/lib/rubocop/cop/style/lambda_call.rb +4 -4
  239. data/lib/rubocop/cop/style/leading_comment_space.rb +2 -1
  240. data/lib/rubocop/cop/style/line_end_concatenation.rb +3 -1
  241. data/lib/rubocop/cop/style/method_call_parentheses.rb +9 -1
  242. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -2
  243. data/lib/rubocop/cop/style/method_def_parentheses.rb +4 -4
  244. data/lib/rubocop/cop/style/method_name.rb +1 -0
  245. data/lib/rubocop/cop/style/missing_else.rb +5 -3
  246. data/lib/rubocop/cop/style/module_function.rb +2 -1
  247. data/lib/rubocop/cop/style/multiline_array_brace_layout.rb +95 -0
  248. data/lib/rubocop/cop/style/multiline_assignment_layout.rb +91 -0
  249. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -2
  250. data/lib/rubocop/cop/style/multiline_block_layout.rb +11 -9
  251. data/lib/rubocop/cop/style/multiline_if_then.rb +1 -0
  252. data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +137 -0
  253. data/lib/rubocop/cop/style/multiline_operation_indentation.rb +25 -135
  254. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +2 -1
  255. data/lib/rubocop/cop/style/mutable_constant.rb +4 -5
  256. data/lib/rubocop/cop/style/negated_if.rb +3 -3
  257. data/lib/rubocop/cop/style/negated_while.rb +3 -3
  258. data/lib/rubocop/cop/style/nested_modifier.rb +6 -5
  259. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +48 -0
  260. data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -1
  261. data/lib/rubocop/cop/style/next.rb +79 -15
  262. data/lib/rubocop/cop/style/nil_comparison.rb +5 -5
  263. data/lib/rubocop/cop/style/non_nil_check.rb +5 -5
  264. data/lib/rubocop/cop/style/not.rb +5 -9
  265. data/lib/rubocop/cop/style/numeric_literals.rb +5 -4
  266. data/lib/rubocop/cop/style/one_line_conditional.rb +3 -2
  267. data/lib/rubocop/cop/style/op_method.rb +7 -4
  268. data/lib/rubocop/cop/style/option_hash.rb +13 -7
  269. data/lib/rubocop/cop/style/optional_arguments.rb +3 -2
  270. data/lib/rubocop/cop/style/parallel_assignment.rb +40 -16
  271. data/lib/rubocop/cop/style/parentheses_around_condition.rb +3 -16
  272. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +3 -2
  273. data/lib/rubocop/cop/style/percent_q_literals.rb +3 -6
  274. data/lib/rubocop/cop/style/perl_backrefs.rb +4 -3
  275. data/lib/rubocop/cop/style/predicate_name.rb +1 -0
  276. data/lib/rubocop/cop/style/proc.rb +3 -2
  277. data/lib/rubocop/cop/style/raise_args.rb +2 -1
  278. data/lib/rubocop/cop/style/redundant_begin.rb +2 -1
  279. data/lib/rubocop/cop/style/redundant_exception.rb +5 -5
  280. data/lib/rubocop/cop/style/redundant_freeze.rb +5 -4
  281. data/lib/rubocop/cop/style/redundant_parentheses.rb +80 -0
  282. data/lib/rubocop/cop/style/redundant_return.rb +5 -4
  283. data/lib/rubocop/cop/style/redundant_self.rb +7 -8
  284. data/lib/rubocop/cop/style/regexp_literal.rb +9 -8
  285. data/lib/rubocop/cop/style/rescue_ensure_alignment.rb +3 -2
  286. data/lib/rubocop/cop/style/rescue_modifier.rb +11 -9
  287. data/lib/rubocop/cop/style/self_assignment.rb +4 -5
  288. data/lib/rubocop/cop/style/semicolon.rb +3 -2
  289. data/lib/rubocop/cop/style/send.rb +3 -1
  290. data/lib/rubocop/cop/style/signal_exception.rb +5 -3
  291. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -1
  292. data/lib/rubocop/cop/style/single_line_methods.rb +7 -7
  293. data/lib/rubocop/cop/style/space_after_colon.rb +2 -1
  294. data/lib/rubocop/cop/style/space_after_comma.rb +1 -0
  295. data/lib/rubocop/cop/style/space_after_control_keyword.rb +5 -5
  296. data/lib/rubocop/cop/style/space_after_method_name.rb +3 -2
  297. data/lib/rubocop/cop/style/space_after_not.rb +4 -3
  298. data/lib/rubocop/cop/style/space_after_semicolon.rb +1 -0
  299. data/lib/rubocop/cop/style/space_around_block_parameters.rb +8 -7
  300. data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +1 -0
  301. data/lib/rubocop/cop/style/space_around_operators.rb +72 -32
  302. data/lib/rubocop/cop/style/space_before_block_braces.rb +2 -1
  303. data/lib/rubocop/cop/style/space_before_comma.rb +1 -0
  304. data/lib/rubocop/cop/style/space_before_comment.rb +2 -1
  305. data/lib/rubocop/cop/style/{single_space_before_first_arg.rb → space_before_first_arg.rb} +13 -4
  306. data/lib/rubocop/cop/style/space_before_modifier_keyword.rb +4 -3
  307. data/lib/rubocop/cop/style/space_before_semicolon.rb +1 -0
  308. data/lib/rubocop/cop/style/space_inside_block_braces.rb +3 -2
  309. data/lib/rubocop/cop/style/space_inside_brackets.rb +1 -0
  310. data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +4 -1
  311. data/lib/rubocop/cop/style/space_inside_parens.rb +1 -0
  312. data/lib/rubocop/cop/style/space_inside_range_literal.rb +5 -4
  313. data/lib/rubocop/cop/style/space_inside_string_interpolation.rb +8 -17
  314. data/lib/rubocop/cop/style/special_global_vars.rb +97 -52
  315. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +16 -9
  316. data/lib/rubocop/cop/style/string_literals.rb +41 -1
  317. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +2 -1
  318. data/lib/rubocop/cop/style/string_methods.rb +2 -1
  319. data/lib/rubocop/cop/style/struct_inheritance.rb +3 -2
  320. data/lib/rubocop/cop/style/symbol_array.rb +74 -7
  321. data/lib/rubocop/cop/style/symbol_literal.rb +4 -7
  322. data/lib/rubocop/cop/style/symbol_proc.rb +11 -7
  323. data/lib/rubocop/cop/style/tab.rb +25 -2
  324. data/lib/rubocop/cop/style/trailing_blank_lines.rb +1 -2
  325. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
  326. data/lib/rubocop/cop/style/trailing_comma_in_literal.rb +56 -0
  327. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +8 -7
  328. data/lib/rubocop/cop/style/trailing_whitespace.rb +2 -1
  329. data/lib/rubocop/cop/style/trivial_accessors.rb +18 -9
  330. data/lib/rubocop/cop/style/unless_else.rb +2 -1
  331. data/lib/rubocop/cop/style/unneeded_capital_w.rb +4 -3
  332. data/lib/rubocop/cop/style/unneeded_interpolation.rb +87 -0
  333. data/lib/rubocop/cop/style/unneeded_percent_q.rb +23 -7
  334. data/lib/rubocop/cop/style/variable_interpolation.rb +8 -6
  335. data/lib/rubocop/cop/style/variable_name.rb +1 -0
  336. data/lib/rubocop/cop/style/when_then.rb +2 -1
  337. data/lib/rubocop/cop/style/while_until_do.rb +3 -2
  338. data/lib/rubocop/cop/style/while_until_modifier.rb +3 -4
  339. data/lib/rubocop/cop/style/word_array.rb +74 -51
  340. data/lib/rubocop/cop/team.rb +21 -15
  341. data/lib/rubocop/cop/util.rb +102 -69
  342. data/lib/rubocop/cop/variable_force.rb +2 -1
  343. data/lib/rubocop/cop/variable_force/assignment.rb +2 -1
  344. data/lib/rubocop/cop/variable_force/locatable.rb +1 -0
  345. data/lib/rubocop/cop/variable_force/reference.rb +1 -0
  346. data/lib/rubocop/cop/variable_force/scope.rb +2 -1
  347. data/lib/rubocop/cop/variable_force/variable.rb +2 -1
  348. data/lib/rubocop/cop/variable_force/variable_table.rb +2 -1
  349. data/lib/rubocop/error.rb +12 -0
  350. data/lib/rubocop/formatter/base_formatter.rb +10 -1
  351. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -0
  352. data/lib/rubocop/formatter/colorizable.rb +6 -1
  353. data/lib/rubocop/formatter/disabled_config_formatter.rb +29 -15
  354. data/lib/rubocop/formatter/disabled_lines_formatter.rb +3 -1
  355. data/lib/rubocop/formatter/emacs_style_formatter.rb +7 -3
  356. data/lib/rubocop/formatter/file_list_formatter.rb +1 -0
  357. data/lib/rubocop/formatter/formatter_set.rb +10 -19
  358. data/lib/rubocop/formatter/fuubar_style_formatter.rb +2 -1
  359. data/lib/rubocop/formatter/html_formatter.rb +15 -14
  360. data/lib/rubocop/formatter/json_formatter.rb +2 -1
  361. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -0
  362. data/lib/rubocop/formatter/progress_formatter.rb +3 -3
  363. data/lib/rubocop/formatter/simple_text_formatter.rb +50 -17
  364. data/lib/rubocop/formatter/text_util.rb +8 -10
  365. data/lib/rubocop/formatter/worst_offenders_formatter.rb +61 -0
  366. data/lib/rubocop/name_similarity.rb +22 -0
  367. data/lib/rubocop/node_pattern.rb +126 -35
  368. data/lib/rubocop/options.rb +28 -19
  369. data/lib/rubocop/path_util.rb +1 -0
  370. data/lib/rubocop/processed_source.rb +41 -16
  371. data/lib/rubocop/rake_task.rb +6 -9
  372. data/lib/rubocop/remote_config.rb +1 -0
  373. data/lib/rubocop/result_cache.rb +60 -43
  374. data/lib/rubocop/runner.rb +48 -45
  375. data/lib/rubocop/string_util.rb +1 -0
  376. data/lib/rubocop/target_finder.rb +2 -1
  377. data/lib/rubocop/token.rb +1 -0
  378. data/lib/rubocop/version.rb +3 -2
  379. data/lib/rubocop/warning.rb +1 -0
  380. data/relnotes/v0.36.0.md +306 -0
  381. data/rubocop.gemspec +3 -9
  382. metadata +48 -92
  383. data/lib/rubocop/cop/lint/space_before_first_arg.rb +0 -44
  384. data/lib/rubocop/cop/rails/default_scope.rb +0 -33
  385. data/lib/rubocop/cop/style/trailing_comma.rb +0 -182
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -21,7 +22,7 @@ module RuboCop
21
22
  include FirstElementLineBreak
22
23
 
23
24
  MSG = 'Add a line break before the first element of a ' \
24
- 'multi-line array.'
25
+ 'multi-line array.'.freeze
25
26
 
26
27
  def on_array(node)
27
28
  return if !node.loc.begin && !assignment_on_same_line?(node)
@@ -32,7 +33,7 @@ module RuboCop
32
33
  private
33
34
 
34
35
  def assignment_on_same_line?(node)
35
- source = node.loc.expression.source_line[0...node.loc.column]
36
+ source = node.source_range.source_line[0...node.loc.column]
36
37
  source =~ /\s*\=\s*$/
37
38
  end
38
39
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -20,14 +21,12 @@ module RuboCop
20
21
  include FirstElementLineBreak
21
22
 
22
23
  MSG = 'Add a line break before the first element of a ' \
23
- 'multi-line hash.'
24
+ 'multi-line hash.'.freeze
24
25
 
25
26
  def on_hash(node)
26
- if node.loc.begin
27
- check_children_line_break(node, node.children)
28
- elsif method_uses_parens?(node.parent, node)
29
- check_children_line_break(node, node.children, node.parent)
30
- end
27
+ # node.loc.begin tells us whether the hash opens with a {
28
+ # If it doesn't, Style/FirstMethodArgumentLineBreak will handle it
29
+ check_children_line_break(node, node.children) if node.loc.begin
31
30
  end
32
31
  end
33
32
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -24,11 +25,23 @@ module RuboCop
24
25
  include FirstElementLineBreak
25
26
 
26
27
  MSG = 'Add a line break before the first argument of a ' \
27
- 'multi-line method argument list.'
28
+ 'multi-line method argument list.'.freeze
28
29
 
29
30
  def on_send(node)
30
31
  _receiver, _name, *args = *node
31
32
 
33
+ # If there is a trailing hash arg without explicit braces, like this:
34
+ #
35
+ # method(1, 'key1' => value1, 'key2' => value2)
36
+ #
37
+ # ...then each key/value pair is treated as a method 'argument'
38
+ # when determining where line breaks should appear.
39
+ if (last_arg = args.last)
40
+ if last_arg.hash_type? && !last_arg.loc.begin # no explicit {
41
+ args = args.concat(args.pop.children)
42
+ end
43
+ end
44
+
32
45
  check_method_line_break(node, args)
33
46
  end
34
47
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -31,7 +32,7 @@ module RuboCop
31
32
  include FirstElementLineBreak
32
33
 
33
34
  MSG = 'Add a line break before the first parameter of a ' \
34
- 'multi-line method parameter list.'
35
+ 'multi-line method parameter list.'.freeze
35
36
 
36
37
  def on_method_def(node, _method_name, args, _body)
37
38
  check_method_line_break(node, args.to_a)
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -69,13 +70,13 @@ module RuboCop
69
70
 
70
71
  # The node must begin inside the parent, otherwise node is the first
71
72
  # part of a chained method call.
72
- node.loc.expression.begin_pos > parent.loc.expression.begin_pos
73
+ node.source_range.begin_pos > parent.source_range.begin_pos
73
74
  end
74
75
 
75
76
  def base_range(send_node, arg_node)
76
77
  Parser::Source::Range.new(processed_source.buffer,
77
- send_node.loc.expression.begin_pos,
78
- arg_node.loc.expression.begin_pos)
78
+ send_node.source_range.begin_pos,
79
+ arg_node.source_range.begin_pos)
79
80
  end
80
81
 
81
82
  # Returns the column of the given range. For single line ranges, this
@@ -94,7 +95,8 @@ module RuboCop
94
95
  # line.
95
96
  def previous_code_line(line_number)
96
97
  @comment_lines ||=
97
- processed_source.comments
98
+ processed_source
99
+ .comments
98
100
  .select { |c| begins_its_line?(c.loc.expression) }
99
101
  .map { |c| c.loc.line }
100
102
 
@@ -1,11 +1,12 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
5
6
  module Style
6
7
  # This cop looks for uses of flip flop operator
7
8
  class FlipFlop < Cop
8
- MSG = 'Avoid the use of flip flop operators.'
9
+ MSG = 'Avoid the use of flip flop operators.'.freeze
9
10
 
10
11
  def on_iflipflop(node)
11
12
  add_offense(node, :expression)
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -31,7 +32,7 @@ module RuboCop
31
32
  return unless method_name == :each && args.empty?
32
33
 
33
34
  if style == :for
34
- end_pos = method.loc.expression.end_pos
35
+ end_pos = method.source_range.end_pos
35
36
  range = Parser::Source::Range.new(processed_source.buffer,
36
37
  end_pos - EACH_LENGTH,
37
38
  end_pos)
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -0,0 +1,89 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module RuboCop
5
+ module Cop
6
+ module Style
7
+ # This cop is designed to help upgrade to Ruby 3.0. It will add the
8
+ # comment `# frozen_string_literal: true` to the top of files to
9
+ # enable frozen string literals. Frozen string literals will be default
10
+ # in Ruby 3.0. The comment will be added below a shebang and encoding
11
+ # comment. The frozen string literal comment is only valid in Ruby 2.3+.
12
+ class FrozenStringLiteralComment < Cop
13
+ include ConfigurableEnforcedStyle
14
+
15
+ MSG = 'Missing frozen string literal comment.'.freeze
16
+ FROZEN_STRING_LITERAL = '# frozen_string_literal:'.freeze
17
+ FROZEN_STRING_LITERAL_ENABLED = '# frozen_string_literal: true'.freeze
18
+ SHEBANG = '#!'.freeze
19
+
20
+ def_node_matcher :frozen_strings, '{(send {dstr str} :<< ...)
21
+ (send {dstr str} :freeze)}'
22
+
23
+ def investigate(processed_source)
24
+ return unless style == :always
25
+ return if processed_source.buffer.source.empty?
26
+
27
+ return if frozen_string_literal_comment_exists?(processed_source)
28
+
29
+ offense(processed_source)
30
+ end
31
+
32
+ def on_send(node)
33
+ return if target_ruby_version < 2.3 && RUBY_VERSION < '2.3.0'
34
+ return unless style == :when_needed
35
+ return if frozen_string_literal_comment_exists?(processed_source)
36
+
37
+ frozen_strings(node) { offense(processed_source) }
38
+ end
39
+
40
+ def autocorrect(_node)
41
+ lambda do |corrector|
42
+ last_special_comment = last_special_comment(processed_source)
43
+ if last_special_comment.nil?
44
+ corrector.insert_before(processed_source.tokens[0].pos,
45
+ "#{FROZEN_STRING_LITERAL_ENABLED}\n")
46
+ else
47
+ corrector.insert_after(last_special_comment.pos,
48
+ "\n#{FROZEN_STRING_LITERAL_ENABLED}")
49
+ end
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def frozen_string_literal_comment_exists?(processed_source)
56
+ first_three_lines =
57
+ [processed_source[0], processed_source[1], processed_source[2]]
58
+ first_three_lines.compact!
59
+ first_three_lines.any? do |line|
60
+ line.start_with?(FROZEN_STRING_LITERAL)
61
+ end
62
+ end
63
+
64
+ def last_special_comment(processed_source)
65
+ token_number = 0
66
+ if processed_source.tokens[token_number].text.start_with?(SHEBANG)
67
+ token = processed_source.tokens[token_number]
68
+ token_number += 1
69
+ end
70
+
71
+ if processed_source.tokens[token_number].text =~
72
+ Encoding::ENCODING_PATTERN
73
+ token = processed_source.tokens[token_number]
74
+ end
75
+
76
+ token
77
+ end
78
+
79
+ def offense(processed_source)
80
+ last_special_comment = last_special_comment(processed_source)
81
+ last_special_comment ||= processed_source.tokens[0]
82
+ range = source_range(processed_source.buffer, 0, 0)
83
+
84
+ add_offense(last_special_comment, range, MSG)
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -10,7 +11,7 @@ module RuboCop
10
11
  #
11
12
  # Note that backreferences like $1, $2, etc are not global variables.
12
13
  class GlobalVars < Cop
13
- MSG = 'Do not introduce global variables.'
14
+ MSG = 'Do not introduce global variables.'.freeze
14
15
 
15
16
  # predefined global variables their English aliases
16
17
  # http://www.zenspider.com/Languages/Ruby/QuickRef.html
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -24,45 +25,96 @@ module RuboCop
24
25
  # def test
25
26
  # work if something
26
27
  # end
28
+ #
29
+ # # bad
30
+ # if something
31
+ # raise 'exception'
32
+ # else
33
+ # ok
34
+ # end
35
+ #
36
+ # # good
37
+ # raise 'exception' if something
38
+ # ok
27
39
  class GuardClause < Cop
28
40
  include ConfigurableEnforcedStyle
29
41
  include IfNode
30
42
  include MinBodyLength
31
43
 
32
44
  MSG = 'Use a guard clause instead of wrapping the code inside a ' \
33
- 'conditional expression.'
45
+ 'conditional expression.'.freeze
46
+
47
+ def_node_matcher :single_line_control_flow_exit?, <<-PATTERN
48
+ [{(send nil {:raise :fail} ...) return break next} single_line?]
49
+ PATTERN
34
50
 
35
51
  def on_def(node)
36
52
  _, _, body = *node
37
53
  return unless body
38
54
 
39
55
  if if?(body)
40
- check_if_node(body)
41
- elsif body.type == :begin
42
- expressions = *body
43
- last_expr = expressions.last
44
-
45
- check_if_node(last_expr) if if?(last_expr)
56
+ check_trailing_if(body)
57
+ elsif body.begin_type?
58
+ last_expr = body.children.last
59
+ check_trailing_if(last_expr) if if?(last_expr)
46
60
  end
47
61
  end
48
62
 
63
+ def on_if(node)
64
+ cond, body, else_body = *node
65
+
66
+ return unless body && else_body
67
+ # discard modifier ifs and ternary_ops
68
+ return if modifier_if?(node) || ternary_op?(node) || elsif?(node)
69
+
70
+ return unless single_line_control_flow_exit?(body) ||
71
+ single_line_control_flow_exit?(else_body)
72
+ return if cond.multiline?
73
+ return if line_too_long_when_corrected?(node)
74
+
75
+ add_offense(node, :keyword, MSG)
76
+ end
77
+
49
78
  private
50
79
 
51
- def if?(body)
52
- body && body.type == :if
80
+ def if?(node)
81
+ node && node.if_type?
53
82
  end
54
83
 
55
- def check_if_node(node)
56
- _cond, body, else_body = *node
84
+ def elsif?(node)
85
+ node.children.last.if_type?
86
+ end
87
+
88
+ def check_trailing_if(node)
89
+ cond, body, else_body = *node
57
90
 
58
91
  return if body && else_body
59
92
  # discard modifier ifs and ternary_ops
60
93
  return if modifier_if?(node) || ternary_op?(node)
94
+ return if cond.multiline?
61
95
  # discard short ifs
62
96
  return unless min_body_length?(node)
97
+ return if line_too_long_when_corrected?(node)
63
98
 
64
99
  add_offense(node, :keyword, MSG)
65
100
  end
101
+
102
+ def line_too_long_when_corrected?(node)
103
+ cond, body, else_body = *node
104
+
105
+ if single_line_control_flow_exit?(body) || !else_body
106
+ line_too_long?(node, body, 'if', cond)
107
+ else
108
+ line_too_long?(node, else_body, 'unless', cond)
109
+ end
110
+ end
111
+
112
+ def line_too_long?(node, body, keyword, condition)
113
+ max = config.for_cop('Metrics/LineLength')['Max'] || 80
114
+ indent = node.loc.column
115
+ # 2 is for spaces on left and right of keyword
116
+ indent + (body.source + keyword + condition.source).length + 2 > max
117
+ end
66
118
  end
67
119
  end
68
120
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -12,9 +13,9 @@ module RuboCop
12
13
  class HashSyntax < Cop
13
14
  include ConfigurableEnforcedStyle
14
15
 
15
- MSG_19 = 'Use the new Ruby 1.9 hash syntax.'
16
- MSG_RUBY19_NO_MIXED_KEYS = "Don't mix styles in the same hash."
17
- MSG_HASH_ROCKETS = 'Use hash rockets syntax.'
16
+ MSG_19 = 'Use the new Ruby 1.9 hash syntax.'.freeze
17
+ MSG_RUBY19_NO_MIXED_KEYS = "Don't mix styles in the same hash.".freeze
18
+ MSG_HASH_ROCKETS = 'Use hash rockets syntax.'.freeze
18
19
 
19
20
  @force_hash_rockets = false
20
21
 
@@ -95,8 +96,7 @@ module RuboCop
95
96
 
96
97
  return false unless key.sym_type?
97
98
 
98
- sym_name = key.loc.expression.source
99
- valid_19_syntax_symbol?(sym_name)
99
+ valid_19_syntax_symbol?(key.source)
100
100
  end
101
101
 
102
102
  def valid_19_syntax_symbol?(sym_name)
@@ -105,15 +105,15 @@ module RuboCop
105
105
  # Most hash keys can be matched against a simple regex.
106
106
  return true if sym_name =~ /\A[_a-z]\w*[?!]?\z/i
107
107
 
108
- # For more complicated hash keys, let the Parser validate the syntax.
109
- RuboCop::ProcessedSource.new("{ #{sym_name}: :foo }").valid_syntax?
108
+ # For more complicated hash keys, let the parser validate the syntax.
109
+ parse("{ #{sym_name}: :foo }").valid_syntax?
110
110
  end
111
111
 
112
112
  def check(pairs, delim, msg)
113
113
  pairs.each do |pair|
114
114
  if pair.loc.operator && pair.loc.operator.is?(delim)
115
115
  add_offense(pair,
116
- pair.loc.expression.begin.join(pair.loc.operator),
116
+ pair.source_range.begin.join(pair.loc.operator),
117
117
  msg) do
118
118
  opposite_style_detected
119
119
  end
@@ -124,7 +124,7 @@ module RuboCop
124
124
  end
125
125
 
126
126
  def autocorrect_ruby19(corrector, node)
127
- key = node.children.first.loc.expression
127
+ key = node.children.first.source_range
128
128
  op = node.loc.operator
129
129
 
130
130
  range = Parser::Source::Range.new(key.source_buffer,
@@ -135,7 +135,7 @@ module RuboCop
135
135
  end
136
136
 
137
137
  def autocorrect_hash_rockets(corrector, node)
138
- key = node.children.first.loc.expression
138
+ key = node.children.first.source_range
139
139
  op = node.loc.operator
140
140
 
141
141
  corrector.insert_after(key, ' => ')
@@ -0,0 +1,93 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module RuboCop
5
+ module Cop
6
+ module Style
7
+ # This cop checks for identical lines at the end of each branch of a
8
+ # conditional statement.
9
+ #
10
+ # @example
11
+ # @bad
12
+ # if condition
13
+ # do_x
14
+ # do_z
15
+ # else
16
+ # do_y
17
+ # do_z
18
+ # end
19
+ #
20
+ # @good
21
+ # if condition
22
+ # do_x
23
+ # else
24
+ # do_y
25
+ # end
26
+ # do_z
27
+ class IdenticalConditionalBranches < Cop
28
+ include IfNode
29
+
30
+ MSG = 'Move `%s` out of the conditional.'.freeze
31
+
32
+ def on_if(node)
33
+ return if elsif?(node)
34
+ _condition, if_branch, else_branch = *node
35
+ branches = expand_elses(else_branch).unshift(if_branch)
36
+
37
+ # return if any branch is empty. An empty branch can be an `if`
38
+ # without an `else`, or a branch that contains only comments.
39
+ return if branches.any?(&:nil?)
40
+
41
+ check_node(branches)
42
+ end
43
+
44
+ def on_case(node)
45
+ return unless node.loc.else
46
+ _condition, *when_branches, else_branch = *node
47
+ return unless else_branch # empty else
48
+ when_branches = expand_when_branches(when_branches)
49
+
50
+ check_node(when_branches.push(else_branch))
51
+ end
52
+
53
+ private
54
+
55
+ def check_node(branches)
56
+ branches = branches.map { |branch| tail(branch) }
57
+
58
+ return unless branches.all? { |branch| branch == branches[0] }
59
+ branches.each do |branch|
60
+ add_offense(branch, :expression, format(MSG, branch.source))
61
+ end
62
+ end
63
+
64
+ # `elsif` branches show up in the if node as nested `else` branches. We
65
+ # need to recursively iterate over all `else` branches.
66
+ def expand_elses(branch)
67
+ if branch.nil?
68
+ [nil]
69
+ elsif branch.if_type?
70
+ _condition, elsif_branch, else_branch = *branch
71
+ expand_elses(else_branch).unshift(elsif_branch)
72
+ else
73
+ [branch]
74
+ end
75
+ end
76
+
77
+ # `when` nodes contain the entire branch including the condition.
78
+ # We only need the contents of the branch, not the condition.
79
+ def expand_when_branches(when_branches)
80
+ when_branches.map { |branch| branch.children[1] }
81
+ end
82
+
83
+ def tail(node)
84
+ if node && node.begin_type?
85
+ node.children.last
86
+ else
87
+ node
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end