rubocop 1.50.2 → 1.59.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (290) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -3
  3. data/config/default.yml +153 -16
  4. data/config/obsoletion.yml +5 -0
  5. data/lib/rubocop/cli/command/auto_generate_config.rb +10 -5
  6. data/lib/rubocop/cli/command/lsp.rb +19 -0
  7. data/lib/rubocop/cli.rb +4 -1
  8. data/lib/rubocop/config.rb +4 -0
  9. data/lib/rubocop/config_finder.rb +2 -2
  10. data/lib/rubocop/config_loader_resolver.rb +4 -3
  11. data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
  12. data/lib/rubocop/config_obsoletion.rb +13 -10
  13. data/lib/rubocop/cop/autocorrect_logic.rb +3 -1
  14. data/lib/rubocop/cop/base.rb +6 -2
  15. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
  16. data/lib/rubocop/cop/bundler/duplicated_group.rb +127 -0
  17. data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
  18. data/lib/rubocop/cop/bundler/gem_version.rb +2 -2
  19. data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
  20. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
  21. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
  22. data/lib/rubocop/cop/gemspec/dependency_version.rb +2 -2
  23. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
  24. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  25. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
  26. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  27. data/lib/rubocop/cop/internal_affairs/cop_description.rb +32 -8
  28. data/lib/rubocop/cop/internal_affairs/example_description.rb +42 -21
  29. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -1
  30. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
  31. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
  32. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +7 -7
  33. data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
  34. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
  35. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  36. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  37. data/lib/rubocop/cop/layout/class_structure.rb +7 -0
  38. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -2
  39. data/lib/rubocop/cop/layout/dot_position.rb +1 -5
  40. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +42 -9
  41. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +27 -4
  42. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
  43. data/lib/rubocop/cop/layout/end_alignment.rb +7 -1
  44. data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
  45. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +6 -6
  46. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  47. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +4 -4
  48. data/lib/rubocop/cop/layout/heredoc_indentation.rb +4 -1
  49. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  50. data/lib/rubocop/cop/layout/indentation_width.rb +3 -3
  51. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  52. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +17 -9
  53. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  54. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -0
  55. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
  56. data/lib/rubocop/cop/layout/redundant_line_break.rb +16 -5
  57. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
  58. data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
  59. data/lib/rubocop/cop/layout/space_after_comma.rb +9 -1
  60. data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
  61. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
  62. data/lib/rubocop/cop/layout/space_around_operators.rb +53 -21
  63. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -0
  64. data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
  65. data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
  66. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +5 -0
  67. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +13 -1
  68. data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -4
  69. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
  70. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  71. data/lib/rubocop/cop/lint/debugger.rb +19 -5
  72. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
  73. data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
  74. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +46 -19
  75. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  76. data/lib/rubocop/cop/lint/erb_new_arguments.rb +6 -7
  77. data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
  78. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
  79. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +1 -1
  80. data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
  81. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
  82. data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
  83. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
  84. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  85. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +78 -0
  86. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  87. data/lib/rubocop/cop/lint/missing_super.rb +34 -5
  88. data/lib/rubocop/cop/lint/mixed_case_range.rb +111 -0
  89. data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
  90. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -7
  91. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
  92. data/lib/rubocop/cop/lint/number_conversion.rb +14 -4
  93. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
  94. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
  95. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -2
  96. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +130 -0
  97. data/lib/rubocop/cop/lint/redundant_require_statement.rb +12 -3
  98. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +63 -4
  99. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
  100. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
  101. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  102. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +14 -8
  103. data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
  104. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -2
  105. data/lib/rubocop/cop/lint/shadowed_exception.rb +5 -11
  106. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +7 -1
  107. data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
  108. data/lib/rubocop/cop/lint/suppressed_exception.rb +2 -2
  109. data/lib/rubocop/cop/lint/symbol_conversion.rb +8 -3
  110. data/lib/rubocop/cop/lint/to_enum_arguments.rb +5 -3
  111. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
  112. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
  113. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
  114. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  115. data/lib/rubocop/cop/lint/useless_assignment.rb +94 -10
  116. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  117. data/lib/rubocop/cop/lint/void.rb +92 -11
  118. data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
  119. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  120. data/lib/rubocop/cop/metrics/class_length.rb +8 -3
  121. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  122. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -2
  123. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +32 -4
  124. data/lib/rubocop/cop/migration/department_name.rb +2 -2
  125. data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
  126. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  127. data/lib/rubocop/cop/mixin/comments_help.rb +19 -11
  128. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  129. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  130. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +14 -11
  131. data/lib/rubocop/cop/mixin/heredoc.rb +6 -2
  132. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -2
  133. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  134. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -8
  135. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  136. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  137. data/lib/rubocop/cop/mixin/string_help.rb +4 -2
  138. data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
  139. data/lib/rubocop/cop/naming/block_forwarding.rb +3 -3
  140. data/lib/rubocop/cop/naming/constant_name.rb +2 -3
  141. data/lib/rubocop/cop/naming/file_name.rb +1 -1
  142. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +3 -1
  143. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +26 -11
  144. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -3
  145. data/lib/rubocop/cop/naming/variable_name.rb +6 -1
  146. data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -2
  147. data/lib/rubocop/cop/style/accessor_grouping.rb +6 -2
  148. data/lib/rubocop/cop/style/alias.rb +9 -8
  149. data/lib/rubocop/cop/style/arguments_forwarding.rb +342 -63
  150. data/lib/rubocop/cop/style/array_first_last.rb +64 -0
  151. data/lib/rubocop/cop/style/array_intersect.rb +13 -5
  152. data/lib/rubocop/cop/style/attr.rb +11 -1
  153. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
  154. data/lib/rubocop/cop/style/begin_block.rb +1 -2
  155. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
  156. data/lib/rubocop/cop/style/block_comments.rb +1 -1
  157. data/lib/rubocop/cop/style/block_delimiters.rb +5 -4
  158. data/lib/rubocop/cop/style/case_like_if.rb +4 -4
  159. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  160. data/lib/rubocop/cop/style/class_check.rb +1 -0
  161. data/lib/rubocop/cop/style/class_equality_comparison.rb +24 -39
  162. data/lib/rubocop/cop/style/collection_compact.rb +22 -11
  163. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  164. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  165. data/lib/rubocop/cop/style/combinable_loops.rb +36 -8
  166. data/lib/rubocop/cop/style/concat_array_literals.rb +2 -1
  167. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
  168. data/lib/rubocop/cop/style/copyright.rb +5 -2
  169. data/lib/rubocop/cop/style/date_time.rb +5 -4
  170. data/lib/rubocop/cop/style/dir.rb +1 -1
  171. data/lib/rubocop/cop/style/dir_empty.rb +8 -14
  172. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
  173. data/lib/rubocop/cop/style/documentation.rb +1 -1
  174. data/lib/rubocop/cop/style/each_with_object.rb +2 -2
  175. data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
  176. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  177. data/lib/rubocop/cop/style/eval_with_location.rb +8 -8
  178. data/lib/rubocop/cop/style/exact_regexp_match.rb +69 -0
  179. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
  180. data/lib/rubocop/cop/style/file_read.rb +2 -2
  181. data/lib/rubocop/cop/style/for.rb +1 -1
  182. data/lib/rubocop/cop/style/format_string.rb +24 -3
  183. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -1
  184. data/lib/rubocop/cop/style/guard_clause.rb +28 -0
  185. data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
  186. data/lib/rubocop/cop/style/hash_each_methods.rb +84 -32
  187. data/lib/rubocop/cop/style/hash_except.rb +21 -9
  188. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  189. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  190. data/lib/rubocop/cop/style/identical_conditional_branches.rb +31 -5
  191. data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
  192. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -0
  193. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  194. data/lib/rubocop/cop/style/inverse_methods.rb +6 -5
  195. data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -6
  196. data/lib/rubocop/cop/style/lambda.rb +3 -3
  197. data/lib/rubocop/cop/style/lambda_call.rb +5 -0
  198. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +3 -2
  199. data/lib/rubocop/cop/style/map_to_hash.rb +10 -4
  200. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +12 -5
  201. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
  202. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
  203. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  204. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
  205. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  206. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  207. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
  208. data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
  209. data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
  210. data/lib/rubocop/cop/style/next.rb +1 -1
  211. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  212. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  213. data/lib/rubocop/cop/style/operator_method_call.rb +8 -2
  214. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  215. data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
  216. data/lib/rubocop/cop/style/redundant_argument.rb +9 -3
  217. data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
  218. data/lib/rubocop/cop/style/redundant_begin.rb +10 -2
  219. data/lib/rubocop/cop/style/redundant_conditional.rb +2 -10
  220. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +38 -0
  221. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +93 -5
  222. data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
  223. data/lib/rubocop/cop/style/redundant_fetch_block.rb +3 -3
  224. data/lib/rubocop/cop/style/redundant_filter_chain.rb +118 -0
  225. data/lib/rubocop/cop/style/redundant_line_continuation.rb +9 -3
  226. data/lib/rubocop/cop/style/redundant_parentheses.rb +54 -21
  227. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +100 -0
  228. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
  229. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
  230. data/lib/rubocop/cop/style/redundant_return.rb +8 -3
  231. data/lib/rubocop/cop/style/redundant_self.rb +17 -2
  232. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +8 -1
  233. data/lib/rubocop/cop/style/redundant_sort.rb +10 -9
  234. data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
  235. data/lib/rubocop/cop/style/redundant_string_escape.rb +3 -1
  236. data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
  237. data/lib/rubocop/cop/style/require_order.rb +11 -5
  238. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
  239. data/lib/rubocop/cop/style/return_nil.rb +6 -2
  240. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +95 -0
  241. data/lib/rubocop/cop/style/sample.rb +2 -1
  242. data/lib/rubocop/cop/style/select_by_regexp.rb +22 -11
  243. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  244. data/lib/rubocop/cop/style/semicolon.rb +20 -4
  245. data/lib/rubocop/cop/style/signal_exception.rb +1 -1
  246. data/lib/rubocop/cop/style/single_argument_dig.rb +7 -3
  247. data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
  248. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  249. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
  250. data/lib/rubocop/cop/style/sole_nested_conditional.rb +6 -2
  251. data/lib/rubocop/cop/style/special_global_vars.rb +3 -4
  252. data/lib/rubocop/cop/style/string_chars.rb +1 -0
  253. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
  254. data/lib/rubocop/cop/style/strip.rb +7 -4
  255. data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
  256. data/lib/rubocop/cop/style/symbol_array.rb +35 -15
  257. data/lib/rubocop/cop/style/unpack_first.rb +11 -14
  258. data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
  259. data/lib/rubocop/cop/style/yoda_condition.rb +4 -2
  260. data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
  261. data/lib/rubocop/cop/team.rb +1 -1
  262. data/lib/rubocop/cop/util.rb +1 -1
  263. data/lib/rubocop/cop/utils/regexp_ranges.rb +113 -0
  264. data/lib/rubocop/cop/variable_force/assignment.rb +45 -4
  265. data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
  266. data/lib/rubocop/cop/variable_force.rb +1 -0
  267. data/lib/rubocop/cops_documentation_generator.rb +1 -1
  268. data/lib/rubocop/ext/regexp_parser.rb +4 -1
  269. data/lib/rubocop/file_finder.rb +4 -7
  270. data/lib/rubocop/formatter/html_formatter.rb +5 -4
  271. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  272. data/lib/rubocop/lsp/logger.rb +22 -0
  273. data/lib/rubocop/lsp/routes.rb +246 -0
  274. data/lib/rubocop/lsp/runtime.rb +99 -0
  275. data/lib/rubocop/lsp/server.rb +68 -0
  276. data/lib/rubocop/lsp/severity.rb +27 -0
  277. data/lib/rubocop/magic_comment.rb +12 -10
  278. data/lib/rubocop/options.rb +11 -1
  279. data/lib/rubocop/result_cache.rb +5 -2
  280. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  281. data/lib/rubocop/rspec/shared_contexts.rb +2 -3
  282. data/lib/rubocop/runner.rb +6 -4
  283. data/lib/rubocop/server/cache.rb +1 -0
  284. data/lib/rubocop/server/client_command/exec.rb +3 -2
  285. data/lib/rubocop/string_interpreter.rb +3 -3
  286. data/lib/rubocop/target_finder.rb +7 -3
  287. data/lib/rubocop/target_ruby.rb +12 -7
  288. data/lib/rubocop/version.rb +10 -6
  289. data/lib/rubocop.rb +19 -0
  290. metadata +54 -15
@@ -8,6 +8,21 @@ module RuboCop
8
8
  # This cop identifies places where `do_something(*args, &block)`
9
9
  # can be replaced by `do_something(...)`.
10
10
  #
11
+ # In Ruby 3.2, anonymous args/kwargs forwarding has been added.
12
+ #
13
+ # This cop also identifies places where `use_args(*args)`/`use_kwargs(**kwargs)` can be
14
+ # replaced by `use_args(*)`/`use_kwargs(**)`; if desired, this functionality can be disabled
15
+ # by setting `UseAnonymousForwarding: false`.
16
+ #
17
+ # And this cop has `RedundantRestArgumentNames`, `RedundantKeywordRestArgumentNames`,
18
+ # and `RedundantBlockArgumentNames` options. This configuration is a list of redundant names
19
+ # that are sufficient for anonymizing meaningless naming.
20
+ #
21
+ # Meaningless names that are commonly used can be anonymized by default:
22
+ # e.g., `*args`, `**options`, `&block`, and so on.
23
+ #
24
+ # Names not on this list are likely to be meaningful and are allowed by default.
25
+ #
11
26
  # @example
12
27
  # # bad
13
28
  # def foo(*args, &block)
@@ -24,7 +39,27 @@ module RuboCop
24
39
  # bar(...)
25
40
  # end
26
41
  #
27
- # @example AllowOnlyRestArgument: true (default)
42
+ # @example UseAnonymousForwarding: true (default, only relevant for Ruby >= 3.2)
43
+ # # bad
44
+ # def foo(*args, **kwargs)
45
+ # args_only(*args)
46
+ # kwargs_only(**kwargs)
47
+ # end
48
+ #
49
+ # # good
50
+ # def foo(*, **)
51
+ # args_only(*)
52
+ # kwargs_only(**)
53
+ # end
54
+ #
55
+ # @example UseAnonymousForwarding: false (only relevant for Ruby >= 3.2)
56
+ # # good
57
+ # def foo(*args, **kwargs)
58
+ # args_only(*args)
59
+ # kwargs_only(**kwargs)
60
+ # end
61
+ #
62
+ # @example AllowOnlyRestArgument: true (default, only relevant for Ruby < 3.2)
28
63
  # # good
29
64
  # def foo(*args)
30
65
  # bar(*args)
@@ -34,7 +69,7 @@ module RuboCop
34
69
  # bar(**kwargs)
35
70
  # end
36
71
  #
37
- # @example AllowOnlyRestArgument: false
72
+ # @example AllowOnlyRestArgument: false (only relevant for Ruby < 3.2)
38
73
  # # bad
39
74
  # # The following code can replace the arguments with `...`,
40
75
  # # but it will change the behavior. Because `...` forwards block also.
@@ -46,6 +81,38 @@ module RuboCop
46
81
  # bar(**kwargs)
47
82
  # end
48
83
  #
84
+ # @example RedundantRestArgumentNames: ['args', 'arguments'] (default)
85
+ # # bad
86
+ # def foo(*args)
87
+ # bar(*args)
88
+ # end
89
+ #
90
+ # # good
91
+ # def foo(*)
92
+ # bar(*)
93
+ # end
94
+ #
95
+ # @example RedundantKeywordRestArgumentNames: ['kwargs', 'options', 'opts'] (default)
96
+ # # bad
97
+ # def foo(**kwargs)
98
+ # bar(**kwargs)
99
+ # end
100
+ #
101
+ # # good
102
+ # def foo(**)
103
+ # bar(**)
104
+ # end
105
+ #
106
+ # @example RedundantBlockArgumentNames: ['blk', 'block', 'proc'] (default)
107
+ # # bad
108
+ # def foo(&block)
109
+ # bar(&block)
110
+ # end
111
+ #
112
+ # # good
113
+ # def foo(&)
114
+ # bar(&)
115
+ # end
49
116
  class ArgumentsForwarding < Base
50
117
  include RangeHelp
51
118
  extend AutoCorrector
@@ -53,102 +120,314 @@ module RuboCop
53
120
 
54
121
  minimum_target_ruby_version 2.7
55
122
 
56
- MSG = 'Use arguments forwarding.'
57
-
58
- # @!method use_rest_arguments?(node)
59
- def_node_matcher :use_rest_arguments?, <<~PATTERN
60
- (args ({restarg kwrestarg} $_) $...)
61
- PATTERN
62
-
63
- # @!method only_rest_arguments?(node, name)
64
- def_node_matcher :only_rest_arguments?, <<~PATTERN
65
- {
66
- (send _ _ (splat (lvar %1)))
67
- (send _ _ (hash (kwsplat (lvar %1))))
68
- }
69
- PATTERN
70
-
71
- # @!method forwarding_method_arguments?(node, rest_name, block_name, kwargs_name)
72
- def_node_matcher :forwarding_method_arguments?, <<~PATTERN
73
- {
74
- (send _ _
75
- (splat (lvar %1))
76
- (block-pass {(lvar %2) nil?}))
77
- (send _ _
78
- (splat (lvar %1))
79
- (hash (kwsplat (lvar %3)))
80
- (block-pass {(lvar %2) nil?}))
81
- }
82
- PATTERN
123
+ FORWARDING_LVAR_TYPES = %i[splat kwsplat block_pass].freeze
124
+ ADDITIONAL_ARG_TYPES = %i[lvar arg].freeze
125
+
126
+ FORWARDING_MSG = 'Use shorthand syntax `...` for arguments forwarding.'
127
+ ARGS_MSG = 'Use anonymous positional arguments forwarding (`*`).'
128
+ KWARGS_MSG = 'Use anonymous keyword arguments forwarding (`**`).'
129
+
130
+ def self.autocorrect_incompatible_with
131
+ [Naming::BlockForwarding]
132
+ end
83
133
 
84
134
  def on_def(node)
85
135
  return unless node.body
86
- return unless (rest_args_name, args = use_rest_arguments?(node.arguments))
87
- return if args.any?(&:default?)
88
136
 
89
- node.each_descendant(:send) do |send_node|
90
- kwargs_name, block_name = extract_argument_names_from(args)
137
+ restarg, kwrestarg, blockarg = extract_forwardable_args(node.arguments)
138
+ forwardable_args = redundant_forwardable_named_args(restarg, kwrestarg, blockarg)
139
+ send_nodes = node.each_descendant(:send).to_a
140
+
141
+ send_classifications = classify_send_nodes(
142
+ node, send_nodes, non_splat_or_block_pass_lvar_references(node.body), forwardable_args
143
+ )
91
144
 
92
- next unless forwarding_method?(send_node, rest_args_name, kwargs_name, block_name) &&
93
- all_lvars_as_forwarding_method_arguments?(node, send_node)
145
+ return if send_classifications.empty?
94
146
 
95
- register_offense_to_forwarding_method_arguments(send_node)
96
- register_offense_to_method_definition_arguments(node)
147
+ if only_forwards_all?(send_classifications)
148
+ add_forward_all_offenses(node, send_classifications, forwardable_args)
149
+ elsif target_ruby_version >= 3.2
150
+ add_post_ruby_32_offenses(node, send_classifications, forwardable_args)
97
151
  end
98
152
  end
153
+
99
154
  alias on_defs on_def
100
155
 
101
156
  private
102
157
 
103
- def extract_argument_names_from(args)
104
- kwargs_name = args.first.source.delete('**') if args.first&.kwrestarg_type?
105
- block_arg_name = args.last.source.delete('&') if args.last&.blockarg_type?
106
-
107
- [kwargs_name, block_arg_name].map { |name| name&.to_sym }
158
+ def extract_forwardable_args(args)
159
+ [args.find(&:restarg_type?), args.find(&:kwrestarg_type?), args.find(&:blockarg_type?)]
108
160
  end
109
161
 
110
- def forwarding_method?(node, rest_arg, kwargs, block_arg)
111
- return only_rest_arguments?(node, rest_arg) unless allow_only_rest_arguments?
162
+ def redundant_forwardable_named_args(restarg, kwrestarg, blockarg)
163
+ restarg_node = redundant_named_arg(restarg, 'RedundantRestArgumentNames', '*')
164
+ kwrestarg_node = redundant_named_arg(kwrestarg, 'RedundantKeywordRestArgumentNames', '**')
165
+ blockarg_node = redundant_named_arg(blockarg, 'RedundantBlockArgumentNames', '&')
112
166
 
113
- forwarding_method_arguments?(node, rest_arg, block_arg, kwargs)
167
+ [restarg_node, kwrestarg_node, blockarg_node]
114
168
  end
115
169
 
116
- def all_lvars_as_forwarding_method_arguments?(def_node, forwarding_method)
117
- lvars = def_node.body.each_descendant(:lvar, :lvasgn)
170
+ def only_forwards_all?(send_classifications)
171
+ send_classifications.all? { |_, c, _, _| c == :all }
172
+ end
118
173
 
119
- begin_pos = forwarding_method.source_range.begin_pos
120
- end_pos = forwarding_method.source_range.end_pos
174
+ def add_forward_all_offenses(node, send_classifications, forwardable_args)
175
+ send_classifications.each do |send_node, _c, forward_rest, _forward_kwrest|
176
+ register_forward_all_offense(send_node, send_node, forward_rest)
177
+ end
121
178
 
122
- lvars.all? { |lvar| lvar.source_range.begin_pos.between?(begin_pos, end_pos) }
179
+ rest_arg, _kwrest_arg, _block_arg = *forwardable_args
180
+ register_forward_all_offense(node, node.arguments, rest_arg)
123
181
  end
124
182
 
125
- def register_offense_to_forwarding_method_arguments(forwarding_method)
126
- add_offense(arguments_range(forwarding_method)) do |corrector|
127
- begin_pos = forwarding_method.loc.selector&.end_pos || forwarding_method.loc.dot.end_pos
128
- range = range_between(begin_pos, forwarding_method.source_range.end_pos)
183
+ def add_post_ruby_32_offenses(def_node, send_classifications, forwardable_args)
184
+ return unless use_anonymous_forwarding?
129
185
 
130
- corrector.replace(range, '(...)')
186
+ rest_arg, kwrest_arg, _block_arg = *forwardable_args
187
+
188
+ send_classifications.each do |send_node, _c, forward_rest, forward_kwrest|
189
+ if forward_rest
190
+ register_forward_args_offense(def_node.arguments, rest_arg)
191
+ register_forward_args_offense(send_node, forward_rest)
192
+ end
193
+
194
+ if forward_kwrest
195
+ register_forward_kwargs_offense(!forward_rest, def_node.arguments, kwrest_arg)
196
+ register_forward_kwargs_offense(!forward_rest, send_node, forward_kwrest)
197
+ end
131
198
  end
132
199
  end
133
200
 
134
- def register_offense_to_method_definition_arguments(method_definition)
135
- add_offense(arguments_range(method_definition)) do |corrector|
136
- arguments_range = range_with_surrounding_space(
137
- method_definition.arguments.source_range, side: :left
201
+ def non_splat_or_block_pass_lvar_references(body)
202
+ body.each_descendant(:lvar, :lvasgn).filter_map do |lvar|
203
+ parent = lvar.parent
204
+
205
+ next if lvar.lvar_type? && FORWARDING_LVAR_TYPES.include?(parent.type)
206
+
207
+ lvar.children.first
208
+ end.uniq
209
+ end
210
+
211
+ def classify_send_nodes(def_node, send_nodes, referenced_lvars, forwardable_args)
212
+ send_nodes.filter_map do |send_node|
213
+ classification_and_forwards = classification_and_forwards(
214
+ def_node,
215
+ send_node,
216
+ referenced_lvars,
217
+ forwardable_args
138
218
  )
139
- corrector.replace(arguments_range, '(...)')
219
+
220
+ next unless classification_and_forwards
221
+
222
+ [send_node, *classification_and_forwards]
140
223
  end
141
224
  end
142
225
 
143
- def arguments_range(node)
144
- arguments = node.arguments
226
+ def classification_and_forwards(def_node, send_node, referenced_lvars, forwardable_args)
227
+ classifier = SendNodeClassifier.new(
228
+ def_node,
229
+ send_node,
230
+ referenced_lvars,
231
+ forwardable_args,
232
+ target_ruby_version: target_ruby_version,
233
+ allow_only_rest_arguments: allow_only_rest_arguments?
234
+ )
145
235
 
146
- range_between(arguments.first.source_range.begin_pos, arguments.last.source_range.end_pos)
236
+ classification = classifier.classification
237
+
238
+ return unless classification
239
+
240
+ [classification, classifier.forwarded_rest_arg, classifier.forwarded_kwrest_arg]
241
+ end
242
+
243
+ def redundant_named_arg(arg, config_name, keyword)
244
+ return nil unless arg
245
+
246
+ redundant_arg_names = cop_config.fetch(config_name, []).map do |redundant_arg_name|
247
+ "#{keyword}#{redundant_arg_name}"
248
+ end << keyword
249
+
250
+ redundant_arg_names.include?(arg.source) ? arg : nil
251
+ end
252
+
253
+ def register_forward_args_offense(def_arguments_or_send, rest_arg_or_splat)
254
+ add_offense(rest_arg_or_splat, message: ARGS_MSG) do |corrector|
255
+ add_parens_if_missing(def_arguments_or_send, corrector)
256
+
257
+ corrector.replace(rest_arg_or_splat, '*')
258
+ end
259
+ end
260
+
261
+ def register_forward_kwargs_offense(add_parens, def_arguments_or_send, kwrest_arg_or_splat)
262
+ add_offense(kwrest_arg_or_splat, message: KWARGS_MSG) do |corrector|
263
+ add_parens_if_missing(def_arguments_or_send, corrector) if add_parens
264
+
265
+ corrector.replace(kwrest_arg_or_splat, '**')
266
+ end
267
+ end
268
+
269
+ def register_forward_all_offense(def_or_send, send_or_arguments, rest_or_splat)
270
+ arg_range = arguments_range(def_or_send, rest_or_splat)
271
+
272
+ add_offense(arg_range, message: FORWARDING_MSG) do |corrector|
273
+ add_parens_if_missing(send_or_arguments, corrector)
274
+
275
+ corrector.replace(arg_range, '...')
276
+ end
277
+ end
278
+
279
+ def arguments_range(node, first_node)
280
+ arguments = node.arguments.reject { |arg| ADDITIONAL_ARG_TYPES.include?(arg.type) }
281
+
282
+ start_node = first_node || arguments.first
283
+
284
+ range_between(start_node.source_range.begin_pos, arguments.last.source_range.end_pos)
147
285
  end
148
286
 
149
287
  def allow_only_rest_arguments?
150
288
  cop_config.fetch('AllowOnlyRestArgument', true)
151
289
  end
290
+
291
+ def use_anonymous_forwarding?
292
+ cop_config.fetch('UseAnonymousForwarding', false)
293
+ end
294
+
295
+ def add_parens_if_missing(node, corrector)
296
+ return if parentheses?(node)
297
+
298
+ add_parentheses(node, corrector)
299
+ end
300
+
301
+ # Classifies send nodes for possible rest/kwrest/all (including block) forwarding.
302
+ class SendNodeClassifier
303
+ extend NodePattern::Macros
304
+
305
+ # @!method forwarded_rest_arg?(node, rest_name)
306
+ def_node_matcher :forwarded_rest_arg?, '(splat (lvar %1))'
307
+
308
+ # @!method extract_forwarded_kwrest_arg(node, kwrest_name)
309
+ def_node_matcher :extract_forwarded_kwrest_arg, '(hash <$(kwsplat (lvar %1)) ...>)'
310
+
311
+ # @!method forwarded_block_arg?(node, block_name)
312
+ def_node_matcher :forwarded_block_arg?, '(block_pass {(lvar %1) nil?})'
313
+
314
+ def initialize(def_node, send_node, referenced_lvars, forwardable_args, **config)
315
+ @def_node = def_node
316
+ @send_node = send_node
317
+ @referenced_lvars = referenced_lvars
318
+ @rest_arg, @kwrest_arg, @block_arg = *forwardable_args
319
+ @rest_arg_name, @kwrest_arg_name, @block_arg_name =
320
+ *forwardable_args.map { |a| a&.name }
321
+ @config = config
322
+ end
323
+
324
+ def forwarded_rest_arg
325
+ return nil if referenced_rest_arg?
326
+
327
+ arguments.find { |arg| forwarded_rest_arg?(arg, @rest_arg_name) }
328
+ end
329
+
330
+ def forwarded_kwrest_arg
331
+ return nil if referenced_kwrest_arg?
332
+
333
+ arguments.filter_map { |arg| extract_forwarded_kwrest_arg(arg, @kwrest_arg_name) }.first
334
+ end
335
+
336
+ def forwarded_block_arg
337
+ return nil if referenced_block_arg?
338
+
339
+ arguments.find { |arg| forwarded_block_arg?(arg, @block_arg_name) }
340
+ end
341
+
342
+ def classification
343
+ return nil unless forwarded_rest_arg || forwarded_kwrest_arg
344
+
345
+ if can_forward_all?
346
+ :all
347
+ else
348
+ :rest_or_kwrest
349
+ end
350
+ end
351
+
352
+ private
353
+
354
+ def can_forward_all?
355
+ return false if any_arg_referenced?
356
+ return false if ruby_32_missing_rest_or_kwest?
357
+ return false unless offensive_block_forwarding?
358
+ return false if additional_kwargs_or_forwarded_kwargs?
359
+
360
+ no_additional_args? || (target_ruby_version >= 3.0 && no_post_splat_args?)
361
+ end
362
+
363
+ def ruby_32_missing_rest_or_kwest?
364
+ target_ruby_version >= 3.2 && !forwarded_rest_and_kwrest_args
365
+ end
366
+
367
+ def offensive_block_forwarding?
368
+ @block_arg ? forwarded_block_arg : allow_offense_for_no_block?
369
+ end
370
+
371
+ def forwarded_rest_and_kwrest_args
372
+ forwarded_rest_arg && forwarded_kwrest_arg
373
+ end
374
+
375
+ def arguments
376
+ @send_node.arguments
377
+ end
378
+
379
+ def referenced_rest_arg?
380
+ @referenced_lvars.include?(@rest_arg_name)
381
+ end
382
+
383
+ def referenced_kwrest_arg?
384
+ @referenced_lvars.include?(@kwrest_arg_name)
385
+ end
386
+
387
+ def referenced_block_arg?
388
+ @referenced_lvars.include?(@block_arg_name)
389
+ end
390
+
391
+ def any_arg_referenced?
392
+ referenced_rest_arg? || referenced_kwrest_arg? || referenced_block_arg?
393
+ end
394
+
395
+ def target_ruby_version
396
+ @config.fetch(:target_ruby_version)
397
+ end
398
+
399
+ def no_post_splat_args?
400
+ return true unless (splat_index = arguments.index(forwarded_rest_arg))
401
+
402
+ arg_after_splat = arguments[splat_index + 1]
403
+ [nil, :hash, :block_pass].include?(arg_after_splat&.type)
404
+ end
405
+
406
+ def additional_kwargs_or_forwarded_kwargs?
407
+ additional_kwargs? || forward_additional_kwargs?
408
+ end
409
+
410
+ def additional_kwargs?
411
+ @def_node.arguments.any? { |a| a.kwarg_type? || a.kwoptarg_type? }
412
+ end
413
+
414
+ def forward_additional_kwargs?
415
+ return false unless forwarded_kwrest_arg
416
+
417
+ !forwarded_kwrest_arg.parent.children.one?
418
+ end
419
+
420
+ def allow_offense_for_no_block?
421
+ !@config.fetch(:allow_only_rest_arguments)
422
+ end
423
+
424
+ def no_additional_args?
425
+ forwardable_count = [@rest_arg, @kwrest_arg, @block_arg].compact.size
426
+
427
+ @def_node.arguments.size == forwardable_count &&
428
+ @send_node.arguments.size == forwardable_count
429
+ end
430
+ end
152
431
  end
153
432
  end
154
433
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Identifies usages of `arr[0]` and `arr[-1]` and suggests to change
7
+ # them to use `arr.first` and `arr.last` instead.
8
+ #
9
+ # The cop is disabled by default due to safety concerns.
10
+ #
11
+ # @safety
12
+ # This cop is unsafe because `[0]` or `[-1]` can be called on a Hash,
13
+ # which returns a value for `0` or `-1` key, but changing these to use
14
+ # `.first` or `.last` will return first/last tuple instead. Also, String
15
+ # does not implement `first`/`last` methods.
16
+ #
17
+ # @example
18
+ # # bad
19
+ # arr[0]
20
+ # arr[-1]
21
+ #
22
+ # # good
23
+ # arr.first
24
+ # arr.last
25
+ # arr[0] = 2
26
+ # arr[0][-2]
27
+ #
28
+ class ArrayFirstLast < Base
29
+ extend AutoCorrector
30
+
31
+ MSG = 'Use `%<preferred>s`.'
32
+ RESTRICT_ON_SEND = %i[[]].freeze
33
+
34
+ # rubocop:disable Metrics/AbcSize
35
+ def on_send(node)
36
+ return unless node.arguments.size == 1 && node.first_argument.int_type?
37
+
38
+ value = node.first_argument.value
39
+ return unless [0, -1].include?(value)
40
+
41
+ node = innermost_braces_node(node)
42
+ return if node.parent && brace_method?(node.parent)
43
+
44
+ preferred = (value.zero? ? 'first' : 'last')
45
+ add_offense(node.loc.selector, message: format(MSG, preferred: preferred)) do |corrector|
46
+ corrector.replace(node.loc.selector, ".#{preferred}")
47
+ end
48
+ end
49
+ # rubocop:enable Metrics/AbcSize
50
+
51
+ private
52
+
53
+ def innermost_braces_node(node)
54
+ node = node.receiver while node.receiver.send_type? && node.receiver.method?(:[])
55
+ node
56
+ end
57
+
58
+ def brace_method?(node)
59
+ node.send_type? && (node.method?(:[]) || node.method?(:[]=))
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -11,6 +11,15 @@ module RuboCop
11
11
  # The `array1.intersect?(array2)` method is faster than
12
12
  # `(array1 & array2).any?` and is more readable.
13
13
  #
14
+ # In cases like the following, compatibility is not ensured,
15
+ # so it will not be detected when using block argument.
16
+ #
17
+ # [source,ruby]
18
+ # ----
19
+ # ([1] & [1,2]).any? { |x| false } # => false
20
+ # [1].intersect?([1,2]) { |x| false } # => true
21
+ # ----
22
+ #
14
23
  # @safety
15
24
  # This cop cannot guarantee that `array1` and `array2` are
16
25
  # actually arrays while method `intersect?` is for arrays only.
@@ -68,16 +77,15 @@ module RuboCop
68
77
  RESTRICT_ON_SEND = (STRAIGHT_METHODS + NEGATED_METHODS).freeze
69
78
 
70
79
  def on_send(node)
80
+ return if (parent = node.parent) && (parent.block_type? || parent.numblock_type?)
71
81
  return unless (receiver, argument, method_name = bad_intersection_check?(node))
72
82
 
73
83
  message = message(receiver.source, argument.source, method_name)
74
84
 
75
85
  add_offense(node, message: message) do |corrector|
76
- if straight?(method_name)
77
- corrector.replace(node, "#{receiver.source}.intersect?(#{argument.source})")
78
- else
79
- corrector.replace(node, "!#{receiver.source}.intersect?(#{argument.source})")
80
- end
86
+ bang = straight?(method_name) ? '' : '!'
87
+
88
+ corrector.replace(node, "#{bang}#{receiver.source}.intersect?(#{argument.source})")
81
89
  end
82
90
  end
83
91
 
@@ -24,7 +24,7 @@ module RuboCop
24
24
  def on_send(node)
25
25
  return unless node.command?(:attr) && node.arguments?
26
26
  # check only for method definitions in class/module body
27
- return if node.parent && !node.parent.class_type? && !class_eval?(node.parent)
27
+ return if allowed_context?(node)
28
28
 
29
29
  message = message(node)
30
30
  add_offense(node.loc.selector, message: message) do |corrector|
@@ -34,6 +34,16 @@ module RuboCop
34
34
 
35
35
  private
36
36
 
37
+ def allowed_context?(node)
38
+ return false unless (class_node = node.each_ancestor(:class, :block).first)
39
+
40
+ (!class_node.class_type? && !class_eval?(class_node)) || define_attr_method?(class_node)
41
+ end
42
+
43
+ def define_attr_method?(node)
44
+ node.each_descendant(:def).any? { |def_node| def_node.method?(:attr) }
45
+ end
46
+
37
47
  def autocorrect(corrector, node)
38
48
  attr_name, setter = *node.arguments
39
49
 
@@ -16,31 +16,38 @@ module RuboCop
16
16
  # File.open('file') do |f|
17
17
  # # ...
18
18
  # end
19
+ #
20
+ # # bad
21
+ # f = Tempfile.open('temp')
22
+ #
23
+ # # good
24
+ # Tempfile.open('temp') do |f|
25
+ # # ...
26
+ # end
19
27
  class AutoResourceCleanup < Base
20
- MSG = 'Use the block version of `%<class>s.%<method>s`.'
21
-
22
- TARGET_METHODS = { File: :open }.freeze
28
+ MSG = 'Use the block version of `%<current>s`.'
29
+ RESTRICT_ON_SEND = %i[open].freeze
23
30
 
24
- RESTRICT_ON_SEND = TARGET_METHODS.values.freeze
31
+ # @!method file_open_method?(node)
32
+ def_node_matcher :file_open_method?, <<~PATTERN
33
+ (send (const {nil? cbase} {:File :Tempfile}) :open ...)
34
+ PATTERN
25
35
 
26
36
  def on_send(node)
27
- TARGET_METHODS.each do |target_class, target_method|
28
- next if node.method_name != target_method
37
+ return if !file_open_method?(node) || cleanup?(node)
29
38
 
30
- target_receiver = s(:const, nil, target_class)
31
- next if node.receiver != target_receiver
39
+ current = node.receiver.source_range.begin.join(node.selector.end).source
32
40
 
33
- next if cleanup?(node)
34
-
35
- add_offense(node, message: format(MSG, class: target_class, method: target_method))
36
- end
41
+ add_offense(node, message: format(MSG, current: current))
37
42
  end
38
43
 
39
44
  private
40
45
 
41
46
  def cleanup?(node)
42
- parent = node.parent
43
- node.block_argument? || (parent && (parent.block_type? || !parent.lvasgn_type?))
47
+ return true if node.block_argument?
48
+ return false unless (parent = node.parent)
49
+
50
+ parent.block_type? || !parent.lvasgn_type?
44
51
  end
45
52
  end
46
53
  end
@@ -3,8 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- #
7
- # This cop checks for BEGIN blocks.
6
+ # Checks for BEGIN blocks.
8
7
  #
9
8
  # @example
10
9
  # # bad
@@ -33,7 +33,7 @@ module RuboCop
33
33
  def on_class(class_node)
34
34
  @macros_to_rewrite[class_node] = Set.new
35
35
 
36
- find_macros(class_node.body).each do |_visibility, macros|
36
+ find_macros(class_node.body).each_value do |macros|
37
37
  bisected = find_bisection(macros)
38
38
  next unless bisected.any?
39
39
 
@@ -74,7 +74,7 @@ module RuboCop
74
74
  def find_macros(class_def)
75
75
  # Find all the macros (`attr_reader`, `attr_writer`, etc.) in the class body
76
76
  # and turn them into `Macro` objects so that they can be processed.
77
- return [] if !class_def || class_def.def_type?
77
+ return {} if !class_def || class_def.def_type?
78
78
 
79
79
  send_nodes =
80
80
  if class_def.send_type?