rubocop 1.80.2 → 1.86.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 (310) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +170 -19
  5. data/config/obsoletion.yml +9 -0
  6. data/lib/rubocop/cache_config.rb +29 -0
  7. data/lib/rubocop/cli/command/auto_generate_config.rb +3 -3
  8. data/lib/rubocop/cli/command/lsp.rb +1 -1
  9. data/lib/rubocop/cli/command/mcp.rb +19 -0
  10. data/lib/rubocop/cli/command/show_cops.rb +2 -2
  11. data/lib/rubocop/cli/command/show_docs_url.rb +1 -1
  12. data/lib/rubocop/cli.rb +28 -6
  13. data/lib/rubocop/comment_config.rb +62 -17
  14. data/lib/rubocop/config.rb +14 -10
  15. data/lib/rubocop/config_finder.rb +1 -1
  16. data/lib/rubocop/config_loader.rb +20 -21
  17. data/lib/rubocop/config_loader_resolver.rb +9 -7
  18. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -2
  19. data/lib/rubocop/config_store.rb +6 -1
  20. data/lib/rubocop/config_validator.rb +1 -1
  21. data/lib/rubocop/cop/autocorrect_logic.rb +8 -4
  22. data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
  23. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
  24. data/lib/rubocop/cop/correctors/alignment_corrector.rb +22 -6
  25. data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
  26. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  27. data/lib/rubocop/cop/documentation.rb +2 -3
  28. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -2
  29. data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
  30. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +10 -5
  31. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
  32. data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
  33. data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
  34. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +9 -9
  35. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  36. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
  37. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  38. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
  39. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  40. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -2
  41. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  42. data/lib/rubocop/cop/layout/case_indentation.rb +3 -1
  43. data/lib/rubocop/cop/layout/class_structure.rb +13 -6
  44. data/lib/rubocop/cop/layout/dot_position.rb +2 -2
  45. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +12 -2
  46. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +31 -13
  47. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
  48. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
  49. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +12 -2
  50. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +16 -2
  51. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
  52. data/lib/rubocop/cop/layout/end_alignment.rb +8 -1
  53. data/lib/rubocop/cop/layout/first_argument_indentation.rb +34 -1
  54. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
  55. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +7 -1
  56. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
  57. data/lib/rubocop/cop/layout/hash_alignment.rb +3 -6
  58. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  59. data/lib/rubocop/cop/layout/heredoc_indentation.rb +33 -3
  60. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  61. data/lib/rubocop/cop/layout/indentation_width.rb +111 -7
  62. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  63. data/lib/rubocop/cop/layout/line_length.rb +26 -9
  64. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +57 -57
  65. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +9 -2
  66. data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
  67. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +56 -56
  68. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +204 -39
  69. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +6 -4
  70. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  71. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
  72. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
  73. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  74. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  75. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  76. data/lib/rubocop/cop/layout/space_around_keyword.rb +4 -2
  77. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
  78. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  79. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
  80. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
  81. data/lib/rubocop/cop/lint/constant_reassignment.rb +59 -9
  82. data/lib/rubocop/cop/lint/constant_resolution.rb +1 -1
  83. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
  84. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  85. data/lib/rubocop/cop/lint/debugger.rb +0 -2
  86. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
  87. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  88. data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -12
  89. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  90. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  91. data/lib/rubocop/cop/lint/empty_conditional_body.rb +6 -1
  92. data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
  93. data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
  94. data/lib/rubocop/cop/lint/empty_when.rb +8 -1
  95. data/lib/rubocop/cop/lint/float_comparison.rb +1 -1
  96. data/lib/rubocop/cop/lint/interpolation_check.rb +7 -2
  97. data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -1
  98. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  99. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +16 -6
  100. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  101. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
  102. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -1
  103. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  104. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
  105. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +0 -9
  106. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
  107. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +23 -6
  108. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -2
  109. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  110. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -0
  111. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +7 -1
  112. data/lib/rubocop/cop/lint/self_assignment.rb +10 -2
  113. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  114. data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
  115. data/lib/rubocop/cop/lint/syntax.rb +25 -1
  116. data/lib/rubocop/cop/lint/to_json.rb +12 -16
  117. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -0
  118. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
  119. data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
  120. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  121. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  122. data/lib/rubocop/cop/lint/useless_assignment.rb +45 -17
  123. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +4 -4
  124. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +2 -0
  125. data/lib/rubocop/cop/lint/useless_or.rb +15 -2
  126. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +24 -9
  127. data/lib/rubocop/cop/lint/void.rb +39 -12
  128. data/lib/rubocop/cop/message_annotator.rb +1 -1
  129. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  130. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  131. data/lib/rubocop/cop/migration/department_name.rb +12 -1
  132. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  133. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +4 -6
  134. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  135. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +5 -5
  136. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  137. data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -60
  138. data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
  139. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  140. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  141. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  142. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  143. data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
  144. data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -5
  145. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  146. data/lib/rubocop/cop/naming/method_name.rb +4 -2
  147. data/lib/rubocop/cop/naming/predicate_method.rb +27 -4
  148. data/lib/rubocop/cop/naming/predicate_prefix.rb +11 -11
  149. data/lib/rubocop/cop/offense.rb +9 -1
  150. data/lib/rubocop/cop/registry.rb +20 -13
  151. data/lib/rubocop/cop/security/eval.rb +15 -2
  152. data/lib/rubocop/cop/security/json_load.rb +33 -11
  153. data/lib/rubocop/cop/style/access_modifier_declarations.rb +15 -4
  154. data/lib/rubocop/cop/style/accessor_grouping.rb +4 -2
  155. data/lib/rubocop/cop/style/alias.rb +4 -1
  156. data/lib/rubocop/cop/style/and_or.rb +1 -0
  157. data/lib/rubocop/cop/style/arguments_forwarding.rb +25 -7
  158. data/lib/rubocop/cop/style/array_intersect.rb +2 -2
  159. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
  160. data/lib/rubocop/cop/style/array_join.rb +4 -2
  161. data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
  162. data/lib/rubocop/cop/style/attr.rb +5 -2
  163. data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
  164. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  165. data/lib/rubocop/cop/style/block_delimiters.rb +27 -34
  166. data/lib/rubocop/cop/style/case_equality.rb +15 -13
  167. data/lib/rubocop/cop/style/class_and_module_children.rb +11 -2
  168. data/lib/rubocop/cop/style/collection_compact.rb +36 -16
  169. data/lib/rubocop/cop/style/colon_method_call.rb +3 -1
  170. data/lib/rubocop/cop/style/concat_array_literals.rb +2 -0
  171. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -18
  172. data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
  173. data/lib/rubocop/cop/style/copyright.rb +1 -1
  174. data/lib/rubocop/cop/style/documentation.rb +6 -6
  175. data/lib/rubocop/cop/style/documentation_method.rb +8 -8
  176. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  177. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  178. data/lib/rubocop/cop/style/each_with_object.rb +2 -0
  179. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  180. data/lib/rubocop/cop/style/empty_class_definition.rb +119 -0
  181. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  182. data/lib/rubocop/cop/style/empty_method.rb +0 -6
  183. data/lib/rubocop/cop/style/encoding.rb +7 -1
  184. data/lib/rubocop/cop/style/end_block.rb +3 -1
  185. data/lib/rubocop/cop/style/endless_method.rb +23 -5
  186. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  187. data/lib/rubocop/cop/style/file_open.rb +84 -0
  188. data/lib/rubocop/cop/style/float_division.rb +15 -1
  189. data/lib/rubocop/cop/style/for.rb +3 -0
  190. data/lib/rubocop/cop/style/format_string_token.rb +49 -5
  191. data/lib/rubocop/cop/style/global_vars.rb +5 -2
  192. data/lib/rubocop/cop/style/guard_clause.rb +27 -22
  193. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
  194. data/lib/rubocop/cop/style/hash_lookup_method.rb +101 -0
  195. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  196. data/lib/rubocop/cop/style/hash_transform_keys.rb +17 -7
  197. data/lib/rubocop/cop/style/hash_transform_values.rb +17 -7
  198. data/lib/rubocop/cop/style/if_inside_else.rb +1 -5
  199. data/lib/rubocop/cop/style/if_unless_modifier.rb +57 -17
  200. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +12 -12
  201. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +4 -1
  202. data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -5
  203. data/lib/rubocop/cop/style/inline_comment.rb +4 -1
  204. data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
  205. data/lib/rubocop/cop/style/lambda_call.rb +8 -8
  206. data/lib/rubocop/cop/style/magic_comment_format.rb +2 -2
  207. data/lib/rubocop/cop/style/map_join.rb +123 -0
  208. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
  209. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
  210. data/lib/rubocop/cop/style/method_def_parentheses.rb +2 -4
  211. data/lib/rubocop/cop/style/module_member_existence_check.rb +107 -0
  212. data/lib/rubocop/cop/style/multiline_if_then.rb +4 -4
  213. data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
  214. data/lib/rubocop/cop/style/mutable_constant.rb +1 -1
  215. data/lib/rubocop/cop/style/negative_array_index.rb +220 -0
  216. data/lib/rubocop/cop/style/nil_comparison.rb +11 -10
  217. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  218. data/lib/rubocop/cop/style/non_nil_check.rb +5 -11
  219. data/lib/rubocop/cop/style/not.rb +2 -0
  220. data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
  221. data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
  222. data/lib/rubocop/cop/style/one_line_conditional.rb +21 -12
  223. data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
  224. data/lib/rubocop/cop/style/parallel_assignment.rb +6 -2
  225. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  226. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -0
  227. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  228. data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
  229. data/lib/rubocop/cop/style/proc.rb +3 -2
  230. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  231. data/lib/rubocop/cop/style/reduce_to_hash.rb +184 -0
  232. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  233. data/lib/rubocop/cop/style/redundant_begin.rb +3 -3
  234. data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
  235. data/lib/rubocop/cop/style/redundant_each.rb +3 -3
  236. data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
  237. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
  238. data/lib/rubocop/cop/style/redundant_format.rb +26 -5
  239. data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
  240. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
  241. data/lib/rubocop/cop/style/redundant_line_continuation.rb +16 -0
  242. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  243. data/lib/rubocop/cop/style/redundant_parentheses.rb +26 -22
  244. data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
  245. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
  246. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
  247. data/lib/rubocop/cop/style/redundant_return.rb +3 -1
  248. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
  249. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  250. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +114 -0
  251. data/lib/rubocop/cop/style/reverse_find.rb +51 -0
  252. data/lib/rubocop/cop/style/safe_navigation.rb +7 -7
  253. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  254. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  255. data/lib/rubocop/cop/style/select_by_regexp.rb +51 -21
  256. data/lib/rubocop/cop/style/semicolon.rb +25 -7
  257. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  258. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -1
  259. data/lib/rubocop/cop/style/single_line_methods.rb +3 -1
  260. data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -1
  261. data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
  262. data/lib/rubocop/cop/style/super_arguments.rb +2 -2
  263. data/lib/rubocop/cop/style/symbol_proc.rb +4 -3
  264. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  265. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
  266. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  267. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  268. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
  269. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  270. data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
  271. data/lib/rubocop/cop/team.rb +4 -4
  272. data/lib/rubocop/cop/util.rb +2 -3
  273. data/lib/rubocop/cop/utils/format_string.rb +10 -0
  274. data/lib/rubocop/cop/variable_force/branch.rb +30 -6
  275. data/lib/rubocop/cops_documentation_generator.rb +4 -4
  276. data/lib/rubocop/directive_comment.rb +48 -4
  277. data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
  278. data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
  279. data/lib/rubocop/formatter/formatter_set.rb +2 -2
  280. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  281. data/lib/rubocop/formatter/simple_text_formatter.rb +0 -2
  282. data/lib/rubocop/formatter/tap_formatter.rb +5 -2
  283. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  284. data/lib/rubocop/formatter.rb +22 -21
  285. data/lib/rubocop/lsp/diagnostic.rb +18 -33
  286. data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
  287. data/lib/rubocop/lsp/routes.rb +12 -5
  288. data/lib/rubocop/lsp/runtime.rb +13 -3
  289. data/lib/rubocop/lsp/stdin_runner.rb +8 -17
  290. data/lib/rubocop/magic_comment.rb +20 -0
  291. data/lib/rubocop/mcp/server.rb +200 -0
  292. data/lib/rubocop/options.rb +10 -1
  293. data/lib/rubocop/path_util.rb +14 -2
  294. data/lib/rubocop/plugin/loader.rb +1 -1
  295. data/lib/rubocop/rake_task.rb +1 -1
  296. data/lib/rubocop/remote_config.rb +10 -8
  297. data/lib/rubocop/result_cache.rb +60 -37
  298. data/lib/rubocop/rspec/cop_helper.rb +8 -0
  299. data/lib/rubocop/rspec/shared_contexts.rb +18 -5
  300. data/lib/rubocop/rspec/support.rb +2 -1
  301. data/lib/rubocop/runner.rb +12 -3
  302. data/lib/rubocop/server/cache.rb +6 -29
  303. data/lib/rubocop/server/core.rb +2 -0
  304. data/lib/rubocop/target_finder.rb +1 -1
  305. data/lib/rubocop/target_ruby.rb +31 -14
  306. data/lib/rubocop/version.rb +2 -2
  307. data/lib/rubocop.rb +20 -0
  308. data/lib/ruby_lsp/rubocop/addon.rb +23 -8
  309. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
  310. metadata +33 -9
@@ -97,8 +97,8 @@ module RuboCop
97
97
  if delimiters.first != delimiters.last
98
98
  # With different delimiters (eg. `[]`, `()`), if there are the same
99
99
  # number of each, escaping is not necessary
100
- delimiter_counts = delimiters.each_with_object({}) do |delimiter, counts|
101
- counts[delimiter] = content.count(delimiter)
100
+ delimiter_counts = delimiters.to_h do |delimiter|
101
+ [delimiter, content.count(delimiter)]
102
102
  end
103
103
 
104
104
  return content if delimiter_counts[delimiters.first] == delimiter_counts[delimiters.last]
@@ -55,10 +55,9 @@ module RuboCop
55
55
 
56
56
  # @api private
57
57
  def builtin?(cop_class)
58
- # any custom method will do
59
- return false unless (m = cop_class.instance_methods(false).first)
58
+ return false unless (name = cop_class.name)
60
59
 
61
- path, _line = cop_class.instance_method(m).source_location
60
+ path, _line = Module.const_source_location(name)
62
61
  path.start_with?(__dir__)
63
62
  end
64
63
  end
@@ -69,8 +69,7 @@ module RuboCop
69
69
  def on_new_investigation
70
70
  return if processed_source.blank?
71
71
 
72
- dependency_declarations(processed_source.ast)
73
- .each_cons(2) do |previous, current|
72
+ dependency_declarations(processed_source.ast).each_cons(2) do |previous, current|
74
73
  next unless consecutive_lines?(previous, current)
75
74
  next unless case_insensitive_out_of_order?(gem_name(current), gem_name(previous))
76
75
  next unless get_dependency_name(previous) == get_dependency_name(current)
@@ -92,7 +92,7 @@ module RuboCop
92
92
  (str "true")
93
93
  PATTERN
94
94
 
95
- def on_block(node) # rubocop:disable Metrics/MethodLength, InternalAffairs/NumblockHandler
95
+ def on_block(node) # rubocop:disable Metrics/MethodLength, InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
96
96
  gem_specification(node) do |block_var|
97
97
  metadata_value = metadata(node)
98
98
  mfa_value = mfa_value(metadata_value)
@@ -3,8 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Gemspec
6
- # Checks that `RUBY_VERSION` constant is not used in gemspec.
7
- # Using `RUBY_VERSION` is dangerous because value of the
6
+ # Checks that `RUBY_VERSION` and `Ruby::VERSION` constants are not used in gemspec.
7
+ # Using `RUBY_VERSION` and `Ruby::VERSION` are dangerous because value of the
8
8
  # constant is determined by `rake release`.
9
9
  # It's possible to have dependency based on ruby version used
10
10
  # to execute `rake release` and not user's ruby version.
@@ -28,15 +28,20 @@ module RuboCop
28
28
  class RubyVersionGlobalsUsage < Base
29
29
  include GemspecHelp
30
30
 
31
- MSG = 'Do not use `RUBY_VERSION` in gemspec file.'
31
+ MSG = 'Do not use `%<ruby_version>s` in gemspec file.'
32
32
 
33
33
  # @!method ruby_version?(node)
34
- def_node_matcher :ruby_version?, '(const {cbase nil?} :RUBY_VERSION)'
34
+ def_node_matcher :ruby_version?, <<~PATTERN
35
+ {
36
+ (const {cbase nil?} :RUBY_VERSION)
37
+ (const (const {cbase nil?} :Ruby) :VERSION)
38
+ }
39
+ PATTERN
35
40
 
36
41
  def on_const(node)
37
42
  return unless gem_spec_with_ruby_version?(node)
38
43
 
39
- add_offense(node)
44
+ add_offense(node, message: format(MSG, ruby_version: node.source))
40
45
  end
41
46
 
42
47
  private
@@ -9,15 +9,15 @@ module RuboCop
9
9
  # the delimiter.
10
10
  #
11
11
  # @example
12
- # # bad
13
- # expect_offense(<<~CODE)
14
- # example_ruby_code
15
- # CODE
12
+ # # bad
13
+ # expect_offense(<<~CODE)
14
+ # example_ruby_code
15
+ # CODE
16
16
  #
17
- # # good
18
- # expect_offense(<<~RUBY)
19
- # example_ruby_code
20
- # RUBY
17
+ # # good
18
+ # expect_offense(<<~RUBY)
19
+ # example_ruby_code
20
+ # RUBY
21
21
  class ExampleHeredocDelimiter < Base
22
22
  extend AutoCorrector
23
23
 
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Checks for missing `itblock` handlers. The blocks with the `it`
7
+ # parameter introduced in Ruby 3.4 are parsed with a node type of
8
+ # `itblock` instead of block. Cops that define `block` handlers
9
+ # need to define `itblock` handlers or disable this cop for them.
10
+ #
11
+ # @example
12
+ #
13
+ # # bad
14
+ # class BlockRelatedCop < Base
15
+ # def on_block(node)
16
+ # end
17
+ # end
18
+ #
19
+ # # good
20
+ # class BlockRelatedCop < Base
21
+ # def on_block(node)
22
+ # end
23
+ #
24
+ # alias on_itblock on_block
25
+ # end
26
+ #
27
+ # class BlockRelatedCop < Base
28
+ # def on_block(node)
29
+ # end
30
+ #
31
+ # alias_method :on_itblock, :on_block
32
+ # end
33
+ #
34
+ # class BlockRelatedCop < Base
35
+ # def on_block(node)
36
+ # end
37
+ #
38
+ # def on_itblock(node)
39
+ # end
40
+ # end
41
+ class ItblockHandler < Base
42
+ MSG = 'Define on_itblock to handle blocks with the `it` parameter.'
43
+
44
+ def on_def(node)
45
+ return unless block_handler?(node)
46
+ return unless node.parent
47
+
48
+ add_offense(node) unless itblock_handler?(node.parent)
49
+ end
50
+
51
+ private
52
+
53
+ # @!method block_handler?(node)
54
+ def_node_matcher :block_handler?, <<~PATTERN
55
+ (def :on_block (args (arg :node)) ...)
56
+ PATTERN
57
+
58
+ # @!method itblock_handler?(node)
59
+ def_node_matcher :itblock_handler?, <<~PATTERN
60
+ {
61
+ `(def :on_itblock (args (arg :node)) ...)
62
+ `(alias (sym :on_itblock) (sym :on_block))
63
+ `(send nil? :alias_method (sym :on_itblock) (sym :on_block))
64
+ }
65
+ PATTERN
66
+ end
67
+ end
68
+ end
69
+ end
@@ -9,6 +9,12 @@ module RuboCop
9
9
  #
10
10
  # @example
11
11
  # # bad
12
+ # node.loc.respond_to?(:begin)
13
+ #
14
+ # # good
15
+ # node.loc?(:begin)
16
+ #
17
+ # # bad
12
18
  # node.loc.respond_to?(:begin) && node.loc.begin
13
19
  #
14
20
  # # good
@@ -29,7 +35,16 @@ module RuboCop
29
35
  class LocationExists < Base
30
36
  extend AutoCorrector
31
37
 
32
- MSG = 'Use `%<replacement>s` instead of `%<source>s`.'
38
+ MSG = 'Use `node.loc?` instead of `loc.respond_to?`.'
39
+ MSG_CORRECTABLE = 'Use `%<replacement>s` instead of `%<source>s`.'
40
+ RESTRICT_ON_SEND = %i[respond_to?].freeze
41
+
42
+ # @!method loc_respond_to?(node)
43
+ def_node_matcher :loc_respond_to?, <<~PATTERN
44
+ (call
45
+ (call $_receiver :loc) :respond_to?
46
+ $(sym _location))
47
+ PATTERN
33
48
 
34
49
  # @!method replaceable_with_loc_is(node)
35
50
  def_node_matcher :replaceable_with_loc_is, <<~PATTERN
@@ -64,6 +79,15 @@ module RuboCop
64
79
  replace_with_loc(node) || replace_with_loc_is(node)
65
80
  end
66
81
 
82
+ def on_send(node)
83
+ return if ignored_node?(node.parent)
84
+
85
+ loc_respond_to?(node) do |receiver, location|
86
+ register_offense(node, replacement(receiver, "loc?(#{location.source})"))
87
+ end
88
+ end
89
+ alias on_csend on_send
90
+
67
91
  private
68
92
 
69
93
  def replace_with_loc(node)
@@ -84,11 +108,13 @@ module RuboCop
84
108
  end
85
109
 
86
110
  def register_offense(node, replacement)
87
- message = format(MSG, replacement: replacement, source: node.source)
111
+ message = format(MSG_CORRECTABLE, replacement: replacement, source: node.source)
88
112
 
89
113
  add_offense(node, message: message) do |corrector|
90
114
  corrector.replace(node, replacement)
91
115
  end
116
+
117
+ ignore_node(node)
92
118
  end
93
119
 
94
120
  def replacement(receiver, rest)
@@ -8,16 +8,16 @@ module RuboCop
8
8
  # method.
9
9
  #
10
10
  # @example
11
- # # bad
12
- # def_node_matcher :foo?, <<~PATTERN
13
- # ...
14
- # PATTERN
11
+ # # bad
12
+ # def_node_matcher :foo?, <<~PATTERN
13
+ # ...
14
+ # PATTERN
15
15
  #
16
- # # good
17
- # # @!method foo?(node)
18
- # def_node_matcher :foo?, <<~PATTERN
19
- # ...
20
- # PATTERN
16
+ # # good
17
+ # # @!method foo?(node)
18
+ # def_node_matcher :foo?, <<~PATTERN
19
+ # ...
20
+ # PATTERN
21
21
  #
22
22
  class NodeMatcherDirective < Base
23
23
  extend AutoCorrector
@@ -7,7 +7,7 @@ module RuboCop
7
7
  # AST Processor for NodePattern ASTs, for use with `InternalAffairs/NodePatternGroups`.
8
8
  #
9
9
  # Looks for sequences and subsequences where the first item is a `node_type` node,
10
- # and converts them to `node_sequence` nodes (not a true `Rubocop::AST::NodePattern`
10
+ # and converts them to `node_sequence` nodes (not a true `RuboCop::AST::NodePattern`
11
11
  # node type).
12
12
  #
13
13
  # The resulting AST will be walked by `InternalAffairs::NodePatternGroups::ASTWalker`
@@ -30,6 +30,8 @@ module RuboCop
30
30
  any_block: %i[block numblock itblock],
31
31
  any_def: %i[def defs],
32
32
  any_match_pattern: %i[match_pattern match_pattern_p],
33
+ any_str: %i[str dstr xstr],
34
+ any_sym: %i[sym dsym],
33
35
  argument: %i[arg optarg restarg kwarg kwoptarg kwrestarg blockarg forward_arg shadowarg],
34
36
  boolean: %i[true false],
35
37
  call: %i[send csend],
@@ -210,7 +212,7 @@ module RuboCop
210
212
  # A heredoc can be a `dstr` without interpolation, but if there is interpolation
211
213
  # there'll be a `begin` node, in which case, we cannot evaluate the pattern.
212
214
  def acceptable_heredoc?(node)
213
- node.type?(:str, :dstr) && node.heredoc? && node.each_child_node(:begin).none?
215
+ node.any_str_type? && node.heredoc? && node.each_child_node(:begin).none?
214
216
  end
215
217
 
216
218
  def process_pattern(pattern_node)
@@ -76,7 +76,7 @@ module RuboCop
76
76
  end
77
77
 
78
78
  def on_send(node) # rubocop:disable InternalAffairs/OnSendWithoutOnCSend
79
- new_identifier = node.first_argument
79
+ return unless (new_identifier = node.first_argument)
80
80
  return unless new_identifier.basic_literal?
81
81
 
82
82
  new_identifier = new_identifier.value
@@ -7,11 +7,11 @@ module RuboCop
7
7
  #
8
8
  # @example
9
9
  #
10
- # # bad
11
- # expect(cop.messages).to eq([described_class::MSG])
10
+ # # bad
11
+ # expect(cop.messages).to eq([described_class::MSG])
12
12
  #
13
- # # good
14
- # expect(cop.messages).to eq(['Do not write bad code like that.'])
13
+ # # good
14
+ # expect(cop.messages).to eq(['Do not write bad code like that.'])
15
15
  #
16
16
  class UselessMessageAssertion < Base
17
17
  MSG = 'Do not specify cop behavior using `described_class::MSG`.'
@@ -7,6 +7,7 @@ require_relative 'internal_affairs/empty_line_between_expect_offense_and_correct
7
7
  require_relative 'internal_affairs/example_description'
8
8
  require_relative 'internal_affairs/example_heredoc_delimiter'
9
9
  require_relative 'internal_affairs/inherit_deprecated_cop_class'
10
+ require_relative 'internal_affairs/itblock_handler'
10
11
  require_relative 'internal_affairs/lambda_or_proc'
11
12
  require_relative 'internal_affairs/location_exists'
12
13
  require_relative 'internal_affairs/location_expression'
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Check that the arguments on a multi-line method call are aligned.
6
+ # Checks that the arguments on a multi-line method call are aligned.
7
7
  #
8
8
  # @example EnforcedStyle: with_first_argument (default)
9
9
  # # good
@@ -52,7 +52,7 @@ module RuboCop
52
52
  'following the first line of a multi-line method call.'
53
53
 
54
54
  def on_send(node)
55
- return if !multiple_arguments?(node) || (node.send_type? && node.method?(:[]=)) ||
55
+ return if !multiple_arguments?(node) || (node.call_type? && node.method?(:[]=)) ||
56
56
  autocorrect_incompatible_with_other_cops?
57
57
 
58
58
  items = flattened_arguments(node)
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Check that the elements of a multi-line array literal are
6
+ # Checks that the elements of a multi-line array literal are
7
7
  # aligned.
8
8
  #
9
9
  # @example EnforcedStyle: with_first_element (default)
@@ -128,7 +128,9 @@ module RuboCop
128
128
  return if case_match_node.single_line?
129
129
  return if enforced_style_end? && end_and_last_conditional_same_line?(case_match_node)
130
130
 
131
- case_match_node.each_in_pattern { |in_pattern_node| check_when(in_pattern_node, 'in') }
131
+ case_match_node.in_pattern_branches.each do |in_pattern_node|
132
+ check_when(in_pattern_node, 'in')
133
+ end
132
134
  end
133
135
 
134
136
  private
@@ -223,7 +223,7 @@ module RuboCop
223
223
  # @param node to be analysed
224
224
  # @return String when the node type is a `:block` then
225
225
  # {classify} recursively with the first children
226
- # @return String when the node type is a `:send` then {find_category}
226
+ # @return String when the node type is a `:send` then {find_send_node_category}
227
227
  # by method name
228
228
  # @return String otherwise trying to {humanize_node} of the current node
229
229
  def classify(node)
@@ -233,9 +233,10 @@ module RuboCop
233
233
  when :block
234
234
  classify(node.send_node)
235
235
  when :send
236
- find_category(node)
236
+ find_send_node_category(node)
237
237
  else
238
- humanize_node(node)
238
+ name = humanize_node(node)
239
+ find_category(name) || name
239
240
  end.to_s
240
241
  end
241
242
 
@@ -244,9 +245,9 @@ module RuboCop
244
245
  # also its visibility.
245
246
  # @param node to be analysed.
246
247
  # @return [String] with the key category or the `method_name` as string
247
- def find_category(node)
248
+ def find_send_node_category(node)
248
249
  name = node.method_name.to_s
249
- category, = categories.find { |_, names| names.include?(name) }
250
+ category = find_category(name)
250
251
  key = category || name
251
252
  visibility_key =
252
253
  if node.def_modifier?
@@ -257,6 +258,12 @@ module RuboCop
257
258
  expected_order.include?(visibility_key) ? visibility_key : key
258
259
  end
259
260
 
261
+ def find_category(name)
262
+ name = name.to_s
263
+ category, = categories.find { |_, names| names.include?(name) }
264
+ category
265
+ end
266
+
260
267
  def walk_over_nested_class_definition(class_node)
261
268
  class_elements(class_node).each do |node|
262
269
  classification = classify(node)
@@ -357,7 +364,7 @@ module RuboCop
357
364
  end
358
365
 
359
366
  def find_heredoc(node)
360
- node.each_node(:str, :dstr, :xstr).find(&:heredoc?)
367
+ node.each_node(:any_str).find(&:heredoc?)
361
368
  end
362
369
 
363
370
  def buffer
@@ -112,7 +112,7 @@ module RuboCop
112
112
  end
113
113
 
114
114
  def last_heredoc_line(node)
115
- if node.send_type?
115
+ if node.call_type?
116
116
  node.arguments.select { |arg| heredoc?(arg) }.map { |arg| arg.loc.heredoc_end.line }.max
117
117
  elsif heredoc?(node)
118
118
  node.loc.heredoc_end.line
@@ -120,7 +120,7 @@ module RuboCop
120
120
  end
121
121
 
122
122
  def heredoc?(node)
123
- node.type?(:str, :dstr) && node.heredoc?
123
+ node.any_str_type? && node.heredoc?
124
124
  end
125
125
 
126
126
  def end_range(node)
@@ -60,6 +60,11 @@ module RuboCop
60
60
  END_OF_HEREDOC_LINE = 1
61
61
  SIMPLE_DIRECTIVE_COMMENT_PATTERN = /\A# *:nocov:\z/.freeze
62
62
 
63
+ # @!method guard_clause_branch?(node)
64
+ def_node_matcher :guard_clause_branch?, <<~PATTERN
65
+ {(send nil? {:raise :fail} ...) return break next}
66
+ PATTERN
67
+
63
68
  def on_if(node)
64
69
  return if correct_style?(node)
65
70
  return if multiple_statements_on_line?(node)
@@ -97,14 +102,16 @@ module RuboCop
97
102
  end
98
103
 
99
104
  def correct_style?(node)
100
- !contains_guard_clause?(node) ||
105
+ !node.if_branch&.guard_clause? ||
101
106
  next_line_rescue_or_ensure?(node) ||
102
107
  next_sibling_parent_empty_or_else?(node) ||
103
108
  next_sibling_empty_or_guard_clause?(node)
104
109
  end
105
110
 
106
111
  def contains_guard_clause?(node)
107
- node.if_branch&.guard_clause?
112
+ return false unless (branch = node.if_branch)
113
+
114
+ branch.guard_clause? || guard_clause_branch?(branch)
108
115
  end
109
116
 
110
117
  def next_line_empty_or_allowed_directive_comment?(line)
@@ -145,8 +152,10 @@ module RuboCop
145
152
  next_sibling.if_type? && contains_guard_clause?(next_sibling)
146
153
  end
147
154
 
155
+ # rubocop:disable Metrics/CyclomaticComplexity
148
156
  def last_heredoc_argument(node)
149
157
  n = last_heredoc_argument_node(node)
158
+ n = n.children.first while n.respond_to?(:begin_type?) && n.begin_type?
150
159
 
151
160
  return n if heredoc?(n)
152
161
  return unless n.respond_to?(:arguments)
@@ -158,6 +167,7 @@ module RuboCop
158
167
 
159
168
  last_heredoc_argument(n.receiver) if n.respond_to?(:receiver)
160
169
  end
170
+ # rubocop:enable Metrics/CyclomaticComplexity
161
171
 
162
172
  def last_heredoc_argument_node(node)
163
173
  return node unless node.respond_to?(:if_branch)
@@ -76,28 +76,40 @@ module RuboCop
76
76
  # # good
77
77
  # class ErrorA < BaseError; end
78
78
  # class ErrorB < BaseError; end
79
- # class ErrorC < BaseError; end
80
79
  #
81
80
  # # good
82
81
  # class ErrorA < BaseError; end
83
82
  #
84
83
  # class ErrorB < BaseError; end
85
84
  #
86
- # class ErrorC < BaseError; end
85
+ # # good - DefLikeMacros: [memoize]
86
+ # memoize :attribute_a
87
+ # memoize :attribute_b
88
+ #
89
+ # # good
90
+ # memoize :attribute_a
91
+ #
92
+ # memoize :attribute_b
87
93
  #
88
94
  # @example AllowAdjacentOneLineDefs: false
89
95
  #
90
96
  # # bad
91
97
  # class ErrorA < BaseError; end
92
98
  # class ErrorB < BaseError; end
93
- # class ErrorC < BaseError; end
94
99
  #
95
100
  # # good
96
101
  # class ErrorA < BaseError; end
97
102
  #
98
103
  # class ErrorB < BaseError; end
99
104
  #
100
- # class ErrorC < BaseError; end
105
+ # # bad - DefLikeMacros: [memoize]
106
+ # memoize :attribute_a
107
+ # memoize :attribute_b
108
+ #
109
+ # # good
110
+ # memoize :attribute_a
111
+ #
112
+ # memoize :attribute_b
101
113
  #
102
114
  class EmptyLineBetweenDefs < Base
103
115
  include RangeHelp
@@ -158,6 +170,8 @@ module RuboCop
158
170
  def def_location(correction_node)
159
171
  if correction_node.any_block_type?
160
172
  correction_node.source_range.join(correction_node.children.first.source_range)
173
+ elsif correction_node.send_type?
174
+ correction_node.source_range
161
175
  else
162
176
  correction_node.loc.keyword.join(correction_node.loc.name)
163
177
  end
@@ -171,12 +185,18 @@ module RuboCop
171
185
  end
172
186
 
173
187
  def empty_line_between_macros
174
- cop_config.fetch('DefLikeMacros', []).map(&:to_sym)
188
+ @empty_line_between_macros ||= cop_config.fetch('DefLikeMacros', []).map(&:to_sym).freeze
175
189
  end
176
190
 
177
191
  def macro_candidate?(node)
178
- node.any_block_type? && node.children.first.macro? &&
179
- empty_line_between_macros.include?(node.children.first.method_name)
192
+ macro_candidate = if node.any_block_type?
193
+ node.send_node
194
+ elsif node.send_type?
195
+ node
196
+ end
197
+ return false unless macro_candidate
198
+
199
+ macro_candidate.macro? && empty_line_between_macros.include?(macro_candidate.method_name)
180
200
  end
181
201
 
182
202
  def method_candidate?(node)
@@ -240,7 +260,9 @@ module RuboCop
240
260
  end
241
261
 
242
262
  def def_start(node)
243
- if node.any_block_type? && node.children.first.send_type?
263
+ node = node.send_node if node.any_block_type?
264
+
265
+ if node.send_type?
244
266
  node.source_range.line
245
267
  else
246
268
  node.loc.keyword.line
@@ -252,11 +274,7 @@ module RuboCop
252
274
  end
253
275
 
254
276
  def end_loc(node)
255
- if node.any_def_type? && node.endless?
256
- node.source_range.end
257
- else
258
- node.loc.end
259
- end
277
+ node.source_range.end
260
278
  end
261
279
 
262
280
  def autocorrect_remove_lines(corrector, newline_pos, count)
@@ -39,7 +39,7 @@ module RuboCop
39
39
 
40
40
  def on_send(node)
41
41
  return if node.receiver || node.arguments.empty?
42
- return if node.parent&.type?(:send, :any_block)
42
+ return if node.parent&.type?(:send, :any_block, :array)
43
43
 
44
44
  return if next_line_empty_or_enable_directive_comment?(node.last_line)
45
45
 
@@ -66,6 +66,7 @@ module RuboCop
66
66
  extend AutoCorrector
67
67
 
68
68
  MSG = 'Add an empty line after attribute accessor.'
69
+ RESTRICT_ON_SEND = %i[attr_reader attr_writer attr_accessor attr].freeze
69
70
 
70
71
  def on_send(node)
71
72
  return unless node.attribute_accessor?
@@ -7,15 +7,25 @@ module RuboCop
7
7
  # the configuration.
8
8
  #
9
9
  # @example EnforcedStyle: no_empty_lines (default)
10
- # # good
10
+ # # bad
11
+ # foo do |bar|
12
+ #
13
+ # # ...
14
+ #
15
+ # end
11
16
  #
17
+ # # good
12
18
  # foo do |bar|
13
19
  # # ...
14
20
  # end
15
21
  #
16
22
  # @example EnforcedStyle: empty_lines
17
- # # good
23
+ # # bad
24
+ # foo do |bar|
25
+ # # ...
26
+ # end
18
27
  #
28
+ # # good
19
29
  # foo do |bar|
20
30
  #
21
31
  # # ...