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,200 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Prefer `Enumerable` predicate methods over expressions with `count`.
7
+ #
8
+ # The cop checks calls to `count` without arguments, or with a
9
+ # block. It doesn't register offenses for `count` with a positional
10
+ # argument because its behavior differs from predicate methods (`count`
11
+ # matches the argument using `==`, while `any?`, `none?` and `one?` use
12
+ # `===`).
13
+ #
14
+ # NOTE: This cop doesn't check `length` and `size` methods because they
15
+ # would yield false positives. For example, `String` implements `length`
16
+ # and `size`, but it doesn't include `Enumerable`.
17
+ #
18
+ # When `count` is used without a block, it measures the collection's
19
+ # size, so the offense is corrected to `empty?` or `!empty?`. The
20
+ # predicate methods `any?`, `none?` and `one?` test element truthiness
21
+ # instead and would return different results for collections with falsey
22
+ # elements (e.g. `[false].count.zero?` is `false`, but `[false].none?`
23
+ # is `true`). For the same reason, `count == 1` and `count > 1` without
24
+ # a block are not flagged.
25
+ #
26
+ # @safety
27
+ # The cop is unsafe because receiver might not include `Enumerable`, or
28
+ # it has nonstandard implementation of `count` or any replacement
29
+ # methods.
30
+ #
31
+ # Blockless `count` is corrected to `empty?`, which `Enumerable` doesn't
32
+ # define. `Range`, `Enumerator` (including lazy ones), `Struct`, `StringIO`
33
+ # and any class that just includes `Enumerable` respond to `count` but not
34
+ # to `empty?`, so `(1...1).count.zero?` is `true` while `(1...1).empty?`
35
+ # raises `NoMethodError`.
36
+ #
37
+ # Autocorrection is unsafe when replacement methods don't iterate over
38
+ # every element in collection and the given block runs side effects:
39
+ #
40
+ # [source,ruby]
41
+ # ----
42
+ # x.count(&:method_with_side_effects).positive?
43
+ # # calls `method_with_side_effects` on every element
44
+ #
45
+ # x.any?(&:method_with_side_effects)
46
+ # # calls `method_with_side_effects` until first element returns a truthy value
47
+ # ----
48
+ #
49
+ # @example
50
+ #
51
+ # # bad
52
+ # x.count.positive?
53
+ # x.count > 0
54
+ # x.count != 0
55
+ #
56
+ # # good
57
+ # !x.empty?
58
+ #
59
+ # # bad
60
+ # x.count(&:foo?).positive?
61
+ # x.count { |item| item.foo? }.positive?
62
+ #
63
+ # # good
64
+ # x.any?(&:foo?)
65
+ # x.any? { |item| item.foo? }
66
+ #
67
+ # # bad
68
+ # x.count.zero?
69
+ # x.count == 0
70
+ #
71
+ # # good
72
+ # x.empty?
73
+ #
74
+ # # bad
75
+ # x.count(&:foo?).zero?
76
+ # x.count(&:foo?) == 0
77
+ #
78
+ # # good
79
+ # x.none?(&:foo?)
80
+ #
81
+ # # bad
82
+ # x.count(&:foo?) == 1
83
+ #
84
+ # # good
85
+ # x.one?(&:foo?)
86
+ #
87
+ # @example AllCops:ActiveSupportExtensionsEnabled: false (default)
88
+ #
89
+ # # good
90
+ # x.count(&:foo?) > 1
91
+ #
92
+ # @example AllCops:ActiveSupportExtensionsEnabled: true
93
+ #
94
+ # # bad
95
+ # x.count(&:foo?) > 1
96
+ #
97
+ # # good
98
+ # x.many?(&:foo?)
99
+ #
100
+ class CollectionQuerying < Base
101
+ include RangeHelp
102
+ extend AutoCorrector
103
+
104
+ MSG = 'Use `%<prefer>s` instead.'
105
+
106
+ RESTRICT_ON_SEND = %i[positive? > != zero? ==].freeze
107
+
108
+ REPLACEMENTS = {
109
+ [:positive?, nil] => 'any?',
110
+ [:>, 0] => 'any?',
111
+ [:!=, 0] => 'any?',
112
+ [:zero?, nil] => 'none?',
113
+ [:==, 0] => 'none?',
114
+ [:==, 1] => 'one?',
115
+ [:>, 1] => 'many?'
116
+ }.freeze
117
+
118
+ NO_BLOCK_REPLACEMENTS = {
119
+ [:positive?, nil] => '!empty?',
120
+ [:>, 0] => '!empty?',
121
+ [:!=, 0] => '!empty?',
122
+ [:zero?, nil] => 'empty?',
123
+ [:==, 0] => 'empty?'
124
+ }.freeze
125
+
126
+ # @!method count_predicate(node)
127
+ def_node_matcher :count_predicate, <<~PATTERN
128
+ (send
129
+ {
130
+ (any_block $(call !nil? :count) _ _)
131
+ $(call !nil? :count (block-pass _)?)
132
+ }
133
+ {
134
+ :positive? |
135
+ :> (int 0) |
136
+ :!= (int 0) |
137
+ :zero? |
138
+ :== (int 0) |
139
+ :== (int 1) |
140
+ :> (int 1)
141
+ })
142
+ PATTERN
143
+
144
+ def on_send(node)
145
+ return unless (count_node = count_predicate(node))
146
+
147
+ replacement = replacement_method(node, count_node)
148
+
149
+ return unless replacement_supported?(node, replacement)
150
+
151
+ offense_range = count_node.loc.selector.join(node.source_range.end)
152
+ add_offense(offense_range, message: format(MSG, prefer: replacement)) do |corrector|
153
+ autocorrect(corrector, node, count_node, replacement)
154
+ end
155
+ end
156
+
157
+ private
158
+
159
+ def replacement_method(node, count_node)
160
+ key = [node.method_name, node.first_argument&.value]
161
+ return REPLACEMENTS.fetch(key) if block_given_to_count?(count_node)
162
+
163
+ NO_BLOCK_REPLACEMENTS[key]
164
+ end
165
+
166
+ def block_given_to_count?(count_node)
167
+ count_node.parent&.any_block_type? || count_node.last_argument&.block_pass_type?
168
+ end
169
+
170
+ def replacement_supported?(node, replacement)
171
+ return false unless replacement
172
+ return false if replacement == 'many?' && !active_support_extensions_enabled?
173
+
174
+ !(replacement.start_with?('!') && receiver_of_call?(node))
175
+ end
176
+
177
+ def receiver_of_call?(node)
178
+ node.parent&.call_type? && node.parent.receiver == node && node.parent.loc.dot
179
+ end
180
+
181
+ def autocorrect(corrector, node, count_node, replacement)
182
+ if replacement.start_with?('!')
183
+ corrector.insert_before(count_node, '!')
184
+ corrector.replace(count_node.loc.selector, 'empty?')
185
+ else
186
+ corrector.replace(count_node.loc.selector, replacement)
187
+ end
188
+
189
+ corrector.remove(removal_range(node))
190
+ end
191
+
192
+ def removal_range(node)
193
+ range = (node.loc.dot || node.loc.selector).join(node.source_range.end)
194
+
195
+ range_with_surrounding_space(range, side: :left)
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
@@ -4,7 +4,9 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # Checks for methods invoked via the `::` operator instead
7
- # of the `.` operator (like `FileUtils::rmdir` instead of `FileUtils.rmdir`).
7
+ # of the `.` operator (like `FileUtils::rmdir` instead of
8
+ # `FileUtils.rmdir`). The `::` operator is conventionally used to
9
+ # reference constants, so using it for method calls can be misleading.
8
10
  #
9
11
  # @example
10
12
  # # bad
@@ -22,10 +24,9 @@ module RuboCop
22
24
 
23
25
  MSG = 'Do not use `::` for method calls.'
24
26
 
25
- # @!method java_type_node?(node)
26
- def_node_matcher :java_type_node?, <<~PATTERN
27
- (send
28
- (const nil? :Java) _)
27
+ # @!method java_root?(node)
28
+ def_node_matcher :java_root?, <<~PATTERN
29
+ (const nil? :Java)
29
30
  PATTERN
30
31
 
31
32
  def self.autocorrect_incompatible_with
@@ -35,11 +36,19 @@ module RuboCop
35
36
  def on_send(node)
36
37
  return unless node.receiver && node.double_colon?
37
38
  return if node.camel_case_method?
38
- # ignore Java interop code like Java::int
39
- return if java_type_node?(node)
39
+ # ignore Java interop code like `Java::int` or `Java::com::method`
40
+ return if java_interop?(node)
40
41
 
41
42
  add_offense(node.loc.dot) { |corrector| corrector.replace(node.loc.dot, '.') }
42
43
  end
44
+
45
+ private
46
+
47
+ def java_interop?(node)
48
+ receiver = node.receiver
49
+ receiver = receiver.receiver while receiver.respond_to?(:receiver) && receiver.receiver
50
+ java_root?(receiver)
51
+ end
43
52
  end
44
53
  end
45
54
  end
@@ -60,32 +60,38 @@ module RuboCop
60
60
  # end
61
61
  #
62
62
  class CombinableLoops < Base
63
+ include RangeHelp
63
64
  extend AutoCorrector
64
65
 
65
66
  MSG = 'Combine this loop with the previous loop.'
66
67
 
67
- # rubocop:disable Metrics/CyclomaticComplexity
68
+ def self.autocorrect_incompatible_with
69
+ [Layout::BlockEndNewline, Layout::RedundantLineBreak]
70
+ end
71
+
68
72
  def on_block(node)
69
73
  return unless node.parent&.begin_type?
70
74
  return unless collection_looping_method?(node)
71
- return unless same_collection_looping_block?(node, node.left_sibling)
72
- return unless node.body && node.left_sibling.body
75
+ return unless combinable_looping_blocks?(node, node.left_sibling)
73
76
 
74
77
  add_offense(node) do |corrector|
75
- next unless node.arguments == node.left_sibling.arguments
78
+ next unless combinable_blocks?(node, node.left_sibling)
76
79
 
77
80
  combine_with_left_sibling(corrector, node)
78
81
  end
79
82
  end
80
- # rubocop:enable Metrics/CyclomaticComplexity
81
83
 
82
84
  alias on_numblock on_block
85
+ alias on_itblock on_block
83
86
 
84
87
  def on_for(node)
85
88
  return unless node.parent&.begin_type?
86
89
  return unless same_collection_looping_for?(node, node.left_sibling)
90
+ return unless node.body && node.left_sibling.body
87
91
 
88
92
  add_offense(node) do |corrector|
93
+ next unless combinable_fors?(node, node.left_sibling)
94
+
89
95
  combine_with_left_sibling(corrector, node)
90
96
  end
91
97
  end
@@ -105,25 +111,102 @@ module RuboCop
105
111
  sibling.send_node.arguments == node.send_node.arguments
106
112
  end
107
113
 
114
+ def combinable_looping_blocks?(node, sibling)
115
+ same_collection_looping_block?(node, sibling) && node.body && sibling.body
116
+ end
117
+
108
118
  def same_collection_looping_for?(node, sibling)
109
119
  sibling&.for_type? && node.collection == sibling.collection
110
120
  end
111
121
 
122
+ def combinable_blocks?(node, sibling)
123
+ return false unless node.arguments == sibling.arguments
124
+ # Numbered and `it` parameters are implicit, so `arguments` is empty for both.
125
+ return false unless node.argument_list == sibling.argument_list
126
+ return false if directive_after_opening?(node)
127
+
128
+ !node.body.type?(:rescue, :ensure) && !sibling.body.type?(:rescue, :ensure)
129
+ end
130
+
131
+ # Combining loops with different iteration variables would leave the second
132
+ # body referencing an undefined variable, so only autocorrect when they match.
133
+ def combinable_fors?(node, sibling)
134
+ node.variable == sibling.variable && !directive_after_opening?(node)
135
+ end
136
+
137
+ # The opening is removed, so a directive after it would end up on a line of
138
+ # its own, where it covers the rest of the file instead of a single line.
139
+ def directive_after_opening?(node)
140
+ opening_line = loop_opening(node).line
141
+ return false if opening_line == node.body.first_line
142
+
143
+ comment = processed_source.comment_at_line(opening_line)
144
+ comment && DirectiveComment.new(comment).start_with_marker?
145
+ end
146
+
147
+ # The block arguments or `{`/`do` of a block, or the `do` or collection of a `for` loop.
148
+ def loop_opening(node)
149
+ if node.for_type?
150
+ node.loc.begin || node.collection.source_range
151
+ else
152
+ (node.block_type? && node.arguments.source_range) || node.loc.begin
153
+ end
154
+ end
155
+
112
156
  def combine_with_left_sibling(corrector, node)
113
- corrector.remove(node.left_sibling.body.source_range.end.join(node.left_sibling.loc.end))
114
- corrector.remove(node.source_range.begin.join(node.body.source_range.begin))
157
+ corrector.remove(closing_with_preceding_space(node.left_sibling, node))
158
+ corrector.remove(opening_with_following_space(node))
115
159
 
116
160
  correct_end_of_block(corrector, node)
117
161
  end
118
162
 
163
+ # Comments and heredoc bodies before the closing delimiter are kept. When
164
+ # the next loop starts on the delimiter's line, the line break before the
165
+ # delimiter is kept too, so that a comment doesn't swallow the next loop.
166
+ def closing_with_preceding_space(loop, next_loop)
167
+ separate_lines = !same_line?(loop.loc.end, next_loop)
168
+
169
+ range_with_surrounding_space(
170
+ loop.loc.end, side: :left, newlines: separate_lines, whitespace: separate_lines
171
+ )
172
+ end
173
+
174
+ # Comments between the opening and the body are kept.
175
+ def opening_with_following_space(node)
176
+ opening = node.source_range.begin.join(loop_opening(node))
177
+
178
+ range_with_surrounding_space(opening, side: :right, whitespace: true)
179
+ end
180
+
119
181
  def correct_end_of_block(corrector, node)
120
182
  return unless node.left_sibling.respond_to?(:braces?)
121
- return if node.right_sibling&.any_block_type?
183
+ return if combined_with_right_sibling?(node)
122
184
 
123
- end_of_block = node.left_sibling.braces? ? '}' : ' end'
185
+ end_of_block = first_combined_block(node).braces? ? '}' : ' end'
124
186
  corrector.remove(node.loc.end)
125
187
  corrector.insert_before(node.source_range.end, end_of_block)
126
188
  end
189
+
190
+ def combined_with_right_sibling?(node)
191
+ sibling = node.right_sibling
192
+ return false unless sibling&.any_block_type?
193
+ # A disabled loop isn't corrected, so it doesn't get merged into this one.
194
+ return false unless enabled_lines?(sibling.source_range)
195
+
196
+ same_collection_looping_block?(sibling, node) && sibling.body &&
197
+ combinable_blocks?(sibling, node)
198
+ end
199
+
200
+ def first_combined_block(node)
201
+ first = node.left_sibling
202
+
203
+ while (previous = first.left_sibling) && enabled_lines?(first.source_range) &&
204
+ combinable_looping_blocks?(first, previous) && combinable_blocks?(first, previous)
205
+ first = previous
206
+ end
207
+
208
+ first
209
+ end
127
210
  end
128
211
  end
129
212
  end
@@ -173,7 +173,7 @@ module RuboCop
173
173
  end
174
174
 
175
175
  def preferred_delimiters_config
176
- config.for_cop('Style/PercentLiteralDelimiters') ['PreferredDelimiters']
176
+ config.for_cop('Style/PercentLiteralDelimiters')['PreferredDelimiters']
177
177
  end
178
178
  end
179
179
  end
@@ -9,8 +9,8 @@ module RuboCop
9
9
  # These keywords are: `class`, `module`, `def`, `begin`, `end`.
10
10
  #
11
11
  # Note that some comments
12
- # (`:nodoc:`, `:yields:`, `rubocop:disable` and `rubocop:todo`)
13
- # and RBS::Inline annotation comments are allowed.
12
+ # (`:nodoc:`, `:yields:`, `rubocop:disable` and `rubocop:todo`),
13
+ # RBS::Inline annotation, and Steep annotation (`steep:ignore`) are allowed.
14
14
  #
15
15
  # Autocorrection removes comments from `end` keyword and keeps comments
16
16
  # for `class`, `module`, `def` and `begin` above the keyword.
@@ -57,8 +57,10 @@ module RuboCop
57
57
 
58
58
  REGEXP = /(?<keyword>\S+).*#/.freeze
59
59
 
60
- SUBCLASS_DEFINITION = /\A\s*class\s+\w+\s*<\s*\w+/.freeze
61
- METHOD_DEFINITION = /\A\s*def\s/.freeze
60
+ SUBCLASS_DEFINITION = /\A\s*class\s+(\w|::)+\s*<\s*(\w|::)+/.freeze
61
+ METHOD_OR_END_DEFINITIONS = /\A\s*(def\s|end)/.freeze
62
+
63
+ STEEP_REGEXP = /#\ssteep:ignore(\s|\z)/.freeze
62
64
 
63
65
  def on_new_investigation
64
66
  processed_source.comments.each do |comment|
@@ -86,6 +88,7 @@ module RuboCop
86
88
  def offensive?(comment)
87
89
  line = source_line(comment)
88
90
  return false if rbs_inline_annotation?(line, comment)
91
+ return false if steep_annotation?(comment)
89
92
 
90
93
  KEYWORD_REGEXES.any? { |r| r.match?(line) } &&
91
94
  ALLOWED_COMMENT_REGEXES.none? { |r| r.match?(line) }
@@ -99,12 +102,16 @@ module RuboCop
99
102
  case line
100
103
  when SUBCLASS_DEFINITION
101
104
  comment.text.start_with?(/#\[.+\]/)
102
- when METHOD_DEFINITION
105
+ when METHOD_OR_END_DEFINITIONS
103
106
  comment.text.start_with?('#:')
104
107
  else
105
108
  false
106
109
  end
107
110
  end
111
+
112
+ def steep_annotation?(comment)
113
+ comment.text.match?(STEEP_REGEXP)
114
+ end
108
115
  end
109
116
  end
110
117
  end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for logical comparison which can be replaced with `Comparable#between?`.
7
+ #
8
+ # NOTE: `Comparable#between?` is on average slightly slower than logical comparison,
9
+ # although the difference generally isn't observable. If you require maximum
10
+ # performance, consider using logical comparison.
11
+ #
12
+ # @safety
13
+ # This cop is unsafe because the receiver may not respond to `between?`.
14
+ #
15
+ # @example
16
+ #
17
+ # # bad
18
+ # x >= min && x <= max
19
+ #
20
+ # # bad
21
+ # x <= max && x >= min
22
+ #
23
+ # # good
24
+ # x.between?(min, max)
25
+ #
26
+ class ComparableBetween < Base
27
+ extend AutoCorrector
28
+
29
+ MSG = 'Prefer `%<prefer>s` over logical comparison.'
30
+
31
+ # @!method logical_comparison_between_by_min_first?(node)
32
+ def_node_matcher :logical_comparison_between_by_min_first?, <<~PATTERN
33
+ (and
34
+ (send
35
+ {$_value :>= $_min | $_min :<= $_value})
36
+ (send
37
+ {$_value :<= $_max | $_max :>= $_value}))
38
+ PATTERN
39
+
40
+ # @!method logical_comparison_between_by_max_first?(node)
41
+ def_node_matcher :logical_comparison_between_by_max_first?, <<~PATTERN
42
+ (and
43
+ (send
44
+ {$_value :<= $_max | $_max :>= $_value})
45
+ (send
46
+ {$_value :>= $_min | $_min :<= $_value}))
47
+ PATTERN
48
+
49
+ def on_and(node)
50
+ logical_comparison_between_by_min_first?(node) do |*args|
51
+ min_and_value, max_and_value = args.each_slice(2).to_a
52
+
53
+ register_offense(node, min_and_value, max_and_value)
54
+ end
55
+
56
+ logical_comparison_between_by_max_first?(node) do |*args|
57
+ max_and_value, min_and_value = args.each_slice(2).to_a
58
+
59
+ register_offense(node, min_and_value, max_and_value)
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def register_offense(node, min_and_value, max_and_value)
66
+ value = (min_and_value & max_and_value).first
67
+ min = min_and_value.find { _1 != value } || value
68
+ max = max_and_value.find { _1 != value } || value
69
+
70
+ prefer = "#{value.source}.between?(#{min.source}, #{max.source})"
71
+ add_offense(node, message: format(MSG, prefer: prefer)) do |corrector|
72
+ corrector.replace(node, prefer)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -90,7 +90,7 @@ module RuboCop
90
90
  max = if_body.source
91
91
  end
92
92
 
93
- prefer = "#{else_body_source}.clamp(#{min}, #{max})"
93
+ prefer = "#{parenthesize_if_needed(else_body)}.clamp(#{min}, #{max})"
94
94
 
95
95
  add_offense(node, message: format(MSG, prefer: prefer)) do |corrector|
96
96
  autocorrect(corrector, node, prefer)
@@ -119,6 +119,17 @@ module RuboCop
119
119
 
120
120
  (lhs.source == else_body && op == :<) || (rhs.source == else_body && op == :>)
121
121
  end
122
+
123
+ # `a + b` must become `(a + b).clamp(low, high)`, not `a + b.clamp(low, high)`
124
+ # (which parses as `a + (b.clamp(low, high))`).
125
+ def parenthesize_if_needed(node)
126
+ if node.type?(:and, :or, :if, :range) || node.assignment? ||
127
+ (node.send_type? && (node.operator_method? || node.unary_operation?))
128
+ "(#{node.source})"
129
+ else
130
+ node.source
131
+ end
132
+ end
122
133
  end
123
134
  end
124
135
  end
@@ -23,6 +23,7 @@ module RuboCop
23
23
  # list.push(qux, quux, corge)
24
24
  #
25
25
  class ConcatArrayLiterals < Base
26
+ include RangeHelp
26
27
  extend AutoCorrector
27
28
 
28
29
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
@@ -30,7 +31,15 @@ module RuboCop
30
31
  'Use `push` with elements as arguments without array brackets instead of `%<current>s`.'
31
32
  RESTRICT_ON_SEND = %i[concat].freeze
32
33
 
33
- # rubocop:disable Metrics
34
+ # `Style/MethodCallWithArgsParentheses` removing the parentheses of the `push(...)`
35
+ # this cop writes in the same pass drops the line continuation a multiline call needs.
36
+ # `Style/TrailingCommaInArguments` adds a comma after the array literal this cop
37
+ # replaces with its elements in the same pass.
38
+ def self.autocorrect_incompatible_with
39
+ [Style::MethodCallWithArgsParentheses, Style::TrailingCommaInArguments]
40
+ end
41
+
42
+ # rubocop:disable-next Metrics
34
43
  def on_send(node)
35
44
  return if node.arguments.empty?
36
45
  return unless node.arguments.all?(&:array_type?)
@@ -52,17 +61,18 @@ module RuboCop
52
61
 
53
62
  add_offense(offense, message: message) do |corrector|
54
63
  if use_percent_literal
55
- corrector.replace(offense, prefer)
64
+ next unless prefer
65
+
66
+ rebuild_call(corrector, offense, prefer)
67
+ elsif node.arguments.any? { |argument| argument.children.empty? }
68
+ # In-place bracket removal would leave dangling commas (e.g.
69
+ # `concat([], [b])` -> `push(, b)`), so rebuild the call instead.
70
+ rebuild_call(corrector, offense, preferred_method(node))
56
71
  else
57
- corrector.replace(node.loc.selector, 'push')
58
- node.arguments.each do |argument|
59
- corrector.remove(argument.loc.begin)
60
- corrector.remove(argument.loc.end)
61
- end
72
+ remove_brackets(corrector, node)
62
73
  end
63
74
  end
64
75
  end
65
- # rubocop:enable Metrics
66
76
  alias on_csend on_send
67
77
 
68
78
  private
@@ -73,7 +83,7 @@ module RuboCop
73
83
 
74
84
  def preferred_method(node)
75
85
  new_arguments =
76
- node.arguments.map do |arg|
86
+ node.arguments.flat_map do |arg|
77
87
  if arg.percent_literal?
78
88
  arg.children.map { |child| child.value.inspect }
79
89
  else
@@ -89,6 +99,52 @@ module RuboCop
89
99
  arg.children.all? { |child| child.type?(:str, :sym) }
90
100
  end
91
101
  end
102
+
103
+ def rebuild_call(corrector, offense, replacement)
104
+ # The comments inside the call would be lost.
105
+ return if comment_in?(offense)
106
+
107
+ corrector.replace(offense, replacement)
108
+ end
109
+
110
+ def comment_in?(range)
111
+ processed_source.each_comment_in_lines(range.line..range.last_line).any? do |comment|
112
+ range.contains?(comment.source_range)
113
+ end
114
+ end
115
+
116
+ def remove_brackets(corrector, node)
117
+ closing_ranges = node.arguments.map { |argument| closing_bracket_range(node, argument) }
118
+ # A comment or a heredoc body there can't be moved out of the way.
119
+ return unless closing_ranges.all? { |range| range.source.match?(/\A[\s,]*\]\z/) }
120
+
121
+ replace_selector(corrector, node)
122
+
123
+ node.arguments.zip(closing_ranges) do |argument, closing_range|
124
+ corrector.remove(argument.loc.begin)
125
+ corrector.remove(closing_range)
126
+ end
127
+ end
128
+
129
+ # Whatever sits between the last element and the `]` of an array that isn't the
130
+ # last argument would end up before the following comma (a newline before it is a
131
+ # syntax error), so it's removed along with the `]`.
132
+ def closing_bracket_range(node, argument)
133
+ return argument.loc.end if argument.equal?(node.last_argument)
134
+
135
+ range_between(argument.children.last.source_range.end_pos, argument.loc.end.end_pos)
136
+ end
137
+
138
+ def replace_selector(corrector, node)
139
+ if node.parenthesized? || node.single_line?
140
+ corrector.replace(node.loc.selector, 'push')
141
+ else
142
+ range = node.loc.selector.join(node.first_argument.source_range.begin)
143
+
144
+ corrector.replace(range, 'push(')
145
+ corrector.insert_after(node.last_argument.loc.end, ')')
146
+ end
147
+ end
92
148
  end
93
149
  end
94
150
  end