rubocop 1.90.0 → 1.92.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 (303) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +241 -11
  4. data/config/obsoletion.yml +9 -0
  5. data/lib/rubocop/cached_data.rb +47 -7
  6. data/lib/rubocop/changed_files.rb +134 -0
  7. data/lib/rubocop/cli/command/cop_names.rb +57 -0
  8. data/lib/rubocop/cli/command/execute_runner.rb +23 -3
  9. data/lib/rubocop/cli/command/explain.rb +34 -0
  10. data/lib/rubocop/cli/command/show_cops.rb +6 -0
  11. data/lib/rubocop/cli/command/show_docs_url.rb +6 -4
  12. data/lib/rubocop/cli.rb +11 -4
  13. data/lib/rubocop/comment_config/directive_range.rb +3 -1
  14. data/lib/rubocop/comment_config/disable_next.rb +49 -3
  15. data/lib/rubocop/comment_config/push_pop.rb +55 -0
  16. data/lib/rubocop/comment_config.rb +32 -53
  17. data/lib/rubocop/config.rb +10 -0
  18. data/lib/rubocop/config_loader.rb +18 -7
  19. data/lib/rubocop/config_loader_resolver.rb +79 -12
  20. data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
  21. data/lib/rubocop/config_obsoletion/removed_cop.rb +9 -1
  22. data/lib/rubocop/config_obsoletion.rb +1 -1
  23. data/lib/rubocop/config_validator.rb +29 -3
  24. data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
  25. data/lib/rubocop/cop/badge.rb +1 -1
  26. data/lib/rubocop/cop/base.rb +57 -24
  27. data/lib/rubocop/cop/bundler/gem_comment.rb +0 -1
  28. data/lib/rubocop/cop/bundler/ordered_gems.rb +0 -8
  29. data/lib/rubocop/cop/cop_documentation.rb +81 -0
  30. data/lib/rubocop/cop/cop_explanation.rb +140 -0
  31. data/lib/rubocop/cop/correctors/alignment_corrector.rb +13 -1
  32. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +22 -7
  33. data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
  34. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +23 -2
  35. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +45 -8
  36. data/lib/rubocop/cop/correctors.rb +2 -2
  37. data/lib/rubocop/cop/documentation.rb +1 -1
  38. data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
  39. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +0 -6
  40. data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
  41. data/lib/rubocop/cop/generator.rb +1 -1
  42. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -5
  43. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +0 -7
  44. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  45. data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
  46. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
  47. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -0
  48. data/lib/rubocop/cop/layout/block_alignment.rb +27 -0
  49. data/lib/rubocop/cop/layout/case_indentation.rb +25 -9
  50. data/lib/rubocop/cop/layout/class_structure.rb +9 -1
  51. data/lib/rubocop/cop/layout/comment_indentation.rb +8 -5
  52. data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
  53. data/lib/rubocop/cop/layout/else_alignment.rb +1 -0
  54. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +14 -5
  55. data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
  56. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
  57. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
  58. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -1
  59. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
  60. data/lib/rubocop/cop/layout/end_alignment.rb +16 -10
  61. data/lib/rubocop/cop/layout/extra_spacing.rb +4 -0
  62. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
  63. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +17 -4
  64. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +5 -3
  65. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
  66. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
  67. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +11 -0
  68. data/lib/rubocop/cop/layout/hash_alignment.rb +15 -10
  69. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -0
  70. data/lib/rubocop/cop/layout/heredoc_indentation.rb +15 -0
  71. data/lib/rubocop/cop/layout/indentation_style.rb +4 -1
  72. data/lib/rubocop/cop/layout/indentation_width.rb +4 -4
  73. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +8 -1
  74. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
  75. data/lib/rubocop/cop/layout/line_length.rb +71 -19
  76. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +12 -0
  77. data/lib/rubocop/cop/layout/multiline_block_layout.rb +8 -1
  78. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +7 -0
  79. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -0
  80. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +14 -0
  81. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
  82. data/lib/rubocop/cop/layout/redundant_line_break.rb +22 -1
  83. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +15 -2
  84. data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
  85. data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
  86. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +10 -4
  87. data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -0
  88. data/lib/rubocop/cop/layout/space_around_operators.rb +5 -1
  89. data/lib/rubocop/cop/layout/space_before_block_braces.rb +4 -1
  90. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +15 -2
  91. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +31 -8
  92. data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
  93. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +2 -1
  94. data/lib/rubocop/cop/lint/argument_mismatch.rb +14 -4
  95. data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -0
  96. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +88 -14
  97. data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
  98. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  99. data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
  100. data/lib/rubocop/cop/lint/literal_as_condition.rb +23 -2
  101. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +63 -19
  102. data/lib/rubocop/cop/lint/loop.rb +24 -2
  103. data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +245 -0
  104. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +19 -4
  105. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  106. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
  107. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  108. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +17 -1
  109. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +42 -17
  110. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +13 -2
  111. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +18 -1
  112. data/lib/rubocop/cop/lint/useless_assignment.rb +14 -7
  113. data/lib/rubocop/cop/lint/void.rb +8 -1
  114. data/lib/rubocop/cop/lint.rb +1 -0
  115. data/lib/rubocop/cop/metrics/class_length.rb +4 -2
  116. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
  117. data/lib/rubocop/cop/metrics/module_length.rb +4 -2
  118. data/lib/rubocop/cop/migration/department_name.rb +1 -1
  119. data/lib/rubocop/cop/mixin/alignment.rb +5 -1
  120. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  121. data/lib/rubocop/cop/mixin/check_line_breakable.rb +17 -14
  122. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +5 -1
  123. data/lib/rubocop/cop/mixin/code_length.rb +10 -2
  124. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -1
  125. data/lib/rubocop/cop/mixin/endless_method_body_help.rb +69 -0
  126. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +2 -2
  127. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +26 -2
  128. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +31 -3
  129. data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
  130. data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
  131. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
  132. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +9 -0
  133. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  134. data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
  135. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +29 -3
  136. data/lib/rubocop/cop/mixin/project_index_help.rb +15 -0
  137. data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +13 -3
  138. data/lib/rubocop/cop/mixin/statement_modifier.rb +22 -2
  139. data/lib/rubocop/cop/mixin.rb +4 -2
  140. data/lib/rubocop/cop/naming/accessor_method_name.rb +0 -16
  141. data/lib/rubocop/cop/naming/block_forwarding.rb +4 -1
  142. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  143. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
  144. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
  145. data/lib/rubocop/cop/naming/predicate_prefix.rb +7 -22
  146. data/lib/rubocop/cop/offense.rb +59 -3
  147. data/lib/rubocop/cop/registry.rb +10 -2
  148. data/lib/rubocop/cop/security/json_load.rb +16 -4
  149. data/lib/rubocop/cop/severity.rb +12 -0
  150. data/lib/rubocop/cop/style/access_modifier_declarations.rb +10 -2
  151. data/lib/rubocop/cop/style/alias.rb +18 -5
  152. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
  153. data/lib/rubocop/cop/style/and_or.rb +4 -0
  154. data/lib/rubocop/cop/style/arguments_forwarding.rb +6 -3
  155. data/lib/rubocop/cop/style/attr.rb +3 -4
  156. data/lib/rubocop/cop/style/bitwise_predicate.rb +6 -4
  157. data/lib/rubocop/cop/style/block_delimiters.rb +29 -3
  158. data/lib/rubocop/cop/style/case_like_if.rb +9 -6
  159. data/lib/rubocop/cop/style/class_and_module_children.rb +54 -16
  160. data/lib/rubocop/cop/style/class_methods_definitions.rb +8 -0
  161. data/lib/rubocop/cop/style/combinable_loops.rb +85 -11
  162. data/lib/rubocop/cop/style/concat_array_literals.rb +46 -7
  163. data/lib/rubocop/cop/style/conditional_assignment.rb +4 -0
  164. data/lib/rubocop/cop/style/constant_visibility.rb +6 -2
  165. data/lib/rubocop/cop/style/data_inheritance.rb +14 -0
  166. data/lib/rubocop/cop/style/directive_scope.rb +154 -21
  167. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +118 -18
  168. data/lib/rubocop/cop/style/documentation_method.rb +1 -9
  169. data/lib/rubocop/cop/style/double_negation.rb +11 -0
  170. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  171. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  172. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  173. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  174. data/lib/rubocop/cop/style/empty_method.rb +15 -3
  175. data/lib/rubocop/cop/style/endless_method.rb +91 -11
  176. data/lib/rubocop/cop/style/exact_regexp_match.rb +45 -8
  177. data/lib/rubocop/cop/style/explicit_block_argument.rb +50 -10
  178. data/lib/rubocop/cop/style/file_null.rb +2 -2
  179. data/lib/rubocop/cop/style/float_division.rb +28 -14
  180. data/lib/rubocop/cop/style/for.rb +44 -1
  181. data/lib/rubocop/cop/style/format_string.rb +28 -6
  182. data/lib/rubocop/cop/style/format_string_token.rb +1 -1
  183. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
  184. data/lib/rubocop/cop/style/guard_clause.rb +13 -1
  185. data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
  186. data/lib/rubocop/cop/style/hash_lookup_method.rb +35 -9
  187. data/lib/rubocop/cop/style/hash_syntax.rb +16 -3
  188. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  189. data/lib/rubocop/cop/style/if_inside_else.rb +21 -1
  190. data/lib/rubocop/cop/style/if_unless_modifier.rb +19 -20
  191. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -0
  192. data/lib/rubocop/cop/style/if_with_semicolon.rb +47 -4
  193. data/lib/rubocop/cop/style/inverse_methods.rb +24 -2
  194. data/lib/rubocop/cop/style/it_block_parameter.rb +32 -3
  195. data/lib/rubocop/cop/style/keyword_parameters_order.rb +3 -1
  196. data/lib/rubocop/cop/style/lambda.rb +18 -0
  197. data/lib/rubocop/cop/style/lambda_call.rb +7 -2
  198. data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
  199. data/lib/rubocop/cop/style/map_into_array.rb +1 -2
  200. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +45 -10
  201. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +25 -2
  202. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +26 -3
  203. data/lib/rubocop/cop/style/method_def_parentheses.rb +29 -3
  204. data/lib/rubocop/cop/style/missing_else.rb +7 -1
  205. data/lib/rubocop/cop/style/multiline_if_modifier.rb +45 -5
  206. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
  207. data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -5
  208. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
  209. data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
  210. data/lib/rubocop/cop/style/mutable_constant.rb +28 -1
  211. data/lib/rubocop/cop/style/negated_if_else_condition.rb +2 -1
  212. data/lib/rubocop/cop/style/negative_array_index.rb +9 -1
  213. data/lib/rubocop/cop/style/nested_modifier.rb +36 -12
  214. data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
  215. data/lib/rubocop/cop/style/next.rb +24 -10
  216. data/lib/rubocop/cop/style/nil_comparison.rb +48 -8
  217. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  218. data/lib/rubocop/cop/style/non_nil_check.rb +18 -2
  219. data/lib/rubocop/cop/style/not.rb +10 -3
  220. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
  221. data/lib/rubocop/cop/style/numeric_predicate.rb +21 -5
  222. data/lib/rubocop/cop/style/one_line_conditional.rb +14 -3
  223. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
  224. data/lib/rubocop/cop/style/parentheses_around_condition.rb +6 -1
  225. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +14 -3
  226. data/lib/rubocop/cop/style/reduce_to_hash.rb +17 -1
  227. data/lib/rubocop/cop/style/redundant_begin.rb +20 -3
  228. data/lib/rubocop/cop/style/redundant_condition.rb +34 -17
  229. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +16 -1
  230. data/lib/rubocop/cop/style/redundant_exception.rb +15 -3
  231. data/lib/rubocop/cop/style/redundant_fetch_block.rb +10 -2
  232. data/lib/rubocop/cop/style/redundant_freeze.rb +10 -1
  233. data/lib/rubocop/cop/style/redundant_parentheses.rb +23 -2
  234. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +7 -0
  235. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
  236. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +25 -5
  237. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +4 -0
  238. data/lib/rubocop/cop/style/regexp_literal.rb +75 -26
  239. data/lib/rubocop/cop/style/require_order.rb +9 -0
  240. data/lib/rubocop/cop/style/rescue_modifier.rb +5 -9
  241. data/lib/rubocop/cop/style/return_nil.rb +17 -2
  242. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
  243. data/lib/rubocop/cop/style/sample.rb +9 -8
  244. data/lib/rubocop/cop/style/self_assignment.rb +12 -15
  245. data/lib/rubocop/cop/style/semicolon.rb +16 -5
  246. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  247. data/lib/rubocop/cop/style/single_line_methods.rb +16 -4
  248. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  249. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +29 -5
  250. data/lib/rubocop/cop/style/string_concatenation.rb +9 -3
  251. data/lib/rubocop/cop/style/struct_inheritance.rb +14 -0
  252. data/lib/rubocop/cop/style/super_arguments.rb +3 -0
  253. data/lib/rubocop/cop/style/symbol_proc.rb +23 -5
  254. data/lib/rubocop/cop/style/ternary_parentheses.rb +23 -1
  255. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  256. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -19
  257. data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
  258. data/lib/rubocop/cop/style/yoda_condition.rb +24 -9
  259. data/lib/rubocop/cop/style/yoda_expression.rb +10 -1
  260. data/lib/rubocop/cop/style.rb +0 -1
  261. data/lib/rubocop/cop/team.rb +10 -5
  262. data/lib/rubocop/cop/util.rb +1 -1
  263. data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
  264. data/lib/rubocop/cop/variable_force/variable.rb +14 -1
  265. data/lib/rubocop/cops_documentation_generator.rb +23 -2
  266. data/lib/rubocop/directive_comment.rb +37 -8
  267. data/lib/rubocop/formatter/base_formatter.rb +22 -0
  268. data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -1
  269. data/lib/rubocop/formatter/formatter_set.rb +6 -1
  270. data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
  271. data/lib/rubocop/formatter/html_formatter.rb +2 -2
  272. data/lib/rubocop/formatter/json_formatter.rb +71 -1
  273. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  274. data/lib/rubocop/formatter/offense_count_formatter.rb +3 -1
  275. data/lib/rubocop/formatter/pacman_formatter.rb +3 -1
  276. data/lib/rubocop/formatter/sarif_formatter.rb +186 -0
  277. data/lib/rubocop/formatter/worst_offenders_formatter.rb +3 -1
  278. data/lib/rubocop/formatter.rb +1 -0
  279. data/lib/rubocop/lsp/runtime.rb +47 -11
  280. data/lib/rubocop/lsp/stdin_runner.rb +11 -5
  281. data/lib/rubocop/lsp.rb +5 -2
  282. data/lib/rubocop/magic_comment.rb +27 -0
  283. data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
  284. data/lib/rubocop/mcp/explain_tool.rb +68 -0
  285. data/lib/rubocop/mcp/scope.rb +65 -0
  286. data/lib/rubocop/mcp/server.rb +184 -76
  287. data/lib/rubocop/mcp/source_files.rb +35 -0
  288. data/lib/rubocop/offense_limit.rb +30 -0
  289. data/lib/rubocop/options.rb +97 -4
  290. data/lib/rubocop/path_util.rb +1 -1
  291. data/lib/rubocop/plugin/configuration_integrator.rb +12 -5
  292. data/lib/rubocop/plugin/loader.rb +1 -1
  293. data/lib/rubocop/rake_task.rb +1 -1
  294. data/lib/rubocop/remote_config.rb +8 -5
  295. data/lib/rubocop/result_cache.rb +36 -18
  296. data/lib/rubocop/runner.rb +160 -49
  297. data/lib/rubocop/server/cache.rb +2 -2
  298. data/lib/rubocop/unified_diff.rb +257 -0
  299. data/lib/rubocop/util.rb +69 -0
  300. data/lib/rubocop/version.rb +1 -1
  301. data/lib/rubocop.rb +9 -1
  302. metadata +21 -6
  303. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
@@ -35,6 +35,7 @@ module RuboCop
35
35
  #
36
36
  class SingleLineMethods < Base
37
37
  include Alignment
38
+ include EndlessMethodBodyHelp
38
39
  extend AutoCorrector
39
40
 
40
41
  MSG = 'Avoid single-line method definitions.'
@@ -67,10 +68,14 @@ module RuboCop
67
68
  return false if target_ruby_version < 3.0
68
69
  return false if disallow_endless_method_style?
69
70
  return false unless body_node
70
- return false if body_node.basic_conditional? || body_node.parent.assignment_method? ||
71
- NOT_SUPPORTED_ENDLESS_METHOD_BODY_TYPES.include?(body_node.type)
71
+ return false if body_node.parent.assignment_method?
72
72
 
73
- !body_node.type?(:begin, :kwbegin)
73
+ !unsupported_endless_method_body?(body_node) && endless_method_body?(body_node)
74
+ end
75
+
76
+ def unsupported_endless_method_body?(body_node)
77
+ body_node.basic_conditional? ||
78
+ NOT_SUPPORTED_ENDLESS_METHOD_BODY_TYPES.include?(body_node.type)
74
79
  end
75
80
 
76
81
  def correct_to_multiline(corrector, node)
@@ -89,8 +94,8 @@ module RuboCop
89
94
 
90
95
  def correct_to_endless(corrector, node)
91
96
  receiver = "#{node.receiver.source}." if node.receiver
92
- arguments = node.arguments.any? ? node.arguments.source : '()'
93
97
  body_source = method_body_source(node.body)
98
+ arguments = endless_arguments(node)
94
99
  replacement = "def #{receiver}#{node.method_name}#{arguments} = #{body_source}"
95
100
 
96
101
  corrector.replace(node, replacement)
@@ -138,6 +143,13 @@ module RuboCop
138
143
  !method_body.arguments.empty? && !method_body.comparison_method?
139
144
  end
140
145
 
146
+ def endless_arguments(node)
147
+ arguments = node.arguments
148
+ return '()' if arguments.none?
149
+
150
+ arguments.loc.begin ? arguments.source : "(#{arguments.source})"
151
+ end
152
+
141
153
  def disallow_endless_method_style?
142
154
  return true unless config.cop_enabled?('Style/EndlessMethod')
143
155
 
@@ -101,7 +101,7 @@ module RuboCop
101
101
  'module (don\'t forget to require it) over `%<global>s`.'
102
102
  MSG_REGULAR = 'Prefer `%<prefer>s` over `%<global>s`.'
103
103
 
104
- ENGLISH_VARS = { # rubocop:disable Style/MutableConstant
104
+ ENGLISH_VARS = { # rubocop:disable Style/MutableConstant -- merged into below, then frozen
105
105
  :$: => [:$LOAD_PATH],
106
106
  :$" => [:$LOADED_FEATURES],
107
107
  :$0 => [:$PROGRAM_NAME],
@@ -50,7 +50,33 @@ module RuboCop
50
50
  end
51
51
 
52
52
  def redundant_parentheses?(node)
53
- style == :require_no_parentheses && parentheses?(node)
53
+ return false unless style == :require_no_parentheses && parentheses?(node)
54
+
55
+ arguments = node.block_node.arguments
56
+ !arguments_require_parentheses?(arguments) && !comment_inside_parentheses?(arguments)
57
+ end
58
+
59
+ def arguments_require_parentheses?(arguments)
60
+ arguments.each_descendant(:any_block, :hash).any? do |node|
61
+ !node.hash_type? || node.braces?
62
+ end
63
+ end
64
+
65
+ def comment_inside_parentheses?(arguments)
66
+ !leading_padding(arguments).source.strip.empty? ||
67
+ !trailing_padding(arguments).source.strip.empty?
68
+ end
69
+
70
+ def leading_padding(arguments)
71
+ first_argument = arguments.children.first
72
+
73
+ arguments.loc.begin.end.join(first_argument.source_range.begin)
74
+ end
75
+
76
+ def trailing_padding(arguments)
77
+ last_argument = arguments.children.last
78
+
79
+ last_argument.source_range.end.join(arguments.loc.end.begin)
54
80
  end
55
81
 
56
82
  def message(_node)
@@ -62,10 +88,8 @@ module RuboCop
62
88
  end
63
89
 
64
90
  def unwanted_parentheses_corrector(corrector, node)
65
- args_loc = node.loc
66
-
67
- corrector.replace(args_loc.begin, '')
68
- corrector.remove(args_loc.end)
91
+ corrector.remove(node.loc.begin.join(leading_padding(node)))
92
+ corrector.remove(trailing_padding(node).join(node.loc.end))
69
93
  end
70
94
 
71
95
  def stabby_lambda_with_args?(node)
@@ -160,7 +160,9 @@ module RuboCop
160
160
  end
161
161
 
162
162
  def adjust_str_literal(part)
163
- if single_quoted?(part)
163
+ if file_keyword?(part)
164
+ "\#{#{part.source}}"
165
+ elsif single_quoted?(part)
164
166
  part.value.gsub(/(\\|"|#\{|#@|#\$)/, '\\\\\&')
165
167
  elsif double_quoted?(part)
166
168
  # Reuse the source as written - rebuilding it from the value via
@@ -178,12 +180,16 @@ module RuboCop
178
180
  end
179
181
  end
180
182
 
183
+ def file_keyword?(str_node)
184
+ str_node.source == '__FILE__' && !str_node.parent.dstr_type?
185
+ end
186
+
181
187
  def single_quoted?(str_node)
182
- str_node.source.start_with?("'")
188
+ str_node.loc.begin && str_node.source.start_with?("'")
183
189
  end
184
190
 
185
191
  def double_quoted?(str_node)
186
- str_node.source.start_with?('"')
192
+ str_node.loc.begin && str_node.source.start_with?('"')
187
193
  end
188
194
 
189
195
  def mode
@@ -10,6 +10,10 @@ module RuboCop
10
10
  # Autocorrection is unsafe because it will change the inheritance
11
11
  # tree (e.g. return value of `Module#ancestors`) of the constant.
12
12
  #
13
+ # It is also unsafe because constants that the class body resolves through its
14
+ # ancestors (e.g. one provided by an included module) fall out of scope inside
15
+ # the block.
16
+ #
13
17
  # @example
14
18
  # # bad
15
19
  # class Person < Struct.new(:first_name, :last_name)
@@ -39,6 +43,7 @@ module RuboCop
39
43
 
40
44
  def on_class(node)
41
45
  return unless struct_constructor?(node.parent_class)
46
+ return if defines_constants?(node.body)
42
47
 
43
48
  add_offense(node.parent_class) do |corrector|
44
49
  corrector.remove(
@@ -58,6 +63,15 @@ module RuboCop
58
63
 
59
64
  private
60
65
 
66
+ # Constants, including nested classes and modules, are scoped to the class when they
67
+ # are defined in a class body, but leak into the enclosing namespace once moved into a
68
+ # `Struct.new` block, so such a class cannot be rewritten as an assignment.
69
+ def defines_constants?(class_body)
70
+ return false unless class_body
71
+
72
+ class_body.each_node(:casgn, :class, :module).any?
73
+ end
74
+
61
75
  def correct_parent(parent, corrector)
62
76
  if parent.block_type?
63
77
  corrector.remove(range_with_surrounding_space(parent.loc.end, newlines: false))
@@ -76,6 +76,9 @@ module RuboCop
76
76
 
77
77
  def on_super(super_node)
78
78
  return unless (def_node = find_def_node(super_node))
79
+ # Zsuper passes a destructured argument as the original value, while
80
+ # `argument_list` flattens it into its parts.
81
+ return if def_node.arguments.any?(&:mlhs_type?)
79
82
 
80
83
  def_node_args = def_node.arguments.argument_list
81
84
  super_args = preprocess_super_args(super_node.arguments)
@@ -142,9 +142,11 @@ module RuboCop
142
142
  include RangeHelp
143
143
  include AllowedMethods
144
144
  include AllowedPattern
145
+ include PatternMatchingHelp
145
146
  extend AutoCorrector
146
147
 
147
148
  MSG = 'Pass `&:%<method>s` as an argument to `%<block_method>s` instead of a block.'
149
+ MSG_LAMBDA_LITERAL = 'Use `lambda(&:%<method>s)` instead of %<original>s.'
148
150
  SUPER_TYPES = %i[super zsuper].freeze
149
151
  LAMBDA_OR_PROC = %i[lambda proc].freeze
150
152
 
@@ -174,6 +176,8 @@ module RuboCop
174
176
  return if proc_node?(dispatch_node)
175
177
  return if LAMBDA_OR_PROC.include?(dispatch_node.method_name)
176
178
  end
179
+ # A pattern accepts a lambda literal, but not `lambda(&:foo)`.
180
+ return if in_pattern?(node)
177
181
  return if unsafe_hash_usage?(dispatch_node)
178
182
  return if unsafe_array_usage?(dispatch_node)
179
183
  return if allowed_method_name?(dispatch_node.method_name)
@@ -207,12 +211,26 @@ module RuboCop
207
211
  end
208
212
 
209
213
  def register_offense(node, method_name, block_method_name)
210
- block_start = node.loc.begin.begin_pos
211
- block_end = node.loc.end.end_pos
212
- range = range_between(block_start, block_end)
213
- message = format(MSG, method: method_name, block_method: block_method_name)
214
+ range = if node.send_node.lambda_literal?
215
+ node.source_range
216
+ else
217
+ node.loc.begin.begin.join(node.loc.end.end)
218
+ end
219
+ message = message(node, method_name, block_method_name)
214
220
 
215
- add_offense(range, message: message) { |corrector| autocorrect(corrector, node) }
221
+ add_offense(range, message: message) do |corrector|
222
+ autocorrect(corrector, node)
223
+ end
224
+ end
225
+
226
+ def message(node, method_name, block_method_name)
227
+ if node.send_node.lambda_literal?
228
+ original = node.single_line? ? "`#{node.source}`" : 'a lambda literal with a block'
229
+
230
+ format(MSG_LAMBDA_LITERAL, method: method_name, original: original)
231
+ else
232
+ format(MSG, method: method_name, block_method: block_method_name)
233
+ end
216
234
  end
217
235
 
218
236
  def autocorrect(corrector, node)
@@ -58,6 +58,7 @@ module RuboCop
58
58
  include SafeAssignment
59
59
  include ConfigurableEnforcedStyle
60
60
  include SurroundingSpace
61
+ include ReparsedEquivalence
61
62
  extend AutoCorrector
62
63
 
63
64
  VARIABLE_TYPES = AST::Node::VARIABLES
@@ -101,7 +102,8 @@ module RuboCop
101
102
  condition = node.condition
102
103
 
103
104
  return nil if parenthesized?(condition) &&
104
- (safe_assignment?(condition) || unsafe_autocorrect?(condition))
105
+ (safe_assignment?(condition) || unsafe_autocorrect?(condition) ||
106
+ verified_by_reparse([condition]).empty?)
105
107
 
106
108
  if parenthesized?(condition)
107
109
  correct_parenthesized(corrector, condition)
@@ -218,6 +220,26 @@ module RuboCop
218
220
  end
219
221
  end
220
222
 
223
+ # Whatever binds looser than the ternary operator (`n += 1`, `a rescue b`,
224
+ # a nested ternary, `yield a`, several statements, ...) changes
225
+ # meaning without the parentheses, so their removal is verified by
226
+ # reparsing.
227
+ def apply_reparse_correction(corrector, condition)
228
+ correct_parenthesized(corrector, condition)
229
+ end
230
+
231
+ # The removed parentheses are the only expected difference.
232
+ def normalize_reparsed_ast(node)
233
+ return node unless node.is_a?(::Parser::AST::Node)
234
+
235
+ children = node.children.map { |child| normalize_reparsed_ast(child) }
236
+ if node.begin_type? && children.one? && children.first.is_a?(::Parser::AST::Node)
237
+ children.first
238
+ else
239
+ node.updated(nil, children)
240
+ end
241
+ end
242
+
221
243
  def correct_unparenthesized(corrector, condition)
222
244
  corrector.wrap(condition, '(', ')')
223
245
  end
@@ -64,7 +64,7 @@ module RuboCop
64
64
 
65
65
  MSG = 'Useless trailing comma present in block arguments.'
66
66
 
67
- def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
67
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler -- a trailing comma needs an explicit parameter list
68
68
  # lambda literal (`->`) never has block arguments.
69
69
  return if node.send_node.lambda_literal?
70
70
  return unless useless_trailing_comma?(node)
@@ -35,19 +35,20 @@ module RuboCop
35
35
 
36
36
  MSG = 'Do not use trailing `_`s in parallel assignment. Prefer `%<code>s`.'
37
37
  UNDERSCORE = '_'
38
+ ARRAY_OPENING = '['
38
39
  DISALLOW = %i[lvasgn splat].freeze
39
40
  private_constant :DISALLOW
40
41
 
41
42
  def on_masgn(node)
42
- ranges = unneeded_ranges(node)
43
-
44
- ranges.each do |range|
43
+ unneeded_ranges(node).each do |range, replacement|
44
+ closing = replacement == ARRAY_OPENING ? ']' : ''
45
45
  good_code = node.source
46
46
  offset = range.begin_pos - node.source_range.begin_pos
47
- good_code[offset, range.size] = ''
47
+ good_code[offset, range.size] = replacement
48
48
 
49
- add_offense(range, message: format(MSG, code: good_code)) do |corrector|
50
- corrector.remove(range)
49
+ add_offense(range, message: format(MSG, code: "#{good_code}#{closing}")) do |corrector|
50
+ corrector.replace(range, replacement)
51
+ corrector.insert_after(node, closing) unless closing.empty?
51
52
  end
52
53
  end
53
54
  end
@@ -115,9 +116,12 @@ module RuboCop
115
116
 
116
117
  return unused_range(node, mlhs_node) if unused_variables_only?(first_offense, variables)
117
118
 
118
- return range_for_parentheses(first_offense, mlhs_node) if Util.parentheses?(mlhs_node)
119
-
120
- range_between(first_offense.source_range.begin_pos, node.loc.operator.begin_pos)
119
+ range = if Util.parentheses?(mlhs_node)
120
+ range_for_parentheses(first_offense, mlhs_node)
121
+ else
122
+ range_between(first_offense.source_range.begin_pos, node.loc.operator.begin_pos)
123
+ end
124
+ [range, '']
121
125
  end
122
126
 
123
127
  def children_offenses(variables)
@@ -129,17 +133,17 @@ module RuboCop
129
133
  end
130
134
 
131
135
  def unused_range(node, mlhs_node)
132
- start_range = mlhs_node.source_range.begin_pos
133
-
134
136
  # `node` can be an `mlhs` when recursing into a nested destructuring
135
- # group; only a `masgn` has a right-hand side to anchor against.
136
- end_range = if node.masgn_type?
137
- node.rhs.source_range.begin_pos
138
- else
139
- mlhs_node.source_range.end_pos
140
- end
141
-
142
- range_between(start_range, end_range)
137
+ # group. Removing the group could leave a dangling comma or put
138
+ # something after a splat, so it is collapsed into a single `_`,
139
+ # which the parent group handles in turn.
140
+ return [mlhs_node.source_range, UNDERSCORE] unless node.masgn_type?
141
+
142
+ rhs = node.rhs
143
+ range = range_between(mlhs_node.source_range.begin_pos, rhs.source_range.begin_pos)
144
+
145
+ # `_, _ = 1, 2` cannot become `1, 2`, so the values become an array literal.
146
+ [range, rhs.array_type? && !rhs.bracketed? ? ARRAY_OPENING : '']
143
147
  end
144
148
 
145
149
  def range_for_parentheses(offense, left)
@@ -59,7 +59,7 @@ module RuboCop
59
59
  private
60
60
 
61
61
  def non_eligible_body?(body)
62
- body&.conditional? || super
62
+ body&.conditional? || body&.kwbegin_type? || super
63
63
  end
64
64
  end
65
65
  end
@@ -104,7 +104,7 @@ module RuboCop
104
104
  valid_yoda?(node)
105
105
 
106
106
  add_offense(node) do |corrector|
107
- corrector.replace(actual_code_range(node), corrected_code(node))
107
+ autocorrect(corrector, node)
108
108
  end
109
109
  end
110
110
 
@@ -138,22 +138,37 @@ module RuboCop
138
138
  format(MSG, source: node.source)
139
139
  end
140
140
 
141
- def corrected_code(node)
142
- lhs = node.receiver
143
- rhs = node.first_argument
144
-
145
- "#{rhs.source} #{reverse_comparison(node.method_name)} #{lhs.source}"
141
+ def autocorrect(corrector, node)
142
+ if constant_portion?(node.first_argument)
143
+ move_argument_to_front(corrector, node)
144
+ else
145
+ move_receiver_to_back(corrector, node)
146
+ end
146
147
  end
147
148
 
148
149
  def constant_portion?(node)
149
150
  node.recursive_literal? || node.const_type?
150
151
  end
151
152
 
152
- def actual_code_range(node)
153
- range_between(node.source_range.begin_pos, node.source_range.end_pos)
153
+ def move_argument_to_front(corrector, node)
154
+ receiver = node.receiver
155
+
156
+ replacement = "#{node.first_argument.source} #{reverse_comparison(node)} "
157
+
158
+ corrector.insert_before(receiver, replacement)
159
+ corrector.remove(receiver.source_range.end.join(node.source_range.end))
154
160
  end
155
161
 
156
- def reverse_comparison(operator)
162
+ def move_receiver_to_back(corrector, node)
163
+ argument = node.first_argument
164
+
165
+ corrector.remove(node.source_range.begin.join(argument.source_range.begin))
166
+ corrector.insert_after(argument, " #{reverse_comparison(node)} #{node.receiver.source}")
167
+ end
168
+
169
+ def reverse_comparison(node)
170
+ operator = node.method_name
171
+
157
172
  REVERSE_COMPARISON.fetch(operator.to_s, operator)
158
173
  end
159
174
 
@@ -43,6 +43,9 @@ module RuboCop
43
43
  MSG = 'Non-literal operand (`%<source>s`) should be first.'
44
44
 
45
45
  RESTRICT_ON_SEND = %i[* + & | ^].freeze
46
+ ARGUMENT_ONLY_TYPES = %i[
47
+ splat block_pass forwarded_args forwarded_restarg forwarded_kwrestarg
48
+ ].freeze
46
49
 
47
50
  def on_new_investigation
48
51
  @offended_nodes = nil
@@ -68,13 +71,19 @@ module RuboCop
68
71
  private
69
72
 
70
73
  def yoda_expression_constant?(lhs, rhs)
71
- constant_portion?(lhs) && !constant_portion?(rhs)
74
+ constant_portion?(lhs) && !constant_portion?(rhs) && operand?(rhs)
72
75
  end
73
76
 
74
77
  def constant_portion?(node)
75
78
  node.type?(:numeric, :const)
76
79
  end
77
80
 
81
+ def operand?(node)
82
+ return false if node.hash_type? && !node.braces?
83
+
84
+ !node.type?(*ARGUMENT_ONLY_TYPES)
85
+ end
86
+
78
87
  def supported_operators
79
88
  @supported_operators ||= Array(cop_config['SupportedOperators']).freeze
80
89
  end
@@ -63,7 +63,6 @@ module RuboCop
63
63
  register_cop :DocumentationMethod, "#{__dir__}/style/documentation_method"
64
64
  register_cop :Documentation, "#{__dir__}/style/documentation"
65
65
  register_cop :DocumentDynamicEvalDefinition, "#{__dir__}/style/document_dynamic_eval_definition"
66
- register_cop :DoubleCopDisableDirective, "#{__dir__}/style/double_cop_disable_directive"
67
66
  register_cop :DoubleNegation, "#{__dir__}/style/double_negation"
68
67
  register_cop :EachForSimpleLoop, "#{__dir__}/style/each_for_simple_loop"
69
68
  register_cop :EachWithObject, "#{__dir__}/style/each_with_object"
@@ -178,7 +178,7 @@ module RuboCop
178
178
  elsif defer_corrections
179
179
  @updated_source = new_source
180
180
  else
181
- File.write(processed_source.file_path, new_source)
181
+ RuboCop::Util.replace_file_contents(processed_source.file_path, new_source)
182
182
  end
183
183
  end
184
184
 
@@ -342,20 +342,25 @@ module RuboCop
342
342
  end
343
343
 
344
344
  def each_corrector(report)
345
- skips = Set.new
345
+ applied = []
346
346
  report.cop_reports.each do |cop_report|
347
- cop = cop_report.cop
347
+ cop_class = cop_report.cop.class
348
348
  corrector = cop_report.corrector
349
349
 
350
350
  next if corrector.nil? || corrector.empty?
351
- next if skips.include?(cop.class)
351
+ next if applied.any? { |other| autocorrect_incompatible?(cop_class, other) }
352
352
 
353
353
  yield corrector
354
354
 
355
- skips.merge(cop.class.autocorrect_incompatible_with)
355
+ applied << cop_class
356
356
  end
357
357
  end
358
358
 
359
+ def autocorrect_incompatible?(cop_class, other)
360
+ cop_class.autocorrect_incompatible_with.include?(other) ||
361
+ other.autocorrect_incompatible_with.include?(cop_class)
362
+ end
363
+
359
364
  def suppress_clobbering
360
365
  yield
361
366
  rescue ::Parser::ClobberingError
@@ -63,7 +63,7 @@ module RuboCop
63
63
  end
64
64
  else
65
65
  # Use a block version to avoid allocating enumerators.
66
- node.each_descendant do # rubocop:disable Lint/UnreachableLoop
66
+ node.each_descendant do # rubocop:disable Lint/UnreachableLoop -- the block form avoids allocating an enumerator
67
67
  return true
68
68
  end
69
69
  end
@@ -48,7 +48,7 @@ module RuboCop
48
48
  end
49
49
 
50
50
  def used?
51
- (!reassigned? && @variable.captured_by_block?) || @referenced
51
+ (!reassigned? && @variable.captured_by_block? && @variable.referenced?) || @referenced
52
52
  end
53
53
 
54
54
  def regexp_named_capture?
@@ -67,7 +67,8 @@ module RuboCop
67
67
 
68
68
  break if !assignment.branch || assignment.branch == reference.branch
69
69
 
70
- unless assignment.branch.may_run_incompletely?
70
+ unless assignment.branch.may_run_incompletely? ||
71
+ exception_may_reach?(assignment.branch, node)
71
72
  (consumed_branches ||= Set.new) << assignment.branch
72
73
  end
73
74
  end
@@ -83,6 +84,18 @@ module RuboCop
83
84
  covers?(conditional, reference_node) && !covers?(conditional.condition, reference_node)
84
85
  end
85
86
 
87
+ # A branch nested in the main body of `begin` can be cut short by an exception
88
+ # too. An earlier assignment in it is visible to a reference in the `rescue` or
89
+ # `ensure` clause, or after a `rescue` that handles the exception.
90
+ def exception_may_reach?(branch, reference_node)
91
+ branch.each_ancestor.any? do |ancestor|
92
+ next false unless ancestor.may_run_incompletely?
93
+ next false if covers?(ancestor.child_node, reference_node)
94
+
95
+ ancestor.control_node.rescue_type? || covers?(ancestor.control_node, reference_node)
96
+ end
97
+ end
98
+
86
99
  def modifier_conditional_of(node)
87
100
  node.each_ancestor(:if, :while, :until).find do |conditional|
88
101
  conditional.modifier_form? && covers?(conditional.condition, node)
@@ -20,6 +20,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
20
20
  safety: ->(data) { safety_object(data.safety_objects, data.cop) },
21
21
  examples: ->(data) { examples(data.example_objects, data.cop) },
22
22
  configuration: ->(data) { configurations(data.cop.department, data.cop, data.config) },
23
+ preview: ->(data) { preview_defaults(data.cop) },
23
24
  references: ->(data) { references(data.cop, data.see_objects) }
24
25
  }.freeze
25
26
 
@@ -194,7 +195,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
194
195
  def configurations(department, cop, cop_config)
195
196
  header = ['Name', 'Default value', 'Configurable values']
196
197
  configs = cop_config.each_key.reject do |key|
197
- key == 'AllowMultipleStyles' ||
198
+ key == 'AllowMultipleStyles' || key == 'Preview' ||
198
199
  (key != 'SupportedTypes' && key.start_with?('Supported'))
199
200
  end
200
201
  return '' if configs.empty?
@@ -209,6 +210,22 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
209
210
  cop_subsection('Configurable attributes', cop) + to_table(header, content)
210
211
  end
211
212
 
213
+ def preview_defaults(cop)
214
+ cop_config = config.for_cop(cop)
215
+ preview = cop_config['Preview']
216
+ return '' unless preview.is_a?(Hash)
217
+
218
+ header = ['Name', 'Current default', 'Preview default']
219
+ content = preview.map do |name, value|
220
+ [name, format_table_value(cop_config[name]), format_table_value(value)]
221
+ end
222
+
223
+ cop_subsection('Preview defaults', cop) +
224
+ 'These defaults apply under xref:versioning.adoc#preview[Preview] and are ' \
225
+ "expected to become the regular defaults in the next major release.\n\n" +
226
+ to_table(header, content)
227
+ end
228
+
212
229
  def configuration_name(department, name)
213
230
  return name unless name == 'AllowMultilineFinalElement'
214
231
 
@@ -389,7 +406,11 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
389
406
  def cop_status(status)
390
407
  return 'Disabled' unless status
391
408
 
392
- status == 'pending' ? 'Pending' : 'Enabled'
409
+ case status
410
+ when 'pending' then 'Pending'
411
+ when 'preview' then 'Preview'
412
+ else 'Enabled'
413
+ end
393
414
  end
394
415
 
395
416
  # HTML anchor are somewhat limited in what characters they can contain, just