rubocop 1.71.1 → 1.92.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (712) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +23 -19
  4. data/config/default.yml +886 -168
  5. data/config/internal_affairs.yml +20 -0
  6. data/config/obsoletion.yml +47 -4
  7. data/exe/rubocop +2 -9
  8. data/lib/rubocop/cache_config.rb +29 -0
  9. data/lib/rubocop/cached_data.rb +50 -5
  10. data/lib/rubocop/changed_files.rb +134 -0
  11. data/lib/rubocop/cli/command/auto_generate_config.rb +36 -4
  12. data/lib/rubocop/cli/command/cop_names.rb +57 -0
  13. data/lib/rubocop/cli/command/execute_runner.rb +54 -3
  14. data/lib/rubocop/cli/command/explain.rb +34 -0
  15. data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
  16. data/lib/rubocop/cli/command/lsp.rb +1 -1
  17. data/lib/rubocop/cli/command/mcp.rb +19 -0
  18. data/lib/rubocop/cli/command/show_cops.rb +8 -2
  19. data/lib/rubocop/cli/command/show_docs_url.rb +8 -10
  20. data/lib/rubocop/cli/command/suggest_extensions.rb +8 -2
  21. data/lib/rubocop/cli.rb +59 -17
  22. data/lib/rubocop/comment_config/directive_range.rb +34 -0
  23. data/lib/rubocop/comment_config/disable_next.rb +143 -0
  24. data/lib/rubocop/comment_config/push_pop.rb +55 -0
  25. data/lib/rubocop/comment_config.rb +98 -45
  26. data/lib/rubocop/config.rb +137 -19
  27. data/lib/rubocop/config_finder.rb +1 -1
  28. data/lib/rubocop/config_loader.rb +75 -49
  29. data/lib/rubocop/config_loader_resolver.rb +124 -33
  30. data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
  31. data/lib/rubocop/config_obsoletion/extracted_cop.rb +6 -3
  32. data/lib/rubocop/config_obsoletion/removed_cop.rb +9 -1
  33. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  34. data/lib/rubocop/config_obsoletion.rb +47 -3
  35. data/lib/rubocop/config_store.rb +7 -2
  36. data/lib/rubocop/config_validator.rb +75 -12
  37. data/lib/rubocop/cop/autocorrect_logic.rb +43 -17
  38. data/lib/rubocop/cop/badge.rb +10 -2
  39. data/lib/rubocop/cop/base.rb +128 -35
  40. data/lib/rubocop/cop/bundler/gem_comment.rb +5 -4
  41. data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
  42. data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -11
  43. data/lib/rubocop/cop/bundler.rb +19 -0
  44. data/lib/rubocop/cop/commissioner.rb +13 -11
  45. data/lib/rubocop/cop/cop_documentation.rb +81 -0
  46. data/lib/rubocop/cop/cop_explanation.rb +140 -0
  47. data/lib/rubocop/cop/corrector.rb +4 -4
  48. data/lib/rubocop/cop/correctors/alignment_corrector.rb +92 -11
  49. data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
  50. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +37 -7
  51. data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
  52. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
  53. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +31 -4
  54. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +35 -5
  55. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +8 -1
  56. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +73 -2
  57. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  58. data/lib/rubocop/cop/correctors.rb +28 -0
  59. data/lib/rubocop/cop/documentation.rb +3 -4
  60. data/lib/rubocop/cop/exclude_limit.rb +31 -5
  61. data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
  62. data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
  63. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  64. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +49 -17
  65. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +2 -9
  66. data/lib/rubocop/cop/gemspec/require_mfa.rb +22 -5
  67. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +12 -7
  68. data/lib/rubocop/cop/gemspec.rb +22 -0
  69. data/lib/rubocop/cop/generator/registration_injector.rb +188 -0
  70. data/lib/rubocop/cop/generator.rb +5 -1
  71. data/lib/rubocop/cop/internal_affairs/example_description.rb +9 -5
  72. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
  73. data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
  74. data/lib/rubocop/cop/internal_affairs/location_exists.rb +142 -0
  75. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
  76. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +16 -20
  77. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  78. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -2
  79. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +6 -2
  80. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +85 -0
  81. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +2 -2
  82. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  83. data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
  84. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  85. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
  86. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
  87. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +13 -2
  88. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
  89. data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
  90. data/lib/rubocop/cop/internal_affairs.rb +3 -16
  91. data/lib/rubocop/cop/layout/argument_alignment.rb +9 -3
  92. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  93. data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
  94. data/lib/rubocop/cop/layout/block_alignment.rb +86 -4
  95. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  96. data/lib/rubocop/cop/layout/case_indentation.rb +28 -10
  97. data/lib/rubocop/cop/layout/class_structure.rb +191 -41
  98. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
  99. data/lib/rubocop/cop/layout/comment_indentation.rb +17 -7
  100. data/lib/rubocop/cop/layout/condition_position.rb +13 -3
  101. data/lib/rubocop/cop/layout/def_end_alignment.rb +5 -1
  102. data/lib/rubocop/cop/layout/dot_position.rb +27 -17
  103. data/lib/rubocop/cop/layout/else_alignment.rb +3 -15
  104. data/lib/rubocop/cop/layout/empty_comment.rb +8 -10
  105. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +27 -9
  106. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +63 -5
  107. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +21 -8
  108. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +46 -21
  109. data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
  110. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
  111. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +34 -4
  112. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
  113. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +2 -0
  114. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +22 -5
  115. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +17 -3
  116. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
  117. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
  118. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
  119. data/lib/rubocop/cop/layout/end_alignment.rb +23 -15
  120. data/lib/rubocop/cop/layout/extra_spacing.rb +109 -3
  121. data/lib/rubocop/cop/layout/first_argument_indentation.rb +82 -3
  122. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +18 -5
  123. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +41 -0
  124. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +36 -23
  125. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
  126. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
  127. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
  128. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +11 -0
  129. data/lib/rubocop/cop/layout/hash_alignment.rb +20 -18
  130. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +9 -5
  131. data/lib/rubocop/cop/layout/heredoc_indentation.rb +48 -3
  132. data/lib/rubocop/cop/layout/indentation_consistency.rb +22 -5
  133. data/lib/rubocop/cop/layout/indentation_style.rb +5 -2
  134. data/lib/rubocop/cop/layout/indentation_width.rb +159 -12
  135. data/lib/rubocop/cop/layout/leading_comment_space.rb +40 -1
  136. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +10 -4
  137. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
  138. data/lib/rubocop/cop/layout/line_length.rb +300 -31
  139. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +69 -57
  140. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +8 -2
  141. data/lib/rubocop/cop/layout/multiline_block_layout.rb +11 -1
  142. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +65 -56
  143. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +7 -1
  144. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +270 -40
  145. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
  146. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  147. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +9 -5
  148. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  149. data/lib/rubocop/cop/layout/redundant_line_break.rb +111 -7
  150. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +29 -9
  151. data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
  152. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  153. data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
  154. data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
  155. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +10 -4
  156. data/lib/rubocop/cop/layout/space_around_keyword.rb +20 -3
  157. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  158. data/lib/rubocop/cop/layout/space_around_operators.rb +30 -4
  159. data/lib/rubocop/cop/layout/space_before_block_braces.rb +5 -1
  160. data/lib/rubocop/cop/layout/space_before_brackets.rb +6 -39
  161. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
  162. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +55 -36
  163. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +32 -8
  164. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
  165. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +2 -12
  166. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  167. data/lib/rubocop/cop/layout.rb +114 -0
  168. data/lib/rubocop/cop/lazy_loader.rb +41 -0
  169. data/lib/rubocop/cop/lint/ambiguous_assignment.rb +9 -17
  170. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +72 -1
  171. data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
  172. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +3 -11
  173. data/lib/rubocop/cop/lint/ambiguous_range.rb +6 -2
  174. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +6 -1
  175. data/lib/rubocop/cop/lint/argument_mismatch.rb +99 -0
  176. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
  177. data/lib/rubocop/cop/lint/assignment_in_condition.rb +15 -1
  178. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  179. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -8
  180. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +4 -3
  181. data/lib/rubocop/cop/lint/constant_reassignment.rb +94 -15
  182. data/lib/rubocop/cop/lint/constant_resolution.rb +31 -6
  183. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +240 -0
  184. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  185. data/lib/rubocop/cop/lint/debugger.rb +13 -4
  186. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  187. data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
  188. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +5 -2
  189. data/lib/rubocop/cop/lint/deprecated_reference.rb +194 -0
  190. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  191. data/lib/rubocop/cop/lint/duplicate_methods.rb +506 -41
  192. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
  193. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  194. data/lib/rubocop/cop/lint/empty_block.rb +4 -4
  195. data/lib/rubocop/cop/lint/empty_conditional_body.rb +22 -65
  196. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  197. data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
  198. data/lib/rubocop/cop/lint/empty_interpolation.rb +14 -1
  199. data/lib/rubocop/cop/lint/empty_when.rb +8 -1
  200. data/lib/rubocop/cop/lint/ensure_return.rb +19 -1
  201. data/lib/rubocop/cop/lint/erb_new_arguments.rb +4 -8
  202. data/lib/rubocop/cop/lint/float_comparison.rb +33 -10
  203. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  204. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +4 -0
  205. data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
  206. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -2
  207. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
  208. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -2
  209. data/lib/rubocop/cop/lint/inherit_exception.rb +53 -7
  210. data/lib/rubocop/cop/lint/interpolation_check.rb +25 -6
  211. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  212. data/lib/rubocop/cop/lint/literal_as_condition.rb +152 -11
  213. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
  214. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +75 -37
  215. data/lib/rubocop/cop/lint/loop.rb +24 -2
  216. data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +245 -0
  217. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +60 -23
  218. data/lib/rubocop/cop/lint/missing_super.rb +31 -1
  219. data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -2
  220. data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
  221. data/lib/rubocop/cop/lint/name_typo.rb +270 -0
  222. data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
  223. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  224. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +20 -0
  225. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +4 -2
  226. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +4 -4
  227. data/lib/rubocop/cop/lint/number_conversion.rb +22 -11
  228. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  229. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +11 -0
  230. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  231. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
  232. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +15 -4
  233. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +20 -14
  234. data/lib/rubocop/cop/lint/raise_exception.rb +30 -11
  235. data/lib/rubocop/cop/lint/rand_one.rb +1 -1
  236. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +160 -39
  237. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +53 -19
  238. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +28 -6
  239. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  240. data/lib/rubocop/cop/lint/redundant_require_statement.rb +5 -25
  241. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +134 -12
  242. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +13 -4
  243. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +267 -0
  244. data/lib/rubocop/cop/lint/redundant_with_index.rb +5 -3
  245. data/lib/rubocop/cop/lint/redundant_with_object.rb +8 -0
  246. data/lib/rubocop/cop/lint/refinement_import_methods.rb +8 -1
  247. data/lib/rubocop/cop/lint/regexp_as_condition.rb +9 -1
  248. data/lib/rubocop/cop/lint/require_parentheses.rb +13 -4
  249. data/lib/rubocop/cop/lint/require_range_parentheses.rb +3 -2
  250. data/lib/rubocop/cop/lint/require_relative_self_path.rb +7 -5
  251. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  252. data/lib/rubocop/cop/lint/rescue_type.rb +2 -2
  253. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  254. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +28 -4
  255. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +56 -6
  256. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
  257. data/lib/rubocop/cop/lint/script_permission.rb +5 -1
  258. data/lib/rubocop/cop/lint/self_assignment.rb +63 -6
  259. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -1
  260. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  261. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  262. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +27 -1
  263. data/lib/rubocop/cop/lint/shared_mutable_default.rb +14 -1
  264. data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
  265. data/lib/rubocop/cop/lint/super_argument_mismatch.rb +179 -0
  266. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  267. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +122 -0
  268. data/lib/rubocop/cop/lint/symbol_conversion.rb +22 -4
  269. data/lib/rubocop/cop/lint/syntax.rb +25 -1
  270. data/lib/rubocop/cop/lint/to_enum_arguments.rb +73 -5
  271. data/lib/rubocop/cop/lint/to_json.rb +20 -17
  272. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  273. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +5 -1
  274. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +54 -11
  275. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +2 -0
  276. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -1
  277. data/lib/rubocop/cop/lint/unreachable_code.rb +16 -9
  278. data/lib/rubocop/cop/lint/unreachable_loop.rb +5 -5
  279. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  280. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  281. data/lib/rubocop/cop/lint/unused_private_method.rb +234 -0
  282. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
  283. data/lib/rubocop/cop/lint/useless_access_modifier.rb +31 -6
  284. data/lib/rubocop/cop/lint/useless_assignment.rb +63 -27
  285. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +107 -0
  286. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +92 -0
  287. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  288. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +11 -10
  289. data/lib/rubocop/cop/lint/useless_or.rb +111 -0
  290. data/lib/rubocop/cop/lint/useless_rescue.rb +2 -3
  291. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +13 -7
  292. data/lib/rubocop/cop/lint/useless_setter_call.rb +11 -5
  293. data/lib/rubocop/cop/lint/useless_times.rb +22 -1
  294. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +201 -0
  295. data/lib/rubocop/cop/lint/void.rb +68 -22
  296. data/lib/rubocop/cop/lint.rb +179 -0
  297. data/lib/rubocop/cop/message_annotator.rb +7 -3
  298. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  299. data/lib/rubocop/cop/metrics/block_length.rb +2 -1
  300. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  301. data/lib/rubocop/cop/metrics/class_length.rb +4 -2
  302. data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
  303. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
  304. data/lib/rubocop/cop/metrics/method_length.rb +3 -2
  305. data/lib/rubocop/cop/metrics/module_length.rb +4 -2
  306. data/lib/rubocop/cop/metrics/perceived_complexity.rb +37 -7
  307. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  308. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
  309. data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
  310. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  311. data/lib/rubocop/cop/metrics.rb +31 -0
  312. data/lib/rubocop/cop/migration/department_name.rb +11 -5
  313. data/lib/rubocop/cop/migration.rb +13 -0
  314. data/lib/rubocop/cop/mixin/alignment.rb +7 -3
  315. data/lib/rubocop/cop/mixin/allowed_methods.rb +5 -5
  316. data/lib/rubocop/cop/mixin/allowed_pattern.rb +9 -5
  317. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  318. data/lib/rubocop/cop/mixin/check_line_breakable.rb +50 -28
  319. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +13 -9
  320. data/lib/rubocop/cop/mixin/code_length.rb +10 -2
  321. data/lib/rubocop/cop/mixin/comments_help.rb +2 -3
  322. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -2
  323. data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
  324. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  325. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +13 -2
  326. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
  327. data/lib/rubocop/cop/mixin/endless_method_body_help.rb +105 -0
  328. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +13 -5
  329. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  330. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +20 -0
  331. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -2
  332. data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
  333. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +68 -21
  334. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +52 -25
  335. data/lib/rubocop/cop/mixin/hash_subset.rb +28 -6
  336. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  337. data/lib/rubocop/cop/mixin/hash_transform_method.rb +32 -78
  338. data/lib/rubocop/cop/mixin/indexed_method_arity.rb +94 -0
  339. data/lib/rubocop/cop/mixin/line_length_help.rb +52 -11
  340. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  341. data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
  342. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
  343. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -1
  344. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +10 -1
  345. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +2 -2
  346. data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
  347. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  348. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +79 -8
  349. data/lib/rubocop/cop/mixin/project_index_help.rb +203 -0
  350. data/lib/rubocop/cop/mixin/range_help.rb +16 -5
  351. data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +181 -0
  352. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  353. data/lib/rubocop/cop/mixin/statement_modifier.rb +69 -12
  354. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  355. data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
  356. data/lib/rubocop/cop/mixin/trailing_comma.rb +23 -6
  357. data/lib/rubocop/cop/mixin/visibility_help.rb +2 -1
  358. data/lib/rubocop/cop/mixin.rb +93 -0
  359. data/lib/rubocop/cop/naming/accessor_method_name.rb +8 -0
  360. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +17 -1
  361. data/lib/rubocop/cop/naming/block_forwarding.rb +7 -4
  362. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  363. data/lib/rubocop/cop/naming/file_name.rb +6 -5
  364. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
  365. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
  366. data/lib/rubocop/cop/naming/inclusive_language.rb +8 -2
  367. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +13 -6
  368. data/lib/rubocop/cop/naming/method_name.rb +190 -15
  369. data/lib/rubocop/cop/naming/predicate_method.rb +330 -0
  370. data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +65 -8
  371. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +12 -7
  372. data/lib/rubocop/cop/naming/variable_name.rb +51 -6
  373. data/lib/rubocop/cop/naming/variable_number.rb +3 -1
  374. data/lib/rubocop/cop/naming.rb +31 -0
  375. data/lib/rubocop/cop/offense.rb +108 -9
  376. data/lib/rubocop/cop/registry.rb +234 -65
  377. data/lib/rubocop/cop/security/eval.rb +17 -3
  378. data/lib/rubocop/cop/security/io_methods.rb +2 -2
  379. data/lib/rubocop/cop/security/json_load.rb +45 -11
  380. data/lib/rubocop/cop/security/marshal_load.rb +1 -1
  381. data/lib/rubocop/cop/security/open.rb +1 -0
  382. data/lib/rubocop/cop/security.rb +19 -0
  383. data/lib/rubocop/cop/severity.rb +12 -0
  384. data/lib/rubocop/cop/style/access_modifier_declarations.rb +83 -14
  385. data/lib/rubocop/cop/style/accessor_grouping.rb +47 -10
  386. data/lib/rubocop/cop/style/alias.rb +33 -8
  387. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
  388. data/lib/rubocop/cop/style/and_or.rb +8 -3
  389. data/lib/rubocop/cop/style/arguments_forwarding.rb +80 -39
  390. data/lib/rubocop/cop/style/array_first_last.rb +13 -3
  391. data/lib/rubocop/cop/style/array_intersect.rb +136 -38
  392. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +50 -0
  393. data/lib/rubocop/cop/style/array_join.rb +4 -2
  394. data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
  395. data/lib/rubocop/cop/style/attr.rb +8 -6
  396. data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
  397. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  398. data/lib/rubocop/cop/style/bitwise_predicate.rb +13 -5
  399. data/lib/rubocop/cop/style/block_delimiters.rb +77 -40
  400. data/lib/rubocop/cop/style/case_equality.rb +29 -15
  401. data/lib/rubocop/cop/style/case_like_if.rb +12 -11
  402. data/lib/rubocop/cop/style/character_literal.rb +2 -2
  403. data/lib/rubocop/cop/style/class_and_module_children.rb +181 -27
  404. data/lib/rubocop/cop/style/class_equality_comparison.rb +22 -14
  405. data/lib/rubocop/cop/style/class_methods_definitions.rb +26 -5
  406. data/lib/rubocop/cop/style/collection_compact.rb +37 -17
  407. data/lib/rubocop/cop/style/collection_methods.rb +1 -0
  408. data/lib/rubocop/cop/style/collection_querying.rb +200 -0
  409. data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
  410. data/lib/rubocop/cop/style/combinable_loops.rb +92 -9
  411. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  412. data/lib/rubocop/cop/style/commented_keyword.rb +12 -5
  413. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  414. data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
  415. data/lib/rubocop/cop/style/concat_array_literals.rb +65 -9
  416. data/lib/rubocop/cop/style/conditional_assignment.rb +58 -24
  417. data/lib/rubocop/cop/style/constant_visibility.rb +23 -12
  418. data/lib/rubocop/cop/style/copyright.rb +27 -12
  419. data/lib/rubocop/cop/style/data_inheritance.rb +25 -0
  420. data/lib/rubocop/cop/style/date_time.rb +4 -4
  421. data/lib/rubocop/cop/style/def_with_parentheses.rb +22 -5
  422. data/lib/rubocop/cop/style/dig_chain.rb +6 -1
  423. data/lib/rubocop/cop/style/dir_empty.rb +4 -0
  424. data/lib/rubocop/cop/style/directive_scope.rb +304 -0
  425. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +184 -20
  426. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
  427. data/lib/rubocop/cop/style/documentation.rb +53 -6
  428. data/lib/rubocop/cop/style/documentation_method.rb +8 -12
  429. data/lib/rubocop/cop/style/double_negation.rb +14 -3
  430. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  431. data/lib/rubocop/cop/style/each_with_object.rb +4 -3
  432. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  433. data/lib/rubocop/cop/style/empty_case_condition.rb +13 -4
  434. data/lib/rubocop/cop/style/empty_class_definition.rb +126 -0
  435. data/lib/rubocop/cop/style/empty_heredoc.rb +4 -0
  436. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  437. data/lib/rubocop/cop/style/empty_literal.rb +12 -3
  438. data/lib/rubocop/cop/style/empty_method.rb +15 -9
  439. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +152 -0
  440. data/lib/rubocop/cop/style/encoding.rb +7 -1
  441. data/lib/rubocop/cop/style/end_block.rb +3 -1
  442. data/lib/rubocop/cop/style/endless_method.rb +256 -19
  443. data/lib/rubocop/cop/style/env_home.rb +4 -0
  444. data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
  445. data/lib/rubocop/cop/style/even_odd.rb +11 -1
  446. data/lib/rubocop/cop/style/exact_regexp_match.rb +52 -8
  447. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  448. data/lib/rubocop/cop/style/explicit_block_argument.rb +62 -9
  449. data/lib/rubocop/cop/style/exponential_notation.rb +5 -4
  450. data/lib/rubocop/cop/style/fetch_env_var.rb +33 -7
  451. data/lib/rubocop/cop/style/file_null.rb +6 -4
  452. data/lib/rubocop/cop/style/file_open.rb +84 -0
  453. data/lib/rubocop/cop/style/file_write.rb +21 -16
  454. data/lib/rubocop/cop/style/float_division.rb +43 -15
  455. data/lib/rubocop/cop/style/for.rb +61 -1
  456. data/lib/rubocop/cop/style/format_string.rb +44 -9
  457. data/lib/rubocop/cop/style/format_string_token.rb +86 -16
  458. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +5 -3
  459. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  460. data/lib/rubocop/cop/style/global_vars.rb +5 -2
  461. data/lib/rubocop/cop/style/guard_clause.rb +58 -40
  462. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +31 -9
  463. data/lib/rubocop/cop/style/hash_conversion.rb +52 -16
  464. data/lib/rubocop/cop/style/hash_each_methods.rb +4 -4
  465. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  466. data/lib/rubocop/cop/style/hash_lookup_method.rb +128 -0
  467. data/lib/rubocop/cop/style/hash_slice.rb +16 -0
  468. data/lib/rubocop/cop/style/hash_syntax.rb +23 -6
  469. data/lib/rubocop/cop/style/hash_transform_keys.rb +19 -9
  470. data/lib/rubocop/cop/style/hash_transform_values.rb +19 -9
  471. data/lib/rubocop/cop/style/identical_conditional_branches.rb +39 -11
  472. data/lib/rubocop/cop/style/if_inside_else.rb +46 -21
  473. data/lib/rubocop/cop/style/if_unless_modifier.rb +101 -70
  474. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +19 -19
  475. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -2
  476. data/lib/rubocop/cop/style/if_with_semicolon.rb +61 -8
  477. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  478. data/lib/rubocop/cop/style/inline_comment.rb +5 -2
  479. data/lib/rubocop/cop/style/inverse_methods.rb +34 -8
  480. data/lib/rubocop/cop/style/invertible_unless_condition.rb +27 -7
  481. data/lib/rubocop/cop/style/ip_addresses.rb +3 -4
  482. data/lib/rubocop/cop/style/it_assignment.rb +69 -12
  483. data/lib/rubocop/cop/style/it_block_parameter.rb +211 -0
  484. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +4 -0
  485. data/lib/rubocop/cop/style/keyword_parameters_order.rb +23 -11
  486. data/lib/rubocop/cop/style/lambda.rb +46 -2
  487. data/lib/rubocop/cop/style/lambda_call.rb +31 -10
  488. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  489. data/lib/rubocop/cop/style/magic_comment_format.rb +4 -4
  490. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +11 -0
  491. data/lib/rubocop/cop/style/map_into_array.rb +6 -4
  492. data/lib/rubocop/cop/style/map_join.rb +123 -0
  493. data/lib/rubocop/cop/style/map_to_hash.rb +13 -5
  494. data/lib/rubocop/cop/style/map_to_set.rb +1 -3
  495. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +110 -27
  496. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
  497. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +58 -6
  498. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +36 -8
  499. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -1
  500. data/lib/rubocop/cop/style/method_def_parentheses.rb +36 -8
  501. data/lib/rubocop/cop/style/min_max_comparison.rb +17 -6
  502. data/lib/rubocop/cop/style/missing_else.rb +7 -1
  503. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +40 -7
  504. data/lib/rubocop/cop/style/mixin_grouping.rb +12 -3
  505. data/lib/rubocop/cop/style/mixin_usage.rb +1 -1
  506. data/lib/rubocop/cop/style/module_function.rb +4 -2
  507. data/lib/rubocop/cop/style/module_member_existence_check.rb +110 -0
  508. data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -1
  509. data/lib/rubocop/cop/style/multiline_if_modifier.rb +47 -5
  510. data/lib/rubocop/cop/style/multiline_if_then.rb +10 -4
  511. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
  512. data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
  513. data/lib/rubocop/cop/style/multiline_method_signature.rb +15 -22
  514. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
  515. data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
  516. data/lib/rubocop/cop/style/multiple_comparison.rb +33 -22
  517. data/lib/rubocop/cop/style/mutable_constant.rb +158 -14
  518. data/lib/rubocop/cop/style/negated_if_else_condition.rb +3 -3
  519. data/lib/rubocop/cop/style/negative_array_index.rb +228 -0
  520. data/lib/rubocop/cop/style/nested_modifier.rb +36 -12
  521. data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
  522. data/lib/rubocop/cop/style/next.rb +68 -10
  523. data/lib/rubocop/cop/style/nil_comparison.rb +53 -13
  524. data/lib/rubocop/cop/style/nil_lambda.rb +9 -1
  525. data/lib/rubocop/cop/style/non_nil_check.rb +21 -11
  526. data/lib/rubocop/cop/style/not.rb +12 -3
  527. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
  528. data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
  529. data/lib/rubocop/cop/style/numeric_predicate.rb +22 -6
  530. data/lib/rubocop/cop/style/object_then.rb +1 -0
  531. data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
  532. data/lib/rubocop/cop/style/one_line_conditional.rb +35 -15
  533. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  534. data/lib/rubocop/cop/style/operator_method_call.rb +10 -2
  535. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  536. data/lib/rubocop/cop/style/optional_arguments.rb +1 -0
  537. data/lib/rubocop/cop/style/parallel_assignment.rb +58 -27
  538. data/lib/rubocop/cop/style/parentheses_around_condition.rb +7 -2
  539. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  540. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +18 -3
  541. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  542. data/lib/rubocop/cop/style/perl_backrefs.rb +5 -3
  543. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  544. data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
  545. data/lib/rubocop/cop/style/proc.rb +4 -2
  546. data/lib/rubocop/cop/style/raise_args.rb +28 -18
  547. data/lib/rubocop/cop/style/reduce_to_hash.rb +216 -0
  548. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  549. data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
  550. data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
  551. data/lib/rubocop/cop/style/redundant_assignment.rb +12 -2
  552. data/lib/rubocop/cop/style/redundant_begin.rb +60 -7
  553. data/lib/rubocop/cop/style/redundant_condition.rb +93 -18
  554. data/lib/rubocop/cop/style/redundant_constant_base.rb +42 -6
  555. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +26 -4
  556. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +17 -3
  557. data/lib/rubocop/cop/style/redundant_each.rb +4 -5
  558. data/lib/rubocop/cop/style/redundant_exception.rb +22 -4
  559. data/lib/rubocop/cop/style/redundant_fetch_block.rb +11 -11
  560. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +9 -0
  561. data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
  562. data/lib/rubocop/cop/style/redundant_format.rb +319 -0
  563. data/lib/rubocop/cop/style/redundant_freeze.rb +13 -5
  564. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +6 -1
  565. data/lib/rubocop/cop/style/redundant_interpolation.rb +12 -3
  566. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +49 -10
  567. data/lib/rubocop/cop/style/redundant_line_continuation.rb +83 -119
  568. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  569. data/lib/rubocop/cop/style/redundant_parentheses.rb +176 -83
  570. data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
  571. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +15 -0
  572. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
  573. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +27 -7
  574. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +16 -0
  575. data/lib/rubocop/cop/style/redundant_return.rb +4 -3
  576. data/lib/rubocop/cop/style/redundant_self.rb +20 -7
  577. data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -3
  578. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +27 -4
  579. data/lib/rubocop/cop/style/redundant_sort.rb +45 -11
  580. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  581. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -2
  582. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +133 -0
  583. data/lib/rubocop/cop/style/regexp_literal.rb +107 -29
  584. data/lib/rubocop/cop/style/require_order.rb +25 -8
  585. data/lib/rubocop/cop/style/rescue_modifier.rb +16 -12
  586. data/lib/rubocop/cop/style/return_nil.rb +19 -4
  587. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
  588. data/lib/rubocop/cop/style/reverse_find.rb +51 -0
  589. data/lib/rubocop/cop/style/safe_navigation.rb +76 -20
  590. data/lib/rubocop/cop/style/sample.rb +19 -13
  591. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  592. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  593. data/lib/rubocop/cop/style/select_by_regexp.rb +54 -22
  594. data/lib/rubocop/cop/style/self_assignment.rb +13 -16
  595. data/lib/rubocop/cop/style/semicolon.rb +56 -14
  596. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +4 -0
  597. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  598. data/lib/rubocop/cop/style/single_line_do_end_block.rb +22 -8
  599. data/lib/rubocop/cop/style/single_line_methods.rb +33 -11
  600. data/lib/rubocop/cop/style/sole_nested_conditional.rb +96 -104
  601. data/lib/rubocop/cop/style/special_global_vars.rb +7 -2
  602. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +32 -6
  603. data/lib/rubocop/cop/style/static_class.rb +21 -0
  604. data/lib/rubocop/cop/style/string_concatenation.rb +38 -16
  605. data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
  606. data/lib/rubocop/cop/style/struct_inheritance.rb +44 -2
  607. data/lib/rubocop/cop/style/super_arguments.rb +7 -6
  608. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  609. data/lib/rubocop/cop/style/symbol_proc.rb +35 -15
  610. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  611. data/lib/rubocop/cop/style/ternary_parentheses.rb +34 -1
  612. data/lib/rubocop/cop/style/time_now.rb +41 -0
  613. data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -2
  614. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +52 -1
  615. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  616. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +2 -2
  617. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  618. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  619. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +35 -32
  620. data/lib/rubocop/cop/style/trivial_accessors.rb +2 -2
  621. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  622. data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
  623. data/lib/rubocop/cop/style/while_until_do.rb +7 -0
  624. data/lib/rubocop/cop/style/while_until_modifier.rb +16 -1
  625. data/lib/rubocop/cop/style/word_array.rb +1 -0
  626. data/lib/rubocop/cop/style/yoda_condition.rb +26 -12
  627. data/lib/rubocop/cop/style/yoda_expression.rb +11 -2
  628. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -3
  629. data/lib/rubocop/cop/style.rb +311 -0
  630. data/lib/rubocop/cop/team.rb +172 -49
  631. data/lib/rubocop/cop/util.rb +7 -10
  632. data/lib/rubocop/cop/utils/format_string.rb +20 -5
  633. data/lib/rubocop/cop/variable_force/assignment.rb +8 -4
  634. data/lib/rubocop/cop/variable_force/branch.rb +30 -6
  635. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  636. data/lib/rubocop/cop/variable_force/variable.rb +42 -11
  637. data/lib/rubocop/cop/variable_force.rb +26 -9
  638. data/lib/rubocop/cops_documentation_generator.rb +49 -15
  639. data/lib/rubocop/directive_comment.rb +147 -5
  640. data/lib/rubocop/ext/regexp_node.rb +0 -1
  641. data/lib/rubocop/feature_loader.rb +0 -6
  642. data/lib/rubocop/file_patterns.rb +9 -1
  643. data/lib/rubocop/formatter/base_formatter.rb +22 -0
  644. data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
  645. data/lib/rubocop/formatter/disabled_config_formatter.rb +57 -14
  646. data/lib/rubocop/formatter/emacs_style_formatter.rb +3 -1
  647. data/lib/rubocop/formatter/formatter_set.rb +7 -2
  648. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  649. data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
  650. data/lib/rubocop/formatter/html_formatter.rb +3 -5
  651. data/lib/rubocop/formatter/json_formatter.rb +82 -7
  652. data/lib/rubocop/formatter/junit_formatter.rb +27 -10
  653. data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
  654. data/lib/rubocop/formatter/offense_count_formatter.rb +5 -4
  655. data/lib/rubocop/formatter/pacman_formatter.rb +5 -2
  656. data/lib/rubocop/formatter/sarif_formatter.rb +186 -0
  657. data/lib/rubocop/formatter/simple_text_formatter.rb +4 -5
  658. data/lib/rubocop/formatter/tap_formatter.rb +8 -3
  659. data/lib/rubocop/formatter/worst_offenders_formatter.rb +5 -4
  660. data/lib/rubocop/formatter.rb +23 -21
  661. data/lib/rubocop/lockfile.rb +18 -0
  662. data/lib/rubocop/lsp/diagnostic.rb +22 -41
  663. data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
  664. data/lib/rubocop/lsp/routes.rb +158 -55
  665. data/lib/rubocop/lsp/runtime.rb +66 -15
  666. data/lib/rubocop/lsp/server.rb +4 -2
  667. data/lib/rubocop/lsp/stdin_runner.rb +38 -19
  668. data/lib/rubocop/lsp.rb +5 -2
  669. data/lib/rubocop/magic_comment.rb +55 -0
  670. data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
  671. data/lib/rubocop/mcp/explain_tool.rb +68 -0
  672. data/lib/rubocop/mcp/scope.rb +65 -0
  673. data/lib/rubocop/mcp/server.rb +307 -0
  674. data/lib/rubocop/mcp/source_files.rb +35 -0
  675. data/lib/rubocop/offense_limit.rb +30 -0
  676. data/lib/rubocop/options.rb +166 -23
  677. data/lib/rubocop/path_util.rb +20 -5
  678. data/lib/rubocop/pending_cops_reporter.rb +51 -0
  679. data/lib/rubocop/plugin/configuration_integrator.rb +153 -0
  680. data/lib/rubocop/plugin/load_error.rb +26 -0
  681. data/lib/rubocop/plugin/loader.rb +100 -0
  682. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  683. data/lib/rubocop/plugin.rb +46 -0
  684. data/lib/rubocop/project_index_loader.rb +82 -0
  685. data/lib/rubocop/rake_task.rb +6 -4
  686. data/lib/rubocop/remote_config.rb +18 -13
  687. data/lib/rubocop/result_cache.rb +110 -65
  688. data/lib/rubocop/rspec/cop_helper.rb +21 -1
  689. data/lib/rubocop/rspec/expect_offense.rb +11 -7
  690. data/lib/rubocop/rspec/shared_contexts.rb +85 -3
  691. data/lib/rubocop/rspec/support.rb +4 -0
  692. data/lib/rubocop/runner.rb +368 -106
  693. data/lib/rubocop/server/cache.rb +67 -48
  694. data/lib/rubocop/server/cli.rb +2 -4
  695. data/lib/rubocop/server/client_command/base.rb +10 -0
  696. data/lib/rubocop/server/client_command/exec.rb +2 -1
  697. data/lib/rubocop/server/client_command/start.rb +11 -1
  698. data/lib/rubocop/server/core.rb +8 -0
  699. data/lib/rubocop/server.rb +14 -0
  700. data/lib/rubocop/target_finder.rb +25 -11
  701. data/lib/rubocop/target_ruby.rb +52 -23
  702. data/lib/rubocop/todo_audit.rb +111 -0
  703. data/lib/rubocop/unified_diff.rb +257 -0
  704. data/lib/rubocop/util.rb +69 -0
  705. data/lib/rubocop/version.rb +48 -10
  706. data/lib/rubocop.rb +35 -682
  707. data/lib/ruby_lsp/rubocop/addon.rb +28 -17
  708. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +99 -0
  709. metadata +129 -21
  710. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
  711. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  712. data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +0 -50
@@ -0,0 +1,270 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'did_you_mean'
5
+ rescue LoadError
6
+ nil
7
+ end
8
+
9
+ module RuboCop
10
+ module Cop
11
+ module Lint
12
+ # Checks for probable typos in constant and method names: a name that
13
+ # does not resolve anywhere in the project, used in a namespace the
14
+ # project does define, with a close-named sibling to suggest instead.
15
+ #
16
+ # The check is powered by the project-wide index, so it only runs when
17
+ # `AllCops/UseProjectIndex` is enabled and the `rubydex` gem is installed.
18
+ # Without the index the cop does nothing.
19
+ #
20
+ # Constants are checked only in qualified references (`Foo::Bar`) whose
21
+ # namespace resolves in the index; bare names cannot be distinguished
22
+ # from constants provided by gems or the standard library. Methods are
23
+ # checked only in calls on constant receivers (`Foo.bar`) whose entire
24
+ # indexed ancestry is resolved, so methods gained through gem classes or
25
+ # dynamic definitions never produce offenses. In both cases an offense
26
+ # requires a similarly named alternative to exist — an unknown name
27
+ # alone is not reported, since the index does not see gems or the
28
+ # standard library.
29
+ #
30
+ # For the same reason, a namespace whose root segment names a gem in the
31
+ # bundle (`Flipper` for the `flipper` gem) is left alone: a project that
32
+ # reopens it (`module Flipper; module Adapters; ...`) makes it resolve in
33
+ # the index, while the members the gem itself defines stay invisible and
34
+ # would look like typos. Enabling `AllCops/ProjectIndexIncludesGems`
35
+ # indexes those sources and restores the check.
36
+ #
37
+ # Names that appear as symbols or inside string literals in the same
38
+ # file are never reported, since they usually belong to runtime
39
+ # definitions the index cannot see (`stub_const`, `const_set`,
40
+ # `define_method`, and the like).
41
+ #
42
+ # @example
43
+ # # bad - Services::UserCraetor is not defined, Services::UserCreator is
44
+ # Services::UserCraetor.new
45
+ #
46
+ # # good
47
+ # Services::UserCreator.new
48
+ #
49
+ # # bad - Report.generate_sumary is not defined, Report.generate_summary is
50
+ # Report.generate_sumary
51
+ #
52
+ # # good
53
+ # Report.generate_summary
54
+ #
55
+ # @example CheckConstants: false
56
+ # # good - constant references are not checked
57
+ # Services::UserCraetor.new
58
+ #
59
+ # @example CheckMethods: false
60
+ # # good - method calls are not checked
61
+ # Report.generate_sumary
62
+ #
63
+ # @example AllowedNames: ['generate_sumary']
64
+ # # good - the name is explicitly allowed
65
+ # Report.generate_sumary
66
+ #
67
+ class NameTypo < Base
68
+ include ProjectIndexHelp
69
+
70
+ CONSTANT_MSG = 'Possible typo: `%<name>s` is not defined in `%<namespace>s`. ' \
71
+ 'Did you mean `%<suggestion>s`?'
72
+ METHOD_MSG = 'Possible typo: `%<receiver>s` does not respond to `%<name>s`. ' \
73
+ 'Did you mean `%<suggestion>s`?'
74
+
75
+ METHOD_MEMBER_REGEXP = /#([a-zA-Z_]\w*[?!]?)\(\)\z/.freeze
76
+ LITERAL_IDENTIFIER_PATTERN = /[a-zA-Z_]\w*[?!]?/.freeze
77
+
78
+ def on_const(node)
79
+ return unless check?('CheckConstants') && checkable_constant?(node)
80
+
81
+ suggestion = constant_typo_suggestion(node)
82
+ return unless suggestion
83
+
84
+ message = format(CONSTANT_MSG, name: node.short_name,
85
+ namespace: node.namespace.const_name,
86
+ suggestion: suggestion)
87
+ add_offense(node.loc.name, message: message)
88
+ end
89
+
90
+ def on_send(node)
91
+ return unless check?('CheckMethods')
92
+ return unless node.receiver&.const_type?
93
+ return if allowed_name?(node.method_name) || defined_check?(node)
94
+
95
+ suggestion = method_typo_suggestion(node)
96
+ return unless suggestion
97
+
98
+ message = format(METHOD_MSG, receiver: node.receiver.const_name,
99
+ name: node.method_name,
100
+ suggestion: suggestion)
101
+ add_offense(node.loc.selector, message: message)
102
+ end
103
+ alias on_csend on_send
104
+
105
+ def on_new_investigation
106
+ @literal_names = nil
107
+ super
108
+ end
109
+
110
+ private
111
+
112
+ def check?(key)
113
+ project_index && defined?(DidYouMean::SpellChecker) && cop_config.fetch(key, true)
114
+ end
115
+
116
+ def checkable_constant?(node)
117
+ node.namespace&.const_type? &&
118
+ !allowed_name?(node.short_name) &&
119
+ !definition_identifier?(node) && !defined_check?(node)
120
+ end
121
+
122
+ def allowed_name?(name)
123
+ cop_config.fetch('AllowedNames', []).include?(name.to_s)
124
+ end
125
+
126
+ # The last segment of a class, module or constant definition is being
127
+ # defined, not referenced.
128
+ def definition_identifier?(node)
129
+ node.parent&.defined_module
130
+ end
131
+
132
+ # `defined?(Foo::Bar)` probes whether a name exists; unknown names
133
+ # there are deliberate.
134
+ def defined_check?(node)
135
+ node.each_ancestor(:defined?).any?
136
+ end
137
+
138
+ def constant_typo_suggestion(node)
139
+ namespace = resolve_constant_in_index(node.namespace)
140
+ return nil unless namespace.is_a?(Rubydex::Namespace)
141
+ return nil if namespace.find_member(node.short_name.to_s)
142
+ return nil unless complete_index_members?(namespace)
143
+ return nil if literal_names.include?(node.short_name.to_s)
144
+
145
+ spell_check(node.short_name, constant_member_names(namespace))
146
+ rescue StandardError
147
+ nil
148
+ end
149
+
150
+ # Whether the index can be trusted to list everything the namespace
151
+ # defines. A name missing from an incomplete member list is not
152
+ # evidence of a typo, so both gaps have to be ruled out first:
153
+ # an ancestor that does not resolve may contribute the name, and so
154
+ # may a gem that reopens the namespace.
155
+ def complete_index_members?(declaration)
156
+ fully_resolved_index_ancestry?(declaration) && !gem_owned_namespace?(declaration)
157
+ end
158
+
159
+ # Whether the namespace's root segment names a gem in the bundle,
160
+ # which is then free to define members the index never sees: gem
161
+ # sources are only indexed when `AllCops/ProjectIndexIncludesGems`
162
+ # is enabled. A project that reopens such a namespace to add its own
163
+ # members (`module Flipper; module Adapters; ...`) makes it resolve
164
+ # in the index while most of what it holds stays invisible.
165
+ def gem_owned_namespace?(declaration)
166
+ return false if config.for_all_cops['ProjectIndexIncludesGems']
167
+
168
+ root = declaration.name.to_s.split('::').first.to_s
169
+ bundled_gem_namespaces.include?(root.downcase)
170
+ end
171
+
172
+ # Gem names normalized towards the constant they conventionally
173
+ # provide: `flipper` for `Flipper`, `activerecord` for `ActiveRecord`.
174
+ def bundled_gem_namespaces
175
+ @bundled_gem_namespaces ||= bundled_gem_names.to_set { |name| name.delete('-_').downcase }
176
+ end
177
+
178
+ # The bundle's gems except those sourced from a local path, whose code
179
+ # lives in the project and is indexed like the rest of it — among them
180
+ # the project's own gem, which its lockfile lists in the `PATH` section.
181
+ def bundled_gem_names
182
+ (config.gem_versions_in_target || {}).keys - (config.path_sourced_gems_in_target || [])
183
+ end
184
+
185
+ # Writers are indexed under the reader's name, so setter calls are
186
+ # verified and spell-checked through the base name.
187
+ def method_typo_suggestion(node)
188
+ setter = setter_call?(node)
189
+ base = setter ? node.method_name.to_s.delete_suffix('=') : node.method_name.to_s
190
+
191
+ declaration = unknown_method_owner(node, base)
192
+ return nil unless declaration
193
+ return nil if literal_names.include?(base)
194
+
195
+ suggestion = spell_check(base, method_member_names(declaration))
196
+ suggestion && setter ? "#{suggestion}=" : suggestion
197
+ rescue StandardError
198
+ nil
199
+ end
200
+
201
+ # The receiver's declaration when it resolves in the index, everything
202
+ # it can inherit or be reopened with is visible there, and the method
203
+ # is not found — nil otherwise.
204
+ def unknown_method_owner(node, base)
205
+ declaration = resolve_constant_in_index(node.receiver)
206
+ return nil unless declaration.is_a?(Rubydex::Namespace)
207
+ return nil if responds_in_index?(declaration, node.method_name.to_s, base)
208
+ return nil unless fully_resolved_index_ancestry?(declaration)
209
+ return nil if gem_owned_namespace?(declaration)
210
+
211
+ declaration
212
+ end
213
+
214
+ def setter_call?(node)
215
+ node.assignment_method? && !node.operator_method?
216
+ end
217
+
218
+ def responds_in_index?(declaration, name, base)
219
+ # Instance methods of a module are also callable on the module
220
+ # itself when exposed with `module_function`.
221
+ [name, base].uniq.any? do |candidate|
222
+ member_name = "#{candidate}()"
223
+ indexed_singleton_member(declaration, member_name) ||
224
+ declaration.find_member(member_name)
225
+ end
226
+ end
227
+
228
+ # Names mentioned as symbols or inside string literals in the current
229
+ # file belong to runtime definitions (`stub_const`, `const_set`,
230
+ # `define_method`) that the index cannot see.
231
+ def literal_names
232
+ @literal_names ||=
233
+ processed_source.ast.each_descendant(:sym, :str)
234
+ .with_object(Set.new) do |literal, names|
235
+ if literal.sym_type?
236
+ names << literal.value.to_s
237
+ else
238
+ # `scan` raises on binary string literals with invalid byte sequences.
239
+ value = literal.value
240
+ value = value.scrub unless value.valid_encoding?
241
+ value.scan(LITERAL_IDENTIFIER_PATTERN) { |token| names << token }
242
+ end
243
+ end
244
+ end
245
+
246
+ def constant_member_names(namespace)
247
+ namespace.members.filter_map do |member|
248
+ name = member.name
249
+ name.split('::').last unless name.include?('#') || name.include?('<')
250
+ end
251
+ end
252
+
253
+ def method_member_names(declaration)
254
+ scopes = declaration.ancestors.filter_map { |ancestor| indexed_singleton_of(ancestor) }
255
+ scopes << declaration
256
+
257
+ scopes.flat_map do |scope|
258
+ scope.members.filter_map { |member| member.name[METHOD_MEMBER_REGEXP, 1] }
259
+ end
260
+ end
261
+
262
+ def spell_check(name, dictionary)
263
+ return nil if dictionary.empty?
264
+
265
+ DidYouMean::SpellChecker.new(dictionary: dictionary.uniq).correct(name.to_s).first
266
+ end
267
+ end
268
+ end
269
+ end
270
+ end
@@ -95,10 +95,10 @@ module RuboCop
95
95
  MSG = 'Method definitions must not be nested. Use `lambda` instead.'
96
96
 
97
97
  def on_def(node)
98
- subject, = *node # rubocop:disable InternalAffairs/NodeDestructuring
98
+ subject, = *node # rubocop:disable InternalAffairs/NodeDestructuring -- the first child differs between `def` and `defs`
99
99
  return if node.defs_type? && allowed_subject_type?(subject)
100
100
 
101
- def_ancestor = node.each_ancestor(:def, :defs).first
101
+ def_ancestor = node.each_ancestor(:any_def).first
102
102
  return unless def_ancestor
103
103
 
104
104
  within_scoping_def =
@@ -31,6 +31,7 @@ module RuboCop
31
31
  end
32
32
  end
33
33
  alias on_numblock on_block
34
+ alias on_itblock on_block
34
35
 
35
36
  private
36
37
 
@@ -39,6 +40,7 @@ module RuboCop
39
40
  {
40
41
  (block (call _recv {:reduce :inject} !sym) _blockargs $(begin ...))
41
42
  (numblock (call _recv {:reduce :inject} !sym) _argscount $(begin ...))
43
+ (itblock (call _recv {:reduce :inject} !sym) _argscount $(begin ...))
42
44
  }
43
45
  PATTERN
44
46
 
@@ -41,12 +41,32 @@ module RuboCop
41
41
  def on_lvasgn(node)
42
42
  node.each_node(:kwbegin) do |kwbegin_node|
43
43
  kwbegin_node.each_node(:return) do |return_node|
44
+ next if return_from_inner_scope?(return_node, kwbegin_node)
45
+
44
46
  add_offense(return_node)
45
47
  end
46
48
  end
47
49
  end
50
+ alias on_ivasgn on_lvasgn
51
+ alias on_cvasgn on_lvasgn
52
+ alias on_gvasgn on_lvasgn
53
+ alias on_casgn on_lvasgn
48
54
  alias on_or_asgn on_lvasgn
49
55
  alias on_op_asgn on_lvasgn
56
+
57
+ private
58
+
59
+ # A `return` inside a nested method definition or lambda within the
60
+ # `begin..end` returns from that inner scope rather than the assignment
61
+ # context, so it is not an offense. A `return` inside a plain block (or
62
+ # `proc`) does propagate out, so it remains an offense.
63
+ def return_from_inner_scope?(return_node, kwbegin_node)
64
+ return_node.each_ancestor do |ancestor|
65
+ break if ancestor == kwbegin_node
66
+ return true if ancestor.any_def_type? || (ancestor.any_block_type? && ancestor.lambda?)
67
+ end
68
+ false
69
+ end
50
70
  end
51
71
  end
52
72
  end
@@ -12,7 +12,7 @@ module RuboCop
12
12
  # always sort the list.
13
13
  #
14
14
  # `Dir.glob` and `Dir[]` sort globbed results by default in Ruby 3.0.
15
- # So all bad cases are acceptable when Ruby 3.0 or higher are used.
15
+ # So all bad cases are acceptable when Ruby 3.0 or higher is used.
16
16
  #
17
17
  # NOTE: This cop will be deprecated and removed when supporting only Ruby 3.0 and higher.
18
18
  #
@@ -65,7 +65,9 @@ module RuboCop
65
65
 
66
66
  maximum_target_ruby_version 2.7
67
67
 
68
- def on_block(node)
68
+ # NOTE: itblock is not handled because this cop is limited to Ruby <= 2.7
69
+ # via `maximum_target_ruby_version`, so itblock nodes (Ruby 3.4+) are never encountered.
70
+ def on_block(node) # rubocop:disable InternalAffairs/ItblockHandler -- limited to Ruby <= 2.7, where `it` blocks do not exist
69
71
  return unless node.body
70
72
  return unless unsorted_dir_loop?(node.send_node)
71
73
 
@@ -46,7 +46,7 @@ module RuboCop
46
46
  def on_return(return_node)
47
47
  return if return_value?(return_node)
48
48
 
49
- return_node.each_ancestor(:block, :def, :defs) do |node|
49
+ return_node.each_ancestor(:any_block, :any_def) do |node|
50
50
  break if scoped_node?(node)
51
51
 
52
52
  # if a proc is passed to `Module#define_method` or
@@ -54,7 +54,7 @@ module RuboCop
54
54
  # non-local exit error
55
55
  break if define_method?(node.send_node)
56
56
 
57
- next unless node.arguments?
57
+ next if node.argument_list.empty?
58
58
 
59
59
  if chained_send?(node.send_node)
60
60
  add_offense(return_node.loc.keyword)
@@ -66,7 +66,7 @@ module RuboCop
66
66
  private
67
67
 
68
68
  def scoped_node?(node)
69
- node.type?(:def, :defs) || node.lambda?
69
+ node.any_def_type? || node.lambda?
70
70
  end
71
71
 
72
72
  def return_value?(return_node)
@@ -74,7 +74,7 @@ module RuboCop
74
74
  end
75
75
 
76
76
  # @!method chained_send?(node)
77
- def_node_matcher :chained_send?, '(send !nil? ...)'
77
+ def_node_matcher :chained_send?, '(call !nil? ...)'
78
78
 
79
79
  # @!method define_method?(node)
80
80
  def_node_matcher :define_method?, <<~PATTERN
@@ -3,9 +3,9 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Warns the usage of unsafe number conversions. Unsafe
7
- # number conversion can cause unexpected error if auto type conversion
8
- # fails. Cop prefer parsing with number class instead.
6
+ # Warns against the usage of unsafe number conversions. Unsafe
7
+ # number conversion can cause an unexpected error if auto type conversion
8
+ # fails. The cop prefers parsing with a number class instead.
9
9
  #
10
10
  # Conversion with `Integer`, `Float`, etc. will raise an `ArgumentError`
11
11
  # if given input that is not numeric (eg. an empty string), whereas
@@ -14,10 +14,10 @@ module RuboCop
14
14
  # always correct to raise if a value is not numeric.
15
15
  #
16
16
  # NOTE: Some values cannot be converted properly using one of the `Kernel`
17
- # method (for instance, `Time` and `DateTime` values are allowed by this
17
+ # methods (for instance, `Time` and `DateTime` values are allowed by this
18
18
  # cop by default). Similarly, Rails' duration methods do not work well
19
19
  # with `Integer()` and can be allowed with `AllowedMethods`. By default,
20
- # there are no methods to allowed.
20
+ # there are no allowed methods.
21
21
  #
22
22
  # @safety
23
23
  # Autocorrection is unsafe because it is not guaranteed that the
@@ -66,7 +66,7 @@ module RuboCop
66
66
  # # good
67
67
  # 10.minutes.to_i
68
68
  #
69
- # @example IgnoredClasses: [Time, DateTime] (default)
69
+ # @example AllowedClasses: [Time, DateTime] (default)
70
70
  #
71
71
  # # good
72
72
  # Time.now.to_datetime.to_i
@@ -117,11 +117,11 @@ module RuboCop
117
117
 
118
118
  message = format(
119
119
  MSG,
120
- current: "#{receiver.source}.#{to_method}",
120
+ current: current_method(node, receiver, to_method),
121
121
  corrected_method: correct_method(node, receiver)
122
122
  )
123
123
  add_offense(node, message: message) do |corrector|
124
- next if part_of_ignored_node?(node)
124
+ next if safe_navigation?(node) || part_of_ignored_node?(node)
125
125
 
126
126
  corrector.replace(node, correct_method(node, node.receiver))
127
127
 
@@ -132,7 +132,7 @@ module RuboCop
132
132
 
133
133
  def handle_as_symbol(node)
134
134
  to_method_symbol(node) do |receiver, sym_node, to_method|
135
- next if receiver.nil? || !node.arguments.one?
135
+ next if receiver.nil? || !node.arguments.one? || node.operator_method?
136
136
 
137
137
  message = format(
138
138
  MSG,
@@ -140,6 +140,8 @@ module RuboCop
140
140
  corrected_method: correct_sym_method(to_method)
141
141
  )
142
142
  add_offense(node, message: message) do |corrector|
143
+ next if part_of_ignored_node?(node)
144
+
143
145
  remove_parentheses(corrector, node) if node.parenthesized?
144
146
 
145
147
  corrector.replace(sym_node, correct_sym_method(to_method))
@@ -156,13 +158,22 @@ module RuboCop
156
158
  "{ |i| #{body} }"
157
159
  end
158
160
 
161
+ def current_method(node, receiver, to_method)
162
+ operator = node.csend_type? ? '&.' : '.'
163
+ "#{receiver.source}#{operator}#{to_method}"
164
+ end
165
+
159
166
  def remove_parentheses(corrector, node)
160
167
  corrector.replace(node.loc.begin, ' ')
161
168
  corrector.remove(node.loc.end)
162
169
  end
163
170
 
171
+ def safe_navigation?(node)
172
+ node.csend_type? || node.each_descendant(:csend).any?
173
+ end
174
+
164
175
  def allow_receiver?(receiver)
165
- if receiver.numeric_type? || (receiver.send_type? &&
176
+ if receiver.numeric_type? || (receiver.call_type? &&
166
177
  (conversion_method?(receiver.method_name) ||
167
178
  allowed_method_name?(receiver.method_name)))
168
179
  true
@@ -188,7 +199,7 @@ module RuboCop
188
199
  end
189
200
 
190
201
  def ignored_classes
191
- cop_config.fetch('IgnoredClasses', [])
202
+ cop_config.fetch('AllowedClasses', [])
192
203
  end
193
204
 
194
205
  def ignored_class?(name)
@@ -16,7 +16,7 @@ module RuboCop
16
16
  # ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
17
17
  # -e:1: _1 is reserved for numbered parameter
18
18
  #
19
- # NOTE: The parametered parameters are from `_1` to `_9`. This cop checks `_0`, and over `_10`
19
+ # NOTE: The numbered parameters are from `_1` to `_9`. This cop checks `_0`, and over `_10`
20
20
  # as well to prevent confusion.
21
21
  #
22
22
  # @example
@@ -15,6 +15,13 @@ module RuboCop
15
15
  # can't determine the type of `x`. If `x` is an `Array` or `String`, it doesn't perform
16
16
  # a numeric operation.
17
17
  #
18
+ # @safety
19
+ # This cop is unsafe because the autocorrection drops the operands, which
20
+ # discards any side effects of evaluating them and can change behavior when
21
+ # the result is not actually constant. For example, `x / x` raises
22
+ # `ZeroDivisionError` when `x` is `0`, and returns `Float::NAN` (not `1`)
23
+ # when `x` is `0.0`; replacing it with `1` silences that.
24
+ #
18
25
  # @example
19
26
  #
20
27
  # # bad
@@ -45,6 +52,7 @@ module RuboCop
45
52
  #
46
53
  class NumericOperationWithConstantResult < Base
47
54
  extend AutoCorrector
55
+
48
56
  MSG = 'Numeric operation with a constant result detected.'
49
57
  RESTRICT_ON_SEND = %i[* / **].freeze
50
58
 
@@ -57,6 +65,9 @@ module RuboCop
57
65
  '(op-asgn (lvasgn $_lhs) $_operation ({int lvar} $_rhs))'
58
66
 
59
67
  def on_send(node)
68
+ # Safe navigation short-circuits to `nil` when the receiver is `nil`, so the
69
+ # result is not constant and replacing it with `0`/`1` would change behavior.
70
+ return if node.csend_type?
60
71
  return unless (lhs, operation, rhs = operation_with_constant_result?(node))
61
72
  return unless (result = constant_result?(lhs, operation, rhs))
62
73
 
@@ -30,7 +30,7 @@ module RuboCop
30
30
  return unless node.lhs&.casgn_type?
31
31
 
32
32
  add_offense(node.loc.operator) do |corrector|
33
- next if node.each_ancestor(:def, :defs).any?
33
+ next if node.each_ancestor(:any_def).any?
34
34
 
35
35
  corrector.replace(node.loc.operator, '=')
36
36
  end
@@ -38,23 +38,23 @@ module RuboCop
38
38
  def on_new_investigation
39
39
  return if processed_source.buffer.source.empty?
40
40
 
41
- encoding_line, frozen_string_literal_line = magic_comment_lines
41
+ encoding_line, other_magic_comment_line = magic_comment_lines
42
42
 
43
- return unless encoding_line && frozen_string_literal_line
44
- return if encoding_line < frozen_string_literal_line
43
+ return unless encoding_line && other_magic_comment_line
44
+ return if encoding_line < other_magic_comment_line
45
45
 
46
46
  range = processed_source.buffer.line_range(encoding_line + 1)
47
47
 
48
48
  add_offense(range) do |corrector|
49
- autocorrect(corrector, encoding_line, frozen_string_literal_line)
49
+ autocorrect(corrector, encoding_line, other_magic_comment_line)
50
50
  end
51
51
  end
52
52
 
53
53
  private
54
54
 
55
- def autocorrect(corrector, encoding_line, frozen_string_literal_line)
55
+ def autocorrect(corrector, encoding_line, other_magic_comment_line)
56
56
  range1 = processed_source.buffer.line_range(encoding_line + 1)
57
- range2 = processed_source.buffer.line_range(frozen_string_literal_line + 1)
57
+ range2 = processed_source.buffer.line_range(other_magic_comment_line + 1)
58
58
 
59
59
  corrector.replace(range1, range2.source)
60
60
  corrector.replace(range2, range1.source)
@@ -66,7 +66,7 @@ module RuboCop
66
66
  leading_magic_comments.each.with_index do |comment, index|
67
67
  if comment.encoding_specified?
68
68
  lines[0] = index
69
- elsif comment.frozen_string_literal_specified?
69
+ elsif comment.valid?
70
70
  lines[1] = index
71
71
  end
72
72
 
@@ -53,6 +53,8 @@ module RuboCop
53
53
  end
54
54
 
55
55
  def after_send(node)
56
+ return if backrefs_unaffected?(node)
57
+
56
58
  @valid_ref = nil
57
59
 
58
60
  if regexp_first_argument?(node)
@@ -111,6 +113,19 @@ module RuboCop
111
113
  end
112
114
  end
113
115
 
116
+ # A call such as `hash[:key]` or `array[0]` cannot involve a regexp match:
117
+ # a non-string literal cannot act as a pattern (whereas `sub`, `gsub`,
118
+ # and `match` treat a string one as a pattern and do set backreferences),
119
+ # and `$~` is frame-local, so a user-defined method cannot change
120
+ # the caller's backreferences either.
121
+ def backrefs_unaffected?(send_node)
122
+ first_argument = send_node.first_argument
123
+ return false unless first_argument&.basic_literal?
124
+ return false if first_argument.str_type?
125
+
126
+ !regexp_receiver?(send_node)
127
+ end
128
+
114
129
  def regexp_first_argument?(send_node)
115
130
  send_node.first_argument&.regexp_type? \
116
131
  && REGEXP_ARGUMENT_METHODS.include?(send_node.method_name)
@@ -119,10 +134,6 @@ module RuboCop
119
134
  def regexp_receiver?(send_node)
120
135
  send_node.receiver&.regexp_type?
121
136
  end
122
-
123
- def nth_ref_receiver?(send_node)
124
- send_node.receiver&.nth_ref_type?
125
- end
126
137
  end
127
138
  end
128
139
  end
@@ -46,13 +46,29 @@ module RuboCop
46
46
 
47
47
  def valid_first_argument?(first_arg)
48
48
  first_arg.operator_keyword? || first_arg.hash_type? || ternary_expression?(first_arg) ||
49
- compound_range?(first_arg)
49
+ compound_range?(first_arg) || invalid_bare_argument?(first_arg)
50
50
  end
51
51
 
52
52
  def compound_range?(first_arg)
53
53
  first_arg.range_type? && first_arg.parenthesized_call?
54
54
  end
55
55
 
56
+ def invalid_bare_argument?(node)
57
+ node = node.children.first while node&.begin_type? && node.children.one?
58
+ return false unless node
59
+
60
+ keyword_operator?(node) || modifier_expression?(node)
61
+ end
62
+
63
+ def keyword_operator?(node)
64
+ (node.operator_keyword? && node.semantic_operator?) ||
65
+ node.rescue_type? || (node.send_type? && node.prefix_not?)
66
+ end
67
+
68
+ def modifier_expression?(node)
69
+ node.type?(:if, :while, :until) && node.modifier_form?
70
+ end
71
+
56
72
  def chained_calls?(node)
57
73
  first_argument = node.first_argument
58
74
  first_argument.call_type? && (node.children.last&.children&.count || 0) > 1
@@ -63,19 +79,9 @@ module RuboCop
63
79
  end
64
80
 
65
81
  def spaces_before_left_parenthesis(node)
66
- receiver = node.receiver
67
- receiver_length = if receiver
68
- receiver.source.length
69
- else
70
- 0
71
- end
72
- without_receiver = node.source[receiver_length..]
73
-
74
- # Escape question mark if any.
75
- method_regexp = Regexp.escape(node.method_name)
76
-
77
- match = without_receiver.match(/^\s*&?\.?\s*#{method_regexp}(\s+)\(/)
78
- match ? match.captures[0].length : 0
82
+ return 0 if node.parenthesized? || !node.first_argument.source.start_with?('(')
83
+
84
+ node.first_argument.source_range.begin_pos - node.loc.selector.end_pos
79
85
  end
80
86
 
81
87
  def space_range(expr, space_length)