rubocop 1.69.2 → 1.72.2

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 (284) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +66 -2
  5. data/lib/rubocop/cli/command/execute_runner.rb +3 -3
  6. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  7. data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
  8. data/lib/rubocop/comment_config.rb +2 -2
  9. data/lib/rubocop/config.rb +17 -4
  10. data/lib/rubocop/config_loader.rb +48 -8
  11. data/lib/rubocop/config_loader_resolver.rb +33 -8
  12. data/lib/rubocop/config_validator.rb +18 -8
  13. data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
  14. data/lib/rubocop/cop/base.rb +6 -0
  15. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  16. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  17. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  18. data/lib/rubocop/cop/internal_affairs/example_description.rb +4 -2
  19. data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
  20. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  21. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  22. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  23. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  24. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  25. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +229 -0
  26. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  27. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  28. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  29. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  30. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  31. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  32. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +7 -1
  33. data/lib/rubocop/cop/internal_affairs.rb +5 -16
  34. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  35. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -8
  36. data/lib/rubocop/cop/layout/block_alignment.rb +3 -1
  37. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  38. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  39. data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
  40. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  41. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  42. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
  43. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  44. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
  45. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  46. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  47. data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
  48. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  49. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  50. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  51. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  52. data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
  53. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
  54. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  55. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  56. data/lib/rubocop/cop/layout/line_length.rb +1 -0
  57. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  58. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  59. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
  60. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
  61. data/lib/rubocop/cop/layout/redundant_line_break.rb +7 -6
  62. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
  63. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  64. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  65. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  66. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  67. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  68. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
  69. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  70. data/lib/rubocop/cop/layout/space_around_operators.rb +3 -3
  71. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  72. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  73. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  74. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  75. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  76. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  77. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +1 -1
  78. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  79. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  80. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
  81. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  82. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  83. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  84. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  85. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  86. data/lib/rubocop/cop/lint/float_comparison.rb +5 -2
  87. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  88. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  89. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  90. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  91. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  92. data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
  93. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  94. data/lib/rubocop/cop/lint/nested_method_definition.rb +8 -4
  95. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  96. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -3
  97. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  98. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +18 -31
  99. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
  100. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  101. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  102. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  103. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +231 -0
  104. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  105. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -1
  106. data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -0
  107. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  108. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
  109. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  110. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  111. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -4
  112. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
  113. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  114. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  115. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
  116. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
  117. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  118. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +80 -0
  119. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  120. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  121. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  122. data/lib/rubocop/cop/lint/void.rb +5 -9
  123. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  124. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  125. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  126. data/lib/rubocop/cop/metrics/method_length.rb +8 -1
  127. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  128. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  129. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  130. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  131. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  132. data/lib/rubocop/cop/mixin/check_line_breakable.rb +11 -11
  133. data/lib/rubocop/cop/mixin/comments_help.rb +4 -2
  134. data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
  135. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  136. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
  137. data/lib/rubocop/cop/mixin/hash_subset.rb +188 -0
  138. data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
  139. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  140. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  141. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +48 -24
  142. data/lib/rubocop/cop/mixin/range_help.rb +3 -3
  143. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  144. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
  145. data/lib/rubocop/cop/mixin/string_help.rb +2 -2
  146. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  147. data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
  148. data/lib/rubocop/cop/naming/block_forwarding.rb +19 -15
  149. data/lib/rubocop/cop/naming/predicate_name.rb +44 -0
  150. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -3
  151. data/lib/rubocop/cop/security/compound_hash.rb +1 -0
  152. data/lib/rubocop/cop/style/access_modifier_declarations.rb +34 -5
  153. data/lib/rubocop/cop/style/and_or.rb +1 -1
  154. data/lib/rubocop/cop/style/arguments_forwarding.rb +39 -23
  155. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  156. data/lib/rubocop/cop/style/block_delimiters.rb +7 -20
  157. data/lib/rubocop/cop/style/class_and_module_children.rb +6 -3
  158. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  159. data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
  160. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  161. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  162. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
  163. data/lib/rubocop/cop/style/documentation.rb +1 -1
  164. data/lib/rubocop/cop/style/double_negation.rb +3 -3
  165. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  166. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  167. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  168. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  169. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  170. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  171. data/lib/rubocop/cop/style/exact_regexp_match.rb +3 -10
  172. data/lib/rubocop/cop/style/explicit_block_argument.rb +15 -2
  173. data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
  174. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  175. data/lib/rubocop/cop/style/float_division.rb +8 -4
  176. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  177. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -6
  178. data/lib/rubocop/cop/style/hash_except.rb +24 -148
  179. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  180. data/lib/rubocop/cop/style/hash_syntax.rb +6 -3
  181. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  182. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  183. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
  184. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  185. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  186. data/lib/rubocop/cop/style/inverse_methods.rb +6 -6
  187. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  188. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  189. data/lib/rubocop/cop/style/map_into_array.rb +1 -1
  190. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  191. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  192. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +19 -12
  193. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  194. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
  195. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -4
  196. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  197. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  198. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  199. data/lib/rubocop/cop/style/multiple_comparison.rb +26 -20
  200. data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
  201. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
  202. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  203. data/lib/rubocop/cop/style/object_then.rb +13 -15
  204. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  205. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -5
  206. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  207. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  208. data/lib/rubocop/cop/style/proc.rb +1 -2
  209. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  210. data/lib/rubocop/cop/style/raise_args.rb +6 -4
  211. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  212. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  213. data/lib/rubocop/cop/style/redundant_condition.rb +2 -2
  214. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
  215. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  216. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  217. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  218. data/lib/rubocop/cop/style/redundant_format.rb +238 -0
  219. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
  220. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  221. data/lib/rubocop/cop/style/redundant_line_continuation.rb +34 -13
  222. data/lib/rubocop/cop/style/redundant_parentheses.rb +28 -14
  223. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
  224. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  225. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  226. data/lib/rubocop/cop/style/redundant_self_assignment.rb +14 -28
  227. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  228. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  229. data/lib/rubocop/cop/style/return_nil.rb +1 -1
  230. data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
  231. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  232. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  233. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  234. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
  235. data/lib/rubocop/cop/style/single_line_methods.rb +3 -4
  236. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  237. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
  238. data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
  239. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  240. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  241. data/lib/rubocop/cop/style/super_arguments.rb +65 -17
  242. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  243. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  244. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
  245. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  246. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  247. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  248. data/lib/rubocop/cop/util.rb +12 -5
  249. data/lib/rubocop/cop/utils/format_string.rb +7 -5
  250. data/lib/rubocop/cop/variable_force/variable.rb +14 -2
  251. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  252. data/lib/rubocop/cops_documentation_generator.rb +13 -13
  253. data/lib/rubocop/directive_comment.rb +44 -10
  254. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  255. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  256. data/lib/rubocop/lsp/logger.rb +2 -2
  257. data/lib/rubocop/lsp/routes.rb +7 -23
  258. data/lib/rubocop/lsp/runtime.rb +17 -49
  259. data/lib/rubocop/lsp/server.rb +0 -2
  260. data/lib/rubocop/lsp/stdin_runner.rb +83 -0
  261. data/lib/rubocop/options.rb +28 -12
  262. data/lib/rubocop/path_util.rb +15 -8
  263. data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
  264. data/lib/rubocop/plugin/load_error.rb +26 -0
  265. data/lib/rubocop/plugin/loader.rb +100 -0
  266. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  267. data/lib/rubocop/plugin.rb +39 -0
  268. data/lib/rubocop/rake_task.rb +4 -1
  269. data/lib/rubocop/result_cache.rb +13 -13
  270. data/lib/rubocop/rspec/cop_helper.rb +9 -0
  271. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  272. data/lib/rubocop/rspec/shared_contexts.rb +4 -1
  273. data/lib/rubocop/rspec/support.rb +1 -2
  274. data/lib/rubocop/runner.rb +5 -6
  275. data/lib/rubocop/server/cache.rb +35 -2
  276. data/lib/rubocop/server/cli.rb +2 -2
  277. data/lib/rubocop/target_finder.rb +1 -0
  278. data/lib/rubocop/target_ruby.rb +15 -0
  279. data/lib/rubocop/version.rb +17 -2
  280. data/lib/rubocop.rb +11 -0
  281. data/lib/ruby_lsp/rubocop/addon.rb +75 -0
  282. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +47 -0
  283. metadata +53 -15
  284. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -136,7 +136,7 @@ module RuboCop
136
136
  def frozen_strings?
137
137
  return true if frozen_string_literals_enabled?
138
138
 
139
- frozen_string_cop_enabled = config.for_cop('Style/FrozenStringLiteralComment')['Enabled']
139
+ frozen_string_cop_enabled = config.cop_enabled?('Style/FrozenStringLiteralComment')
140
140
  frozen_string_cop_enabled &&
141
141
  !frozen_string_literals_disabled? &&
142
142
  string_literals_frozen_by_default?.nil?
@@ -109,7 +109,7 @@ module RuboCop
109
109
  end
110
110
 
111
111
  def max_line_length
112
- return unless config.for_cop('Layout/LineLength')['Enabled']
112
+ return unless config.cop_enabled?('Layout/LineLength')
113
113
 
114
114
  config.for_cop('Layout/LineLength')['Max']
115
115
  end
@@ -86,7 +86,7 @@ module RuboCop
86
86
  return if node.method?(:eval) && !valid_eval_receiver?(node.receiver)
87
87
 
88
88
  code = node.first_argument
89
- return unless code && (code.str_type? || code.dstr_type?)
89
+ return unless code&.type?(:str, :dstr)
90
90
 
91
91
  check_location(node, code)
92
92
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for exact regexp match inside Regexp literals.
6
+ # Checks for exact regexp match inside `Regexp` literals.
7
7
  #
8
8
  # @example
9
9
  #
@@ -40,15 +40,8 @@ module RuboCop
40
40
  def on_send(node)
41
41
  return unless (receiver = node.receiver)
42
42
  return unless (regexp = exact_regexp_match(node))
43
-
44
- parsed_regexp = begin
45
- Regexp::Parser.parse(regexp)
46
- rescue Regexp::Parser::Error
47
- # Upon encountering an invalid regular expression,
48
- # we aim to proceed and identify any remaining potential offenses.
49
- end
50
-
51
- return unless parsed_regexp && exact_match_pattern?(parsed_regexp)
43
+ return unless (parsed_regexp = parse_regexp(regexp))
44
+ return unless exact_match_pattern?(parsed_regexp)
52
45
 
53
46
  prefer = "#{receiver.source} #{new_method(node)} '#{parsed_regexp[1].text}'"
54
47
 
@@ -123,7 +123,7 @@ module RuboCop
123
123
  end
124
124
 
125
125
  def call_like?(node)
126
- node.call_type? || node.zsuper_type? || node.super_type?
126
+ node.type?(:call, :zsuper, :super)
127
127
  end
128
128
 
129
129
  def insert_argument(node, corrector, block_name)
@@ -135,7 +135,13 @@ module RuboCop
135
135
  end
136
136
 
137
137
  def correct_call_node(node, corrector, block_name)
138
- corrector.insert_after(node, "(&#{block_name})")
138
+ new_arguments = if node.zsuper_type?
139
+ args = build_new_arguments_for_zsuper(node) << "&#{block_name}"
140
+ args.join(', ')
141
+ else
142
+ "&#{block_name}"
143
+ end
144
+ corrector.insert_after(node, "(#{new_arguments})")
139
145
  return unless node.parenthesized?
140
146
 
141
147
  args_begin = Util.args_begin(node)
@@ -144,6 +150,13 @@ module RuboCop
144
150
  corrector.remove(range)
145
151
  end
146
152
 
153
+ def build_new_arguments_for_zsuper(node)
154
+ def_node = node.each_ancestor(:def, :defs).first
155
+ def_node.arguments.map do |arg|
156
+ arg.optarg_type? ? arg.node_parts[0] : arg.source
157
+ end
158
+ end
159
+
147
160
  def block_body_range(block_node, send_node)
148
161
  range_between(send_node.source_range.end_pos, block_node.loc.end.end_pos)
149
162
  end
@@ -8,7 +8,7 @@ module RuboCop
8
8
  #
9
9
  # * `scientific` which enforces a mantissa between 1 (inclusive) and 10 (exclusive).
10
10
  # * `engineering` which enforces the exponent to be a multiple of 3 and the mantissa
11
- # to be between 0.1 (inclusive) and 10 (exclusive).
11
+ # to be between 0.1 (inclusive) and 1000 (exclusive).
12
12
  # * `integral` which enforces the mantissa to always be a whole number without
13
13
  # trailing zeroes.
14
14
  #
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # Suggests `ENV.fetch` for the replacement of `ENV[]`.
7
7
  # `ENV[]` silently fails and returns `nil` when the environment variable is unset,
8
8
  # which may cause unexpected behaviors when the developer forgets to set it.
9
- # On the other hand, `ENV.fetch` raises KeyError or returns the explicitly
9
+ # On the other hand, `ENV.fetch` raises `KeyError` or returns the explicitly
10
10
  # specified default value.
11
11
  #
12
12
  # @example
@@ -65,19 +65,23 @@ module RuboCop
65
65
 
66
66
  # @!method right_coerce?(node)
67
67
  def_node_matcher :right_coerce?, <<~PATTERN
68
- (send _ :/ (send _ :to_f))
68
+ (send _ :/ #to_f_method?)
69
69
  PATTERN
70
70
  # @!method left_coerce?(node)
71
71
  def_node_matcher :left_coerce?, <<~PATTERN
72
- (send (send _ :to_f) :/ _)
72
+ (send #to_f_method? :/ _)
73
73
  PATTERN
74
74
  # @!method both_coerce?(node)
75
75
  def_node_matcher :both_coerce?, <<~PATTERN
76
- (send (send _ :to_f) :/ (send _ :to_f))
76
+ (send #to_f_method? :/ #to_f_method?)
77
77
  PATTERN
78
78
  # @!method any_coerce?(node)
79
79
  def_node_matcher :any_coerce?, <<~PATTERN
80
- {(send _ :/ (send _ :to_f)) (send (send _ :to_f) :/ _)}
80
+ {(send _ :/ #to_f_method?) (send #to_f_method? :/ _)}
81
+ PATTERN
82
+ # @!method to_f_method?(node)
83
+ def_node_matcher :to_f_method?, <<~PATTERN
84
+ (send !nil? :to_f)
81
85
  PATTERN
82
86
 
83
87
  def on_send(node)
@@ -151,7 +151,7 @@ module RuboCop
151
151
 
152
152
  def frozen_string_literal_comment(processed_source)
153
153
  processed_source.tokens.find do |token|
154
- token.text.start_with?(FROZEN_STRING_LITERAL)
154
+ token.text.start_with?(FROZEN_STRING_LITERAL_REGEXP)
155
155
  end
156
156
  end
157
157
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for uses of `each_key` and `each_value` Hash methods.
6
+ # Checks for uses of `each_key` and `each_value` `Hash` methods.
7
7
  #
8
8
  # NOTE: If you have an array of two-element arrays, you can put
9
9
  # parentheses around the block arguments to indicate that you're not
@@ -44,7 +44,7 @@ module RuboCop
44
44
 
45
45
  # @!method kv_each(node)
46
46
  def_node_matcher :kv_each, <<~PATTERN
47
- ({block numblock} $(call (call _ ${:keys :values}) :each) ...)
47
+ (any_block $(call (call _ ${:keys :values}) :each) ...)
48
48
  PATTERN
49
49
 
50
50
  # @!method each_arguments(node)
@@ -162,10 +162,7 @@ module RuboCop
162
162
 
163
163
  def use_array_converter_method_as_preceding?(node)
164
164
  return false unless (preceding_method = node.children.first.children.first)
165
- unless preceding_method.call_type? ||
166
- preceding_method.block_type? || preceding_method.numblock_type?
167
- return false
168
- end
165
+ return false unless preceding_method.type?(:call, :any_block)
169
166
 
170
167
  ARRAY_CONVERTER_METHODS.include?(preceding_method.method_name)
171
168
  end
@@ -10,8 +10,10 @@ module RuboCop
10
10
  # (`Hash#except` was added in Ruby 3.0.)
11
11
  #
12
12
  # For safe detection, it is limited to commonly used string and symbol comparisons
13
- # when used `==`.
14
- # And do not check `Hash#delete_if` and `Hash#keep_if` to change receiver object.
13
+ # when using `==` or `!=`.
14
+ #
15
+ # This cop doesn't check for `Hash#delete_if` and `Hash#keep_if` because they
16
+ # modify the receiver.
15
17
  #
16
18
  # @safety
17
19
  # This cop is unsafe because it cannot be guaranteed that the receiver
@@ -30,6 +32,21 @@ module RuboCop
30
32
  # {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].include?(k) }
31
33
  # {foo: 1, bar: 2, baz: 3}.filter {|k, v| !%i[bar].include?(k) }
32
34
  #
35
+ # # good
36
+ # {foo: 1, bar: 2, baz: 3}.except(:bar)
37
+ #
38
+ # @example AllCops:ActiveSupportExtensionsEnabled: false (default)
39
+ #
40
+ # # good
41
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].exclude?(k) }
42
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].exclude?(k) }
43
+ #
44
+ # # good
45
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| k.in?(%i[bar]) }
46
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| !k.in?(%i[bar]) }
47
+ #
48
+ # @example AllCops:ActiveSupportExtensionsEnabled: true
49
+ #
33
50
  # # bad
34
51
  # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].exclude?(k) }
35
52
  # {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].exclude?(k) }
@@ -42,161 +59,20 @@ module RuboCop
42
59
  # {foo: 1, bar: 2, baz: 3}.except(:bar)
43
60
  #
44
61
  class HashExcept < Base
45
- include RangeHelp
62
+ include HashSubset
46
63
  extend TargetRubyVersion
47
64
  extend AutoCorrector
48
65
 
49
66
  minimum_target_ruby_version 3.0
50
67
 
51
- MSG = 'Use `%<prefer>s` instead.'
52
- RESTRICT_ON_SEND = %i[reject select filter].freeze
53
-
54
- # @!method bad_method_with_poro?(node)
55
- def_node_matcher :bad_method_with_poro?, <<~PATTERN
56
- (block
57
- (call _ _)
58
- (args
59
- $(arg _)
60
- (arg _))
61
- {
62
- $(send
63
- _ {:== :!= :eql? :include?} _)
64
- (send
65
- $(send
66
- _ {:== :!= :eql? :include?} _) :!)
67
- })
68
- PATTERN
69
-
70
- # @!method bad_method_with_active_support?(node)
71
- def_node_matcher :bad_method_with_active_support?, <<~PATTERN
72
- (block
73
- (send _ _)
74
- (args
75
- $(arg _)
76
- (arg _))
77
- {
78
- $(send
79
- _ {:== :!= :eql? :in? :include? :exclude?} _)
80
- (send
81
- $(send
82
- _ {:== :!= :eql? :in? :include? :exclude?} _) :!)
83
- })
84
- PATTERN
85
-
86
- def on_send(node)
87
- block = node.parent
88
- return unless bad_method?(block) && semantically_except_method?(node, block)
89
-
90
- except_key = except_key(block)
91
- return if except_key.nil? || !safe_to_register_offense?(block, except_key)
92
-
93
- range = offense_range(node)
94
- preferred_method = "except(#{except_key_source(except_key)})"
95
-
96
- add_offense(range, message: format(MSG, prefer: preferred_method)) do |corrector|
97
- corrector.replace(range, preferred_method)
98
- end
99
- end
100
- alias on_csend on_send
101
-
102
68
  private
103
69
 
104
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
105
- def bad_method?(block)
106
- if active_support_extensions_enabled?
107
- bad_method_with_active_support?(block) do |key_arg, send_node|
108
- if send_node.method?(:in?) && send_node.receiver&.source != key_arg.source
109
- return false
110
- end
111
- return true if !send_node.method?(:include?) && !send_node.method?(:exclude?)
112
-
113
- send_node.first_argument&.source == key_arg.source
114
- end
115
- else
116
- bad_method_with_poro?(block) do |key_arg, send_node|
117
- !send_node.method?(:include?) || send_node.first_argument&.source == key_arg.source
118
- end
119
- end
120
- end
121
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
122
-
123
- def semantically_except_method?(send, block)
124
- body = block.body
125
-
126
- negated = body.method?('!')
127
- body = body.receiver if negated
128
-
129
- case send.method_name
130
- when :reject
131
- body.method?('==') || body.method?('eql?') || included?(negated, body)
132
- when :select, :filter
133
- body.method?('!=') || not_included?(negated, body)
134
- else
135
- false
136
- end
137
- end
138
-
139
- def included?(negated, body)
140
- if negated
141
- body.method?('exclude?')
142
- else
143
- body.method?('include?') || body.method?('in?')
144
- end
145
- end
146
-
147
- def not_included?(negated, body)
148
- included?(!negated, body)
149
- end
150
-
151
- def safe_to_register_offense?(block, except_key)
152
- extracted = extract_body_if_negated(block.body)
153
- if extracted.method?('in?') || extracted.method?('include?') ||
154
- extracted.method?('exclude?')
155
- return true
156
- end
157
- return true if block.body.method?('eql?')
158
-
159
- except_key.sym_type? || except_key.str_type?
160
- end
161
-
162
- def extract_body_if_negated(body)
163
- return body unless body.method?('!')
164
-
165
- body.receiver
166
- end
167
-
168
- def except_key_source(key)
169
- if key.array_type?
170
- key = if key.percent_literal?
171
- key.each_value.map { |v| decorate_source(v) }
172
- else
173
- key.each_value.map(&:source)
174
- end
175
- return key.join(', ')
176
- end
177
-
178
- key.literal? ? key.source : "*#{key.source}"
179
- end
180
-
181
- def decorate_source(value)
182
- return ":\"#{value.source}\"" if value.dsym_type?
183
- return "\"#{value.source}\"" if value.dstr_type?
184
- return ":#{value.source}" if value.sym_type?
185
-
186
- "'#{value.source}'"
187
- end
188
-
189
- def except_key(node)
190
- key_argument = node.argument_list.first.source
191
- body = extract_body_if_negated(node.body)
192
- lhs, _method_name, rhs = *body
193
- return if [lhs, rhs].map(&:source).none?(key_argument)
194
-
195
- [lhs, rhs].find { |operand| operand.source != key_argument }
70
+ def semantically_subset_method?(node)
71
+ semantically_except_method?(node)
196
72
  end
197
73
 
198
- def offense_range(node)
199
- range_between(node.loc.selector.begin_pos, node.parent.loc.end.end_pos)
74
+ def preferred_method_name
75
+ 'except'
200
76
  end
201
77
  end
202
78
  end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for usages of `Hash#reject`, `Hash#select`, and `Hash#filter` methods
7
+ # that can be replaced with `Hash#slice` method.
8
+ #
9
+ # This cop should only be enabled on Ruby version 2.5 or higher.
10
+ # (`Hash#slice` was added in Ruby 2.5.)
11
+ #
12
+ # For safe detection, it is limited to commonly used string and symbol comparisons
13
+ # when using `==` or `!=`.
14
+ #
15
+ # This cop doesn't check for `Hash#delete_if` and `Hash#keep_if` because they
16
+ # modify the receiver.
17
+ #
18
+ # @safety
19
+ # This cop is unsafe because it cannot be guaranteed that the receiver
20
+ # is a `Hash` or responds to the replacement method.
21
+ #
22
+ # @example
23
+ #
24
+ # # bad
25
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k == :bar }
26
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| k != :bar }
27
+ # {foo: 1, bar: 2, baz: 3}.filter {|k, v| k == :bar }
28
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k.eql?(:bar) }
29
+ #
30
+ # # bad
31
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].include?(k) }
32
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].include?(k) }
33
+ # {foo: 1, bar: 2, baz: 3}.filter {|k, v| %i[bar].include?(k) }
34
+ #
35
+ # # good
36
+ # {foo: 1, bar: 2, baz: 3}.slice(:bar)
37
+ #
38
+ # @example AllCops:ActiveSupportExtensionsEnabled: false (default)
39
+ #
40
+ # # good
41
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].exclude?(k) }
42
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].exclude?(k) }
43
+ #
44
+ # # good
45
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k.in?(%i[bar]) }
46
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !k.in?(%i[bar]) }
47
+ #
48
+ # @example AllCops:ActiveSupportExtensionsEnabled: true
49
+ #
50
+ # # bad
51
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].exclude?(k) }
52
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].exclude?(k) }
53
+ #
54
+ # # bad
55
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k.in?(%i[bar]) }
56
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !k.in?(%i[bar]) }
57
+ #
58
+ # # good
59
+ # {foo: 1, bar: 2, baz: 3}.slice(:bar)
60
+ #
61
+ class HashSlice < Base
62
+ include HashSubset
63
+ extend TargetRubyVersion
64
+ extend AutoCorrector
65
+
66
+ minimum_target_ruby_version 2.5
67
+
68
+ private
69
+
70
+ def semantically_subset_method?(node)
71
+ semantically_slice_method?(node)
72
+ end
73
+
74
+ def preferred_method_name
75
+ 'slice'
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -137,6 +137,7 @@ module RuboCop
137
137
  MSG_19 = 'Use the new Ruby 1.9 hash syntax.'
138
138
  MSG_NO_MIXED_KEYS = "Don't mix styles in the same hash."
139
139
  MSG_HASH_ROCKETS = 'Use hash rockets syntax.'
140
+ NO_MIXED_KEYS_STYLES = %i[ruby19_no_mixed_keys no_mixed_keys].freeze
140
141
 
141
142
  def on_hash(node)
142
143
  pairs = node.pairs
@@ -196,7 +197,7 @@ module RuboCop
196
197
  def autocorrect(corrector, node)
197
198
  if style == :hash_rockets || force_hash_rockets?(node.parent.pairs)
198
199
  autocorrect_hash_rockets(corrector, node)
199
- elsif style == :ruby19_no_mixed_keys || style == :no_mixed_keys
200
+ elsif NO_MIXED_KEYS_STYLES.include?(style)
200
201
  autocorrect_no_mixed_keys(corrector, node)
201
202
  else
202
203
  autocorrect_ruby19(corrector, node)
@@ -208,7 +209,7 @@ module RuboCop
208
209
  end
209
210
 
210
211
  def word_symbol_pair?(pair)
211
- return false unless pair.key.sym_type? || pair.key.dsym_type?
212
+ return false unless pair.key.type?(:sym, :dsym)
212
213
 
213
214
  acceptable_19_syntax_symbol?(pair.key.source)
214
215
  end
@@ -272,7 +273,9 @@ module RuboCop
272
273
  end
273
274
 
274
275
  def argument_without_space?(node)
275
- node.argument? && node.source_range.begin_pos == node.parent.loc.selector.end_pos
276
+ return false if !node.argument? || !node.parent.loc.selector
277
+
278
+ node.source_range.begin_pos == node.parent.loc.selector.end_pos
276
279
  end
277
280
 
278
281
  def autocorrect_hash_rockets(corrector, pair_node)
@@ -203,17 +203,36 @@ module RuboCop
203
203
  corrector.remove(range)
204
204
  next if inserted_expression
205
205
 
206
- if insert_position == :after_condition
207
- corrector.insert_after(node, "\n#{expression.source}")
206
+ if node.parent&.assignment?
207
+ correct_assignment(corrector, node, expression, insert_position)
208
208
  else
209
- corrector.insert_before(node, "#{expression.source}\n")
209
+ correct_no_assignment(corrector, node, expression, insert_position)
210
210
  end
211
+
211
212
  inserted_expression = true
212
213
  end
213
214
  end
214
215
  end
215
216
  # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
216
217
 
218
+ def correct_assignment(corrector, node, expression, insert_position)
219
+ if insert_position == :after_condition
220
+ assignment = node.parent.source_range.with(end_pos: node.source_range.begin_pos)
221
+ corrector.remove(assignment)
222
+ corrector.insert_after(node, "\n#{assignment.source}#{expression.source}")
223
+ else
224
+ corrector.insert_before(node.parent, "#{expression.source}\n")
225
+ end
226
+ end
227
+
228
+ def correct_no_assignment(corrector, node, expression, insert_position)
229
+ if insert_position == :after_condition
230
+ corrector.insert_after(node, "\n#{expression.source}")
231
+ else
232
+ corrector.insert_before(node, "#{expression.source}\n")
233
+ end
234
+ end
235
+
217
236
  def last_child_of_parent?(node)
218
237
  return true unless (parent = node.parent)
219
238
 
@@ -103,7 +103,7 @@ module RuboCop
103
103
 
104
104
  def defined_argument_is_undefined?(if_node, defined_node)
105
105
  defined_argument = defined_node.first_argument
106
- return false unless defined_argument.lvar_type? || defined_argument.send_type?
106
+ return false unless defined_argument.type?(:lvar, :send)
107
107
 
108
108
  if_node.left_siblings.none? do |sibling|
109
109
  sibling.respond_to?(:lvasgn_type?) && sibling.lvasgn_type? &&
@@ -112,11 +112,11 @@ module RuboCop
112
112
  end
113
113
 
114
114
  def pattern_matching_nodes(condition)
115
- if condition.match_pattern_type? || condition.match_pattern_p_type?
115
+ if condition.type?(:match_pattern, :match_pattern_p)
116
116
  [condition]
117
117
  else
118
118
  condition.each_descendant.select do |node|
119
- node.match_pattern_type? || node.match_pattern_p_type?
119
+ node.type?(:match_pattern, :match_pattern_p)
120
120
  end
121
121
  end
122
122
  end
@@ -67,7 +67,7 @@ module RuboCop
67
67
 
68
68
  # @!method if_with_boolean_literal_branches?(node)
69
69
  def_node_matcher :if_with_boolean_literal_branches?, <<~PATTERN
70
- (if #return_boolean_value? {(true) (false) | (false) (true)})
70
+ (if #return_boolean_value? <true false>)
71
71
  PATTERN
72
72
  # @!method double_negative?(node)
73
73
  def_node_matcher :double_negative?, '(send (send _ :!) :!)'
@@ -42,7 +42,7 @@ module RuboCop
42
42
  def message(node)
43
43
  template = if require_newline?(node)
44
44
  MSG_NEWLINE
45
- elsif node.else_branch&.if_type? || node.else_branch&.begin_type? ||
45
+ elsif node.else_branch&.type?(:if, :begin) ||
46
46
  use_masgn_or_block_in_branches?(node)
47
47
  MSG_IF_ELSE
48
48
  else
@@ -66,7 +66,7 @@ module RuboCop
66
66
 
67
67
  def use_masgn_or_block_in_branches?(node)
68
68
  node.branches.compact.any? do |branch|
69
- branch.masgn_type? || branch.block_type? || branch.numblock_type?
69
+ branch.type?(:masgn, :any_block)
70
70
  end
71
71
  end
72
72
 
@@ -68,7 +68,7 @@ module RuboCop
68
68
  end
69
69
 
70
70
  def autocorrect(corrector, node)
71
- if node.while_post_type? || node.until_post_type?
71
+ if node.type?(:while_post, :until_post)
72
72
  replace_begin_end_with_modifier(corrector, node)
73
73
  elsif node.modifier_form?
74
74
  replace_source(corrector, node.source_range, modifier_replacement(node))
@@ -60,18 +60,18 @@ module RuboCop
60
60
  def_node_matcher :inverse_candidate?, <<~PATTERN
61
61
  {
62
62
  (send $(call $(...) $_ $...) :!)
63
- (send ({block numblock} $(call $(...) $_) $...) :!)
63
+ (send (any_block $(call $(...) $_) $...) :!)
64
64
  (send (begin $(call $(...) $_ $...)) :!)
65
65
  }
66
66
  PATTERN
67
67
 
68
68
  # @!method inverse_block?(node)
69
69
  def_node_matcher :inverse_block?, <<~PATTERN
70
- ({block numblock} $(call (...) $_) ... { $(call ... :!)
71
- $(send (...) {:!= :!~} ...)
72
- (begin ... $(call ... :!))
73
- (begin ... $(send (...) {:!= :!~} ...))
74
- })
70
+ (any_block $(call (...) $_) ... { $(call ... :!)
71
+ $(send (...) {:!= :!~} ...)
72
+ (begin ... $(call ... :!))
73
+ (begin ... $(send (...) {:!= :!~} ...))
74
+ })
75
75
  PATTERN
76
76
 
77
77
  def on_send(node)
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for assignments to a local `it` variable inside a block
7
+ # where `it` can refer to the first anonymous parameter as of Ruby 3.4.
8
+ #
9
+ # Although Ruby allows reassigning `it` in these cases, it could
10
+ # cause confusion if `it` is used as a block parameter elsewhere.
11
+ # For consistency, this also applies to numblocks and blocks with
12
+ # parameters, even though `it` cannot be used in those cases.
13
+ #
14
+ # @example
15
+ # # bad
16
+ # foo { it = 5 }
17
+ # foo { |bar| it = bar }
18
+ # foo { it = _2 }
19
+ #
20
+ # # good - use a different variable name
21
+ # foo { var = 5 }
22
+ # foo { |bar| var = bar }
23
+ # foo { bar = _2 }
24
+ class ItAssignment < Base
25
+ MSG = '`it` is the default block parameter; consider another name.'
26
+
27
+ def on_lvasgn(node)
28
+ return unless node.name == :it
29
+ return unless node.each_ancestor(:any_block).any?
30
+
31
+ add_offense(node.loc.name)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end