rubocop 1.31.1 → 1.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (462) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +5 -5
  4. data/config/default.yml +342 -52
  5. data/config/obsoletion.yml +23 -1
  6. data/exe/rubocop +1 -1
  7. data/lib/rubocop/arguments_env.rb +17 -0
  8. data/lib/rubocop/arguments_file.rb +17 -0
  9. data/lib/rubocop/cache_config.rb +29 -0
  10. data/lib/rubocop/cli/command/{auto_genenerate_config.rb → auto_generate_config.rb} +9 -2
  11. data/lib/rubocop/cli/command/execute_runner.rb +14 -9
  12. data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
  13. data/lib/rubocop/cli/command/suggest_extensions.rb +61 -16
  14. data/lib/rubocop/cli.rb +56 -9
  15. data/lib/rubocop/comment_config.rb +60 -1
  16. data/lib/rubocop/config.rb +48 -20
  17. data/lib/rubocop/config_finder.rb +68 -0
  18. data/lib/rubocop/config_loader.rb +46 -68
  19. data/lib/rubocop/config_loader_resolver.rb +11 -12
  20. data/lib/rubocop/config_obsoletion/changed_parameter.rb +5 -0
  21. data/lib/rubocop/config_obsoletion/parameter_rule.rb +4 -0
  22. data/lib/rubocop/config_obsoletion.rb +9 -4
  23. data/lib/rubocop/config_validator.rb +1 -1
  24. data/lib/rubocop/cop/autocorrect_logic.rb +29 -13
  25. data/lib/rubocop/cop/badge.rb +9 -4
  26. data/lib/rubocop/cop/base.rb +115 -83
  27. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  28. data/lib/rubocop/cop/commissioner.rb +19 -6
  29. data/lib/rubocop/cop/cop.rb +54 -34
  30. data/lib/rubocop/cop/corrector.rb +31 -11
  31. data/lib/rubocop/cop/correctors/alignment_corrector.rb +3 -3
  32. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +3 -3
  33. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +3 -3
  34. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  35. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +23 -7
  36. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +2 -7
  37. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +58 -0
  38. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  39. data/lib/rubocop/cop/gemspec/dependency_version.rb +17 -19
  40. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -1
  41. data/lib/rubocop/cop/gemspec/development_dependencies.rb +107 -0
  42. data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
  43. data/lib/rubocop/cop/generator/require_file_injector.rb +2 -2
  44. data/lib/rubocop/cop/generator.rb +5 -2
  45. data/lib/rubocop/cop/internal_affairs/cop_description.rb +8 -6
  46. data/lib/rubocop/cop/internal_affairs/create_empty_file.rb +37 -0
  47. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +111 -0
  48. data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +1 -1
  49. data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
  50. data/lib/rubocop/cop/internal_affairs/location_expression.rb +37 -0
  51. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +3 -3
  52. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -1
  53. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +69 -0
  54. data/lib/rubocop/cop/internal_affairs/processed_source_buffer_name.rb +42 -0
  55. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +11 -3
  56. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  57. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
  58. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +66 -0
  59. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +62 -0
  60. data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +60 -0
  61. data/lib/rubocop/cop/internal_affairs.rb +9 -0
  62. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  63. data/lib/rubocop/cop/layout/block_alignment.rb +16 -12
  64. data/lib/rubocop/cop/layout/block_end_newline.rb +31 -9
  65. data/lib/rubocop/cop/layout/class_structure.rb +37 -27
  66. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -1
  67. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +2 -6
  68. data/lib/rubocop/cop/layout/comment_indentation.rb +3 -1
  69. data/lib/rubocop/cop/layout/empty_comment.rb +3 -3
  70. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
  71. data/lib/rubocop/cop/layout/empty_lines.rb +3 -1
  72. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -2
  73. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +2 -0
  74. data/lib/rubocop/cop/layout/end_alignment.rb +9 -1
  75. data/lib/rubocop/cop/layout/end_of_line.rb +4 -4
  76. data/lib/rubocop/cop/layout/extra_spacing.rb +15 -6
  77. data/lib/rubocop/cop/layout/first_argument_indentation.rb +15 -4
  78. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +6 -5
  79. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +35 -8
  80. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +5 -5
  81. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +36 -1
  82. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +57 -8
  83. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +52 -19
  84. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +10 -4
  85. data/lib/rubocop/cop/layout/heredoc_indentation.rb +8 -11
  86. data/lib/rubocop/cop/layout/indentation_style.rb +7 -2
  87. data/lib/rubocop/cop/layout/indentation_width.rb +6 -2
  88. data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
  89. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  90. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +80 -12
  91. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +18 -8
  92. data/lib/rubocop/cop/layout/line_length.rb +8 -1
  93. data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +31 -1
  94. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
  95. data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -1
  96. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +29 -1
  97. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +39 -2
  98. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +77 -0
  99. data/lib/rubocop/cop/layout/redundant_line_break.rb +9 -10
  100. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -2
  101. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  102. data/lib/rubocop/cop/layout/space_around_keyword.rb +3 -3
  103. data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
  104. data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
  105. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
  106. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +2 -2
  107. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +22 -20
  108. data/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb +3 -0
  109. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +27 -9
  110. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +30 -3
  111. data/lib/rubocop/cop/layout/space_inside_parens.rb +2 -2
  112. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +34 -0
  113. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +10 -6
  114. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +5 -4
  115. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +1 -1
  116. data/lib/rubocop/cop/layout/trailing_whitespace.rb +12 -5
  117. data/lib/rubocop/cop/legacy/corrections_proxy.rb +1 -1
  118. data/lib/rubocop/cop/legacy/corrector.rb +1 -1
  119. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +39 -8
  120. data/lib/rubocop/cop/lint/ambiguous_operator.rb +4 -0
  121. data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
  122. data/lib/rubocop/cop/lint/constant_resolution.rb +5 -1
  123. data/lib/rubocop/cop/lint/debugger.rb +27 -31
  124. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +66 -110
  125. data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
  126. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  127. data/lib/rubocop/cop/lint/duplicate_branch.rb +0 -2
  128. data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
  129. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +122 -0
  130. data/lib/rubocop/cop/lint/duplicate_methods.rb +48 -18
  131. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +26 -9
  132. data/lib/rubocop/cop/lint/duplicate_require.rb +1 -1
  133. data/lib/rubocop/cop/lint/else_layout.rb +3 -7
  134. data/lib/rubocop/cop/lint/empty_block.rb +3 -7
  135. data/lib/rubocop/cop/lint/empty_class.rb +3 -1
  136. data/lib/rubocop/cop/lint/empty_conditional_body.rb +110 -2
  137. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  138. data/lib/rubocop/cop/lint/erb_new_arguments.rb +11 -11
  139. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +14 -7
  140. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +15 -17
  141. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  142. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -2
  143. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  144. data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
  145. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  146. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +48 -2
  147. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
  148. data/lib/rubocop/cop/lint/missing_super.rb +31 -2
  149. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  150. data/lib/rubocop/cop/lint/nested_method_definition.rb +53 -9
  151. data/lib/rubocop/cop/lint/next_without_accumulator.rb +25 -6
  152. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +68 -28
  153. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +12 -0
  154. data/lib/rubocop/cop/lint/number_conversion.rb +28 -6
  155. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
  156. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -0
  157. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
  158. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -2
  159. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
  160. data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
  161. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  162. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +49 -9
  163. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +6 -6
  164. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
  165. data/lib/rubocop/cop/lint/redundant_require_statement.rb +48 -10
  166. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +13 -0
  167. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  168. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +35 -15
  169. data/lib/rubocop/cop/lint/redundant_with_index.rb +14 -11
  170. data/lib/rubocop/cop/lint/redundant_with_object.rb +13 -12
  171. data/lib/rubocop/cop/lint/refinement_import_methods.rb +2 -1
  172. data/lib/rubocop/cop/lint/regexp_as_condition.rb +6 -0
  173. data/lib/rubocop/cop/lint/require_parentheses.rb +3 -1
  174. data/lib/rubocop/cop/lint/require_range_parentheses.rb +57 -0
  175. data/lib/rubocop/cop/lint/rescue_type.rb +3 -3
  176. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +41 -8
  177. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +1 -1
  178. data/lib/rubocop/cop/lint/script_permission.rb +1 -1
  179. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -4
  180. data/lib/rubocop/cop/lint/shadowed_exception.rb +16 -11
  181. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +28 -3
  182. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  183. data/lib/rubocop/cop/lint/syntax.rb +4 -0
  184. data/lib/rubocop/cop/lint/to_enum_arguments.rb +13 -3
  185. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
  186. data/lib/rubocop/cop/lint/unreachable_loop.rb +12 -6
  187. data/lib/rubocop/cop/lint/unused_method_argument.rb +6 -1
  188. data/lib/rubocop/cop/lint/useless_access_modifier.rb +17 -12
  189. data/lib/rubocop/cop/lint/useless_assignment.rb +56 -1
  190. data/lib/rubocop/cop/lint/useless_method_definition.rb +12 -4
  191. data/lib/rubocop/cop/lint/useless_rescue.rb +89 -0
  192. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +15 -5
  193. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  194. data/lib/rubocop/cop/lint/void.rb +92 -21
  195. data/lib/rubocop/cop/metrics/abc_size.rb +4 -2
  196. data/lib/rubocop/cop/metrics/block_length.rb +16 -11
  197. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
  198. data/lib/rubocop/cop/metrics/class_length.rb +11 -5
  199. data/lib/rubocop/cop/metrics/collection_literal_length.rb +76 -0
  200. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  201. data/lib/rubocop/cop/metrics/method_length.rb +17 -11
  202. data/lib/rubocop/cop/metrics/module_length.rb +10 -5
  203. data/lib/rubocop/cop/metrics/parameter_lists.rb +27 -0
  204. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  205. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +3 -6
  206. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +9 -6
  207. data/lib/rubocop/cop/migration/department_name.rb +1 -1
  208. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  209. data/lib/rubocop/cop/mixin/allowed_identifiers.rb +2 -2
  210. data/lib/rubocop/cop/mixin/allowed_methods.rb +23 -2
  211. data/lib/rubocop/cop/mixin/allowed_pattern.rb +17 -1
  212. data/lib/rubocop/cop/mixin/annotation_comment.rb +14 -7
  213. data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -1
  214. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  215. data/lib/rubocop/cop/mixin/comments_help.rb +29 -7
  216. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +21 -9
  217. data/lib/rubocop/cop/mixin/def_node.rb +2 -7
  218. data/lib/rubocop/cop/mixin/documentation_comment.rb +1 -1
  219. data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -1
  220. data/lib/rubocop/cop/mixin/first_element_line_break.rb +11 -7
  221. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
  222. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +1 -1
  223. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +152 -12
  224. data/lib/rubocop/cop/mixin/hash_transform_method.rb +13 -9
  225. data/lib/rubocop/cop/mixin/line_length_help.rb +11 -2
  226. data/lib/rubocop/cop/mixin/method_complexity.rb +13 -16
  227. data/lib/rubocop/cop/mixin/min_branches_count.rb +40 -0
  228. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +7 -14
  229. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +5 -6
  230. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  231. data/lib/rubocop/cop/mixin/percent_array.rb +58 -1
  232. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
  233. data/lib/rubocop/cop/mixin/range_help.rb +22 -5
  234. data/lib/rubocop/cop/mixin/require_library.rb +2 -0
  235. data/lib/rubocop/cop/mixin/rescue_node.rb +5 -3
  236. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  237. data/lib/rubocop/cop/mixin/statement_modifier.rb +18 -3
  238. data/lib/rubocop/cop/mixin/surrounding_space.rb +13 -11
  239. data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -2
  240. data/lib/rubocop/cop/mixin/visibility_help.rb +40 -5
  241. data/lib/rubocop/cop/naming/ascii_identifiers.rb +1 -1
  242. data/lib/rubocop/cop/naming/block_forwarding.rb +5 -1
  243. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  244. data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +3 -1
  245. data/lib/rubocop/cop/naming/constant_name.rb +3 -3
  246. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +1 -1
  247. data/lib/rubocop/cop/naming/inclusive_language.rb +28 -6
  248. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +22 -7
  249. data/lib/rubocop/cop/naming/method_name.rb +3 -3
  250. data/lib/rubocop/cop/naming/predicate_name.rb +31 -2
  251. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +12 -4
  252. data/lib/rubocop/cop/registry.rb +73 -45
  253. data/lib/rubocop/cop/security/compound_hash.rb +2 -1
  254. data/lib/rubocop/cop/style/access_modifier_declarations.rb +92 -3
  255. data/lib/rubocop/cop/style/accessor_grouping.rb +46 -20
  256. data/lib/rubocop/cop/style/alias.rb +9 -1
  257. data/lib/rubocop/cop/style/arguments_forwarding.rb +6 -5
  258. data/lib/rubocop/cop/style/array_intersect.rb +111 -0
  259. data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
  260. data/lib/rubocop/cop/style/attr.rb +11 -1
  261. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +1 -1
  262. data/lib/rubocop/cop/style/block_comments.rb +2 -2
  263. data/lib/rubocop/cop/style/block_delimiters.rb +44 -10
  264. data/lib/rubocop/cop/style/case_equality.rb +40 -10
  265. data/lib/rubocop/cop/style/case_like_if.rb +20 -3
  266. data/lib/rubocop/cop/style/character_literal.rb +1 -1
  267. data/lib/rubocop/cop/style/class_and_module_children.rb +8 -15
  268. data/lib/rubocop/cop/style/class_equality_comparison.rb +94 -12
  269. data/lib/rubocop/cop/style/class_methods_definitions.rb +2 -1
  270. data/lib/rubocop/cop/style/collection_compact.rb +21 -5
  271. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  272. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  273. data/lib/rubocop/cop/style/combinable_loops.rb +29 -7
  274. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  275. data/lib/rubocop/cop/style/comment_annotation.rb +1 -1
  276. data/lib/rubocop/cop/style/commented_keyword.rb +2 -2
  277. data/lib/rubocop/cop/style/comparable_clamp.rb +125 -0
  278. data/lib/rubocop/cop/style/concat_array_literals.rb +94 -0
  279. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -14
  280. data/lib/rubocop/cop/style/copyright.rb +6 -3
  281. data/lib/rubocop/cop/style/data_inheritance.rb +75 -0
  282. data/lib/rubocop/cop/style/dir_empty.rb +60 -0
  283. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
  284. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +2 -2
  285. data/lib/rubocop/cop/style/documentation.rb +22 -10
  286. data/lib/rubocop/cop/style/documentation_method.rb +10 -4
  287. data/lib/rubocop/cop/style/double_negation.rb +4 -2
  288. data/lib/rubocop/cop/style/each_for_simple_loop.rb +41 -6
  289. data/lib/rubocop/cop/style/each_with_object.rb +40 -9
  290. data/lib/rubocop/cop/style/empty_block_parameter.rb +2 -2
  291. data/lib/rubocop/cop/style/empty_else.rb +37 -0
  292. data/lib/rubocop/cop/style/empty_heredoc.rb +73 -0
  293. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +2 -2
  294. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  295. data/lib/rubocop/cop/style/endless_method.rb +1 -1
  296. data/lib/rubocop/cop/style/eval_with_location.rb +4 -4
  297. data/lib/rubocop/cop/style/exact_regexp_match.rb +62 -0
  298. data/lib/rubocop/cop/style/explicit_block_argument.rb +5 -1
  299. data/lib/rubocop/cop/style/fetch_env_var.rb +10 -177
  300. data/lib/rubocop/cop/style/file_empty.rb +71 -0
  301. data/lib/rubocop/cop/style/file_read.rb +1 -1
  302. data/lib/rubocop/cop/style/file_write.rb +1 -1
  303. data/lib/rubocop/cop/style/for.rb +2 -0
  304. data/lib/rubocop/cop/style/format_string_token.rb +25 -6
  305. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  306. data/lib/rubocop/cop/style/guard_clause.rb +127 -38
  307. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -0
  308. data/lib/rubocop/cop/style/hash_each_methods.rb +48 -12
  309. data/lib/rubocop/cop/style/hash_except.rb +27 -16
  310. data/lib/rubocop/cop/style/hash_like_case.rb +3 -9
  311. data/lib/rubocop/cop/style/hash_syntax.rb +26 -2
  312. data/lib/rubocop/cop/style/identical_conditional_branches.rb +15 -0
  313. data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
  314. data/lib/rubocop/cop/style/if_unless_modifier.rb +112 -16
  315. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +29 -2
  316. data/lib/rubocop/cop/style/if_with_semicolon.rb +4 -4
  317. data/lib/rubocop/cop/style/infinite_loop.rb +2 -5
  318. data/lib/rubocop/cop/style/inverse_methods.rb +15 -11
  319. data/lib/rubocop/cop/style/invertible_unless_condition.rb +118 -0
  320. data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -1
  321. data/lib/rubocop/cop/style/magic_comment_format.rb +307 -0
  322. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +2 -2
  323. data/lib/rubocop/cop/style/map_to_hash.rb +4 -1
  324. data/lib/rubocop/cop/style/map_to_set.rb +64 -0
  325. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +40 -24
  326. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -1
  327. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +48 -41
  328. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +21 -2
  329. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +4 -1
  330. data/lib/rubocop/cop/style/method_def_parentheses.rb +11 -4
  331. data/lib/rubocop/cop/style/min_max.rb +3 -3
  332. data/lib/rubocop/cop/style/min_max_comparison.rb +83 -0
  333. data/lib/rubocop/cop/style/missing_else.rb +13 -1
  334. data/lib/rubocop/cop/style/mixin_grouping.rb +4 -4
  335. data/lib/rubocop/cop/style/module_function.rb +30 -8
  336. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -1
  337. data/lib/rubocop/cop/style/multiline_if_modifier.rb +0 -4
  338. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
  339. data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
  340. data/lib/rubocop/cop/style/multiline_method_signature.rb +7 -4
  341. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +18 -3
  342. data/lib/rubocop/cop/style/negated_if_else_condition.rb +17 -10
  343. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +9 -0
  344. data/lib/rubocop/cop/style/next.rb +3 -5
  345. data/lib/rubocop/cop/style/nil_lambda.rb +4 -4
  346. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +11 -3
  347. data/lib/rubocop/cop/style/numeric_literals.rb +16 -1
  348. data/lib/rubocop/cop/style/numeric_predicate.rb +43 -9
  349. data/lib/rubocop/cop/style/object_then.rb +5 -0
  350. data/lib/rubocop/cop/style/one_line_conditional.rb +3 -6
  351. data/lib/rubocop/cop/style/operator_method_call.rb +67 -0
  352. data/lib/rubocop/cop/style/parallel_assignment.rb +29 -19
  353. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -3
  354. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  355. data/lib/rubocop/cop/style/perl_backrefs.rb +22 -1
  356. data/lib/rubocop/cop/style/proc.rb +4 -1
  357. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  358. data/lib/rubocop/cop/style/redundant_argument.rb +3 -0
  359. data/lib/rubocop/cop/style/redundant_begin.rb +3 -0
  360. data/lib/rubocop/cop/style/redundant_condition.rb +41 -8
  361. data/lib/rubocop/cop/style/redundant_conditional.rb +0 -4
  362. data/lib/rubocop/cop/style/redundant_constant_base.rb +85 -0
  363. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +45 -0
  364. data/lib/rubocop/cop/style/redundant_each.rb +116 -0
  365. data/lib/rubocop/cop/style/redundant_fetch_block.rb +7 -5
  366. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +58 -0
  367. data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
  368. data/lib/rubocop/cop/style/redundant_interpolation.rb +2 -2
  369. data/lib/rubocop/cop/style/redundant_line_continuation.rb +183 -0
  370. data/lib/rubocop/cop/style/redundant_parentheses.rb +22 -24
  371. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  372. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +9 -3
  373. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +21 -4
  374. data/lib/rubocop/cop/style/redundant_return.rb +7 -0
  375. data/lib/rubocop/cop/style/redundant_self.rb +2 -0
  376. data/lib/rubocop/cop/style/redundant_sort.rb +24 -9
  377. data/lib/rubocop/cop/style/redundant_sort_by.rb +24 -8
  378. data/lib/rubocop/cop/style/redundant_string_escape.rb +183 -0
  379. data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
  380. data/lib/rubocop/cop/style/require_order.rb +138 -0
  381. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
  382. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -2
  383. data/lib/rubocop/cop/style/safe_navigation.rb +41 -10
  384. data/lib/rubocop/cop/style/select_by_regexp.rb +13 -5
  385. data/lib/rubocop/cop/style/self_assignment.rb +2 -2
  386. data/lib/rubocop/cop/style/semicolon.rb +63 -5
  387. data/lib/rubocop/cop/style/signal_exception.rb +8 -6
  388. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  389. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
  390. data/lib/rubocop/cop/style/sole_nested_conditional.rb +17 -8
  391. data/lib/rubocop/cop/style/special_global_vars.rb +2 -2
  392. data/lib/rubocop/cop/style/static_class.rb +32 -1
  393. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  394. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -1
  395. data/lib/rubocop/cop/style/string_literals.rb +1 -5
  396. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  397. data/lib/rubocop/cop/style/symbol_array.rb +6 -5
  398. data/lib/rubocop/cop/style/symbol_proc.rb +42 -10
  399. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -13
  400. data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -1
  401. data/lib/rubocop/cop/style/trailing_body_on_class.rb +1 -0
  402. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -4
  403. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  404. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -1
  405. data/lib/rubocop/cop/style/trivial_accessors.rb +4 -1
  406. data/lib/rubocop/cop/style/unless_logical_operators.rb +1 -0
  407. data/lib/rubocop/cop/style/unpack_first.rb +3 -3
  408. data/lib/rubocop/cop/style/word_array.rb +59 -5
  409. data/lib/rubocop/cop/style/yoda_condition.rb +13 -6
  410. data/lib/rubocop/cop/style/yoda_expression.rb +90 -0
  411. data/lib/rubocop/cop/style/zero_length_predicate.rb +40 -19
  412. data/lib/rubocop/cop/team.rb +63 -56
  413. data/lib/rubocop/cop/util.rb +44 -8
  414. data/lib/rubocop/cop/variable_force/assignment.rb +5 -1
  415. data/lib/rubocop/cop/variable_force/scope.rb +3 -3
  416. data/lib/rubocop/cop/variable_force/variable.rb +5 -3
  417. data/lib/rubocop/cop/variable_force/variable_table.rb +6 -4
  418. data/lib/rubocop/cop/variable_force.rb +18 -30
  419. data/lib/rubocop/cops_documentation_generator.rb +45 -15
  420. data/lib/rubocop/directive_comment.rb +4 -4
  421. data/lib/rubocop/ext/comment.rb +18 -0
  422. data/lib/rubocop/ext/processed_source.rb +2 -0
  423. data/lib/rubocop/ext/range.rb +15 -0
  424. data/lib/rubocop/ext/regexp_node.rb +1 -1
  425. data/lib/rubocop/ext/regexp_parser.rb +1 -1
  426. data/lib/rubocop/feature_loader.rb +94 -0
  427. data/lib/rubocop/file_patterns.rb +43 -0
  428. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
  429. data/lib/rubocop/formatter/disabled_config_formatter.rb +26 -9
  430. data/lib/rubocop/formatter/html_formatter.rb +4 -4
  431. data/lib/rubocop/formatter/junit_formatter.rb +4 -1
  432. data/lib/rubocop/formatter/markdown_formatter.rb +1 -1
  433. data/lib/rubocop/formatter/offense_count_formatter.rb +8 -5
  434. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
  435. data/lib/rubocop/formatter/tap_formatter.rb +1 -1
  436. data/lib/rubocop/formatter/worst_offenders_formatter.rb +6 -3
  437. data/lib/rubocop/formatter.rb +4 -1
  438. data/lib/rubocop/options.rb +55 -22
  439. data/lib/rubocop/path_util.rb +50 -22
  440. data/lib/rubocop/rake_task.rb +5 -1
  441. data/lib/rubocop/result_cache.rb +26 -24
  442. data/lib/rubocop/rspec/cop_helper.rb +26 -3
  443. data/lib/rubocop/rspec/expect_offense.rb +6 -4
  444. data/lib/rubocop/rspec/shared_contexts.rb +31 -14
  445. data/lib/rubocop/rspec/support.rb +17 -2
  446. data/lib/rubocop/runner.rb +73 -18
  447. data/lib/rubocop/server/cache.rb +48 -2
  448. data/lib/rubocop/server/cli.rb +62 -19
  449. data/lib/rubocop/server/client_command/base.rb +1 -1
  450. data/lib/rubocop/server/client_command/exec.rb +6 -1
  451. data/lib/rubocop/server/client_command/start.rb +6 -1
  452. data/lib/rubocop/server/core.rb +42 -10
  453. data/lib/rubocop/server/helper.rb +1 -1
  454. data/lib/rubocop/server/server_command/exec.rb +1 -1
  455. data/lib/rubocop/server/socket_reader.rb +5 -1
  456. data/lib/rubocop/server.rb +1 -1
  457. data/lib/rubocop/target_finder.rb +1 -1
  458. data/lib/rubocop/target_ruby.rb +5 -5
  459. data/lib/rubocop/version.rb +10 -4
  460. data/lib/rubocop.rb +45 -9
  461. metadata +58 -33
  462. data/lib/rubocop/cop/mixin/ignored_methods.rb +0 -52
@@ -6,6 +6,13 @@ module RuboCop
6
6
  # Use a guard clause instead of wrapping the code inside a conditional
7
7
  # expression
8
8
  #
9
+ # A condition with an `elsif` or `else` branch is allowed unless
10
+ # one of `return`, `break`, `next`, `raise`, or `fail` is used
11
+ # in the body of the conditional expression.
12
+ #
13
+ # NOTE: Autocorrect works in most cases except with if-else statements
14
+ # that contain logical operators such as `foo || raise('exception')`
15
+ #
9
16
  # @example
10
17
  # # bad
11
18
  # def test
@@ -50,35 +57,44 @@ module RuboCop
50
57
  #
51
58
  # @example AllowConsecutiveConditionals: false (default)
52
59
  # # bad
53
- # if foo?
54
- # work
55
- # end
60
+ # def test
61
+ # if foo?
62
+ # work
63
+ # end
56
64
  #
57
- # if bar? # <- reports an offense
58
- # work
65
+ # if bar? # <- reports an offense
66
+ # work
67
+ # end
59
68
  # end
60
69
  #
61
70
  # @example AllowConsecutiveConditionals: true
62
71
  # # good
63
- # if foo?
64
- # work
65
- # end
72
+ # def test
73
+ # if foo?
74
+ # work
75
+ # end
66
76
  #
67
- # if bar?
68
- # work
77
+ # if bar?
78
+ # work
79
+ # end
69
80
  # end
70
81
  #
71
82
  # # bad
72
- # if foo?
73
- # work
74
- # end
83
+ # def test
84
+ # if foo?
85
+ # work
86
+ # end
75
87
  #
76
- # do_something
88
+ # do_something
77
89
  #
78
- # if bar? # <- reports an offense
79
- # work
90
+ # if bar? # <- reports an offense
91
+ # work
92
+ # end
80
93
  # end
94
+ #
81
95
  class GuardClause < Base
96
+ extend AutoCorrector
97
+ include RangeHelp
82
98
  include MinBodyLength
83
99
  include StatementModifier
84
100
 
@@ -90,40 +106,49 @@ module RuboCop
90
106
 
91
107
  return unless body
92
108
 
93
- if body.if_type?
94
- check_ending_if(body)
95
- elsif body.begin_type?
96
- final_expression = body.children.last
97
- check_ending_if(final_expression) if final_expression&.if_type?
98
- end
109
+ check_ending_body(body)
99
110
  end
100
111
  alias on_defs on_def
101
112
 
102
113
  def on_if(node)
103
114
  return if accepted_form?(node)
104
115
 
105
- guard_clause_in_if = node.if_branch&.guard_clause?
106
- guard_clause_in_else = node.else_branch&.guard_clause?
107
- guard_clause = guard_clause_in_if || guard_clause_in_else
108
- return unless guard_clause
116
+ if (guard_clause = node.if_branch&.guard_clause?)
117
+ kw = node.loc.keyword.source
118
+ guard = :if
119
+ elsif (guard_clause = node.else_branch&.guard_clause?)
120
+ kw = node.inverse_keyword
121
+ guard = :else
122
+ else
123
+ return
124
+ end
109
125
 
110
- kw = if guard_clause_in_if
111
- node.loc.keyword.source
112
- else
113
- node.inverse_keyword
114
- end
126
+ guard = nil if and_or_guard_clause?(guard_clause)
115
127
 
116
- register_offense(node, guard_clause_source(guard_clause), kw)
128
+ register_offense(node, guard_clause_source(guard_clause), kw, guard)
117
129
  end
118
130
 
119
131
  private
120
132
 
133
+ def check_ending_body(body)
134
+ return if body.nil?
135
+
136
+ if body.if_type?
137
+ check_ending_if(body)
138
+ elsif body.begin_type?
139
+ final_expression = body.children.last
140
+ check_ending_if(final_expression) if final_expression&.if_type?
141
+ end
142
+ end
143
+
121
144
  def check_ending_if(node)
122
145
  return if accepted_form?(node, ending: true) || !min_body_length?(node)
123
146
  return if allowed_consecutive_conditionals? &&
124
147
  consecutive_conditionals?(node.parent, node)
125
148
 
126
149
  register_offense(node, 'return', node.inverse_keyword)
150
+
151
+ check_ending_body(node.if_branch)
127
152
  end
128
153
 
129
154
  def consecutive_conditionals?(parent, node)
@@ -134,28 +159,88 @@ module RuboCop
134
159
  end
135
160
  end
136
161
 
137
- def register_offense(node, scope_exiting_keyword, conditional_keyword)
162
+ def register_offense(node, scope_exiting_keyword, conditional_keyword, guard = nil)
138
163
  condition, = node.node_parts
139
164
  example = [scope_exiting_keyword, conditional_keyword, condition.source].join(' ')
140
165
  if too_long_for_single_line?(node, example)
141
166
  return if trivial?(node)
142
167
 
143
168
  example = "#{conditional_keyword} #{condition.source}; #{scope_exiting_keyword}; end"
169
+ replacement = <<~RUBY.chomp
170
+ #{conditional_keyword} #{condition.source}
171
+ #{scope_exiting_keyword}
172
+ end
173
+ RUBY
144
174
  end
145
175
 
146
- add_offense(node.loc.keyword, message: format(MSG, example: example))
176
+ add_offense(node.loc.keyword, message: format(MSG, example: example)) do |corrector|
177
+ next if node.else? && guard.nil?
178
+
179
+ autocorrect(corrector, node, condition, replacement || example, guard)
180
+ end
147
181
  end
148
182
 
149
- def guard_clause_source(guard_clause)
150
- parent = guard_clause.parent
183
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
184
+ def autocorrect(corrector, node, condition, replacement, guard)
185
+ corrector.replace(node.loc.keyword.join(condition.source_range), replacement)
186
+
187
+ if_branch = node.if_branch
188
+ else_branch = node.else_branch
189
+
190
+ corrector.replace(node.loc.begin, "\n") if node.loc.begin&.is?('then')
191
+
192
+ if if_branch&.send_type? && heredoc?(if_branch.last_argument)
193
+ autocorrect_heredoc_argument(corrector, node, if_branch, else_branch, guard)
194
+ elsif else_branch&.send_type? && heredoc?(else_branch.last_argument)
195
+ autocorrect_heredoc_argument(corrector, node, else_branch, if_branch, guard)
196
+ else
197
+ corrector.remove(node.loc.end)
198
+ return unless node.else?
151
199
 
152
- if parent.and_type? || parent.or_type?
200
+ corrector.remove(node.loc.else)
201
+ corrector.remove(range_of_branch_to_remove(node, guard))
202
+ end
203
+ end
204
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
205
+
206
+ def heredoc?(argument)
207
+ argument.respond_to?(:heredoc?) && argument.heredoc?
208
+ end
209
+
210
+ def autocorrect_heredoc_argument(corrector, node, heredoc_branch, leave_branch, guard)
211
+ return unless node.else?
212
+
213
+ remove_whole_lines(corrector, leave_branch.source_range)
214
+ remove_whole_lines(corrector, node.loc.else)
215
+ remove_whole_lines(corrector, node.loc.end)
216
+ remove_whole_lines(corrector, range_of_branch_to_remove(node, guard))
217
+ corrector.insert_after(
218
+ heredoc_branch.last_argument.loc.heredoc_end, "\n#{leave_branch.source}"
219
+ )
220
+ end
221
+
222
+ def range_of_branch_to_remove(node, guard)
223
+ branch = case guard
224
+ when :if then node.if_branch
225
+ when :else then node.else_branch
226
+ end
227
+
228
+ branch.source_range
229
+ end
230
+
231
+ def guard_clause_source(guard_clause)
232
+ if and_or_guard_clause?(guard_clause)
153
233
  guard_clause.parent.source
154
234
  else
155
235
  guard_clause.source
156
236
  end
157
237
  end
158
238
 
239
+ def and_or_guard_clause?(guard_clause)
240
+ parent = guard_clause.parent
241
+ parent.and_type? || parent.or_type?
242
+ end
243
+
159
244
  def too_long_for_single_line?(node, example)
160
245
  max = max_line_length
161
246
  max && node.source_range.column + example.length > max
@@ -170,7 +255,7 @@ module RuboCop
170
255
  end
171
256
 
172
257
  def accepted_if?(node, ending)
173
- return true if node.modifier_form? || node.ternary?
258
+ return true if node.modifier_form? || node.ternary? || node.elsif_conditional?
174
259
 
175
260
  if ending
176
261
  node.else?
@@ -179,6 +264,10 @@ module RuboCop
179
264
  end
180
265
  end
181
266
 
267
+ def remove_whole_lines(corrector, range)
268
+ corrector.remove(range_by_whole_lines(range, include_final_newline: true))
269
+ end
270
+
182
271
  def allowed_consecutive_conditionals?
183
272
  cop_config.fetch('AllowConsecutiveConditionals', false)
184
273
  end
@@ -34,6 +34,7 @@ module RuboCop
34
34
  extend AutoCorrector
35
35
 
36
36
  def on_hash(node)
37
+ return if node.children.first&.kwsplat_type?
37
38
  return unless (array = containing_array(node))
38
39
  return unless last_array_item?(array, node) && explicit_array?(array)
39
40
 
@@ -35,29 +35,53 @@ module RuboCop
35
35
 
36
36
  # @!method kv_each(node)
37
37
  def_node_matcher :kv_each, <<~PATTERN
38
- (block $(send (send _ ${:keys :values}) :each) ...)
38
+ ({block numblock} $(send (send _ ${:keys :values}) :each) ...)
39
+ PATTERN
40
+
41
+ # @!method kv_each_with_block_pass(node)
42
+ def_node_matcher :kv_each_with_block_pass, <<~PATTERN
43
+ (send $(send _ ${:keys :values}) :each (block_pass (sym _)))
39
44
  PATTERN
40
45
 
41
46
  def on_block(node)
42
- register_kv_offense(node)
47
+ kv_each(node) do |target, method|
48
+ register_kv_offense(target, method)
49
+ end
50
+ end
51
+
52
+ alias on_numblock on_block
53
+
54
+ def on_block_pass(node)
55
+ kv_each_with_block_pass(node.parent) do |target, method|
56
+ register_kv_with_block_pass_offense(node, target, method)
57
+ end
43
58
  end
44
59
 
45
60
  private
46
61
 
47
- def register_kv_offense(node)
48
- kv_each(node) do |target, method|
49
- parent_receiver = target.receiver.receiver
50
- return unless parent_receiver
51
- return if allowed_receiver?(parent_receiver)
62
+ def register_kv_offense(target, method)
63
+ return unless (parent_receiver = target.receiver.receiver)
64
+ return if allowed_receiver?(parent_receiver)
52
65
 
53
- msg = format(message, prefer: "each_#{method[0..-2]}", current: "#{method}.each")
66
+ add_offense(kv_range(target), message: format_message(method)) do |corrector|
67
+ correct_key_value_each(target, corrector)
68
+ end
69
+ end
54
70
 
55
- add_offense(kv_range(target), message: msg) do |corrector|
56
- correct_key_value_each(target, corrector)
57
- end
71
+ def register_kv_with_block_pass_offense(node, target, method)
72
+ return unless (parent_receiver = node.parent.receiver.receiver)
73
+ return if allowed_receiver?(parent_receiver)
74
+
75
+ range = target.loc.selector.with(end_pos: node.parent.loc.selector.end_pos)
76
+ add_offense(range, message: format_message(method)) do |corrector|
77
+ corrector.replace(range, "each_#{method[0..-2]}")
58
78
  end
59
79
  end
60
80
 
81
+ def format_message(method_name)
82
+ format(MSG, prefer: "each_#{method_name[0..-2]}", current: "#{method_name}.each")
83
+ end
84
+
61
85
  def check_argument(variable)
62
86
  return unless variable.block_argument?
63
87
 
@@ -94,11 +118,23 @@ module RuboCop
94
118
  end
95
119
 
96
120
  def allowed_receiver?(receiver)
97
- receiver_name = receiver.send_type? ? receiver.method_name.to_s : receiver.source
121
+ receiver_name = receiver_name(receiver)
98
122
 
99
123
  allowed_receivers.include?(receiver_name)
100
124
  end
101
125
 
126
+ def receiver_name(receiver)
127
+ if receiver.send_type?
128
+ if receiver.receiver
129
+ "#{receiver_name(receiver.receiver)}.#{receiver.method_name}"
130
+ else
131
+ receiver.method_name.to_s
132
+ end
133
+ else
134
+ receiver.source
135
+ end
136
+ end
137
+
102
138
  def allowed_receivers
103
139
  cop_config.fetch('AllowedReceivers', [])
104
140
  end
@@ -13,6 +13,10 @@ module RuboCop
13
13
  # when used `==`.
14
14
  # And do not check `Hash#delete_if` and `Hash#keep_if` to change receiver object.
15
15
  #
16
+ # @safety
17
+ # This cop is unsafe because it cannot be guaranteed that the receiver
18
+ # is a `Hash` or responds to the replacement method.
19
+ #
16
20
  # @example
17
21
  #
18
22
  # # bad
@@ -41,13 +45,13 @@ module RuboCop
41
45
  (block
42
46
  (send _ _)
43
47
  (args
44
- (arg _)
48
+ $(arg _)
45
49
  (arg _))
46
50
  {
47
- (send
51
+ $(send
48
52
  _ {:== :!= :eql? :include?} _)
49
53
  (send
50
- (send
54
+ $(send
51
55
  _ {:== :!= :eql? :include?} _) :!)
52
56
  })
53
57
  PATTERN
@@ -57,13 +61,13 @@ module RuboCop
57
61
  (block
58
62
  (send _ _)
59
63
  (args
60
- (arg _)
64
+ $(arg _)
61
65
  (arg _))
62
66
  {
63
- (send
67
+ $(send
64
68
  _ {:== :!= :eql? :in? :include? :exclude?} _)
65
69
  (send
66
- (send
70
+ $(send
67
71
  _ {:== :!= :eql? :in? :include? :exclude?} _) :!)
68
72
  })
69
73
  PATTERN
@@ -85,13 +89,24 @@ module RuboCop
85
89
 
86
90
  private
87
91
 
92
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
88
93
  def bad_method?(block)
89
94
  if active_support_extensions_enabled?
90
- bad_method_with_active_support?(block)
95
+ bad_method_with_active_support?(block) do |key_arg, send_node|
96
+ if send_node.method?(:in?) && send_node.receiver&.source != key_arg.source
97
+ return false
98
+ end
99
+ return true if !send_node.method?(:include?) && !send_node.method?(:exclude?)
100
+
101
+ send_node.first_argument&.source == key_arg.source
102
+ end
91
103
  else
92
- bad_method_with_poro?(block)
104
+ bad_method_with_poro?(block) do |key_arg, send_node|
105
+ !send_node.method?(:include?) || send_node.first_argument&.source == key_arg.source
106
+ end
93
107
  end
94
108
  end
109
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
95
110
 
96
111
  def semantically_except_method?(send, block)
97
112
  body = block.body
@@ -118,8 +133,8 @@ module RuboCop
118
133
  end
119
134
 
120
135
  def safe_to_register_offense?(block, except_key)
121
- extracted = extract_body_if_nagated(block.body)
122
- if extracted.method?('in?') || extracted.method?('include?') || \
136
+ extracted = extract_body_if_negated(block.body)
137
+ if extracted.method?('in?') || extracted.method?('include?') ||
123
138
  extracted.method?('exclude?')
124
139
  return true
125
140
  end
@@ -128,7 +143,7 @@ module RuboCop
128
143
  except_key.sym_type? || except_key.str_type?
129
144
  end
130
145
 
131
- def extract_body_if_nagated(body)
146
+ def extract_body_if_negated(body)
132
147
  return body unless body.method?('!')
133
148
 
134
149
  body.receiver
@@ -157,12 +172,8 @@ module RuboCop
157
172
 
158
173
  def except_key(node)
159
174
  key_argument = node.argument_list.first.source
160
- body = extract_body_if_nagated(node.body)
175
+ body = extract_body_if_negated(node.body)
161
176
  lhs, _method_name, rhs = *body
162
-
163
- return lhs if body.method?('include?')
164
- return lhs if body.method?('exclude?')
165
- return rhs if body.method?('in?')
166
177
  return if [lhs, rhs].map(&:source).none?(key_argument)
167
178
 
168
179
  [lhs, rhs].find { |operand| operand.source != key_argument }
@@ -37,6 +37,8 @@ module RuboCop
37
37
  # end
38
38
  #
39
39
  class HashLikeCase < Base
40
+ include MinBranchesCount
41
+
40
42
  MSG = 'Consider replacing `case-when` with a hash lookup.'
41
43
 
42
44
  # @!method hash_like_case?(node)
@@ -49,7 +51,7 @@ module RuboCop
49
51
  PATTERN
50
52
 
51
53
  def on_case(node)
52
- return if node.when_branches.size < min_branches_count
54
+ return unless min_branches_count?(node)
53
55
 
54
56
  hash_like_case?(node) do |condition_nodes, body_nodes|
55
57
  if nodes_of_same_type?(condition_nodes) && nodes_of_same_type?(body_nodes)
@@ -63,14 +65,6 @@ module RuboCop
63
65
  def nodes_of_same_type?(nodes)
64
66
  nodes.all? { |node| node.type == nodes.first.type }
65
67
  end
66
-
67
- def min_branches_count
68
- length = cop_config['MinBranchesCount'] || 3
69
- return length if length.is_a?(Integer) && length.positive?
70
-
71
- warn Rainbow('`MinBranchesCount` needs to be a positive integer!').red
72
- exit!
73
- end
74
68
  end
75
69
  end
76
70
  end
@@ -28,6 +28,7 @@ module RuboCop
28
28
  # * always - forces use of the 3.1 syntax (e.g. {foo:})
29
29
  # * never - forces use of explicit hash literal value
30
30
  # * either - accepts both shorthand and explicit use of hash literal value
31
+ # * consistent - forces use of the 3.1 syntax only if all values can be omitted in the hash
31
32
  #
32
33
  # @example EnforcedStyle: ruby19 (default)
33
34
  # # bad
@@ -87,8 +88,28 @@ module RuboCop
87
88
  # {foo: foo, bar: bar}
88
89
  #
89
90
  # # good
91
+ # {foo: foo, bar:}
92
+ #
93
+ # # good
94
+ # {foo:, bar:}
95
+ #
96
+ # @example EnforcedShorthandSyntax: consistent
97
+ #
98
+ # # bad - `foo` and `bar` values can be omitted
99
+ # {foo: foo, bar: bar}
100
+ #
101
+ # # bad - `bar` value can be omitted
102
+ # {foo:, bar: bar}
103
+ #
104
+ # # bad - mixed syntaxes
105
+ # {foo:, bar: baz}
106
+ #
107
+ # # good
90
108
  # {foo:, bar:}
91
109
  #
110
+ # # good - can't omit `baz`
111
+ # {foo: foo, bar: baz}
112
+ #
92
113
  class HashSyntax < Base
93
114
  include ConfigurableEnforcedStyle
94
115
  include HashShorthandSyntax
@@ -104,6 +125,8 @@ module RuboCop
104
125
 
105
126
  return if pairs.empty?
106
127
 
128
+ on_hash_for_mixed_shorthand(node)
129
+
107
130
  if style == :hash_rockets || force_hash_rockets?(pairs)
108
131
  hash_rockets_check(pairs)
109
132
  elsif style == :ruby19_no_mixed_keys
@@ -187,7 +210,7 @@ module RuboCop
187
210
  return true if /\A[_a-z]\w*[?!]?\z/i.match?(sym_name)
188
211
 
189
212
  # For more complicated hash keys, let the parser validate the syntax.
190
- ProcessedSource.new("{ #{sym_name}: :foo }", target_ruby_version).valid_syntax?
213
+ parse("{ #{sym_name}: :foo }").valid_syntax?
191
214
  end
192
215
 
193
216
  def check(pairs, delim, msg)
@@ -227,13 +250,14 @@ module RuboCop
227
250
  end
228
251
 
229
252
  def argument_without_space?(node)
230
- node.argument? && node.loc.expression.begin_pos == node.parent.loc.selector.end_pos
253
+ node.argument? && node.source_range.begin_pos == node.parent.loc.selector.end_pos
231
254
  end
232
255
 
233
256
  def autocorrect_hash_rockets(corrector, pair_node)
234
257
  op = pair_node.loc.operator
235
258
 
236
259
  key_with_hash_rocket = ":#{pair_node.key.source}#{pair_node.inverse_delimiter(true)}"
260
+ key_with_hash_rocket += pair_node.key.source if pair_node.value_omission?
237
261
  corrector.replace(pair_node.key, key_with_hash_rocket)
238
262
  corrector.remove(range_with_surrounding_space(op))
239
263
  end
@@ -136,6 +136,7 @@ module RuboCop
136
136
 
137
137
  private
138
138
 
139
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
139
140
  def check_branches(node, branches)
140
141
  # return if any branch is empty. An empty branch can be an `if`
141
142
  # without an `else` or a branch that contains only comments.
@@ -144,9 +145,13 @@ module RuboCop
144
145
  tails = branches.map { |branch| tail(branch) }
145
146
  check_expressions(node, tails, :after_condition) if duplicated_expressions?(node, tails)
146
147
 
148
+ return if last_child_of_parent?(node) &&
149
+ branches.any? { |branch| single_child_branch?(branch) }
150
+
147
151
  heads = branches.map { |branch| head(branch) }
148
152
  check_expressions(node, heads, :before_condition) if duplicated_expressions?(node, heads)
149
153
  end
154
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
150
155
 
151
156
  def duplicated_expressions?(node, expressions)
152
157
  unique_expressions = expressions.uniq
@@ -180,6 +185,16 @@ module RuboCop
180
185
  end
181
186
  end
182
187
 
188
+ def last_child_of_parent?(node)
189
+ return true unless (parent = node.parent)
190
+
191
+ parent.child_nodes.last == node
192
+ end
193
+
194
+ def single_child_branch?(branch_node)
195
+ !branch_node.begin_type? || branch_node.children.size == 1
196
+ end
197
+
183
198
  def message(node)
184
199
  format(MSG, source: node.source)
185
200
  end
@@ -59,11 +59,13 @@ module RuboCop
59
59
  # end
60
60
  #
61
61
  class IfInsideElse < Base
62
+ include IgnoredNode
62
63
  include RangeHelp
63
64
  extend AutoCorrector
64
65
 
65
66
  MSG = 'Convert `if` nested inside `else` to `elsif`.'
66
67
 
68
+ # rubocop:disable Metrics/CyclomaticComplexity
67
69
  def on_if(node)
68
70
  return if node.ternary? || node.unless?
69
71
 
@@ -73,9 +75,13 @@ module RuboCop
73
75
  return if allow_if_modifier_in_else_branch?(else_branch)
74
76
 
75
77
  add_offense(else_branch.loc.keyword) do |corrector|
78
+ next if part_of_ignored_node?(node)
79
+
76
80
  autocorrect(corrector, else_branch)
81
+ ignore_node(node)
77
82
  end
78
83
  end
84
+ # rubocop:enable Metrics/CyclomaticComplexity
79
85
 
80
86
  private
81
87