rubocop 0.86.0 → 0.89.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/bin/rubocop-profile +32 -0
  4. data/config/default.yml +198 -25
  5. data/lib/rubocop.rb +30 -5
  6. data/lib/rubocop/cli.rb +2 -4
  7. data/lib/rubocop/cli/command/auto_genenerate_config.rb +42 -7
  8. data/lib/rubocop/cli/command/base.rb +1 -0
  9. data/lib/rubocop/cli/command/execute_runner.rb +1 -1
  10. data/lib/rubocop/cli/command/show_cops.rb +3 -3
  11. data/lib/rubocop/cli/command/version.rb +2 -2
  12. data/lib/rubocop/comment_config.rb +5 -7
  13. data/lib/rubocop/config.rb +20 -3
  14. data/lib/rubocop/config_loader.rb +41 -69
  15. data/lib/rubocop/config_loader_resolver.rb +3 -3
  16. data/lib/rubocop/config_obsoletion.rb +6 -2
  17. data/lib/rubocop/config_store.rb +4 -0
  18. data/lib/rubocop/config_validator.rb +2 -4
  19. data/lib/rubocop/cop/autocorrect_logic.rb +14 -24
  20. data/lib/rubocop/cop/badge.rb +1 -1
  21. data/lib/rubocop/cop/base.rb +407 -0
  22. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +10 -20
  23. data/lib/rubocop/cop/commissioner.rb +47 -50
  24. data/lib/rubocop/cop/cop.rb +85 -236
  25. data/lib/rubocop/cop/corrector.rb +38 -115
  26. data/lib/rubocop/cop/correctors/line_break_corrector.rb +4 -4
  27. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +26 -0
  28. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  29. data/lib/rubocop/cop/correctors/punctuation_corrector.rb +1 -1
  30. data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +15 -18
  31. data/lib/rubocop/cop/force.rb +1 -0
  32. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +38 -12
  33. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +1 -1
  34. data/lib/rubocop/cop/generator.rb +1 -1
  35. data/lib/rubocop/cop/generator/configuration_injector.rb +2 -2
  36. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +4 -12
  37. data/lib/rubocop/cop/internal_affairs/node_destructuring.rb +1 -1
  38. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +11 -14
  39. data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +8 -8
  40. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +10 -7
  41. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +7 -8
  42. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -2
  43. data/lib/rubocop/cop/layout/block_alignment.rb +1 -1
  44. data/lib/rubocop/cop/layout/case_indentation.rb +18 -19
  45. data/lib/rubocop/cop/layout/class_structure.rb +5 -44
  46. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  47. data/lib/rubocop/cop/layout/empty_lines.rb +0 -2
  48. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
  49. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -8
  50. data/lib/rubocop/cop/layout/end_alignment.rb +3 -2
  51. data/lib/rubocop/cop/layout/extra_spacing.rb +22 -36
  52. data/lib/rubocop/cop/layout/first_argument_indentation.rb +4 -0
  53. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +1 -1
  54. data/lib/rubocop/cop/layout/hash_alignment.rb +1 -2
  55. data/lib/rubocop/cop/layout/heredoc_indentation.rb +2 -2
  56. data/lib/rubocop/cop/layout/indentation_style.rb +0 -2
  57. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  58. data/lib/rubocop/cop/layout/multiline_block_layout.rb +16 -6
  59. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +1 -1
  60. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +0 -2
  61. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +22 -27
  62. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +33 -66
  63. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +3 -2
  64. data/lib/rubocop/cop/legacy/corrections_proxy.rb +49 -0
  65. data/lib/rubocop/cop/legacy/corrector.rb +29 -0
  66. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +7 -4
  67. data/lib/rubocop/cop/lint/ambiguous_operator.rb +15 -10
  68. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +11 -13
  69. data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -2
  70. data/lib/rubocop/cop/lint/big_decimal_new.rb +10 -10
  71. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +50 -0
  72. data/lib/rubocop/cop/lint/boolean_symbol.rb +16 -11
  73. data/lib/rubocop/cop/lint/circular_argument_reference.rb +1 -1
  74. data/lib/rubocop/cop/lint/constant_resolution.rb +1 -1
  75. data/lib/rubocop/cop/lint/debugger.rb +7 -1
  76. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +9 -10
  77. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +21 -17
  78. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +8 -2
  79. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +1 -1
  80. data/lib/rubocop/cop/lint/duplicate_elsif_condition.rb +39 -0
  81. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +1 -1
  82. data/lib/rubocop/cop/lint/duplicate_methods.rb +9 -6
  83. data/lib/rubocop/cop/lint/duplicate_rescue_exception.rb +60 -0
  84. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  85. data/lib/rubocop/cop/lint/else_layout.rb +1 -1
  86. data/lib/rubocop/cop/lint/empty_conditional_body.rb +67 -0
  87. data/lib/rubocop/cop/lint/empty_ensure.rb +5 -5
  88. data/lib/rubocop/cop/lint/empty_expression.rb +2 -2
  89. data/lib/rubocop/cop/lint/empty_interpolation.rb +5 -6
  90. data/lib/rubocop/cop/lint/empty_when.rb +2 -2
  91. data/lib/rubocop/cop/lint/ensure_return.rb +27 -29
  92. data/lib/rubocop/cop/lint/erb_new_arguments.rb +11 -10
  93. data/lib/rubocop/cop/lint/flip_flop.rb +1 -1
  94. data/lib/rubocop/cop/lint/float_comparison.rb +93 -0
  95. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  96. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +5 -4
  97. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +13 -14
  98. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +5 -4
  99. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +8 -8
  100. data/lib/rubocop/cop/lint/inherit_exception.rb +12 -7
  101. data/lib/rubocop/cop/lint/interpolation_check.rb +21 -5
  102. data/lib/rubocop/cop/lint/literal_as_condition.rb +14 -2
  103. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +7 -7
  104. data/lib/rubocop/cop/lint/loop.rb +23 -2
  105. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +6 -5
  106. data/lib/rubocop/cop/lint/missing_super.rb +99 -0
  107. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  108. data/lib/rubocop/cop/lint/multiple_comparison.rb +6 -9
  109. data/lib/rubocop/cop/lint/nested_method_definition.rb +15 -21
  110. data/lib/rubocop/cop/lint/nested_percent_literal.rb +1 -1
  111. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  112. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +84 -13
  113. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +2 -2
  114. data/lib/rubocop/cop/lint/number_conversion.rb +6 -9
  115. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +11 -13
  116. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +90 -0
  117. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +12 -13
  118. data/lib/rubocop/cop/lint/percent_string_array.rb +13 -12
  119. data/lib/rubocop/cop/lint/percent_symbol_array.rb +13 -12
  120. data/lib/rubocop/cop/lint/raise_exception.rb +12 -10
  121. data/lib/rubocop/cop/lint/rand_one.rb +3 -3
  122. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +41 -40
  123. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +7 -11
  124. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -7
  125. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +15 -11
  126. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +6 -13
  127. data/lib/rubocop/cop/lint/redundant_with_index.rb +11 -14
  128. data/lib/rubocop/cop/lint/redundant_with_object.rb +11 -14
  129. data/lib/rubocop/cop/lint/regexp_as_condition.rb +4 -6
  130. data/lib/rubocop/cop/lint/require_parentheses.rb +2 -2
  131. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  132. data/lib/rubocop/cop/lint/rescue_type.rb +8 -8
  133. data/lib/rubocop/cop/lint/return_in_void_context.rb +2 -4
  134. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -6
  135. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +14 -10
  136. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +10 -2
  137. data/lib/rubocop/cop/lint/script_permission.rb +10 -7
  138. data/lib/rubocop/cop/lint/self_assignment.rb +78 -0
  139. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -11
  140. data/lib/rubocop/cop/lint/shadowed_argument.rb +3 -3
  141. data/lib/rubocop/cop/lint/shadowed_exception.rb +2 -2
  142. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +3 -3
  143. data/lib/rubocop/cop/lint/struct_new_override.rb +1 -1
  144. data/lib/rubocop/cop/lint/suppressed_exception.rb +4 -7
  145. data/lib/rubocop/cop/lint/syntax.rb +11 -26
  146. data/lib/rubocop/cop/lint/to_json.rb +4 -6
  147. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +34 -0
  148. data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +4 -4
  149. data/lib/rubocop/cop/lint/unified_integer.rb +4 -6
  150. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  151. data/lib/rubocop/cop/lint/unreachable_loop.rb +174 -0
  152. data/lib/rubocop/cop/lint/unused_block_argument.rb +8 -3
  153. data/lib/rubocop/cop/lint/unused_method_argument.rb +9 -4
  154. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +1 -1
  155. data/lib/rubocop/cop/lint/uri_regexp.rb +11 -47
  156. data/lib/rubocop/cop/lint/useless_access_modifier.rb +26 -16
  157. data/lib/rubocop/cop/lint/useless_assignment.rb +4 -4
  158. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +6 -15
  159. data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -6
  160. data/lib/rubocop/cop/lint/void.rb +3 -7
  161. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  162. data/lib/rubocop/cop/metrics/block_length.rb +24 -2
  163. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
  164. data/lib/rubocop/cop/metrics/class_length.rb +26 -3
  165. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +2 -1
  166. data/lib/rubocop/cop/metrics/method_length.rb +25 -2
  167. data/lib/rubocop/cop/metrics/module_length.rb +26 -3
  168. data/lib/rubocop/cop/metrics/parameter_lists.rb +2 -6
  169. data/lib/rubocop/cop/metrics/perceived_complexity.rb +7 -8
  170. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +48 -5
  171. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +157 -0
  172. data/lib/rubocop/cop/metrics/utils/repeated_csend_discount.rb +37 -0
  173. data/lib/rubocop/cop/migration/department_name.rb +14 -16
  174. data/lib/rubocop/cop/mixin/alignment.rb +2 -1
  175. data/lib/rubocop/cop/mixin/allowed_methods.rb +19 -0
  176. data/lib/rubocop/cop/mixin/array_min_size.rb +1 -1
  177. data/lib/rubocop/cop/mixin/auto_corrector.rb +12 -0
  178. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  179. data/lib/rubocop/cop/mixin/code_length.rb +26 -5
  180. data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -1
  181. data/lib/rubocop/cop/mixin/enforce_superclass.rb +3 -1
  182. data/lib/rubocop/cop/mixin/hash_transform_method.rb +5 -11
  183. data/lib/rubocop/cop/mixin/line_length_help.rb +1 -3
  184. data/lib/rubocop/cop/mixin/method_complexity.rb +10 -2
  185. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -2
  186. data/lib/rubocop/cop/mixin/nil_methods.rb +3 -5
  187. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +6 -1
  188. data/lib/rubocop/cop/mixin/percent_array.rb +2 -6
  189. data/lib/rubocop/cop/mixin/range_help.rb +18 -4
  190. data/lib/rubocop/cop/mixin/statement_modifier.rb +39 -10
  191. data/lib/rubocop/cop/mixin/surrounding_space.rb +4 -24
  192. data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -4
  193. data/lib/rubocop/cop/mixin/uncommunicative_name.rb +10 -15
  194. data/lib/rubocop/cop/mixin/unused_argument.rb +4 -6
  195. data/lib/rubocop/cop/mixin/visibility_help.rb +50 -0
  196. data/lib/rubocop/cop/naming/accessor_method_name.rb +4 -2
  197. data/lib/rubocop/cop/naming/ascii_identifiers.rb +29 -6
  198. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +3 -3
  199. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  200. data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +2 -2
  201. data/lib/rubocop/cop/naming/constant_name.rb +2 -2
  202. data/lib/rubocop/cop/naming/file_name.rb +3 -3
  203. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +2 -2
  204. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +2 -2
  205. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +2 -2
  206. data/lib/rubocop/cop/naming/method_name.rb +1 -1
  207. data/lib/rubocop/cop/naming/method_parameter_name.rb +2 -2
  208. data/lib/rubocop/cop/naming/predicate_name.rb +6 -10
  209. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +12 -11
  210. data/lib/rubocop/cop/naming/variable_name.rb +1 -1
  211. data/lib/rubocop/cop/naming/variable_number.rb +1 -1
  212. data/lib/rubocop/cop/offense.rb +16 -2
  213. data/lib/rubocop/cop/registry.rb +3 -3
  214. data/lib/rubocop/cop/security/eval.rb +2 -2
  215. data/lib/rubocop/cop/security/json_load.rb +6 -8
  216. data/lib/rubocop/cop/security/marshal_load.rb +2 -4
  217. data/lib/rubocop/cop/security/open.rb +2 -2
  218. data/lib/rubocop/cop/security/yaml_load.rb +6 -6
  219. data/lib/rubocop/cop/style/access_modifier_declarations.rb +16 -9
  220. data/lib/rubocop/cop/style/accessor_grouping.rb +149 -0
  221. data/lib/rubocop/cop/style/alias.rb +41 -36
  222. data/lib/rubocop/cop/style/and_or.rb +9 -11
  223. data/lib/rubocop/cop/style/array_coercion.rb +63 -0
  224. data/lib/rubocop/cop/style/array_join.rb +6 -8
  225. data/lib/rubocop/cop/style/ascii_comments.rb +4 -4
  226. data/lib/rubocop/cop/style/attr.rb +11 -9
  227. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +5 -7
  228. data/lib/rubocop/cop/style/bare_percent_literals.rb +10 -12
  229. data/lib/rubocop/cop/style/begin_block.rb +2 -2
  230. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +141 -0
  231. data/lib/rubocop/cop/style/block_comments.rb +14 -18
  232. data/lib/rubocop/cop/style/block_delimiters.rb +23 -23
  233. data/lib/rubocop/cop/style/case_equality.rb +22 -3
  234. data/lib/rubocop/cop/style/case_like_if.rb +220 -0
  235. data/lib/rubocop/cop/style/class_and_module_children.rb +14 -11
  236. data/lib/rubocop/cop/style/class_check.rb +7 -9
  237. data/lib/rubocop/cop/style/class_methods.rb +7 -11
  238. data/lib/rubocop/cop/style/class_vars.rb +24 -7
  239. data/lib/rubocop/cop/style/collection_methods.rb +11 -17
  240. data/lib/rubocop/cop/style/colon_method_call.rb +8 -9
  241. data/lib/rubocop/cop/style/colon_method_definition.rb +6 -6
  242. data/lib/rubocop/cop/style/command_literal.rb +23 -24
  243. data/lib/rubocop/cop/style/comment_annotation.rb +15 -15
  244. data/lib/rubocop/cop/style/commented_keyword.rb +6 -3
  245. data/lib/rubocop/cop/style/conditional_assignment.rb +13 -4
  246. data/lib/rubocop/cop/style/constant_visibility.rb +3 -2
  247. data/lib/rubocop/cop/style/copyright.rb +12 -12
  248. data/lib/rubocop/cop/style/date_time.rb +2 -2
  249. data/lib/rubocop/cop/style/def_with_parentheses.rb +8 -10
  250. data/lib/rubocop/cop/style/dir.rb +9 -12
  251. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +7 -9
  252. data/lib/rubocop/cop/style/documentation.rb +6 -8
  253. data/lib/rubocop/cop/style/documentation_method.rb +1 -1
  254. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +12 -15
  255. data/lib/rubocop/cop/style/double_negation.rb +2 -2
  256. data/lib/rubocop/cop/style/each_for_simple_loop.rb +5 -8
  257. data/lib/rubocop/cop/style/each_with_object.rb +16 -19
  258. data/lib/rubocop/cop/style/empty_case_condition.rb +19 -20
  259. data/lib/rubocop/cop/style/empty_else.rb +17 -19
  260. data/lib/rubocop/cop/style/empty_literal.rb +20 -21
  261. data/lib/rubocop/cop/style/empty_method.rb +10 -13
  262. data/lib/rubocop/cop/style/encoding.rb +5 -9
  263. data/lib/rubocop/cop/style/end_block.rb +4 -6
  264. data/lib/rubocop/cop/style/eval_with_location.rb +9 -7
  265. data/lib/rubocop/cop/style/even_odd.rb +7 -11
  266. data/lib/rubocop/cop/style/expand_path_arguments.rb +23 -22
  267. data/lib/rubocop/cop/style/explicit_block_argument.rb +102 -0
  268. data/lib/rubocop/cop/style/exponential_notation.rb +7 -9
  269. data/lib/rubocop/cop/style/float_division.rb +8 -11
  270. data/lib/rubocop/cop/style/for.rb +11 -15
  271. data/lib/rubocop/cop/style/format_string.rb +21 -19
  272. data/lib/rubocop/cop/style/format_string_token.rb +10 -12
  273. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +19 -41
  274. data/lib/rubocop/cop/style/global_std_stream.rb +65 -0
  275. data/lib/rubocop/cop/style/global_vars.rb +2 -2
  276. data/lib/rubocop/cop/style/guard_clause.rb +5 -6
  277. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +69 -0
  278. data/lib/rubocop/cop/style/hash_each_methods.rb +5 -8
  279. data/lib/rubocop/cop/style/hash_like_case.rb +76 -0
  280. data/lib/rubocop/cop/style/hash_syntax.rb +4 -3
  281. data/lib/rubocop/cop/style/hash_transform_keys.rb +3 -2
  282. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -1
  283. data/lib/rubocop/cop/style/identical_conditional_branches.rb +2 -2
  284. data/lib/rubocop/cop/style/if_inside_else.rb +3 -3
  285. data/lib/rubocop/cop/style/if_unless_modifier.rb +18 -40
  286. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +11 -3
  287. data/lib/rubocop/cop/style/if_with_semicolon.rb +3 -6
  288. data/lib/rubocop/cop/style/implicit_runtime_error.rb +1 -1
  289. data/lib/rubocop/cop/style/infinite_loop.rb +24 -24
  290. data/lib/rubocop/cop/style/inline_comment.rb +3 -3
  291. data/lib/rubocop/cop/style/inverse_methods.rb +22 -32
  292. data/lib/rubocop/cop/style/lambda.rb +7 -12
  293. data/lib/rubocop/cop/style/lambda_call.rb +14 -13
  294. data/lib/rubocop/cop/style/line_end_concatenation.rb +19 -16
  295. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -1
  296. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +16 -11
  297. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +4 -8
  298. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +8 -7
  299. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -2
  300. data/lib/rubocop/cop/style/method_def_parentheses.rb +11 -16
  301. data/lib/rubocop/cop/style/min_max.rb +8 -12
  302. data/lib/rubocop/cop/style/missing_else.rb +11 -21
  303. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +10 -3
  304. data/lib/rubocop/cop/style/mixin_grouping.rb +24 -27
  305. data/lib/rubocop/cop/style/mixin_usage.rb +1 -1
  306. data/lib/rubocop/cop/style/module_function.rb +10 -13
  307. data/lib/rubocop/cop/style/multiline_block_chain.rb +10 -1
  308. data/lib/rubocop/cop/style/multiline_if_modifier.rb +3 -10
  309. data/lib/rubocop/cop/style/multiline_if_then.rb +4 -10
  310. data/lib/rubocop/cop/style/multiline_memoization.rb +14 -12
  311. data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -2
  312. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +4 -6
  313. data/lib/rubocop/cop/style/multiline_when_then.rb +7 -9
  314. data/lib/rubocop/cop/style/multiple_comparison.rb +1 -1
  315. data/lib/rubocop/cop/style/mutable_constant.rb +27 -24
  316. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +5 -6
  317. data/lib/rubocop/cop/style/numeric_predicate.rb +7 -4
  318. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +42 -0
  319. data/lib/rubocop/cop/style/parallel_assignment.rb +5 -5
  320. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  321. data/lib/rubocop/cop/style/proc.rb +1 -1
  322. data/lib/rubocop/cop/style/random_with_offset.rb +5 -10
  323. data/lib/rubocop/cop/style/redundant_assignment.rb +117 -0
  324. data/lib/rubocop/cop/style/redundant_condition.rb +15 -3
  325. data/lib/rubocop/cop/style/redundant_exception.rb +18 -10
  326. data/lib/rubocop/cop/style/redundant_fetch_block.rb +26 -7
  327. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +50 -0
  328. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
  329. data/lib/rubocop/cop/style/redundant_parentheses.rb +7 -1
  330. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +2 -1
  331. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +11 -11
  332. data/lib/rubocop/cop/style/redundant_sort.rb +26 -12
  333. data/lib/rubocop/cop/style/rescue_standard_error.rb +1 -1
  334. data/lib/rubocop/cop/style/safe_navigation.rb +4 -4
  335. data/lib/rubocop/cop/style/signal_exception.rb +3 -1
  336. data/lib/rubocop/cop/style/single_argument_dig.rb +54 -0
  337. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  338. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +3 -2
  339. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  340. data/lib/rubocop/cop/style/string_concatenation.rb +92 -0
  341. data/lib/rubocop/cop/style/struct_inheritance.rb +3 -3
  342. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  343. data/lib/rubocop/cop/style/symbol_proc.rb +2 -2
  344. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +9 -32
  345. data/lib/rubocop/cop/style/trivial_accessors.rb +8 -7
  346. data/lib/rubocop/cop/style/zero_length_predicate.rb +12 -8
  347. data/lib/rubocop/cop/team.rb +98 -82
  348. data/lib/rubocop/cop/tokens_util.rb +84 -0
  349. data/lib/rubocop/cop/util.rb +3 -13
  350. data/lib/rubocop/cop/utils/format_string.rb +1 -2
  351. data/lib/rubocop/cop/variable_force.rb +0 -2
  352. data/lib/rubocop/cop/variable_force/branch.rb +1 -0
  353. data/lib/rubocop/cop/variable_force/variable.rb +7 -5
  354. data/lib/rubocop/cops_documentation_generator.rb +282 -0
  355. data/lib/rubocop/error.rb +1 -0
  356. data/lib/rubocop/file_finder.rb +12 -12
  357. data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -2
  358. data/lib/rubocop/formatter/formatter_set.rb +1 -0
  359. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  360. data/lib/rubocop/name_similarity.rb +1 -3
  361. data/lib/rubocop/options.rb +18 -11
  362. data/lib/rubocop/path_util.rb +17 -17
  363. data/lib/rubocop/rake_task.rb +7 -9
  364. data/lib/rubocop/result_cache.rb +12 -8
  365. data/lib/rubocop/rspec/cop_helper.rb +4 -4
  366. data/lib/rubocop/rspec/expect_offense.rb +53 -22
  367. data/lib/rubocop/rspec/shared_contexts.rb +16 -17
  368. data/lib/rubocop/runner.rb +35 -34
  369. data/lib/rubocop/target_finder.rb +13 -10
  370. data/lib/rubocop/target_ruby.rb +1 -1
  371. data/lib/rubocop/version.rb +2 -2
  372. metadata +40 -11
  373. data/lib/rubocop/cop/lint/useless_comparison.rb +0 -28
  374. data/lib/rubocop/cop/mixin/classish_length.rb +0 -37
  375. data/lib/rubocop/cop/mixin/parser_diagnostic.rb +0 -37
  376. data/lib/rubocop/cop/mixin/too_many_lines.rb +0 -35
  377. data/lib/rubocop/cop/style/method_missing_super.rb +0 -34
@@ -30,11 +30,13 @@ module RuboCop
30
30
  #
31
31
  # puts 'hello, world'
32
32
  #
33
- class ScriptPermission < Cop
33
+ class ScriptPermission < Base
34
+ extend AutoCorrector
35
+
34
36
  MSG = "Script file %<file>s doesn't have execute permission."
35
37
  SHEBANG = '#!'
36
38
 
37
- def investigate(processed_source)
39
+ def on_new_investigation
38
40
  return if @options.key?(:stdin)
39
41
  return if Platform.windows?
40
42
  return unless processed_source.start_with?(SHEBANG)
@@ -42,17 +44,18 @@ module RuboCop
42
44
 
43
45
  comment = processed_source.comments[0]
44
46
  message = format_message_from(processed_source)
45
- add_offense(comment, message: message)
46
- end
47
47
 
48
- def autocorrect(node)
49
- lambda do |_corrector|
50
- FileUtils.chmod('+x', node.loc.expression.source_buffer.name)
48
+ add_offense(comment, message: message) do
49
+ autocorrect(comment) if autocorrect_requested?
51
50
  end
52
51
  end
53
52
 
54
53
  private
55
54
 
55
+ def autocorrect(comment)
56
+ FileUtils.chmod('+x', comment.loc.expression.source_buffer.name)
57
+ end
58
+
56
59
  def executable?(processed_source)
57
60
  # Returns true if stat is executable or if the operating system
58
61
  # doesn't distinguish executable files from nonexecutable files.
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # This cop checks for self-assignments.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # foo = foo
11
+ # foo, bar = foo, bar
12
+ # Foo = Foo
13
+ #
14
+ # # good
15
+ # foo = bar
16
+ # foo, bar = bar, foo
17
+ # Foo = Bar
18
+ #
19
+ class SelfAssignment < Base
20
+ MSG = 'Self-assignment detected.'
21
+
22
+ ASSIGNMENT_TYPE_TO_RHS_TYPE = {
23
+ lvasgn: :lvar,
24
+ ivasgn: :ivar,
25
+ cvasgn: :cvar,
26
+ gvasgn: :gvar
27
+ }.freeze
28
+
29
+ def on_lvasgn(node)
30
+ lhs, rhs = *node
31
+ return unless rhs
32
+
33
+ rhs_type = ASSIGNMENT_TYPE_TO_RHS_TYPE[node.type]
34
+
35
+ add_offense(node) if rhs.type == rhs_type && rhs.source == lhs.to_s
36
+ end
37
+ alias on_ivasgn on_lvasgn
38
+ alias on_cvasgn on_lvasgn
39
+ alias on_gvasgn on_lvasgn
40
+
41
+ def on_casgn(node)
42
+ lhs_scope, lhs_name, rhs = *node
43
+ return unless rhs&.const_type?
44
+
45
+ rhs_scope, rhs_name = *rhs
46
+ add_offense(node) if lhs_scope == rhs_scope && lhs_name == rhs_name
47
+ end
48
+
49
+ def on_masgn(node)
50
+ add_offense(node) if multiple_self_assignment?(node)
51
+ end
52
+
53
+ def on_or_asgn(node)
54
+ lhs, rhs = *node
55
+ add_offense(node) if rhs_matches_lhs?(rhs, lhs)
56
+ end
57
+ alias on_and_asgn on_or_asgn
58
+
59
+ private
60
+
61
+ def multiple_self_assignment?(node)
62
+ lhs, rhs = *node
63
+ return false unless rhs.array_type?
64
+ return false unless lhs.children.size == rhs.children.size
65
+
66
+ lhs.children.zip(rhs.children).all? do |lhs_item, rhs_item|
67
+ rhs_matches_lhs?(rhs_item, lhs_item)
68
+ end
69
+ end
70
+
71
+ def rhs_matches_lhs?(rhs, lhs)
72
+ rhs.type == ASSIGNMENT_TYPE_TO_RHS_TYPE[lhs.type] &&
73
+ rhs.children.first == lhs.children.first
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -34,8 +34,9 @@ module RuboCop
34
34
  # Foo.prepend Bar
35
35
  # Foo.extend Bar
36
36
  #
37
- class SendWithMixinArgument < Cop
37
+ class SendWithMixinArgument < Base
38
38
  include RangeHelp
39
+ extend AutoCorrector
39
40
 
40
41
  MSG = 'Use `%<method>s %<module_name>s` instead of `%<bad_method>s`.'
41
42
  MIXIN_METHODS = %i[include prepend extend].freeze
@@ -53,16 +54,9 @@ module RuboCop
53
54
  method, module_name.source, bad_location(node).source
54
55
  )
55
56
 
56
- add_offense(node, location: bad_location(node), message: message)
57
- end
58
- end
59
-
60
- def autocorrect(node)
61
- send_with_mixin_argument?(node) do |method, module_name|
62
- lambda do |corrector|
63
- corrector.replace(
64
- bad_location(node), "#{method} #{module_name.source}"
65
- )
57
+ bad_location = bad_location(node)
58
+ add_offense(bad_location, message: message) do |corrector|
59
+ corrector.replace(bad_location, "#{method} #{module_name.source}")
66
60
  end
67
61
  end
68
62
  end
@@ -63,14 +63,14 @@ module RuboCop
63
63
  # bar
64
64
  # end
65
65
  #
66
- class ShadowedArgument < Cop
66
+ class ShadowedArgument < Base
67
67
  MSG = 'Argument `%<argument>s` was shadowed by a local variable ' \
68
68
  'before it was used.'
69
69
 
70
70
  def_node_search :uses_var?, '(lvar %)'
71
71
 
72
- def join_force?(force_class)
73
- force_class == VariableForce
72
+ def self.joining_forces
73
+ VariableForce
74
74
  end
75
75
 
76
76
  def after_leaving_scope(scope, _variable_table)
@@ -43,7 +43,7 @@ module RuboCop
43
43
  # handle_standard_error
44
44
  # end
45
45
  #
46
- class ShadowedException < Cop
46
+ class ShadowedException < Base
47
47
  include RescueNode
48
48
  include RangeHelp
49
49
 
@@ -62,7 +62,7 @@ module RuboCop
62
62
  return if !rescue_group_rescues_multiple_levels &&
63
63
  sorted?(rescued_groups)
64
64
 
65
- add_offense(node, location: offense_range(rescues))
65
+ add_offense(offense_range(rescues))
66
66
  end
67
67
 
68
68
  private
@@ -31,11 +31,11 @@ module RuboCop
31
31
  # do_something(bar)
32
32
  # end
33
33
  # end
34
- class ShadowingOuterLocalVariable < Cop
34
+ class ShadowingOuterLocalVariable < Base
35
35
  MSG = 'Shadowing outer local variable - `%<variable>s`.'
36
36
 
37
- def join_force?(force_class)
38
- force_class == VariableForce
37
+ def self.joining_forces
38
+ VariableForce
39
39
  end
40
40
 
41
41
  def before_declaring_variable(variable, variable_table)
@@ -21,7 +21,7 @@ module RuboCop
21
21
  # g.clone #=> #<struct Good id=1, name="foo">
22
22
  # g.count #=> 2
23
23
  #
24
- class StructNewOverride < Cop
24
+ class StructNewOverride < Base
25
25
  MSG = '`%<member_name>s` member overrides `Struct#%<method_name>s`' \
26
26
  ' and it may be unexpected.'
27
27
 
@@ -64,7 +64,7 @@ module RuboCop
64
64
  # rescue
65
65
  # # do nothing
66
66
  # end
67
- class SuppressedException < Cop
67
+ class SuppressedException < Base
68
68
  MSG = 'Do not suppress exceptions.'
69
69
 
70
70
  def on_resbody(node)
@@ -77,13 +77,10 @@ module RuboCop
77
77
  private
78
78
 
79
79
  def comment_between_rescue_and_end?(node)
80
- end_line = nil
81
- node.each_ancestor(:kwbegin, :def, :defs, :block) do |ancestor|
82
- end_line = ancestor.loc.end.line
83
- break
84
- end
85
- return false unless end_line
80
+ ancestor = node.each_ancestor(:kwbegin, :def, :defs, :block).first
81
+ return unless ancestor
86
82
 
83
+ end_line = ancestor.loc.end.line
87
84
  processed_source[node.first_line...end_line].any? { |line| comment_line?(line) }
88
85
  end
89
86
  end
@@ -3,49 +3,34 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This is not actually a cop. It does not inspect anything. It just
7
- # provides methods to repack Parser's diagnostics/errors
6
+ # This cop repacks Parser's diagnostics/errors
8
7
  # into RuboCop's offenses.
9
- class Syntax < Cop
10
- PseudoSourceRange = Struct.new(:line, :column, :source_line, :begin_pos,
11
- :end_pos)
12
-
13
- ERROR_SOURCE_RANGE = PseudoSourceRange.new(1, 0, '', 0, 1).freeze
14
-
15
- def self.offenses_from_processed_source(processed_source,
16
- config, options)
17
- cop = new(config, options)
18
-
19
- cop.add_offense_from_error(processed_source.parser_error) if processed_source.parser_error
20
-
8
+ class Syntax < Base
9
+ def on_other_file
10
+ add_offense_from_error(processed_source.parser_error) if processed_source.parser_error
21
11
  processed_source.diagnostics.each do |diagnostic|
22
- cop.add_offense_from_diagnostic(diagnostic,
23
- processed_source.ruby_version)
12
+ add_offense_from_diagnostic(diagnostic,
13
+ processed_source.ruby_version)
24
14
  end
25
-
26
- cop.offenses
15
+ super
27
16
  end
28
17
 
18
+ private
19
+
29
20
  def add_offense_from_diagnostic(diagnostic, ruby_version)
30
21
  message =
31
22
  "#{diagnostic.message}\n(Using Ruby #{ruby_version} parser; " \
32
23
  'configure using `TargetRubyVersion` parameter, under `AllCops`)'
33
- add_offense(nil,
34
- location: diagnostic.location,
24
+ add_offense(diagnostic.location,
35
25
  message: message,
36
26
  severity: diagnostic.level)
37
27
  end
38
28
 
39
29
  def add_offense_from_error(error)
40
30
  message = beautify_message(error.message)
41
- add_offense(nil,
42
- location: ERROR_SOURCE_RANGE,
43
- message: message,
44
- severity: :fatal)
31
+ add_global_offense(message, severity: :fatal)
45
32
  end
46
33
 
47
- private
48
-
49
34
  def beautify_message(message)
50
35
  message = message.capitalize
51
36
  message << '.' unless message.end_with?('.')
@@ -17,18 +17,16 @@ module RuboCop
17
17
  # def to_json(*_args)
18
18
  # end
19
19
  #
20
- class ToJSON < Cop
20
+ class ToJSON < Base
21
+ extend AutoCorrector
22
+
21
23
  MSG = ' `#to_json` requires an optional argument to be parsable ' \
22
24
  'via JSON.generate(obj).'
23
25
 
24
26
  def on_def(node)
25
27
  return unless node.method?(:to_json) && node.arguments.empty?
26
28
 
27
- add_offense(node)
28
- end
29
-
30
- def autocorrect(node)
31
- lambda do |corrector|
29
+ add_offense(node) do |corrector|
32
30
  # The following used `*_args` because `to_json(*args)` has
33
31
  # an offense of `Lint/UnusedMethodArgument` cop if `*args`
34
32
  # is not used.
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # This cop checks for top level return with arguments. If there is a
7
+ # top-level return statement with an argument, then the argument is
8
+ # always ignored. This is detected automatically since Ruby 2.7.
9
+ #
10
+ # @example
11
+ #
12
+ # # Detected since Ruby 2.7
13
+ # return 1 # 1 is always ignored.
14
+ class TopLevelReturnWithArgument < Cop
15
+ # This cop works by validating the ancestors of the return node. A
16
+ # top-level return node's ancestors should not be of block, def, or
17
+ # defs type.
18
+
19
+ MSG = 'Top level return with argument detected.'
20
+
21
+ def on_return(return_node)
22
+ add_offense(return_node) if return_node.arguments? && ancestors_valid?(return_node)
23
+ end
24
+
25
+ private
26
+
27
+ def ancestors_valid?(return_node)
28
+ prohibited_ancestors = return_node.each_ancestor(:block, :def, :defs)
29
+ prohibited_ancestors.none?
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -40,11 +40,11 @@ module RuboCop
40
40
  # {_id: _id, profit: revenue - cost}
41
41
  # end
42
42
  #
43
- class UnderscorePrefixedVariableName < Cop
43
+ class UnderscorePrefixedVariableName < Base
44
44
  MSG = 'Do not use prefix `_` for a variable that is used.'
45
45
 
46
- def join_force?(force_class)
47
- force_class == VariableForce
46
+ def self.joining_forces
47
+ VariableForce
48
48
  end
49
49
 
50
50
  def after_leaving_scope(scope, _variable_table)
@@ -66,7 +66,7 @@ module RuboCop
66
66
  node.loc.name
67
67
  end
68
68
 
69
- add_offense(nil, location: location)
69
+ add_offense(location)
70
70
  end
71
71
 
72
72
  private
@@ -17,7 +17,9 @@ module RuboCop
17
17
  # # good
18
18
  #
19
19
  # 1.is_a?(Integer)
20
- class UnifiedInteger < Cop
20
+ class UnifiedInteger < Base
21
+ extend AutoCorrector
22
+
21
23
  MSG = 'Use `Integer` instead of `%<klass>s`.'
22
24
 
23
25
  def_node_matcher :fixnum_or_bignum_const, <<~PATTERN
@@ -29,11 +31,7 @@ module RuboCop
29
31
 
30
32
  return unless klass
31
33
 
32
- add_offense(node, message: format(MSG, klass: klass))
33
- end
34
-
35
- def autocorrect(node)
36
- lambda do |corrector|
34
+ add_offense(node, message: format(MSG, klass: klass)) do |corrector|
37
35
  corrector.replace(node.loc.name, 'Integer')
38
36
  end
39
37
  end
@@ -34,7 +34,7 @@ module RuboCop
34
34
  # def some_method
35
35
  # do_something
36
36
  # end
37
- class UnreachableCode < Cop
37
+ class UnreachableCode < Base
38
38
  MSG = 'Unreachable code detected.'
39
39
 
40
40
  def on_begin(node)
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # This cop checks for loops that will have at most one iteration.
7
+ #
8
+ # A loop that can never reach the second iteration is a possible error in the code.
9
+ # In rare cases where only one iteration (or at most one iteration) is intended behavior,
10
+ # the code should be refactored to use `if` conditionals.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # while node
15
+ # do_something(node)
16
+ # node = node.parent
17
+ # break
18
+ # end
19
+ #
20
+ # # good
21
+ # while node
22
+ # do_something(node)
23
+ # node = node.parent
24
+ # end
25
+ #
26
+ # # bad
27
+ # def verify_list(head)
28
+ # item = head
29
+ # begin
30
+ # if verify(item)
31
+ # return true
32
+ # else
33
+ # return false
34
+ # end
35
+ # end while(item)
36
+ # end
37
+ #
38
+ # # good
39
+ # def verify_list(head)
40
+ # item = head
41
+ # begin
42
+ # if verify(item)
43
+ # item = item.next
44
+ # else
45
+ # return false
46
+ # end
47
+ # end while(item)
48
+ #
49
+ # true
50
+ # end
51
+ #
52
+ # # bad
53
+ # def find_something(items)
54
+ # items.each do |item|
55
+ # if something?(item)
56
+ # return item
57
+ # else
58
+ # raise NotFoundError
59
+ # end
60
+ # end
61
+ # end
62
+ #
63
+ # # good
64
+ # def find_something(items)
65
+ # items.each do |item|
66
+ # if something?(item)
67
+ # return item
68
+ # end
69
+ # end
70
+ # raise NotFoundError
71
+ # end
72
+ #
73
+ class UnreachableLoop < Base
74
+ MSG = 'This loop will have at most one iteration.'
75
+
76
+ def on_while(node)
77
+ check(node)
78
+ end
79
+ alias on_until on_while
80
+ alias on_while_post on_while
81
+ alias on_until_post on_while
82
+ alias on_for on_while
83
+
84
+ def on_block(node)
85
+ check(node) if loop_method?(node)
86
+ end
87
+
88
+ private
89
+
90
+ def loop_method?(node)
91
+ return false unless node.block_type?
92
+
93
+ send_node = node.send_node
94
+ send_node.enumerable_method? || send_node.enumerator_method? || send_node.method?(:loop)
95
+ end
96
+
97
+ def check(node)
98
+ statements = statements(node)
99
+ break_statement = statements.find { |statement| break_statement?(statement) }
100
+ return unless break_statement
101
+
102
+ add_offense(node) unless preceded_by_continue_statement?(break_statement)
103
+ end
104
+
105
+ def statements(node)
106
+ body = node.body
107
+
108
+ if body.nil?
109
+ []
110
+ elsif body.begin_type?
111
+ body.children
112
+ else
113
+ [body]
114
+ end
115
+ end
116
+
117
+ def_node_matcher :break_command?, <<~PATTERN
118
+ {
119
+ return break
120
+ (send
121
+ {nil? (const {nil? cbase} :Kernel)}
122
+ {:raise :fail :throw :exit :exit! :abort}
123
+ ...)
124
+ }
125
+ PATTERN
126
+
127
+ def break_statement?(node)
128
+ return true if break_command?(node)
129
+
130
+ case node.type
131
+ when :begin, :kwbegin
132
+ statements = *node
133
+ statements.any? { |statement| break_statement?(statement) }
134
+ when :if
135
+ check_if(node)
136
+ when :case
137
+ check_case(node)
138
+ else
139
+ false
140
+ end
141
+ end
142
+
143
+ def check_if(node)
144
+ if_branch = node.if_branch
145
+ else_branch = node.else_branch
146
+ if_branch && else_branch &&
147
+ break_statement?(if_branch) && break_statement?(else_branch)
148
+ end
149
+
150
+ def check_case(node)
151
+ else_branch = node.else_branch
152
+ return false unless else_branch
153
+ return false unless break_statement?(else_branch)
154
+
155
+ node.when_branches.all? do |branch|
156
+ branch.body && break_statement?(branch.body)
157
+ end
158
+ end
159
+
160
+ def preceded_by_continue_statement?(break_statement)
161
+ left_siblings_of(break_statement).any? do |sibling|
162
+ next if sibling.loop_keyword? || loop_method?(sibling)
163
+
164
+ sibling.each_descendant(:next, :redo).any?
165
+ end
166
+ end
167
+
168
+ def left_siblings_of(node)
169
+ node.parent.children[0, node.sibling_index]
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end