rubocop 1.69.2 → 1.75.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 (360) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +4 -4
  4. data/config/default.yml +154 -23
  5. data/config/internal_affairs.yml +20 -0
  6. data/config/obsoletion.yml +3 -1
  7. data/lib/rubocop/cli/command/execute_runner.rb +3 -3
  8. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  9. data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
  10. data/lib/rubocop/cli.rb +1 -1
  11. data/lib/rubocop/comment_config.rb +2 -2
  12. data/lib/rubocop/config.rb +52 -10
  13. data/lib/rubocop/config_loader.rb +52 -9
  14. data/lib/rubocop/config_loader_resolver.rb +36 -10
  15. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
  16. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  17. data/lib/rubocop/config_obsoletion.rb +46 -2
  18. data/lib/rubocop/config_validator.rb +20 -9
  19. data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
  20. data/lib/rubocop/cop/base.rb +6 -0
  21. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  22. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  23. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  24. data/lib/rubocop/cop/internal_affairs/example_description.rb +7 -3
  25. data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
  26. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  27. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  28. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  29. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  30. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  31. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +230 -0
  32. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +91 -0
  33. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  34. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  35. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  36. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  37. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  38. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  39. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  40. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +7 -1
  41. data/lib/rubocop/cop/internal_affairs.rb +6 -16
  42. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  43. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -8
  44. data/lib/rubocop/cop/layout/block_alignment.rb +3 -1
  45. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  46. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  47. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +4 -4
  48. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  49. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  50. data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
  51. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  52. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  53. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +28 -1
  54. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
  55. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  56. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
  57. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  58. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  59. data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
  60. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  61. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  62. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  63. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  64. data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
  65. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
  66. data/lib/rubocop/cop/layout/indentation_width.rb +1 -0
  67. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  68. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  69. data/lib/rubocop/cop/layout/line_length.rb +9 -4
  70. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
  71. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  72. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  73. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
  74. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
  75. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  76. data/lib/rubocop/cop/layout/redundant_line_break.rb +16 -11
  77. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -5
  78. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  79. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  80. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  81. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  82. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  83. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
  84. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  85. data/lib/rubocop/cop/layout/space_around_operators.rb +7 -4
  86. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  87. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  88. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  89. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -0
  90. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  91. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  92. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  93. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  94. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +1 -1
  95. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  96. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  97. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
  98. data/lib/rubocop/cop/lint/debugger.rb +3 -3
  99. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  100. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  101. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -17
  102. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  103. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  104. data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
  105. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  106. data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
  107. data/lib/rubocop/cop/lint/float_comparison.rb +6 -8
  108. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  109. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  110. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  111. data/lib/rubocop/cop/lint/literal_as_condition.rb +103 -9
  112. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  113. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  114. data/lib/rubocop/cop/lint/mixed_case_range.rb +3 -3
  115. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  116. data/lib/rubocop/cop/lint/nested_method_definition.rb +9 -5
  117. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  118. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -3
  119. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
  120. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +18 -31
  121. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  122. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
  123. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  124. data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
  125. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  126. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  127. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  128. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +261 -0
  129. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  130. data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
  131. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  132. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  133. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -1
  134. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +8 -1
  135. data/lib/rubocop/cop/lint/shared_mutable_default.rb +76 -0
  136. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  137. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
  138. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  139. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  140. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  141. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  142. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -4
  143. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +3 -1
  144. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  145. data/lib/rubocop/cop/lint/unreachable_code.rb +2 -1
  146. data/lib/rubocop/cop/lint/unreachable_loop.rb +6 -6
  147. data/lib/rubocop/cop/lint/useless_access_modifier.rb +5 -4
  148. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  149. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +71 -0
  150. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  151. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  152. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  153. data/lib/rubocop/cop/lint/void.rb +12 -9
  154. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  155. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  156. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  157. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  158. data/lib/rubocop/cop/metrics/method_length.rb +9 -1
  159. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  160. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  161. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  162. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  163. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  164. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  165. data/lib/rubocop/cop/mixin/check_line_breakable.rb +13 -13
  166. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -2
  167. data/lib/rubocop/cop/mixin/comments_help.rb +4 -2
  168. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  169. data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
  170. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  171. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  172. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
  173. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +0 -1
  174. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
  175. data/lib/rubocop/cop/mixin/hash_subset.rb +203 -0
  176. data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
  177. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  178. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  179. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +48 -24
  180. data/lib/rubocop/cop/mixin/range_help.rb +15 -3
  181. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  182. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
  183. data/lib/rubocop/cop/mixin/string_help.rb +2 -2
  184. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  185. data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
  186. data/lib/rubocop/cop/mixin/trailing_comma.rb +15 -3
  187. data/lib/rubocop/cop/naming/block_forwarding.rb +19 -15
  188. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  189. data/lib/rubocop/cop/naming/method_name.rb +64 -8
  190. data/lib/rubocop/cop/naming/predicate_name.rb +44 -0
  191. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -3
  192. data/lib/rubocop/cop/naming/variable_name.rb +51 -6
  193. data/lib/rubocop/cop/registry.rb +9 -6
  194. data/lib/rubocop/cop/security/compound_hash.rb +1 -0
  195. data/lib/rubocop/cop/style/access_modifier_declarations.rb +34 -5
  196. data/lib/rubocop/cop/style/accessor_grouping.rb +19 -5
  197. data/lib/rubocop/cop/style/and_or.rb +1 -1
  198. data/lib/rubocop/cop/style/arguments_forwarding.rb +39 -23
  199. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  200. data/lib/rubocop/cop/style/array_intersect.rb +39 -28
  201. data/lib/rubocop/cop/style/block_delimiters.rb +9 -21
  202. data/lib/rubocop/cop/style/class_and_module_children.rb +35 -10
  203. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  204. data/lib/rubocop/cop/style/collection_methods.rb +2 -1
  205. data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
  206. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  207. data/lib/rubocop/cop/style/commented_keyword.rb +10 -3
  208. data/lib/rubocop/cop/style/comparable_between.rb +75 -0
  209. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  210. data/lib/rubocop/cop/style/conditional_assignment.rb +9 -4
  211. data/lib/rubocop/cop/style/documentation.rb +1 -1
  212. data/lib/rubocop/cop/style/double_negation.rb +4 -4
  213. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  214. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  215. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  216. data/lib/rubocop/cop/style/empty_literal.rb +5 -1
  217. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  218. data/lib/rubocop/cop/style/endless_method.rb +163 -18
  219. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  220. data/lib/rubocop/cop/style/exact_regexp_match.rb +3 -10
  221. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  222. data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
  223. data/lib/rubocop/cop/style/exponential_notation.rb +3 -3
  224. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  225. data/lib/rubocop/cop/style/float_division.rb +8 -4
  226. data/lib/rubocop/cop/style/for.rb +1 -0
  227. data/lib/rubocop/cop/style/format_string_token.rb +38 -11
  228. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  229. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  230. data/lib/rubocop/cop/style/guard_clause.rb +2 -1
  231. data/lib/rubocop/cop/style/hash_each_methods.rb +6 -8
  232. data/lib/rubocop/cop/style/hash_except.rb +24 -148
  233. data/lib/rubocop/cop/style/hash_fetch_chain.rb +105 -0
  234. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  235. data/lib/rubocop/cop/style/hash_syntax.rb +9 -3
  236. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  237. data/lib/rubocop/cop/style/if_inside_else.rb +10 -13
  238. data/lib/rubocop/cop/style/if_unless_modifier.rb +5 -5
  239. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
  240. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  241. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  242. data/lib/rubocop/cop/style/inverse_methods.rb +15 -11
  243. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  244. data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
  245. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  246. data/lib/rubocop/cop/style/it_block_parameter.rb +100 -0
  247. data/lib/rubocop/cop/style/keyword_parameters_order.rb +14 -8
  248. data/lib/rubocop/cop/style/lambda.rb +1 -0
  249. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  250. data/lib/rubocop/cop/style/map_into_array.rb +2 -1
  251. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  252. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  253. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +23 -16
  254. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  255. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
  256. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
  257. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  258. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  259. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -2
  260. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
  261. data/lib/rubocop/cop/style/multiple_comparison.rb +26 -20
  262. data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
  263. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
  264. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  265. data/lib/rubocop/cop/style/next.rb +44 -0
  266. data/lib/rubocop/cop/style/object_then.rb +14 -15
  267. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  268. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -5
  269. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  270. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  271. data/lib/rubocop/cop/style/proc.rb +2 -2
  272. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  273. data/lib/rubocop/cop/style/raise_args.rb +14 -12
  274. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  275. data/lib/rubocop/cop/style/redundant_begin.rb +2 -1
  276. data/lib/rubocop/cop/style/redundant_condition.rb +59 -2
  277. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +16 -5
  278. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  279. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  280. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  281. data/lib/rubocop/cop/style/redundant_format.rb +257 -0
  282. data/lib/rubocop/cop/style/redundant_freeze.rb +3 -3
  283. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  284. data/lib/rubocop/cop/style/redundant_line_continuation.rb +34 -13
  285. data/lib/rubocop/cop/style/redundant_parentheses.rb +30 -15
  286. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
  287. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  288. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  289. data/lib/rubocop/cop/style/redundant_self.rb +1 -0
  290. data/lib/rubocop/cop/style/redundant_self_assignment.rb +14 -28
  291. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  292. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  293. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  294. data/lib/rubocop/cop/style/rescue_modifier.rb +3 -0
  295. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  296. data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
  297. data/lib/rubocop/cop/style/select_by_regexp.rb +4 -1
  298. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  299. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  300. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  301. data/lib/rubocop/cop/style/single_line_do_end_block.rb +4 -3
  302. data/lib/rubocop/cop/style/single_line_methods.rb +6 -7
  303. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  304. data/lib/rubocop/cop/style/sole_nested_conditional.rb +41 -106
  305. data/lib/rubocop/cop/style/string_concatenation.rb +2 -2
  306. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  307. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  308. data/lib/rubocop/cop/style/super_arguments.rb +66 -19
  309. data/lib/rubocop/cop/style/symbol_proc.rb +2 -0
  310. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  311. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -1
  312. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
  313. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  314. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  315. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  316. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  317. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  318. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  319. data/lib/rubocop/cop/util.rb +12 -5
  320. data/lib/rubocop/cop/utils/format_string.rb +10 -5
  321. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  322. data/lib/rubocop/cop/variable_force/variable.rb +10 -3
  323. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  324. data/lib/rubocop/cop/variable_force.rb +1 -1
  325. data/lib/rubocop/cops_documentation_generator.rb +25 -14
  326. data/lib/rubocop/directive_comment.rb +45 -11
  327. data/lib/rubocop/ext/regexp_node.rb +0 -1
  328. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  329. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  330. data/lib/rubocop/lsp/logger.rb +2 -2
  331. data/lib/rubocop/lsp/routes.rb +7 -23
  332. data/lib/rubocop/lsp/runtime.rb +18 -50
  333. data/lib/rubocop/lsp/server.rb +0 -2
  334. data/lib/rubocop/lsp/stdin_runner.rb +85 -0
  335. data/lib/rubocop/magic_comment.rb +8 -0
  336. data/lib/rubocop/options.rb +28 -12
  337. data/lib/rubocop/path_util.rb +15 -8
  338. data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
  339. data/lib/rubocop/plugin/load_error.rb +26 -0
  340. data/lib/rubocop/plugin/loader.rb +100 -0
  341. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  342. data/lib/rubocop/plugin.rb +46 -0
  343. data/lib/rubocop/rake_task.rb +4 -1
  344. data/lib/rubocop/result_cache.rb +13 -13
  345. data/lib/rubocop/rspec/cop_helper.rb +13 -1
  346. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  347. data/lib/rubocop/rspec/shared_contexts.rb +39 -1
  348. data/lib/rubocop/rspec/support.rb +4 -2
  349. data/lib/rubocop/runner.rb +10 -7
  350. data/lib/rubocop/server/cache.rb +47 -11
  351. data/lib/rubocop/server/cli.rb +2 -2
  352. data/lib/rubocop/target_finder.rb +2 -1
  353. data/lib/rubocop/target_ruby.rb +16 -1
  354. data/lib/rubocop/version.rb +30 -8
  355. data/lib/rubocop.rb +16 -1
  356. data/lib/ruby_lsp/rubocop/addon.rb +75 -0
  357. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +65 -0
  358. metadata +59 -16
  359. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  360. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -0,0 +1,261 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for redundant uses of `to_s`, `to_sym`, `to_i`, `to_f`, `to_d`, `to_r`, `to_c`,
7
+ # `to_a`, `to_h`, and `to_set`.
8
+ #
9
+ # When one of these methods is called on an object of the same type, that object
10
+ # is returned, making the call unnecessary. The cop detects conversion methods called
11
+ # on object literals, class constructors, class `[]` methods, and the `Kernel` methods
12
+ # `String()`, `Integer()`, `Float()`, BigDecimal(), `Rational()`, `Complex()`, and `Array()`.
13
+ #
14
+ # Specifically, these cases are detected for each conversion method:
15
+ #
16
+ # * `to_s` when called on a string literal, interpolated string, heredoc,
17
+ # or with `String.new` or `String()`.
18
+ # * `to_sym` when called on a symbol literal or interpolated symbol.
19
+ # * `to_i` when called on an integer literal or with `Integer()`.
20
+ # * `to_f` when called on a float literal of with `Float()`.
21
+ # * `to_r` when called on a rational literal or with `Rational()`.
22
+ # * `to_c` when called on a complex literal of with `Complex()`.
23
+ # * `to_a` when called on an array literal, or with `Array.new`, `Array()` or `Array[]`.
24
+ # * `to_h` when called on a hash literal, or with `Hash.new`, `Hash()` or `Hash[]`.
25
+ # * `to_set` when called on `Set.new` or `Set[]`.
26
+ #
27
+ # In all cases, chaining one same `to_*` conversion methods listed above is redundant.
28
+ #
29
+ # The cop can also register an offense for chaining conversion methods on methods that are
30
+ # expected to return a specific type regardless of receiver (eg. `foo.inspect.to_s` and
31
+ # `foo.to_json.to_s`).
32
+ #
33
+ # @example
34
+ # # bad
35
+ # "text".to_s
36
+ # :sym.to_sym
37
+ # 42.to_i
38
+ # 8.5.to_f
39
+ # 12r.to_r
40
+ # 1i.to_c
41
+ # [].to_a
42
+ # {}.to_h
43
+ # Set.new.to_set
44
+ #
45
+ # # good
46
+ # "text"
47
+ # :sym
48
+ # 42
49
+ # 8.5
50
+ # 12r
51
+ # 1i
52
+ # []
53
+ # {}
54
+ # Set.new
55
+ #
56
+ # # bad
57
+ # Integer(var).to_i
58
+ #
59
+ # # good
60
+ # Integer(var)
61
+ #
62
+ # # good - chaining to a type constructor with exceptions suppressed
63
+ # # in this case, `Integer()` could return `nil`
64
+ # Integer(var, exception: false).to_i
65
+ #
66
+ # # bad - chaining the same conversion
67
+ # foo.to_s.to_s
68
+ #
69
+ # # good
70
+ # foo.to_s
71
+ #
72
+ # # bad - chaining a conversion to a method that is expected to return the same type
73
+ # foo.inspect.to_s
74
+ # foo.to_json.to_s
75
+ #
76
+ # # good
77
+ # foo.inspect
78
+ # foo.to_json
79
+ #
80
+ class RedundantTypeConversion < Base
81
+ extend AutoCorrector
82
+
83
+ MSG = 'Redundant `%<method>s` detected.'
84
+
85
+ # Maps conversion methods to the node types for the literals of that type
86
+ LITERAL_NODE_TYPES = {
87
+ to_s: %i[str dstr],
88
+ to_sym: %i[sym dsym],
89
+ to_i: %i[int],
90
+ to_f: %i[float],
91
+ to_r: %i[rational],
92
+ to_c: %i[complex],
93
+ to_a: %i[array],
94
+ to_h: %i[hash],
95
+ to_set: [] # sets don't have a literal or node type
96
+ }.freeze
97
+
98
+ # Maps each conversion method to the pattern matcher for that type's constructors
99
+ # Not every type has a constructor, for instance Symbol.
100
+ CONSTRUCTOR_MAPPING = {
101
+ to_s: 'string_constructor?',
102
+ to_i: 'integer_constructor?',
103
+ to_f: 'float_constructor?',
104
+ to_d: 'bigdecimal_constructor?',
105
+ to_r: 'rational_constructor?',
106
+ to_c: 'complex_constructor?',
107
+ to_a: 'array_constructor?',
108
+ to_h: 'hash_constructor?',
109
+ to_set: 'set_constructor?'
110
+ }.freeze
111
+
112
+ # Methods that already are expected to return a given type, which makes a further
113
+ # conversion redundant.
114
+ TYPED_METHODS = { to_s: %i[inspect to_json] }.freeze
115
+
116
+ CONVERSION_METHODS = Set[*LITERAL_NODE_TYPES.keys].freeze
117
+ RESTRICT_ON_SEND = CONVERSION_METHODS + [:to_d]
118
+
119
+ private_constant :LITERAL_NODE_TYPES, :CONSTRUCTOR_MAPPING
120
+
121
+ # @!method type_constructor?(node, type_symbol)
122
+ def_node_matcher :type_constructor?, <<~PATTERN
123
+ (send {nil? (const {cbase nil?} :Kernel)} %1 ...)
124
+ PATTERN
125
+
126
+ # @!method string_constructor?(node)
127
+ def_node_matcher :string_constructor?, <<~PATTERN
128
+ {
129
+ (send (const {cbase nil?} :String) :new ...)
130
+ #type_constructor?(:String)
131
+ }
132
+ PATTERN
133
+
134
+ # @!method integer_constructor?(node)
135
+ def_node_matcher :integer_constructor?, <<~PATTERN
136
+ #type_constructor?(:Integer)
137
+ PATTERN
138
+
139
+ # @!method float_constructor?(node)
140
+ def_node_matcher :float_constructor?, <<~PATTERN
141
+ #type_constructor?(:Float)
142
+ PATTERN
143
+
144
+ # @!method bigdecimal_constructor?(node)
145
+ def_node_matcher :bigdecimal_constructor?, <<~PATTERN
146
+ #type_constructor?(:BigDecimal)
147
+ PATTERN
148
+
149
+ # @!method rational_constructor?(node)
150
+ def_node_matcher :rational_constructor?, <<~PATTERN
151
+ #type_constructor?(:Rational)
152
+ PATTERN
153
+
154
+ # @!method complex_constructor?(node)
155
+ def_node_matcher :complex_constructor?, <<~PATTERN
156
+ #type_constructor?(:Complex)
157
+ PATTERN
158
+
159
+ # @!method array_constructor?(node)
160
+ def_node_matcher :array_constructor?, <<~PATTERN
161
+ {
162
+ (send (const {cbase nil?} :Array) {:new :[]} ...)
163
+ #type_constructor?(:Array)
164
+ }
165
+ PATTERN
166
+
167
+ # @!method hash_constructor?(node)
168
+ def_node_matcher :hash_constructor?, <<~PATTERN
169
+ {
170
+ (block (send (const {cbase nil?} :Hash) :new) ...)
171
+ (send (const {cbase nil?} :Hash) {:new :[]} ...)
172
+ (send {nil? (const {cbase nil?} :Kernel)} :Hash ...)
173
+ }
174
+ PATTERN
175
+
176
+ # @!method set_constructor?(node)
177
+ def_node_matcher :set_constructor?, <<~PATTERN
178
+ {
179
+ (send (const {cbase nil?} :Set) {:new :[]} ...)
180
+ }
181
+ PATTERN
182
+
183
+ # @!method exception_false_keyword_argument?(node)
184
+ def_node_matcher :exception_false_keyword_argument?, <<~PATTERN
185
+ (hash (pair (sym :exception) false))
186
+ PATTERN
187
+
188
+ # rubocop:disable Metrics/AbcSize
189
+ def on_send(node)
190
+ return if hash_or_set_with_block?(node)
191
+
192
+ receiver = find_receiver(node)
193
+ return unless literal_receiver?(node, receiver) ||
194
+ constructor?(node, receiver) ||
195
+ chained_conversion?(node, receiver) ||
196
+ chained_to_typed_method?(node, receiver)
197
+
198
+ message = format(MSG, method: node.method_name)
199
+
200
+ add_offense(node.loc.selector, message: message) do |corrector|
201
+ corrector.remove(node.loc.dot.join(node.loc.selector))
202
+ end
203
+ end
204
+ # rubocop:enable Metrics/AbcSize
205
+ alias on_csend on_send
206
+
207
+ private
208
+
209
+ def hash_or_set_with_block?(node)
210
+ return false if !node.method?(:to_h) && !node.method?(:to_set)
211
+
212
+ node.parent&.any_block_type? || node.last_argument&.block_pass_type?
213
+ end
214
+
215
+ def find_receiver(node)
216
+ receiver = node.receiver
217
+ return unless receiver
218
+
219
+ while receiver.begin_type?
220
+ break unless receiver.children.one?
221
+
222
+ receiver = receiver.children.first
223
+ end
224
+
225
+ receiver
226
+ end
227
+
228
+ def literal_receiver?(node, receiver)
229
+ return false unless receiver
230
+
231
+ receiver.type?(*LITERAL_NODE_TYPES[node.method_name])
232
+ end
233
+
234
+ def constructor?(node, receiver)
235
+ matcher = CONSTRUCTOR_MAPPING[node.method_name]
236
+ return false unless matcher
237
+
238
+ public_send(matcher, receiver) && !constructor_suppresses_exceptions?(receiver)
239
+ end
240
+
241
+ def constructor_suppresses_exceptions?(receiver)
242
+ # If the constructor suppresses exceptions with `exception: false`, it is possible
243
+ # it could return `nil`, and therefore a chained conversion is not redundant.
244
+ receiver.arguments.any? { |arg| exception_false_keyword_argument?(arg) }
245
+ end
246
+
247
+ def chained_conversion?(node, receiver)
248
+ return false unless receiver&.call_type?
249
+
250
+ receiver.method?(node.method_name)
251
+ end
252
+
253
+ def chained_to_typed_method?(node, receiver)
254
+ return false unless receiver&.call_type?
255
+
256
+ TYPED_METHODS.fetch(node.method_name, []).include?(receiver.method_name)
257
+ end
258
+ end
259
+ end
260
+ end
261
+ end
@@ -53,6 +53,7 @@ module RuboCop
53
53
  # rubocop:enable Metrics/AbcSize
54
54
 
55
55
  alias on_numblock on_block
56
+ alias on_itblock on_block
56
57
 
57
58
  private
58
59
 
@@ -64,6 +65,8 @@ module RuboCop
64
65
  (args (arg _)) ...)
65
66
  (numblock
66
67
  $(call _ {:each_with_index :with_index} ...) 1 ...)
68
+ (itblock
69
+ $(call _ {:each_with_index :with_index} ...) _ ...)
67
70
  }
68
71
  PATTERN
69
72
 
@@ -49,6 +49,7 @@ module RuboCop
49
49
  end
50
50
 
51
51
  alias on_numblock on_block
52
+ alias on_itblock on_block
52
53
 
53
54
  private
54
55
 
@@ -59,6 +60,8 @@ module RuboCop
59
60
  $(call _ {:each_with_object :with_object} _) (args (arg _)) ...)
60
61
  (numblock
61
62
  $(call _ {:each_with_object :with_object} _) 1 ...)
63
+ (itblock
64
+ $(call _ {:each_with_object :with_object} _) _ ...)
62
65
  }
63
66
  PATTERN
64
67
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for `rescue` blocks targeting the Exception class.
6
+ # Checks for `rescue` blocks targeting the `Exception` class.
7
7
  #
8
8
  # @example
9
9
  #
@@ -32,25 +32,23 @@ module RuboCop
32
32
  class ReturnInVoidContext < Base
33
33
  MSG = 'Do not return a value in `%<method>s`.'
34
34
 
35
+ # Returning out of these methods only exits the block itself.
36
+ SCOPE_CHANGING_METHODS = %i[lambda define_method define_singleton_method].freeze
37
+
35
38
  def on_return(return_node)
36
39
  return unless return_node.descendants.any?
37
40
 
38
- context_node = non_void_context(return_node)
39
-
40
- return unless context_node&.def_type?
41
- return unless context_node&.void_context?
41
+ def_node = return_node.each_ancestor(:any_def).first
42
+ return unless def_node&.void_context?
43
+ return if return_node.each_ancestor(:any_block).any? do |block_node|
44
+ SCOPE_CHANGING_METHODS.include?(block_node.method_name)
45
+ end
42
46
 
43
47
  add_offense(
44
48
  return_node.loc.keyword,
45
- message: format(message, method: context_node.method_name)
49
+ message: format(message, method: def_node.method_name)
46
50
  )
47
51
  end
48
-
49
- private
50
-
51
- def non_void_context(return_node)
52
- return_node.each_ancestor(:block, :def, :defs).first
53
- end
54
52
  end
55
53
  end
56
54
  end
@@ -33,7 +33,7 @@ module RuboCop
33
33
  def_node_matcher :bad_method?, <<~PATTERN
34
34
  {
35
35
  (send $(csend ...) $_ ...)
36
- (send $({block numblock} (csend ...) ...) $_ ...)
36
+ (send $(any_block (csend ...) ...) $_ ...)
37
37
  }
38
38
  PATTERN
39
39
 
@@ -97,12 +97,19 @@ module RuboCop
97
97
  end
98
98
 
99
99
  def require_parentheses?(send_node)
100
+ return true if operator_inside_hash?(send_node)
100
101
  return false unless send_node.comparison_method?
101
102
  return false unless (node = send_node.parent)
102
103
 
103
104
  (node.respond_to?(:logical_operator?) && node.logical_operator?) ||
104
105
  (node.respond_to?(:comparison_method?) && node.comparison_method?)
105
106
  end
107
+
108
+ def operator_inside_hash?(send_node)
109
+ # If an operator call (without a dot) is inside a hash, it needs
110
+ # to be parenthesized when converted to safe navigation.
111
+ send_node.parent&.pair_type? && !send_node.loc.dot
112
+ end
106
113
  end
107
114
  end
108
115
  end
@@ -56,19 +56,26 @@ module RuboCop
56
56
 
57
57
  outer_local_variable = variable_table.find_variable(variable.name)
58
58
  return unless outer_local_variable
59
+ return if variable_used_in_declaration_of_outer?(variable, outer_local_variable)
59
60
  return if same_conditions_node_different_branch?(variable, outer_local_variable)
60
61
 
61
62
  message = format(MSG, variable: variable.name)
62
63
  add_offense(variable.declaration_node, message: message)
63
64
  end
64
65
 
66
+ private
67
+
68
+ def variable_used_in_declaration_of_outer?(variable, outer_local_variable)
69
+ variable.scope.node.each_ancestor.any?(outer_local_variable.declaration_node)
70
+ end
71
+
65
72
  def same_conditions_node_different_branch?(variable, outer_local_variable)
66
73
  variable_node = variable_node(variable)
67
74
  return false unless node_or_its_ascendant_conditional?(variable_node)
68
75
 
69
76
  outer_local_variable_node =
70
77
  find_conditional_node_from_ascendant(outer_local_variable.declaration_node)
71
- return true unless outer_local_variable_node
78
+ return false unless outer_local_variable_node
72
79
  return false unless outer_local_variable_node.conditional?
73
80
  return true if variable_node == outer_local_variable_node
74
81
 
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for `Hash` creation with a mutable default value.
7
+ # Creating a `Hash` in such a way will share the default value
8
+ # across all keys, causing unexpected behavior when modifying it.
9
+ #
10
+ # For example, when the `Hash` was created with an `Array` as the argument,
11
+ # calling `hash[:foo] << 'bar'` will also change the value of all
12
+ # other keys that have not been explicitly assigned to.
13
+ #
14
+ # @example
15
+ # # bad
16
+ # Hash.new([])
17
+ # Hash.new({})
18
+ # Hash.new(Array.new)
19
+ # Hash.new(Hash.new)
20
+ #
21
+ # # okay -- In rare cases that intentionally have this behavior,
22
+ # # without disabling the cop, you can set the default explicitly.
23
+ # h = Hash.new
24
+ # h.default = []
25
+ # h[:a] << 1
26
+ # h[:b] << 2
27
+ # h # => {:a => [1, 2], :b => [1, 2]}
28
+ #
29
+ # # okay -- beware this will discard mutations and only remember assignments
30
+ # Hash.new { Array.new }
31
+ # Hash.new { Hash.new }
32
+ # Hash.new { {} }
33
+ # Hash.new { [] }
34
+ #
35
+ # # good - frozen solution will raise an error when mutation attempted
36
+ # Hash.new([].freeze)
37
+ # Hash.new({}.freeze)
38
+ #
39
+ # # good - using a proc will create a new object for each key
40
+ # h = Hash.new
41
+ # h.default_proc = ->(h, k) { [] }
42
+ # h.default_proc = ->(h, k) { {} }
43
+ #
44
+ # # good - using a block will create a new object for each key
45
+ # Hash.new { |h, k| h[k] = [] }
46
+ # Hash.new { |h, k| h[k] = {} }
47
+ class SharedMutableDefault < Base
48
+ MSG = 'Do not create a Hash with a mutable default value ' \
49
+ 'as the default value can accidentally be changed.'
50
+ RESTRICT_ON_SEND = %i[new].freeze
51
+
52
+ # @!method hash_initialized_with_mutable_shared_object?(node)
53
+ def_node_matcher :hash_initialized_with_mutable_shared_object?, <<~PATTERN
54
+ {
55
+ (send (const {nil? cbase} :Hash) :new [
56
+ {array hash (send (const {nil? cbase} {:Array :Hash}) :new)}
57
+ !#capacity_keyword_argument?
58
+ ])
59
+ (send (const {nil? cbase} :Hash) :new hash #capacity_keyword_argument?)
60
+ }
61
+ PATTERN
62
+
63
+ # @!method capacity_keyword_argument?(node)
64
+ def_node_matcher :capacity_keyword_argument?, <<~PATTERN
65
+ (hash (pair (sym :capacity) _))
66
+ PATTERN
67
+
68
+ def on_send(node)
69
+ return unless hash_initialized_with_mutable_shared_object?(node)
70
+
71
+ add_offense(node)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -116,7 +116,7 @@ module RuboCop
116
116
  private
117
117
 
118
118
  def comment_between_rescue_and_end?(node)
119
- ancestor = node.each_ancestor(:kwbegin, :def, :defs, :block, :numblock).first
119
+ ancestor = node.each_ancestor(:kwbegin, :any_def, :any_block).first
120
120
  return false unless ancestor
121
121
 
122
122
  end_line = ancestor.loc.end&.line || ancestor.loc.last_line
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for cases where exceptions unrelated to the numeric constructors `Integer()`,
7
+ # `Float()`, `BigDecimal()`, `Complex()`, and `Rational()` may be unintentionally swallowed.
8
+ #
9
+ # @safety
10
+ # The cop is unsafe for autocorrection because unexpected errors occurring in the argument
11
+ # passed to numeric constructor (e.g., `Integer()`) can lead to incompatible behavior.
12
+ # For example, changing it to `Integer(potential_exception_method_call, exception: false)`
13
+ # ensures that exceptions raised by `potential_exception_method_call` are not ignored.
14
+ #
15
+ # [source,ruby]
16
+ # ----
17
+ # Integer(potential_exception_method_call) rescue nil
18
+ # ----
19
+ #
20
+ # @example
21
+ #
22
+ # # bad
23
+ # Integer(arg) rescue nil
24
+ #
25
+ # # bad
26
+ # begin
27
+ # Integer(arg)
28
+ # rescue
29
+ # nil
30
+ # end
31
+ #
32
+ # # bad
33
+ # begin
34
+ # Integer(arg)
35
+ # rescue
36
+ # end
37
+ #
38
+ # # good
39
+ # Integer(arg, exception: false)
40
+ #
41
+ class SuppressedExceptionInNumberConversion < Base
42
+ extend AutoCorrector
43
+ extend TargetRubyVersion
44
+
45
+ MSG = 'Use `%<prefer>s` instead.'
46
+ EXPECTED_EXCEPTION_CLASSES = %w[ArgumentError TypeError ::ArgumentError ::TypeError].freeze
47
+
48
+ # @!method numeric_constructor_rescue_nil(node)
49
+ def_node_matcher :numeric_constructor_rescue_nil, <<~PATTERN
50
+ (rescue
51
+ $#numeric_method?
52
+ (resbody nil? nil? (nil)) nil?)
53
+ PATTERN
54
+
55
+ # @!method begin_numeric_constructor_rescue_nil(node)
56
+ def_node_matcher :begin_numeric_constructor_rescue_nil, <<~PATTERN
57
+ (kwbegin
58
+ (rescue
59
+ $#numeric_method?
60
+ (resbody $_? nil?
61
+ {(nil) nil?}) nil?))
62
+ PATTERN
63
+
64
+ # @!method numeric_method?(node)
65
+ def_node_matcher :numeric_method?, <<~PATTERN
66
+ {
67
+ (call #constructor_receiver? {:Integer :BigDecimal :Complex :Rational}
68
+ _ _?)
69
+ (call #constructor_receiver? :Float
70
+ _)
71
+ }
72
+ PATTERN
73
+
74
+ # @!method constructor_receiver?(node)
75
+ def_node_matcher :constructor_receiver?, <<~PATTERN
76
+ {nil? (const {nil? cbase} :Kernel)}
77
+ PATTERN
78
+
79
+ minimum_target_ruby_version 2.6
80
+
81
+ # rubocop:disable Metrics/AbcSize
82
+ def on_rescue(node)
83
+ if (method, exception_classes = begin_numeric_constructor_rescue_nil(node.parent))
84
+ return unless expected_exception_classes_only?(exception_classes)
85
+
86
+ node = node.parent
87
+ else
88
+ return unless (method = numeric_constructor_rescue_nil(node))
89
+ end
90
+
91
+ arguments = method.arguments.map(&:source) << 'exception: false'
92
+ prefer = "#{method.method_name}(#{arguments.join(', ')})"
93
+ prefer = "#{method.receiver.source}#{method.loc.dot.source}#{prefer}" if method.receiver
94
+
95
+ add_offense(node, message: format(MSG, prefer: prefer)) do |corrector|
96
+ corrector.replace(node, prefer)
97
+ end
98
+ end
99
+ # rubocop:enable Metrics/AbcSize
100
+
101
+ private
102
+
103
+ def expected_exception_classes_only?(exception_classes)
104
+ return true unless (arguments = exception_classes.first)
105
+
106
+ (arguments.values.map(&:source) - EXPECTED_EXCEPTION_CLASSES).none?
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -78,7 +78,7 @@ module RuboCop
78
78
  def on_send(node)
79
79
  return unless node.receiver
80
80
 
81
- if node.receiver.str_type? || node.receiver.sym_type?
81
+ if node.receiver.type?(:str, :sym)
82
82
  register_offense(node, correction: node.receiver.value.to_sym.inspect)
83
83
  elsif node.receiver.dstr_type?
84
84
  register_offense(node, correction: ":\"#{node.receiver.value.to_sym}\"")
@@ -6,9 +6,12 @@ module RuboCop
6
6
  # Repacks Parser's diagnostics/errors
7
7
  # into RuboCop's offenses.
8
8
  class Syntax < Base
9
+ LEVELS = %i[error fatal].freeze
10
+
9
11
  def on_other_file
10
12
  add_offense_from_error(processed_source.parser_error) if processed_source.parser_error
11
- processed_source.diagnostics.each do |diagnostic|
13
+ syntax_errors = processed_source.diagnostics.select { |d| LEVELS.include?(d.level) }
14
+ syntax_errors.each do |diagnostic|
12
15
  add_offense_from_diagnostic(diagnostic, processed_source.ruby_version)
13
16
  end
14
17
  super
@@ -45,7 +45,7 @@ module RuboCop
45
45
  PATTERN
46
46
 
47
47
  def on_send(node)
48
- def_node = node.each_ancestor(:def, :defs).first
48
+ def_node = node.each_ancestor(:any_def).first
49
49
  return unless def_node
50
50
 
51
51
  enum_conversion_call?(node) do |method_node, arguments|
@@ -40,7 +40,7 @@ module RuboCop
40
40
  # top-level return node's ancestors should not be of block, def, or
41
41
  # defs type.
42
42
  def top_level_return?(return_node)
43
- return_node.each_ancestor(:block, :def, :defs).none?
43
+ return_node.each_ancestor(:block, :any_def).none?
44
44
  end
45
45
  end
46
46
  end
@@ -55,12 +55,9 @@ module RuboCop
55
55
  return if node.each_descendant(:dstr).any?
56
56
 
57
57
  regexp_constructor(node) do |text|
58
- Regexp::Parser.parse(text.value)&.each_expression do |expr|
58
+ parse_regexp(text.value)&.each_expression do |expr|
59
59
  detect_offenses(text, expr)
60
60
  end
61
- rescue Regexp::Parser::Error
62
- # Upon encountering an invalid regular expression,
63
- # we aim to proceed and identify any remaining potential offenses.
64
61
  end
65
62
  end
66
63
 
@@ -53,6 +53,7 @@ module RuboCop
53
53
  end
54
54
 
55
55
  alias on_numblock on_block
56
+ alias on_itblock on_block
56
57
 
57
58
  private
58
59
 
@@ -74,6 +75,7 @@ module RuboCop
74
75
 
75
76
  def arg_count(node)
76
77
  return node.children[1] if node.numblock_type? # the maximum numbered param for the block
78
+ return 1 if node.itblock_type? # `it` block parameter is always one
77
79
 
78
80
  # Only `arg`, `optarg` and `mlhs` (destructuring) count as arguments that
79
81
  # can be used. Keyword arguments are not used for these methods so are
@@ -81,7 +83,7 @@ module RuboCop
81
83
  node.arguments.count do |arg|
82
84
  return Float::INFINITY if arg.restarg_type?
83
85
 
84
- arg.arg_type? || arg.optarg_type? || arg.mlhs_type?
86
+ arg.type?(:arg, :optarg, :mlhs)
85
87
  end
86
88
  end
87
89
  end