rubocop 1.79.2 → 1.87.0

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 (376) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +185 -20
  5. data/config/obsoletion.yml +9 -0
  6. data/exe/rubocop +1 -8
  7. data/lib/rubocop/cache_config.rb +29 -0
  8. data/lib/rubocop/cli/command/auto_generate_config.rb +30 -4
  9. data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
  10. data/lib/rubocop/cli/command/lsp.rb +1 -1
  11. data/lib/rubocop/cli/command/mcp.rb +19 -0
  12. data/lib/rubocop/cli/command/show_cops.rb +2 -2
  13. data/lib/rubocop/cli/command/show_docs_url.rb +4 -8
  14. data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
  15. data/lib/rubocop/cli.rb +35 -9
  16. data/lib/rubocop/comment_config.rb +59 -17
  17. data/lib/rubocop/config.rb +14 -10
  18. data/lib/rubocop/config_finder.rb +1 -1
  19. data/lib/rubocop/config_loader.rb +37 -23
  20. data/lib/rubocop/config_loader_resolver.rb +20 -10
  21. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -2
  22. data/lib/rubocop/config_store.rb +7 -2
  23. data/lib/rubocop/config_validator.rb +1 -1
  24. data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
  25. data/lib/rubocop/cop/base.rb +8 -2
  26. data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
  27. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
  28. data/lib/rubocop/cop/correctors/alignment_corrector.rb +26 -7
  29. data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
  30. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
  31. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -5
  32. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +33 -2
  33. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  34. data/lib/rubocop/cop/correctors.rb +28 -0
  35. data/lib/rubocop/cop/documentation.rb +2 -3
  36. data/lib/rubocop/cop/exclude_limit.rb +31 -5
  37. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
  38. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -2
  39. data/lib/rubocop/cop/gemspec/require_mfa.rb +5 -5
  40. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +12 -7
  41. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
  42. data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
  43. data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
  44. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
  45. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +9 -9
  46. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  47. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
  48. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  49. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
  50. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  51. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -2
  52. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  53. data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
  54. data/lib/rubocop/cop/layout/case_indentation.rb +3 -1
  55. data/lib/rubocop/cop/layout/class_structure.rb +14 -7
  56. data/lib/rubocop/cop/layout/dot_position.rb +2 -2
  57. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +26 -7
  58. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +31 -13
  59. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +2 -2
  60. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
  61. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +12 -2
  62. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +16 -2
  63. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
  64. data/lib/rubocop/cop/layout/end_alignment.rb +10 -3
  65. data/lib/rubocop/cop/layout/first_argument_indentation.rb +34 -1
  66. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
  67. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +7 -1
  68. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
  69. data/lib/rubocop/cop/layout/hash_alignment.rb +3 -6
  70. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  71. data/lib/rubocop/cop/layout/heredoc_indentation.rb +33 -3
  72. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  73. data/lib/rubocop/cop/layout/indentation_width.rb +123 -7
  74. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  75. data/lib/rubocop/cop/layout/line_length.rb +26 -9
  76. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +57 -57
  77. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +9 -2
  78. data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
  79. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +56 -56
  80. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
  81. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +229 -39
  82. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +8 -4
  83. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  84. data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -1
  85. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
  86. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  87. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  88. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  89. data/lib/rubocop/cop/layout/space_around_keyword.rb +4 -2
  90. data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -1
  91. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
  92. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  93. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  94. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
  95. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +4 -3
  96. data/lib/rubocop/cop/lint/constant_reassignment.rb +93 -11
  97. data/lib/rubocop/cop/lint/constant_resolution.rb +6 -6
  98. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
  99. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  100. data/lib/rubocop/cop/lint/debugger.rb +0 -2
  101. data/lib/rubocop/cop/lint/deprecated_constants.rb +1 -1
  102. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
  103. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  104. data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -12
  105. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
  106. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  107. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  108. data/lib/rubocop/cop/lint/empty_conditional_body.rb +6 -1
  109. data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
  110. data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
  111. data/lib/rubocop/cop/lint/empty_when.rb +8 -1
  112. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  113. data/lib/rubocop/cop/lint/float_comparison.rb +1 -1
  114. data/lib/rubocop/cop/lint/interpolation_check.rb +7 -2
  115. data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -1
  116. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  117. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -9
  118. data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
  119. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  120. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
  121. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +4 -2
  122. data/lib/rubocop/cop/lint/number_conversion.rb +6 -6
  123. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  124. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -13
  125. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
  126. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +2 -11
  127. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
  128. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +23 -6
  129. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -2
  130. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +3 -3
  131. data/lib/rubocop/cop/lint/require_relative_self_path.rb +3 -1
  132. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  133. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -0
  134. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +7 -1
  135. data/lib/rubocop/cop/lint/self_assignment.rb +15 -6
  136. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  137. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  138. data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
  139. data/lib/rubocop/cop/lint/syntax.rb +25 -1
  140. data/lib/rubocop/cop/lint/to_json.rb +12 -16
  141. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -0
  142. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -1
  143. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
  144. data/lib/rubocop/cop/lint/unreachable_code.rb +7 -5
  145. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  146. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  147. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
  148. data/lib/rubocop/cop/lint/useless_assignment.rb +48 -25
  149. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +4 -4
  150. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +2 -0
  151. data/lib/rubocop/cop/lint/useless_or.rb +15 -2
  152. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +1 -1
  153. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +37 -11
  154. data/lib/rubocop/cop/lint/void.rb +39 -12
  155. data/lib/rubocop/cop/message_annotator.rb +1 -1
  156. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  157. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  158. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  159. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  160. data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
  161. data/lib/rubocop/cop/migration/department_name.rb +12 -1
  162. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  163. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +4 -6
  164. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  165. data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
  166. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
  167. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +5 -5
  168. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  169. data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -60
  170. data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
  171. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  172. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  173. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  174. data/lib/rubocop/cop/mixin/project_index_help.rb +48 -0
  175. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  176. data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
  177. data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -5
  178. data/lib/rubocop/cop/mixin.rb +86 -0
  179. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  180. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  181. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  182. data/lib/rubocop/cop/naming/method_name.rb +5 -3
  183. data/lib/rubocop/cop/naming/predicate_method.rb +32 -8
  184. data/lib/rubocop/cop/naming/predicate_prefix.rb +12 -12
  185. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
  186. data/lib/rubocop/cop/offense.rb +17 -1
  187. data/lib/rubocop/cop/registry.rb +62 -38
  188. data/lib/rubocop/cop/security/eval.rb +15 -2
  189. data/lib/rubocop/cop/security/io_methods.rb +1 -1
  190. data/lib/rubocop/cop/security/json_load.rb +33 -11
  191. data/lib/rubocop/cop/style/access_modifier_declarations.rb +15 -4
  192. data/lib/rubocop/cop/style/accessor_grouping.rb +4 -2
  193. data/lib/rubocop/cop/style/alias.rb +14 -2
  194. data/lib/rubocop/cop/style/and_or.rb +1 -0
  195. data/lib/rubocop/cop/style/arguments_forwarding.rb +25 -7
  196. data/lib/rubocop/cop/style/array_intersect.rb +46 -12
  197. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
  198. data/lib/rubocop/cop/style/array_join.rb +4 -2
  199. data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
  200. data/lib/rubocop/cop/style/attr.rb +5 -2
  201. data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
  202. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  203. data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
  204. data/lib/rubocop/cop/style/block_delimiters.rb +27 -34
  205. data/lib/rubocop/cop/style/case_equality.rb +15 -13
  206. data/lib/rubocop/cop/style/character_literal.rb +2 -2
  207. data/lib/rubocop/cop/style/class_and_module_children.rb +19 -2
  208. data/lib/rubocop/cop/style/collection_compact.rb +36 -16
  209. data/lib/rubocop/cop/style/colon_method_call.rb +3 -1
  210. data/lib/rubocop/cop/style/concat_array_literals.rb +2 -0
  211. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -18
  212. data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
  213. data/lib/rubocop/cop/style/copyright.rb +22 -11
  214. data/lib/rubocop/cop/style/date_time.rb +2 -2
  215. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +1 -1
  216. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
  217. data/lib/rubocop/cop/style/documentation.rb +6 -6
  218. data/lib/rubocop/cop/style/documentation_method.rb +8 -8
  219. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  220. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  221. data/lib/rubocop/cop/style/each_with_object.rb +2 -0
  222. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  223. data/lib/rubocop/cop/style/empty_class_definition.rb +119 -0
  224. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  225. data/lib/rubocop/cop/style/empty_method.rb +0 -6
  226. data/lib/rubocop/cop/style/encoding.rb +7 -1
  227. data/lib/rubocop/cop/style/end_block.rb +3 -1
  228. data/lib/rubocop/cop/style/endless_method.rb +23 -5
  229. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  230. data/lib/rubocop/cop/style/file_open.rb +84 -0
  231. data/lib/rubocop/cop/style/file_write.rb +18 -16
  232. data/lib/rubocop/cop/style/float_division.rb +15 -1
  233. data/lib/rubocop/cop/style/for.rb +3 -0
  234. data/lib/rubocop/cop/style/format_string.rb +4 -3
  235. data/lib/rubocop/cop/style/format_string_token.rb +49 -5
  236. data/lib/rubocop/cop/style/global_vars.rb +5 -2
  237. data/lib/rubocop/cop/style/guard_clause.rb +27 -22
  238. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
  239. data/lib/rubocop/cop/style/hash_conversion.rb +1 -1
  240. data/lib/rubocop/cop/style/hash_lookup_method.rb +106 -0
  241. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  242. data/lib/rubocop/cop/style/hash_transform_keys.rb +17 -7
  243. data/lib/rubocop/cop/style/hash_transform_values.rb +17 -7
  244. data/lib/rubocop/cop/style/if_inside_else.rb +16 -7
  245. data/lib/rubocop/cop/style/if_unless_modifier.rb +57 -17
  246. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +12 -12
  247. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +4 -1
  248. data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -5
  249. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  250. data/lib/rubocop/cop/style/inline_comment.rb +4 -1
  251. data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
  252. data/lib/rubocop/cop/style/lambda_call.rb +8 -8
  253. data/lib/rubocop/cop/style/magic_comment_format.rb +3 -3
  254. data/lib/rubocop/cop/style/map_join.rb +123 -0
  255. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
  256. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
  257. data/lib/rubocop/cop/style/method_def_parentheses.rb +2 -4
  258. data/lib/rubocop/cop/style/min_max_comparison.rb +1 -1
  259. data/lib/rubocop/cop/style/module_member_existence_check.rb +110 -0
  260. data/lib/rubocop/cop/style/multiline_if_then.rb +4 -4
  261. data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
  262. data/lib/rubocop/cop/style/mutable_constant.rb +1 -1
  263. data/lib/rubocop/cop/style/negative_array_index.rb +220 -0
  264. data/lib/rubocop/cop/style/nil_comparison.rb +11 -10
  265. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  266. data/lib/rubocop/cop/style/non_nil_check.rb +5 -11
  267. data/lib/rubocop/cop/style/not.rb +2 -0
  268. data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
  269. data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
  270. data/lib/rubocop/cop/style/one_line_conditional.rb +21 -12
  271. data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
  272. data/lib/rubocop/cop/style/parallel_assignment.rb +6 -2
  273. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  274. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -0
  275. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  276. data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
  277. data/lib/rubocop/cop/style/proc.rb +3 -2
  278. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  279. data/lib/rubocop/cop/style/reduce_to_hash.rb +200 -0
  280. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  281. data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
  282. data/lib/rubocop/cop/style/redundant_begin.rb +37 -3
  283. data/lib/rubocop/cop/style/redundant_condition.rb +6 -3
  284. data/lib/rubocop/cop/style/redundant_constant_base.rb +5 -5
  285. data/lib/rubocop/cop/style/redundant_each.rb +3 -3
  286. data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
  287. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
  288. data/lib/rubocop/cop/style/redundant_format.rb +26 -5
  289. data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
  290. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
  291. data/lib/rubocop/cop/style/redundant_line_continuation.rb +16 -0
  292. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  293. data/lib/rubocop/cop/style/redundant_parentheses.rb +36 -30
  294. data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
  295. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
  296. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +2 -2
  297. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
  298. data/lib/rubocop/cop/style/redundant_return.rb +3 -1
  299. data/lib/rubocop/cop/style/redundant_self.rb +2 -2
  300. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
  301. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  302. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +114 -0
  303. data/lib/rubocop/cop/style/regexp_literal.rb +31 -2
  304. data/lib/rubocop/cop/style/rescue_modifier.rb +3 -3
  305. data/lib/rubocop/cop/style/reverse_find.rb +51 -0
  306. data/lib/rubocop/cop/style/safe_navigation.rb +25 -8
  307. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  308. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  309. data/lib/rubocop/cop/style/select_by_regexp.rb +51 -21
  310. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  311. data/lib/rubocop/cop/style/semicolon.rb +25 -7
  312. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  313. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -1
  314. data/lib/rubocop/cop/style/single_line_methods.rb +3 -1
  315. data/lib/rubocop/cop/style/sole_nested_conditional.rb +12 -3
  316. data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
  317. data/lib/rubocop/cop/style/string_concatenation.rb +17 -13
  318. data/lib/rubocop/cop/style/struct_inheritance.rb +13 -0
  319. data/lib/rubocop/cop/style/super_arguments.rb +2 -2
  320. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  321. data/lib/rubocop/cop/style/symbol_proc.rb +7 -6
  322. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  323. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -2
  324. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
  325. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  326. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  327. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
  328. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  329. data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
  330. data/lib/rubocop/cop/style/while_until_modifier.rb +16 -0
  331. data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
  332. data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
  333. data/lib/rubocop/cop/team.rb +87 -36
  334. data/lib/rubocop/cop/util.rb +2 -3
  335. data/lib/rubocop/cop/utils/format_string.rb +10 -0
  336. data/lib/rubocop/cop/variable_force/branch.rb +30 -6
  337. data/lib/rubocop/cop/variable_force/variable.rb +1 -1
  338. data/lib/rubocop/cop/variable_force.rb +9 -7
  339. data/lib/rubocop/cops_documentation_generator.rb +4 -4
  340. data/lib/rubocop/directive_comment.rb +48 -4
  341. data/lib/rubocop/file_patterns.rb +9 -1
  342. data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
  343. data/lib/rubocop/formatter/disabled_config_formatter.rb +24 -7
  344. data/lib/rubocop/formatter/formatter_set.rb +2 -2
  345. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  346. data/lib/rubocop/formatter/simple_text_formatter.rb +0 -2
  347. data/lib/rubocop/formatter/tap_formatter.rb +5 -2
  348. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  349. data/lib/rubocop/formatter.rb +22 -21
  350. data/lib/rubocop/lsp/diagnostic.rb +18 -33
  351. data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
  352. data/lib/rubocop/lsp/routes.rb +43 -7
  353. data/lib/rubocop/lsp/runtime.rb +13 -4
  354. data/lib/rubocop/lsp/stdin_runner.rb +8 -17
  355. data/lib/rubocop/magic_comment.rb +20 -0
  356. data/lib/rubocop/mcp/server.rb +200 -0
  357. data/lib/rubocop/options.rb +35 -4
  358. data/lib/rubocop/path_util.rb +14 -2
  359. data/lib/rubocop/plugin/loader.rb +1 -1
  360. data/lib/rubocop/project_index_loader.rb +66 -0
  361. data/lib/rubocop/rake_task.rb +1 -1
  362. data/lib/rubocop/remote_config.rb +10 -8
  363. data/lib/rubocop/result_cache.rb +61 -38
  364. data/lib/rubocop/rspec/cop_helper.rb +8 -0
  365. data/lib/rubocop/rspec/shared_contexts.rb +39 -5
  366. data/lib/rubocop/rspec/support.rb +2 -1
  367. data/lib/rubocop/runner.rb +134 -57
  368. data/lib/rubocop/server/cache.rb +6 -29
  369. data/lib/rubocop/server/core.rb +2 -0
  370. data/lib/rubocop/target_finder.rb +17 -10
  371. data/lib/rubocop/target_ruby.rb +31 -14
  372. data/lib/rubocop/version.rb +21 -3
  373. data/lib/rubocop.rb +28 -96
  374. data/lib/ruby_lsp/rubocop/addon.rb +23 -8
  375. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
  376. metadata +38 -9
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for unreachable `in` pattern branches in `case...in` statements.
7
+ #
8
+ # An `in` branch is unreachable when a previous branch uses an unguarded
9
+ # catch-all pattern that matches any value unconditionally. Any `in` branches
10
+ # (and `else`) that follow such a catch-all are dead code.
11
+ #
12
+ # A catch-all pattern is one of:
13
+ #
14
+ # * A bare variable capture (`in x`)
15
+ # * An underscore (`in _`)
16
+ # * A pattern alias where the left side is a catch-all (`in _ => y`)
17
+ # * An alternation pattern where at least one alternative is a catch-all
18
+ # (`in _ | Integer`)
19
+ #
20
+ # NOTE: A catch-all pattern with a guard clause (e.g., `in _ if condition`)
21
+ # does NOT make subsequent branches unreachable because the guard might
22
+ # not be satisfied.
23
+ #
24
+ # @example
25
+ #
26
+ # # bad
27
+ # case value
28
+ # in Integer
29
+ # handle_integer
30
+ # in x
31
+ # handle_other
32
+ # in String
33
+ # handle_string
34
+ # else
35
+ # handle_else
36
+ # end
37
+ #
38
+ # # good
39
+ # case value
40
+ # in Integer
41
+ # handle_integer
42
+ # in String
43
+ # handle_string
44
+ # in x
45
+ # handle_other
46
+ # end
47
+ #
48
+ # # bad - else is unreachable after catch-all
49
+ # case value
50
+ # in Integer
51
+ # handle_integer
52
+ # in _
53
+ # handle_other
54
+ # else
55
+ # handle_else
56
+ # end
57
+ #
58
+ # # good - guard clause means catch-all might not match
59
+ # case value
60
+ # in x if x.positive?
61
+ # handle_positive
62
+ # in Integer
63
+ # handle_integer
64
+ # else
65
+ # handle_other
66
+ # end
67
+ #
68
+ class UnreachablePatternBranch < Base
69
+ extend TargetRubyVersion
70
+
71
+ MSG = 'Unreachable `in` pattern branch detected.'
72
+ MSG_ELSE = 'Unreachable `else` branch detected.'
73
+
74
+ minimum_target_ruby_version 2.7
75
+
76
+ def on_case_match(case_node)
77
+ catch_all_found = false
78
+
79
+ case_node.in_pattern_branches.each do |in_pattern_node|
80
+ if catch_all_found
81
+ add_offense(in_pattern_node)
82
+ next
83
+ end
84
+
85
+ pattern = in_pattern_node.pattern
86
+ guard = in_pattern_node.children[1]
87
+
88
+ catch_all_found = true if catch_all_pattern?(pattern) && guard.nil?
89
+ end
90
+
91
+ return unless catch_all_found && case_node.else?
92
+
93
+ add_offense(case_node.loc.else, message: MSG_ELSE)
94
+ end
95
+
96
+ private
97
+
98
+ def catch_all_pattern?(pattern)
99
+ case pattern.type
100
+ when :match_var
101
+ true
102
+ when :match_as, :begin
103
+ catch_all_pattern?(pattern.children[0])
104
+ when :match_alt
105
+ pattern.children.any? { |child| catch_all_pattern?(child) }
106
+ else
107
+ false
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -95,10 +95,20 @@ module RuboCop
95
95
  return unless variable.method_argument?
96
96
  return if variable.keyword_argument? && cop_config['AllowUnusedKeywordArguments']
97
97
  return if ignored_method?(variable.scope.node.body)
98
+ return if block_argument_with_yield?(variable)
98
99
 
99
100
  super
100
101
  end
101
102
 
103
+ def block_argument_with_yield?(variable)
104
+ return false unless variable.declaration_node.blockarg_type?
105
+
106
+ method_body = variable.scope.node.body
107
+ return false unless method_body
108
+
109
+ method_body.yield_type? || method_body.each_descendant(:yield).any?
110
+ end
111
+
102
112
  def ignored_method?(body)
103
113
  (cop_config['IgnoreEmptyMethods'] && body.nil?) ||
104
114
  (cop_config['IgnoreNotImplementedMethods'] && not_implemented?(body))
@@ -17,6 +17,7 @@ module RuboCop
17
17
  #
18
18
  # # good
19
19
  # CGI.escape('http://example.com')
20
+ # URI.encode_uri_component(uri) # Since Ruby 3.1
20
21
  # URI.encode_www_form([['example', 'param'], ['lang', 'en']])
21
22
  # URI.encode_www_form(page: 10, locale: 'en')
22
23
  # URI.encode_www_form_component('http://example.com')
@@ -27,6 +28,7 @@ module RuboCop
27
28
  #
28
29
  # # good
29
30
  # CGI.unescape(enc_uri)
31
+ # URI.decode_uri_component(uri) # Since Ruby 3.1
30
32
  # URI.decode_www_form(enc_uri)
31
33
  # URI.decode_www_form_component(enc_uri)
32
34
  class UriEscapeUnescape < Base
@@ -40,8 +40,6 @@ module RuboCop
40
40
  class UselessAssignment < Base
41
41
  extend AutoCorrector
42
42
 
43
- include RangeHelp
44
-
45
43
  MSG = 'Useless assignment to variable - `%<variable>s`.'
46
44
 
47
45
  def self.joining_forces
@@ -52,32 +50,39 @@ module RuboCop
52
50
  scope.variables.each_value { |variable| check_for_unused_assignments(variable) }
53
51
  end
54
52
 
55
- # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
56
53
  def check_for_unused_assignments(variable)
57
54
  return if variable.should_be_unused?
58
55
 
59
56
  variable.assignments.reverse_each do |assignment|
60
- assignment_node = assignment.node
61
- next if assignment.used? || part_of_ignored_node?(assignment_node)
57
+ check_for_unused_assignment(variable, assignment)
58
+ end
59
+ end
62
60
 
63
- message = message_for_useless_assignment(assignment)
64
- range = offense_range(assignment)
61
+ def check_for_unused_assignment(variable, assignment)
62
+ assignment_node = assignment.node
65
63
 
66
- add_offense(range, message: message) do |corrector|
67
- # In cases like `x = 1, y = 2`, where removing a variable would cause a syntax error,
68
- # and where changing `x ||= 1` to `x = 1` would cause `NameError`,
69
- # the autocorrect will be skipped, even if the variable is unused.
70
- if sequential_assignment?(assignment_node) || assignment_node.parent&.or_asgn_type?
71
- next
72
- end
64
+ return if ignored_assignment?(variable, assignment_node, assignment)
73
65
 
74
- autocorrect(corrector, assignment)
75
- end
66
+ message = message_for_useless_assignment(assignment)
67
+ range = offense_range(assignment)
76
68
 
77
- ignore_node(assignment_node) if chained_assignment?(assignment_node)
69
+ add_offense(range, message: message) do |corrector|
70
+ # In cases like `x = 1, y = 2`, where removing a variable would cause a syntax error,
71
+ # and where changing `x ||= 1` to `x = 1` would cause `NameError`,
72
+ # the autocorrect will be skipped, even if the variable is unused.
73
+ next if sequential_assignment?(assignment_node) ||
74
+ assignment_node.parent&.or_asgn_type?
75
+
76
+ autocorrect(corrector, assignment)
78
77
  end
78
+
79
+ ignore_node(assignment_node) if chained_assignment?(assignment_node)
80
+ end
81
+
82
+ def ignored_assignment?(variable, assignment_node, assignment)
83
+ assignment.used? || part_of_ignored_node?(assignment_node) ||
84
+ variable_in_loop_condition?(assignment_node, variable)
79
85
  end
80
- # rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
81
86
 
82
87
  def message_for_useless_assignment(assignment)
83
88
  variable = assignment.variable
@@ -182,12 +187,9 @@ module RuboCop
182
187
  # rubocop:enable Metrics/AbcSize
183
188
 
184
189
  def remove_exception_assignment_part(corrector, node)
185
- corrector.remove(
186
- range_between(
187
- (node.parent.children.first&.source_range || node.parent.location.keyword).end_pos,
188
- node.source_range.end_pos
189
- )
190
- )
190
+ range = node.parent.children.first&.source_range || node.parent.location.keyword
191
+
192
+ corrector.remove(range.end.join(node.source_range.end))
191
193
  end
192
194
 
193
195
  def rename_variable_with_underscore(corrector, node)
@@ -206,7 +208,28 @@ module RuboCop
206
208
  end
207
209
 
208
210
  def remove_local_variable_assignment_part(corrector, node)
209
- corrector.replace(node, node.expression.source)
211
+ corrector.remove(node.loc.name.begin.join(node.expression.source_range.begin))
212
+ end
213
+
214
+ def variable_in_loop_condition?(assignment_node, variable)
215
+ return false if assignment_node.each_ancestor(:any_def).any?
216
+
217
+ loop_node = assignment_node.each_ancestor.find do |ancestor|
218
+ ancestor.type?(*VariableForce::LOOP_TYPES)
219
+ end
220
+
221
+ return false unless loop_node.respond_to?(:condition)
222
+
223
+ condition_node = loop_node.condition
224
+ variable_name = variable.name
225
+
226
+ return true if condition_node.lvar_type? && condition_node.children.first == variable_name
227
+
228
+ condition_node.each_descendant(:lvar) do |lvar_node|
229
+ return true if lvar_node.children.first == variable_name
230
+ end
231
+
232
+ false
210
233
  end
211
234
  end
212
235
  end
@@ -48,12 +48,12 @@ module RuboCop
48
48
 
49
49
  def after_private_modifier?(left_siblings)
50
50
  access_modifier_candidates = left_siblings.compact.select do |left_sibling|
51
- left_sibling.respond_to?(:send_type?) && left_sibling.send_type?
51
+ left_sibling.respond_to?(:bare_access_modifier?) && left_sibling.bare_access_modifier?
52
52
  end
53
53
 
54
- access_modifier_candidates.any? do |candidate|
55
- candidate.command?(:private) && candidate.arguments.none?
56
- end
54
+ return false if access_modifier_candidates.empty?
55
+
56
+ access_modifier_candidates.last.command?(:private)
57
57
  end
58
58
 
59
59
  def private_constantize?(right_siblings, const_value)
@@ -67,6 +67,8 @@ module RuboCop
67
67
  PATTERN
68
68
 
69
69
  def on_send(node)
70
+ return unless node.receiver
71
+
70
72
  unless (prev_arg_node, default_value_node = default_value_argument_and_block(node.parent))
71
73
  return
72
74
  end
@@ -9,6 +9,13 @@ module RuboCop
9
9
  # on `nil` (e.g. `nil.to_i` evaluates to `0`). Therefore, OR expressions
10
10
  # appended after these methods will never evaluate.
11
11
  #
12
+ # @safety
13
+ # As shown in the examples below, there are generally two possible ways to correct the
14
+ # offense, but this cop's autocorrection always chooses the option that preserves the
15
+ # current behavior. While this does not change how the code behaves, that option is not
16
+ # necessarily the appropriate fix in every situation. For this reason, the autocorrection
17
+ # provided by this cop is considered unsafe.
18
+ #
12
19
  # @example
13
20
  #
14
21
  # # bad
@@ -64,6 +71,8 @@ module RuboCop
64
71
  # x&.to_s or fallback
65
72
  #
66
73
  class UselessOr < Base
74
+ extend AutoCorrector
75
+
67
76
  MSG = '`%<rhs>s` will never evaluate because `%<lhs>s` always returns a truthy value.'
68
77
 
69
78
  TRUTHY_RETURN_VALUE_METHODS = Set[:to_a, :to_c, :to_d, :to_i, :to_f, :to_h, :to_r,
@@ -89,8 +98,12 @@ module RuboCop
89
98
  private
90
99
 
91
100
  def report_offense(or_node, truthy_node)
92
- add_offense(or_node.loc.operator.join(or_node.rhs.source_range),
93
- message: format(MSG, lhs: truthy_node.source, rhs: or_node.rhs.source))
101
+ add_offense(
102
+ or_node.loc.operator.join(or_node.rhs.source_range),
103
+ message: format(MSG, lhs: truthy_node.source, rhs: or_node.rhs.source)
104
+ ) do |corrector|
105
+ corrector.replace(or_node, or_node.lhs.source)
106
+ end
94
107
  end
95
108
  end
96
109
  end
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # Looks for `ruby2_keywords` calls for methods that do not need it.
7
7
  #
8
8
  # `ruby2_keywords` should only be called on methods that accept an argument splat
9
- # (`\*args`) but do not explicit keyword arguments (`k:` or `k: true`) or
9
+ # (`\*args`) but do not have explicit keyword arguments (`k:` or `k: true`) or
10
10
  # a keyword splat (`**kwargs`).
11
11
  #
12
12
  # @example
@@ -31,7 +31,7 @@ module RuboCop
31
31
  @checked_nodes[node] = true
32
32
 
33
33
  case node.type
34
- when :def, :class, :module, :sclass
34
+ when :def, :defs, :class, :module, :sclass
35
35
  return false
36
36
  when :send
37
37
  return non_nil_method?(node.method_name) if node.receiver == receiver
@@ -53,16 +53,14 @@ module RuboCop
53
53
  return true
54
54
  end
55
55
  when :when
56
- node.each_condition do |condition|
56
+ node.conditions.each do |condition|
57
57
  return true if _cant_be_nil?(condition, receiver)
58
58
  end
59
59
  when :lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn
60
60
  return true if _cant_be_nil?(node.expression, receiver)
61
61
  end
62
62
 
63
- # Due to how `if/else` are implemented (`elsif` is a child of `if` or another `elsif`),
64
- # using left_siblings will not work correctly for them.
65
- if !else_branch?(node) || (node.if_type? && !node.elsif?)
63
+ if sequentially_reached?(node)
66
64
  node.left_siblings.reverse_each do |sibling|
67
65
  next unless sibling.is_a?(AST::Node)
68
66
 
@@ -82,28 +80,48 @@ module RuboCop
82
80
  !NIL_METHODS.include?(method_name) && !@additional_nil_methods.include?(method_name)
83
81
  end
84
82
 
85
- # rubocop:disable Metrics/PerceivedComplexity
83
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
86
84
  def sole_condition_of_parent_if?(node)
85
+ child = node
87
86
  parent = node.parent
88
87
 
89
88
  while parent
90
89
  if parent.if_type?
91
- if parent.condition == node
92
- return true
93
- elsif parent.elsif?
94
- parent = find_top_if(parent)
90
+ unless parent.unless?
91
+ condition = parent.condition
92
+ return true if !child.equal?(condition) && non_nil_condition?(condition, node)
95
93
  end
94
+
95
+ parent = find_top_if(parent) if parent.elsif?
96
96
  elsif else_branch?(parent)
97
97
  # Find the top `if` for `else`.
98
98
  parent = parent.parent
99
99
  end
100
100
 
101
+ child = parent
101
102
  parent = parent&.parent
102
103
  end
103
104
 
104
105
  false
105
106
  end
106
- # rubocop:enable Metrics/PerceivedComplexity
107
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
108
+
109
+ def non_nil_condition?(condition, node)
110
+ return true if condition == node
111
+
112
+ condition.csend_type? && csend_root_receiver(condition) == node
113
+ end
114
+
115
+ # Whether control reaches `node` by falling through its left siblings rather than by
116
+ # a non-sequential entry. A `resbody` is entered via an exception, the `ensure` branch
117
+ # runs even after a partway raise, and the `else` arm of an `if/elsif` chain is reached by
118
+ # branching (its `if/case` siblings are walked via parent recursion instead).
119
+ def sequentially_reached?(node)
120
+ return false if node.resbody_type?
121
+ return false if node.parent&.ensure_type? && node.parent.branch.equal?(node)
122
+
123
+ !else_branch?(node) || (node.if_type? && !node.elsif?)
124
+ end
107
125
 
108
126
  def else_branch?(node)
109
127
  node.parent&.if_type? && node.parent.else_branch == node
@@ -114,6 +132,14 @@ module RuboCop
114
132
 
115
133
  node
116
134
  end
135
+
136
+ def csend_root_receiver(node)
137
+ return unless (receiver = node.receiver)
138
+
139
+ receiver = receiver.receiver while receiver.call_type? && receiver.receiver
140
+
141
+ receiver
142
+ end
117
143
  end
118
144
  end
119
145
  end
@@ -16,6 +16,12 @@ module RuboCop
16
16
  # enumerator.each { |item| item >= 2 } #=> [2, 3]
17
17
  # ----
18
18
  #
19
+ # NOTE: Return values in assignment method definitions such as `def foo=(arg)` are
20
+ # detected because they are in a void context. However, autocorrection does not remove
21
+ # the return value, as that would change behavior. In such cases, whether to remove
22
+ # the return value or rename the method to something more appropriate should be left to
23
+ # the user.
24
+ #
19
25
  # @example CheckForMethodsWithNoSideEffects: false (default)
20
26
  # # bad
21
27
  # def some_method
@@ -81,8 +87,9 @@ module RuboCop
81
87
  def on_block(node)
82
88
  return unless node.body && !node.body.begin_type?
83
89
  return unless in_void_context?(node.body)
90
+ return if node.method?(:each)
84
91
 
85
- check_void_op(node.body) { node.method?(:each) }
92
+ check_void_op(node.body)
86
93
  check_expression(node.body)
87
94
  end
88
95
  alias on_numblock on_block
@@ -101,22 +108,23 @@ module RuboCop
101
108
 
102
109
  def check_begin(node)
103
110
  expressions = *node
104
- expressions.pop unless in_void_context?(node)
111
+ inside_each_block = node.each_ancestor(:any_block).first&.method?(:each)
112
+ expressions.pop if !in_void_context?(node) || inside_each_block
105
113
  expressions.each do |expr|
106
- check_void_op(expr) do
107
- block_node = node.each_ancestor(:any_block).first
108
-
109
- block_node&.method?(:each)
110
- end
111
-
114
+ check_void_op(expr) { inside_each_block }
112
115
  check_expression(expr)
113
116
  end
114
117
  end
115
118
 
116
119
  def check_expression(expr)
117
- expr = expr.body if expr.if_type?
118
- return unless expr
120
+ return check_if_expression(expr) if expr.if_type?
121
+ return check_case_expression(expr) if expr.case_type?
122
+ return check_case_match_expression(expr) if expr.case_match_type?
119
123
 
124
+ check_void_expression_nodes(expr)
125
+ end
126
+
127
+ def check_void_expression_nodes(expr)
120
128
  check_literal(expr)
121
129
  check_var(expr)
122
130
  check_self(expr)
@@ -126,6 +134,22 @@ module RuboCop
126
134
  check_nonmutating(expr)
127
135
  end
128
136
 
137
+ def check_if_expression(if_node)
138
+ check_void_expression_nodes(if_node.body) if if_node.body
139
+ end
140
+
141
+ def check_case_expression(case_node)
142
+ case_node.each_when { |when_node| check_expression(when_node.body) if when_node.body }
143
+ check_expression(case_node.else_branch) if case_node.else_branch
144
+ end
145
+
146
+ def check_case_match_expression(case_node)
147
+ case_node.each_in_pattern do |in_pattern_node|
148
+ check_expression(in_pattern_node.body) if in_pattern_node.body
149
+ end
150
+ check_expression(case_node.else_branch) if case_node.else_branch
151
+ end
152
+
129
153
  # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
130
154
  def check_void_op(node, &block)
131
155
  node = node.children.first while node&.begin_type?
@@ -162,7 +186,9 @@ module RuboCop
162
186
  end
163
187
 
164
188
  def check_literal(node)
165
- return if !entirely_literal?(node) || node.xstr_type? || node.range_type?
189
+ if !entirely_literal?(node) || node.xstr_type? || node.range_type? || node.nil_type?
190
+ return
191
+ end
166
192
 
167
193
  add_offense(node, message: format(LIT_MSG, lit: node.source)) do |corrector|
168
194
  autocorrect_void_expression(corrector, node)
@@ -232,7 +258,8 @@ module RuboCop
232
258
  end
233
259
 
234
260
  def autocorrect_void_expression(corrector, node)
235
- return if node.parent.if_type?
261
+ return if node.parent.type?(:if, :case, :when, :case_match, :in_pattern)
262
+ return if (def_node = node.each_ancestor(:any_def).first) && def_node.assignment_method?
236
263
 
237
264
  corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
238
265
  end
@@ -102,7 +102,7 @@ module RuboCop
102
102
  def reference_urls
103
103
  urls = cop_config
104
104
  .values_at('References', 'Reference') # Support legacy Reference key
105
- .flat_map { Array(_1) }
105
+ .flat_map { |url| Array(url) }
106
106
  .reject(&:empty?)
107
107
 
108
108
  urls unless urls.empty?
@@ -17,7 +17,7 @@ module RuboCop
17
17
  #
18
18
  # NOTE: The `ExcludedMethods` configuration is deprecated and only kept
19
19
  # for backwards compatibility. Please use `AllowedMethods` and `AllowedPatterns`
20
- # instead. By default, there are no methods to allowed.
20
+ # instead. By default, there are no allowed methods.
21
21
  #
22
22
  # @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
23
23
  #
@@ -4,6 +4,8 @@ module RuboCop
4
4
  module Cop
5
5
  module Metrics
6
6
  # Checks for excessive nesting of conditional and looping constructs.
7
+ # Deeply nested code is harder to read, understand, and maintain.
8
+ # Extracting nested logic into methods improves clarity.
7
9
  #
8
10
  # You can configure if blocks are considered using the `CountBlocks` and `CountModifierForms`
9
11
  # options. When both are set to `false` (the default) blocks and modifier forms are not
@@ -11,6 +13,27 @@ module RuboCop
11
13
  # calculation as well.
12
14
  #
13
15
  # The maximum level of nesting allowed is configurable.
16
+ #
17
+ # @example Max: 3 (default)
18
+ # # bad
19
+ # if condition1
20
+ # if condition2
21
+ # if condition3
22
+ # if condition4
23
+ # do_something
24
+ # end
25
+ # end
26
+ # end
27
+ # end
28
+ #
29
+ # # good
30
+ # if condition1
31
+ # if condition2
32
+ # if condition3
33
+ # do_something
34
+ # end
35
+ # end
36
+ # end
14
37
  class BlockNesting < Base
15
38
  NESTING_BLOCKS = %i[case case_match if while while_post until until_post for resbody].freeze
16
39
 
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # NOTE: The `ExcludedMethods` and `IgnoredMethods` configuration is
16
16
  # deprecated and only kept for backwards compatibility.
17
17
  # Please use `AllowedMethods` and `AllowedPatterns` instead.
18
- # By default, there are no methods to allowed.
18
+ # By default, there are no allowed methods.
19
19
  #
20
20
  # @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
21
21
  #
@@ -84,7 +84,10 @@ module RuboCop
84
84
  end
85
85
 
86
86
  def assignment?(node)
87
- return compound_assignment(node) if node.masgn_type? || node.shorthand_asgn?
87
+ if node.masgn_type? || node.shorthand_asgn?
88
+ compound_assignment(node)
89
+ return false
90
+ end
88
91
 
89
92
  node.for_type? ||
90
93
  (node.respond_to?(:setter_method?) && node.setter_method?) ||
@@ -101,8 +104,6 @@ module RuboCop
101
104
  child.respond_to?(:setter_method?) && !child.setter_method?
102
105
  end
103
106
  @assignment += will_be_miscounted
104
-
105
- false
106
107
  end
107
108
 
108
109
  def simple_assignment?(node)
@@ -43,7 +43,7 @@ module RuboCop
43
43
  end
44
44
  end
45
45
 
46
- # Returns true iff name is a known iterating type (e.g. :each, :transform_values)
46
+ # Returns true only when name is a known iterating type (e.g. :each, :transform_values).
47
47
  def iterating_method?(name)
48
48
  KNOWN_ITERATING_METHODS.include? name
49
49
  end
@@ -1,10 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Lint/RedundantCopDisableDirective needs to be disabled so as
4
+ # to be able to provide examples of rubocop:disable comments.
5
+ # rubocop:disable Lint/RedundantCopDisableDirective
3
6
  module RuboCop
4
7
  module Cop
5
8
  module Migration
6
- # Check that cop names in rubocop:disable comments are given with
9
+ # Checks that cop names in rubocop:disable comments are given with
7
10
  # department name.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # # rubocop:disable AbcSize
15
+ #
16
+ # # good
17
+ # # rubocop:disable Metrics/AbcSize
8
18
  class DepartmentName < Base
9
19
  include RangeHelp
10
20
  extend AutoCorrector
@@ -79,3 +89,4 @@ module RuboCop
79
89
  end
80
90
  end
81
91
  end
92
+ # rubocop:enable Lint/RedundantCopDisableDirective
@@ -222,12 +222,12 @@ module RuboCop
222
222
  def already_on_multiple_lines?(node)
223
223
  return node.first_line != node.last_argument.last_line if node.any_def_type?
224
224
 
225
- !node.single_line?
225
+ node.multiline?
226
226
  end
227
227
 
228
228
  def chained_to_heredoc?(node)
229
229
  while (node = node.receiver)
230
- return true if node.type?(:str, :dstr, :xstr) && node.heredoc?
230
+ return true if node.any_str_type? && node.heredoc?
231
231
  end
232
232
 
233
233
  false