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,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 checks for uses of the case equality operator(===).
7
8
  class CaseEquality < Cop
8
- MSG = 'Avoid the use of the case equality operator `===`.'
9
+ MSG = 'Avoid the use of the case equality operator `===`.'.freeze
9
10
 
10
11
  def on_send(node)
11
12
  _receiver, method_name, *_args = *node
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -64,7 +65,7 @@ module RuboCop
64
65
 
65
66
  def autocorrect(node)
66
67
  when_column = node.location.keyword.column
67
- source_buffer = node.loc.expression.source_buffer
68
+ source_buffer = node.source_range.source_buffer
68
69
  begin_pos = node.loc.keyword.begin_pos
69
70
  whitespace = Parser::Source::Range.new(source_buffer,
70
71
  begin_pos - when_column,
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -7,22 +8,25 @@ module RuboCop
7
8
  class CharacterLiteral < Cop
8
9
  include StringHelp
9
10
 
10
- MSG = 'Do not use the character literal - use string literal instead.'
11
+ MSG = 'Do not use the character literal - ' \
12
+ 'use string literal instead.'.freeze
11
13
 
12
14
  def offense?(node)
13
15
  # we don't register an offense for things like ?\C-\M-d
14
16
  node.loc.begin.is?('?') &&
15
- node.loc.expression.source.size.between?(2, 3)
17
+ node.source.size.between?(2, 3)
16
18
  end
17
19
 
18
20
  def autocorrect(node)
19
21
  lambda do |corrector|
20
- string = node.loc.expression.source[1..-1]
22
+ string = node.source[1..-1]
21
23
 
22
- if string.length == 1 # normal character
23
- corrector.replace(node.loc.expression, "'#{string}'")
24
- elsif string.length == 2 # special character like \n
25
- corrector.replace(node.loc.expression, %("#{string}"))
24
+ # special character like \n
25
+ # or ' which needs to use "" or be escaped.
26
+ if string.length == 2 || string == "'"
27
+ corrector.replace(node.source_range, %("#{string}"))
28
+ elsif string.length == 1 # normal character
29
+ corrector.replace(node.source_range, "'#{string}'")
26
30
  end
27
31
  end
28
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
@@ -6,7 +7,7 @@ module RuboCop
6
7
  # This cops checks for class and module names with
7
8
  # an underscore in them.
8
9
  class ClassAndModuleCamelCase < Cop
9
- MSG = 'Use CamelCase for classes and modules.'
10
+ MSG = 'Use CamelCase for classes and modules.'.freeze
10
11
 
11
12
  def on_class(node)
12
13
  check_name(node)
@@ -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,10 +22,10 @@ module RuboCop
21
22
  include ConfigurableEnforcedStyle
22
23
 
23
24
  NESTED_MSG = 'Use nested module/class definitions instead of ' \
24
- 'compact style.'
25
+ 'compact style.'.freeze
25
26
 
26
27
  COMPACT_MSG = 'Use compact module/class definition instead of ' \
27
- 'nested style.'
28
+ 'nested style.'.freeze
28
29
 
29
30
  def on_class(node)
30
31
  _name, _superclass, body = *node
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -7,7 +8,7 @@ module RuboCop
7
8
  class ClassCheck < Cop
8
9
  include ConfigurableEnforcedStyle
9
10
 
10
- MSG = 'Prefer `Object#%s` over `Object#%s`.'
11
+ MSG = 'Prefer `Object#%s` over `Object#%s`.'.freeze
11
12
 
12
13
  def on_send(node)
13
14
  _receiver, method_name, *_args = *node
@@ -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
  # end
22
23
  # end
23
24
  class ClassMethods < Cop
24
- MSG = 'Use `self.%s` instead of `%s.%s`.'
25
+ MSG = 'Use `self.%s` instead of `%s.%s`.'.freeze
25
26
 
26
27
  def on_class(node)
27
28
  name, _superclass, body = *node
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -7,7 +8,7 @@ module RuboCop
7
8
  # are signaled only on assignment to class variables to
8
9
  # reduced the number of offenses that would be reported.
9
10
  class ClassVars < Cop
10
- MSG = 'Replace class var %s with a class instance var.'
11
+ MSG = 'Replace class var %s with a class instance var.'.freeze
11
12
 
12
13
  def on_cvasgn(node)
13
14
  add_offense(node, :name)
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -30,8 +31,8 @@ module RuboCop
30
31
  include OnMethodDef
31
32
 
32
33
  MSG_INDENT =
33
- 'Indent `)` the same as the start of the line where `(` is.'
34
- MSG_ALIGN = 'Align `)` with `(`.'
34
+ 'Indent `)` the same as the start of the line where `(` is.'.freeze
35
+ MSG_ALIGN = 'Align `)` with `(`.'.freeze
35
36
 
36
37
  def on_send(node)
37
38
  _receiver, _method_name, *args = *node
@@ -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,7 +13,7 @@ module RuboCop
12
13
  class CollectionMethods < Cop
13
14
  include MethodPreference
14
15
 
15
- MSG = 'Prefer `%s` over `%s`.'
16
+ MSG = 'Prefer `%s` over `%s`.'.freeze
16
17
 
17
18
  def on_block(node)
18
19
  method, _args, _body = *node
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -6,10 +7,10 @@ module RuboCop
6
7
  # This cop checks for methods invoked via the :: operator instead
7
8
  # of the . operator (like FileUtils::rmdir instead of FileUtils.rmdir).
8
9
  class ColonMethodCall < Cop
9
- MSG = 'Do not use `::` for method calls.'
10
+ MSG = 'Do not use `::` for method calls.'.freeze
10
11
 
11
12
  JAVA_TYPES = [:byte, :boolean, :byte, :short, :char,
12
- :int, :long, :float, :double]
13
+ :int, :long, :float, :double].freeze
13
14
 
14
15
  JAVA_TYPE_NODES =
15
16
  JAVA_TYPES.map { |t| s(:send, s(:const, nil, :Java), t) }
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -29,8 +30,8 @@ module RuboCop
29
30
  class CommandLiteral < Cop
30
31
  include ConfigurableEnforcedStyle
31
32
 
32
- MSG_USE_BACKTICKS = 'Use backticks around command string.'
33
- MSG_USE_PERCENT_X = 'Use `%x` around command string.'
33
+ MSG_USE_BACKTICKS = 'Use backticks around command string.'.freeze
34
+ MSG_USE_PERCENT_X = 'Use `%x` around command string.'.freeze
34
35
 
35
36
  def on_xstr(node)
36
37
  return if heredoc_literal?(node)
@@ -95,11 +96,11 @@ module RuboCop
95
96
  def autocorrect(node)
96
97
  return if contains_backtick?(node)
97
98
 
98
- if backtick_literal?(node)
99
- replacement = ['%x', ''].zip(preferred_delimiters).map(&:join)
100
- else
101
- replacement = %w(` `)
102
- end
99
+ replacement = if backtick_literal?(node)
100
+ ['%x', ''].zip(preferred_delimiters).map(&:join)
101
+ else
102
+ %w(` `)
103
+ end
103
104
 
104
105
  lambda do |corrector|
105
106
  corrector.replace(node.loc.begin, replacement.first)
@@ -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,9 +11,9 @@ module RuboCop
10
11
 
11
12
  MSG = 'Annotation keywords like `%s` should be all upper case, ' \
12
13
  'followed by a colon, and a space, ' \
13
- 'then a note describing the problem.'
14
+ 'then a note describing the problem.'.freeze
14
15
  MISSING_NOTE = 'Annotation comment, with keyword `%s`, ' \
15
- 'is missing a note.'
16
+ 'is missing a note.'.freeze
16
17
 
17
18
  def investigate(processed_source)
18
19
  processed_source.comments.each_with_index do |comment, ix|
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module RuboCop
4
5
  module Cop
@@ -7,7 +8,7 @@ module RuboCop
7
8
  class CommentIndentation < Cop
8
9
  include AutocorrectAlignment
9
10
 
10
- MSG = 'Incorrect indentation detected (column %d instead of %d).'
11
+ MSG = 'Incorrect indentation detected (column %d instead of %d).'.freeze
11
12
 
12
13
  def investigate(processed_source)
13
14
  processed_source.comments.each { |comment| check(comment) }
@@ -51,14 +52,11 @@ module RuboCop
51
52
  end
52
53
 
53
54
  def less_indented?(line)
54
- keyword = 'end\b'
55
- bracket = '[}\]]'
56
- line =~ /^\s*(#{keyword}|#{bracket})/
55
+ line =~ /^\s*(end\b|[\}\]])/
57
56
  end
58
57
 
59
58
  def two_alternatives?(line)
60
- keyword = '(else|elsif|when|rescue|ensure)\b'
61
- line =~ /^\s*#{keyword}/
59
+ line =~ /^\s*(else|elsif|when|rescue|ensure)\b/
62
60
  end
63
61
  end
64
62
  end
@@ -0,0 +1,362 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module RuboCop
5
+ module Cop
6
+ module Style
7
+ # Helper module to provide common methods to classes needed for the
8
+ # ConditionalAssignment Cop.
9
+ module ConditionalAssignmentHelper
10
+ EQUAL = '='.freeze
11
+
12
+ # `elsif` branches show up in the `node` as an `else`. We need
13
+ # to recursively iterate over all `else` branches and consider all
14
+ # but the last `node` an `elsif` branch and consider the last `node`
15
+ # the actual `else` branch.
16
+ def expand_elses(branch)
17
+ elsif_branches = expand_elsif(branch)
18
+ else_branch = elsif_branches.any? ? elsif_branches.pop : branch
19
+ [elsif_branches, else_branch]
20
+ end
21
+
22
+ # `when` nodes contain the entire branch including the condition.
23
+ # We only need the contents of the branch, not the condition.
24
+ def expand_when_branches(when_branches)
25
+ when_branches.map { |branch| branch.children[1] }
26
+ end
27
+
28
+ def correct_branches(corrector, branches)
29
+ branches.each do |branch|
30
+ *_, assignment = *branch
31
+ corrector.replace(branch.source_range, assignment.source)
32
+ end
33
+ end
34
+
35
+ def tail(branch)
36
+ branch.begin_type? ? [*branch].last : branch
37
+ end
38
+
39
+ def lhs(node)
40
+ case node.type
41
+ when :send
42
+ lhs_for_send(node)
43
+ when :op_asgn
44
+ "#{node.children[0].source} #{node.children[1]}= "
45
+ when :and_asgn
46
+ "#{node.children[0].source} &&= "
47
+ when :or_asgn
48
+ "#{node.children[0].source} ||= "
49
+ when *ConditionalAssignment::VARIABLE_ASSIGNMENT_TYPES
50
+ "#{node.children[0]} = "
51
+ else
52
+ node.source
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def expand_elsif(node, elsif_branches = [])
59
+ return [] if node.nil? || !node.if_type?
60
+ _condition, elsif_branch, else_branch = *node
61
+ elsif_branches << elsif_branch
62
+ if else_branch && else_branch.if_type?
63
+ expand_elsif(else_branch, elsif_branches)
64
+ else
65
+ elsif_branches << else_branch
66
+ end
67
+ elsif_branches
68
+ end
69
+
70
+ def lhs_for_send(node)
71
+ receiver = node.receiver.nil? ? '' : node.receiver.source
72
+
73
+ if node.method_name == :[]=
74
+ indices = node.children[2...-1].map(&:source).join(', ')
75
+ "#{receiver}[#{indices}] = "
76
+ elsif node.method_name.to_s.end_with?(EQUAL) &&
77
+ ![:!=, :==].include?(node.method_name)
78
+ "#{receiver}.#{node.method_name[0...-1]} = "
79
+ else
80
+ "#{receiver} #{node.method_name} "
81
+ end
82
+ end
83
+ end
84
+
85
+ # Check for `if` and `case` statements where each branch is used for
86
+ # assignment to the same variable when using the return of the
87
+ # condition can be used instead.
88
+ #
89
+ # @example
90
+ # # bad
91
+ # if foo
92
+ # bar = 1
93
+ # else
94
+ # bar = 2
95
+ # end
96
+ #
97
+ # case foo
98
+ # when 'a'
99
+ # bar += 1
100
+ # else
101
+ # bar += 2
102
+ # end
103
+ #
104
+ # if foo
105
+ # some_method
106
+ # bar = 1
107
+ # else
108
+ # some_other_method
109
+ # bar = 2
110
+ # end
111
+ #
112
+ # # good
113
+ # bar = if foo
114
+ # 1
115
+ # else
116
+ # 2
117
+ # end
118
+ #
119
+ # bar += case foo
120
+ # when 'a'
121
+ # 1
122
+ # else
123
+ # 2
124
+ # end
125
+ #
126
+ # bar << if foo
127
+ # some_method
128
+ # 1
129
+ # else
130
+ # some_other_method
131
+ # 2
132
+ # end
133
+ class ConditionalAssignment < Cop
134
+ include IfNode
135
+ include ConditionalAssignmentHelper
136
+
137
+ MSG = 'Use the return of the conditional for variable assignment ' \
138
+ 'and comparison.'.freeze
139
+ VARIABLE_ASSIGNMENT_TYPES =
140
+ [:casgn, :cvasgn, :gvasgn, :ivasgn, :lvasgn].freeze
141
+ ASSIGNMENT_TYPES =
142
+ VARIABLE_ASSIGNMENT_TYPES + [:and_asgn, :or_asgn, :op_asgn].freeze
143
+ IF = 'if'.freeze
144
+ UNLESS = 'unless'.freeze
145
+ LINE_LENGTH = 'Metrics/LineLength'.freeze
146
+ INDENTATION_WIDTH = 'Style/IndentationWidth'.freeze
147
+ ENABLED = 'Enabled'.freeze
148
+ MAX = 'Max'.freeze
149
+ SINGLE_LINE_CONDITIONS_ONLY = 'SingleLineConditionsOnly'.freeze
150
+ WIDTH = 'Width'.freeze
151
+ METHODS = [:[]=, :<<, :=~, :!~, :<=>].freeze
152
+
153
+ def lhs_all_match?(branches)
154
+ first_lhs = lhs(branches.first)
155
+ branches.all? { |branch| lhs(branch) == first_lhs }
156
+ end
157
+
158
+ def on_if(node)
159
+ return if elsif?(node)
160
+
161
+ _condition, if_branch, else_branch = *node
162
+ elsif_branches, else_branch = expand_elses(else_branch)
163
+ return unless else_branch # empty else
164
+
165
+ branches = [if_branch, *elsif_branches, else_branch]
166
+
167
+ check_node(node, branches)
168
+ end
169
+
170
+ def on_case(node)
171
+ _condition, *when_branches, else_branch = *node
172
+ return unless else_branch # empty else
173
+
174
+ when_branches = expand_when_branches(when_branches)
175
+ branches = [*when_branches, else_branch]
176
+
177
+ check_node(node, branches)
178
+ end
179
+
180
+ def autocorrect(node)
181
+ if ternary_op?(node)
182
+ TernaryCorrector.correct(node)
183
+ else
184
+ case node.loc.keyword.source
185
+ when IF
186
+ IfCorrector.correct(node)
187
+ when UNLESS
188
+ UnlessCorrector.correct(node)
189
+ else
190
+ CaseCorrector.correct(node)
191
+ end
192
+ end
193
+ end
194
+
195
+ private
196
+
197
+ def assignment_types_match?(*nodes)
198
+ return unless assignment_type?(nodes.first)
199
+ first_type = nodes.first.type
200
+ nodes.all? { |node| node.type == first_type }
201
+ end
202
+
203
+ # The shovel operator `<<` does not have its own type. It is a `send`
204
+ # type.
205
+ def assignment_type?(branch)
206
+ return true if ASSIGNMENT_TYPES.include?(branch.type)
207
+
208
+ if branch.send_type?
209
+ _variable, method, = *branch
210
+ return true if METHODS.include?(method)
211
+ return true if method.to_s.end_with?(EQUAL)
212
+ end
213
+
214
+ false
215
+ end
216
+
217
+ def check_node(node, branches)
218
+ return unless branches.all?
219
+ last_statements = branches.map { |branch| tail(branch) }
220
+ return unless lhs_all_match?(last_statements)
221
+ return if last_statements.any?(&:masgn_type?)
222
+ return unless assignment_types_match?(*last_statements)
223
+
224
+ return if single_line_conditions_only? && branches.any?(&:begin_type?)
225
+ return if correction_exceeds_line_limit?(node, branches)
226
+
227
+ add_offense(node, :expression)
228
+ end
229
+
230
+ # If `Metrics/LineLength` is enabled, we do not want to introduce an
231
+ # offense by auto-correcting this cop. Find the max configured line
232
+ # length. Find the longest line of condition. Remove the assignment
233
+ # from lines that contain the offending assignment because after
234
+ # correcting, this will not be on the line anymore. Check if the length
235
+ # of the longest line + the length of the corrected assignment is
236
+ # greater than the max configured line length
237
+ def correction_exceeds_line_limit?(node, branches)
238
+ return false unless config.for_cop(LINE_LENGTH)[ENABLED]
239
+ assignment = lhs(tail(branches[0]))
240
+ assignment_regex = /#{assignment.gsub(' ', '\s*')}/
241
+ max_line_length = config.for_cop(LINE_LENGTH)[MAX]
242
+ indentation_width = config.for_cop(INDENTATION_WIDTH)[WIDTH] || 2
243
+ return true if longest_rhs(branches) + indentation_width +
244
+ assignment.length > max_line_length
245
+ lines = node.source.lines.map do |line|
246
+ line.chomp.sub(assignment_regex, '')
247
+ end
248
+ longest_line = lines.max_by(&:length)
249
+ (longest_line + assignment).length > max_line_length
250
+ end
251
+
252
+ def longest_rhs(branches)
253
+ branches.map { |branch| branch.children.last.source.length }.max
254
+ end
255
+
256
+ def lines_with_numbers(node)
257
+ line_nos = node.loc.line..node.loc.last_line
258
+ node.source.lines.zip(line_nos)
259
+ end
260
+
261
+ def single_line_conditions_only?
262
+ cop_config[SINGLE_LINE_CONDITIONS_ONLY]
263
+ end
264
+ end
265
+
266
+ # Corrector to correct conditional assignment in ternary conditions.
267
+ class TernaryCorrector
268
+ class << self
269
+ include ConditionalAssignmentHelper
270
+
271
+ def correct(node)
272
+ condition, if_branch, else_branch = *node
273
+ _variable, *_operator, if_rhs = *if_branch
274
+ _else_variable, *_operator, else_rhs = *else_branch
275
+ condition = condition.source
276
+ if_rhs = if_rhs.source
277
+ else_rhs = else_rhs.source
278
+
279
+ ternary = "#{condition} ? #{if_rhs} : #{else_rhs}"
280
+ if if_branch.send_type? && if_branch.method_name != :[]=
281
+ ternary = "(#{ternary})"
282
+ end
283
+ correction = "#{lhs(if_branch)}#{ternary}"
284
+
285
+ lambda do |corrector|
286
+ corrector.replace(node.source_range, correction)
287
+ end
288
+ end
289
+ end
290
+ end
291
+
292
+ # Corrector to correct conditional assignment in `if` statements.
293
+ class IfCorrector
294
+ class << self
295
+ include ConditionalAssignmentHelper
296
+
297
+ def correct(node)
298
+ _condition, if_branch, else_branch = *node
299
+ if_branch = tail(if_branch)
300
+ _variable, *_operator, if_assignment = *if_branch
301
+ elsif_branches, else_branch = expand_elses(else_branch)
302
+ elsif_branches.map! { |branch| tail(branch) }
303
+ else_branch = tail(else_branch)
304
+ _else_variable, *_operator, else_assignment = *else_branch
305
+
306
+ lambda do |corrector|
307
+ corrector.insert_before(node.source_range, lhs(if_branch))
308
+ corrector.replace(if_branch.source_range, if_assignment.source)
309
+ correct_branches(corrector, elsif_branches)
310
+ corrector.replace(else_branch.source_range,
311
+ else_assignment.source)
312
+ end
313
+ end
314
+ end
315
+ end
316
+
317
+ # Corrector to correct conditional assignment in `case` statements.
318
+ class CaseCorrector
319
+ class << self
320
+ include ConditionalAssignmentHelper
321
+
322
+ def correct(node)
323
+ _condition, *when_branches, else_branch = *node
324
+ else_branch = tail(else_branch)
325
+ when_branches = expand_when_branches(when_branches)
326
+ when_branches.map! { |when_branch| tail(when_branch) }
327
+ _variable, *_operator, else_assignment = *else_branch
328
+
329
+ lambda do |corrector|
330
+ corrector.insert_before(node.source_range, lhs(else_branch))
331
+ correct_branches(corrector, when_branches)
332
+ corrector.replace(else_branch.source_range,
333
+ else_assignment.source)
334
+ end
335
+ end
336
+ end
337
+ end
338
+
339
+ # Corrector to correct conditional assignment in `unless` statements.
340
+ class UnlessCorrector
341
+ class << self
342
+ include ConditionalAssignmentHelper
343
+
344
+ def correct(node)
345
+ _condition, else_branch, if_branch = *node
346
+ if_branch = tail(if_branch)
347
+ else_branch = tail(else_branch)
348
+ _variable, *_operator, if_assignment = *if_branch
349
+ _else_variable, *_operator, else_assignment = *else_branch
350
+
351
+ lambda do |corrector|
352
+ corrector.insert_before(node.source_range, lhs(if_branch))
353
+ corrector.replace(if_branch.source_range, if_assignment.source)
354
+ corrector.replace(else_branch.source_range,
355
+ else_assignment.source)
356
+ end
357
+ end
358
+ end
359
+ end
360
+ end
361
+ end
362
+ end