rubocop 1.89.0 → 1.91.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 (248) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +309 -14
  3. data/config/obsoletion.yml +9 -0
  4. data/exe/rubocop +1 -1
  5. data/lib/rubocop/cached_data.rb +7 -2
  6. data/lib/rubocop/changed_files.rb +112 -0
  7. data/lib/rubocop/cli/command/execute_runner.rb +52 -1
  8. data/lib/rubocop/cli.rb +11 -7
  9. data/lib/rubocop/comment_config/directive_range.rb +34 -0
  10. data/lib/rubocop/comment_config/disable_next.rb +143 -0
  11. data/lib/rubocop/comment_config/push_pop.rb +55 -0
  12. data/lib/rubocop/comment_config.rb +50 -64
  13. data/lib/rubocop/config.rb +33 -5
  14. data/lib/rubocop/config_loader.rb +13 -6
  15. data/lib/rubocop/config_loader_resolver.rb +50 -9
  16. data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
  17. data/lib/rubocop/config_obsoletion/removed_cop.rb +8 -0
  18. data/lib/rubocop/config_obsoletion.rb +1 -1
  19. data/lib/rubocop/config_validator.rb +19 -5
  20. data/lib/rubocop/cop/autocorrect_logic.rb +8 -0
  21. data/lib/rubocop/cop/badge.rb +1 -1
  22. data/lib/rubocop/cop/base.rb +49 -5
  23. data/lib/rubocop/cop/corrector.rb +3 -3
  24. data/lib/rubocop/cop/correctors.rb +2 -2
  25. data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
  26. data/lib/rubocop/cop/generator.rb +1 -1
  27. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -2
  28. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -2
  29. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  30. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -0
  31. data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
  32. data/lib/rubocop/cop/layout/class_structure.rb +102 -26
  33. data/lib/rubocop/cop/layout/comment_indentation.rb +8 -5
  34. data/lib/rubocop/cop/layout/else_alignment.rb +1 -0
  35. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -2
  36. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +63 -5
  37. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
  38. data/lib/rubocop/cop/layout/end_alignment.rb +1 -2
  39. data/lib/rubocop/cop/layout/extra_spacing.rb +105 -3
  40. data/lib/rubocop/cop/layout/first_argument_indentation.rb +21 -1
  41. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +17 -4
  42. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +11 -0
  43. data/lib/rubocop/cop/layout/hash_alignment.rb +6 -5
  44. data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
  45. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -2
  46. data/lib/rubocop/cop/layout/line_length.rb +20 -3
  47. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -2
  48. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +5 -5
  49. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -2
  50. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +14 -3
  51. data/lib/rubocop/cop/layout/space_around_operators.rb +12 -1
  52. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +2 -4
  53. data/lib/rubocop/cop/lint/ambiguous_range.rb +1 -2
  54. data/lib/rubocop/cop/lint/argument_mismatch.rb +99 -0
  55. data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -0
  56. data/lib/rubocop/cop/lint/constant_reassignment.rb +17 -11
  57. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +165 -15
  58. data/lib/rubocop/cop/lint/deprecated_reference.rb +11 -2
  59. data/lib/rubocop/cop/lint/duplicate_methods.rb +113 -15
  60. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  61. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -2
  62. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -2
  63. data/lib/rubocop/cop/lint/interpolation_check.rb +1 -2
  64. data/lib/rubocop/cop/lint/literal_as_condition.rb +11 -8
  65. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +3 -6
  66. data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +185 -0
  67. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +25 -12
  68. data/lib/rubocop/cop/lint/name_typo.rb +53 -6
  69. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  70. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
  71. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +15 -0
  72. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +17 -1
  73. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +122 -29
  74. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +47 -7
  75. data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -2
  76. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -2
  77. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -2
  78. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +1 -2
  79. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -2
  80. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -2
  81. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +2 -4
  82. data/lib/rubocop/cop/lint/super_argument_mismatch.rb +179 -0
  83. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +1 -2
  84. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -2
  85. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -2
  86. data/lib/rubocop/cop/lint/unused_private_method.rb +94 -17
  87. data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -2
  88. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -2
  89. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +36 -0
  90. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  91. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -2
  92. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +61 -7
  93. data/lib/rubocop/cop/lint/void.rb +1 -2
  94. data/lib/rubocop/cop/lint.rb +3 -0
  95. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -2
  96. data/lib/rubocop/cop/migration/department_name.rb +1 -2
  97. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  98. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  99. data/lib/rubocop/cop/mixin/comments_help.rb +1 -2
  100. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -2
  101. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +11 -1
  102. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +7 -4
  103. data/lib/rubocop/cop/mixin/hash_subset.rb +1 -2
  104. data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
  105. data/lib/rubocop/cop/mixin/indexed_method_arity.rb +94 -0
  106. data/lib/rubocop/cop/mixin/line_length_help.rb +7 -1
  107. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +62 -6
  108. data/lib/rubocop/cop/mixin/range_help.rb +1 -2
  109. data/lib/rubocop/cop/mixin/statement_modifier.rb +13 -7
  110. data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -4
  111. data/lib/rubocop/cop/mixin.rb +6 -2
  112. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +16 -0
  113. data/lib/rubocop/cop/naming/block_forwarding.rb +4 -1
  114. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  115. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +2 -4
  116. data/lib/rubocop/cop/naming/method_name.rb +5 -2
  117. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -2
  118. data/lib/rubocop/cop/offense.rb +27 -4
  119. data/lib/rubocop/cop/registry.rb +43 -11
  120. data/lib/rubocop/cop/severity.rb +12 -0
  121. data/lib/rubocop/cop/style/access_modifier_declarations.rb +3 -2
  122. data/lib/rubocop/cop/style/accessor_grouping.rb +1 -2
  123. data/lib/rubocop/cop/style/arguments_forwarding.rb +5 -8
  124. data/lib/rubocop/cop/style/array_first_last.rb +1 -2
  125. data/lib/rubocop/cop/style/bitwise_predicate.rb +1 -2
  126. data/lib/rubocop/cop/style/block_delimiters.rb +3 -6
  127. data/lib/rubocop/cop/style/case_like_if.rb +5 -7
  128. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -2
  129. data/lib/rubocop/cop/style/combinable_loops.rb +1 -2
  130. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -2
  131. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -2
  132. data/lib/rubocop/cop/style/constant_visibility.rb +6 -3
  133. data/lib/rubocop/cop/style/copyright.rb +1 -2
  134. data/lib/rubocop/cop/style/data_inheritance.rb +14 -0
  135. data/lib/rubocop/cop/style/directive_scope.rb +304 -0
  136. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +83 -13
  137. data/lib/rubocop/cop/style/documentation_method.rb +1 -9
  138. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  139. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  140. data/lib/rubocop/cop/style/empty_case_condition.rb +1 -2
  141. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  142. data/lib/rubocop/cop/style/empty_method.rb +12 -2
  143. data/lib/rubocop/cop/style/endless_method.rb +31 -12
  144. data/lib/rubocop/cop/style/file_null.rb +2 -2
  145. data/lib/rubocop/cop/style/float_division.rb +10 -16
  146. data/lib/rubocop/cop/style/for.rb +5 -0
  147. data/lib/rubocop/cop/style/format_string_token.rb +1 -2
  148. data/lib/rubocop/cop/style/guard_clause.rb +5 -2
  149. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -2
  150. data/lib/rubocop/cop/style/hash_lookup_method.rb +3 -0
  151. data/lib/rubocop/cop/style/hash_syntax.rb +1 -2
  152. data/lib/rubocop/cop/style/identical_conditional_branches.rb +2 -4
  153. data/lib/rubocop/cop/style/if_inside_else.rb +1 -2
  154. data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -2
  155. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +1 -2
  156. data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
  157. data/lib/rubocop/cop/style/map_to_hash.rb +1 -2
  158. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -4
  159. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
  160. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +1 -2
  161. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -2
  162. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -2
  163. data/lib/rubocop/cop/style/negative_array_index.rb +2 -4
  164. data/lib/rubocop/cop/style/nested_modifier.rb +9 -4
  165. data/lib/rubocop/cop/style/nil_comparison.rb +36 -9
  166. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  167. data/lib/rubocop/cop/style/non_nil_check.rb +18 -2
  168. data/lib/rubocop/cop/style/not.rb +3 -1
  169. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
  170. data/lib/rubocop/cop/style/one_line_conditional.rb +1 -1
  171. data/lib/rubocop/cop/style/operator_method_call.rb +1 -2
  172. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -2
  173. data/lib/rubocop/cop/style/parentheses_around_condition.rb +6 -1
  174. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -2
  175. data/lib/rubocop/cop/style/redundant_condition.rb +6 -8
  176. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +11 -3
  177. data/lib/rubocop/cop/style/redundant_each.rb +1 -2
  178. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
  179. data/lib/rubocop/cop/style/redundant_format.rb +2 -4
  180. data/lib/rubocop/cop/style/redundant_parentheses.rb +13 -5
  181. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +1 -2
  182. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
  183. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +6 -6
  184. data/lib/rubocop/cop/style/redundant_return.rb +1 -2
  185. data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -2
  186. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -2
  187. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -2
  188. data/lib/rubocop/cop/style/safe_navigation.rb +1 -2
  189. data/lib/rubocop/cop/style/sample.rb +11 -6
  190. data/lib/rubocop/cop/style/select_by_regexp.rb +1 -2
  191. data/lib/rubocop/cop/style/semicolon.rb +2 -4
  192. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  193. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
  194. data/lib/rubocop/cop/style/sole_nested_conditional.rb +1 -2
  195. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  196. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -0
  197. data/lib/rubocop/cop/style/string_concatenation.rb +18 -5
  198. data/lib/rubocop/cop/style/struct_inheritance.rb +14 -0
  199. data/lib/rubocop/cop/style/super_arguments.rb +1 -2
  200. data/lib/rubocop/cop/style/symbol_proc.rb +1 -2
  201. data/lib/rubocop/cop/style/time_now.rb +41 -0
  202. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  203. data/lib/rubocop/cop/style/yoda_condition.rb +1 -2
  204. data/lib/rubocop/cop/style.rb +2 -1
  205. data/lib/rubocop/cop/team.rb +11 -3
  206. data/lib/rubocop/cop/util.rb +3 -5
  207. data/lib/rubocop/cop/variable_force/variable.rb +1 -2
  208. data/lib/rubocop/cops_documentation_generator.rb +26 -8
  209. data/lib/rubocop/directive_comment.rb +73 -10
  210. data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -1
  211. data/lib/rubocop/formatter/emacs_style_formatter.rb +3 -1
  212. data/lib/rubocop/formatter/formatter_set.rb +2 -1
  213. data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
  214. data/lib/rubocop/formatter/html_formatter.rb +2 -4
  215. data/lib/rubocop/formatter/json_formatter.rb +11 -6
  216. data/lib/rubocop/formatter/junit_formatter.rb +26 -9
  217. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -2
  218. data/lib/rubocop/formatter/sarif_formatter.rb +181 -0
  219. data/lib/rubocop/formatter/simple_text_formatter.rb +4 -3
  220. data/lib/rubocop/formatter/tap_formatter.rb +3 -1
  221. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -2
  222. data/lib/rubocop/formatter.rb +1 -0
  223. data/lib/rubocop/lockfile.rb +18 -0
  224. data/lib/rubocop/lsp/diagnostic.rb +4 -8
  225. data/lib/rubocop/lsp/routes.rb +48 -19
  226. data/lib/rubocop/magic_comment.rb +27 -0
  227. data/lib/rubocop/mcp/server.rb +1 -2
  228. data/lib/rubocop/options.rb +69 -7
  229. data/lib/rubocop/path_util.rb +2 -3
  230. data/lib/rubocop/plugin/configuration_integrator.rb +6 -3
  231. data/lib/rubocop/plugin/loader.rb +1 -1
  232. data/lib/rubocop/rake_task.rb +1 -2
  233. data/lib/rubocop/remote_config.rb +4 -4
  234. data/lib/rubocop/result_cache.rb +16 -5
  235. data/lib/rubocop/rspec/expect_offense.rb +2 -4
  236. data/lib/rubocop/rspec/shared_contexts.rb +4 -2
  237. data/lib/rubocop/runner.rb +90 -44
  238. data/lib/rubocop/server/cache.rb +1 -2
  239. data/lib/rubocop/server/cli.rb +2 -4
  240. data/lib/rubocop/server.rb +14 -0
  241. data/lib/rubocop/target_finder.rb +4 -1
  242. data/lib/rubocop/todo_audit.rb +111 -0
  243. data/lib/rubocop/unified_diff.rb +257 -0
  244. data/lib/rubocop/version.rb +3 -5
  245. data/lib/rubocop.rb +7 -1
  246. data/lib/ruby_lsp/rubocop/addon.rb +1 -2
  247. metadata +18 -6
  248. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
@@ -45,7 +45,7 @@ module RuboCop
45
45
  @project_dir_cache_key ||= project_dir[1..].tr('/', '+')
46
46
  end
47
47
 
48
- # rubocop:disable Metrics/AbcSize
48
+ # rubocop:disable-next Metrics/AbcSize
49
49
  def restart_key(args_config_file_path: nil)
50
50
  lockfile_path = LOCKFILE_NAMES.map do |lockfile_name|
51
51
  Pathname(project_dir).join(lockfile_name)
@@ -61,7 +61,6 @@ module RuboCop
61
61
 
62
62
  Digest::SHA1.hexdigest(version_data + config_data + inherit_from_data + require_data)
63
63
  end
64
- # rubocop:enable Metrics/AbcSize
65
64
 
66
65
  def dir
67
66
  dir_path.tap do |d|
@@ -55,7 +55,7 @@ module RuboCop
55
55
 
56
56
  private
57
57
 
58
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
58
+ # rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
59
59
  def process_arguments(argv)
60
60
  server_arguments = delete_server_argument_from(argv)
61
61
 
@@ -84,9 +84,8 @@ module RuboCop
84
84
 
85
85
  STATUS_SUCCESS
86
86
  end
87
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
88
87
 
89
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
88
+ # rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/MethodLength
90
89
  def run_command(server_command, detach:)
91
90
  case server_command
92
91
  when '--server'
@@ -107,7 +106,6 @@ module RuboCop
107
106
  Server::ClientCommand::Status.new.run
108
107
  end
109
108
  end
110
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength
111
109
 
112
110
  def fetch_cache_root_path_from(arguments)
113
111
  cache_root = arguments.detect { |argument| argument.start_with?('--cache-root') }
@@ -17,6 +17,11 @@ module RuboCop
17
17
  module Server
18
18
  TIMEOUT = 20
19
19
 
20
+ # Options that start a long-lived protocol server on stdio in the current process.
21
+ # They must never be forwarded to the server process, which would run them as
22
+ # a lint request and silently produce no protocol response.
23
+ IN_PROCESS_PROTOCOL_OPTIONS = %w[--lsp --mcp].freeze
24
+
20
25
  autoload :CLI, 'rubocop/server/cli'
21
26
  autoload :Cache, 'rubocop/server/cache'
22
27
  autoload :ClientCommand, 'rubocop/server/client_command'
@@ -36,6 +41,15 @@ module RuboCop
36
41
  Cache.pid_running?
37
42
  end
38
43
 
44
+ # Whether the invocation should be forwarded to the running server process.
45
+ # `--lsp` and `--mcp` always run in the current process even when the server is running:
46
+ # they serve a protocol on stdio, which the server's `exec` command cannot do.
47
+ def forward_to_server?(argv = ARGV)
48
+ return false unless running?
49
+
50
+ (IN_PROCESS_PROTOCOL_OPTIONS & argv).empty?
51
+ end
52
+
39
53
  def wait_for_running_status!(expected)
40
54
  start_time = Time.now
41
55
  while Server.running? != expected
@@ -21,7 +21,10 @@ module RuboCop
21
21
 
22
22
  args.uniq.each do |arg|
23
23
  files += if File.directory?(arg)
24
- target_files_in_dir(arg.chomp(File::SEPARATOR))
24
+ # Expand the directory so that the traversal can prune directories the
25
+ # config excludes - the exclude patterns are absolute paths, and glued
26
+ # onto a relative base (`rubocop .`) they never match anything.
27
+ target_files_in_dir(File.expand_path(arg.chomp(File::SEPARATOR)))
25
28
  else
26
29
  process_explicit_path(arg, mode)
27
30
  end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # Audits `.rubocop_todo.yml` for `Exclude` entries that are no longer
5
+ # needed: files a cop would not flag anymore, or files that no longer
6
+ # exist. Used by the `--report-unused-todo-entries` option.
7
+ # @api private
8
+ class TodoAudit
9
+ Entry = Struct.new(:cop_name, :path)
10
+
11
+ def initialize(config_store, options)
12
+ @config_store = config_store
13
+ @options = options
14
+ end
15
+
16
+ # @return [Array<Entry>, nil] the unused entries, or `nil` when there is
17
+ # no todo file to audit
18
+ def unused_entries
19
+ return nil unless todo_path
20
+
21
+ entries = todo_exclude_entries
22
+ return [] if entries.empty?
23
+
24
+ offending_cops = offending_cops_without_todo(entries)
25
+ entries.reject { |entry| offending_cops[absolute(entry.path)]&.include?(entry.cop_name) }
26
+ end
27
+
28
+ def todo_file
29
+ CLI::Command::AutoGenerateConfig::AUTO_GENERATED_FILE
30
+ end
31
+
32
+ private
33
+
34
+ def todo_path
35
+ return @todo_path if defined?(@todo_path)
36
+
37
+ path = File.expand_path(todo_file)
38
+ @todo_path = File.exist?(path) ? path : nil
39
+ end
40
+
41
+ def todo_exclude_entries
42
+ yaml = YAML.safe_load_file(todo_path, permitted_classes: [Regexp, Symbol], aliases: true)
43
+ return [] unless yaml.is_a?(Hash)
44
+
45
+ yaml.flat_map do |cop_name, cop_config|
46
+ next [] unless auditable_cop?(cop_name, cop_config)
47
+
48
+ cop_config['Exclude'].grep(String).map { |path| Entry.new(cop_name, path) }
49
+ end
50
+ end
51
+
52
+ # Only registered cops with an `Exclude` list can be audited - for an
53
+ # unknown cop (e.g. from an extension that is not loaded in this run)
54
+ # the absence of offenses proves nothing.
55
+ def auditable_cop?(cop_name, cop_config)
56
+ cop_name.include?('/') &&
57
+ cop_config.is_a?(Hash) &&
58
+ cop_config['Exclude'].is_a?(Array) &&
59
+ Cop::Registry.global.contains_cop_matching?([cop_name])
60
+ end
61
+
62
+ # Inspects every file the todo entries mention, with the todo exclusions
63
+ # subtracted from the configuration, and returns the names of the cops
64
+ # that still report offenses, keyed by absolute file path.
65
+ def offending_cops_without_todo(entries)
66
+ files = entries.map { |entry| absolute(entry.path) }.uniq.select { |file| File.file?(file) }
67
+
68
+ files.to_h do |file|
69
+ offenses = inspect_file(file, entries)
70
+ [file, offenses.to_set(&:cop_name)]
71
+ end
72
+ end
73
+
74
+ def inspect_file(file, entries)
75
+ config = audit_config(@config_store.for_file(file), entries)
76
+ team = Cop::Team.mobilize(Cop::Registry.global, config, @options.merge(autocorrect: false))
77
+
78
+ processed_source = ProcessedSource.from_file(
79
+ file, config.target_ruby_version, parser_engine: config.parser_engine
80
+ )
81
+ processed_source.config = config
82
+ processed_source.registry = Cop::Registry.global
83
+
84
+ team.investigate(processed_source).offenses.reject(&:disabled?)
85
+ end
86
+
87
+ # A copy of the configuration with the todo exclusions removed for the
88
+ # audited cops, so their offenses in the listed files become visible.
89
+ def audit_config(config, entries)
90
+ hash = config.to_hash.dup
91
+
92
+ entries.group_by(&:cop_name).each do |cop_name, cop_entries|
93
+ cop_config = hash[cop_name]
94
+ next unless cop_config.is_a?(Hash) && cop_config['Exclude'].is_a?(Array)
95
+
96
+ hash[cop_name] = subtract_excludes(cop_config, cop_entries)
97
+ end
98
+
99
+ Config.create(hash, config.loaded_path, check: false)
100
+ end
101
+
102
+ def subtract_excludes(cop_config, cop_entries)
103
+ removals = cop_entries.map { |entry| absolute(entry.path) }
104
+ cop_config.merge('Exclude' => cop_config['Exclude'] - removals)
105
+ end
106
+
107
+ def absolute(path)
108
+ File.expand_path(path, File.dirname(todo_path))
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,257 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # Renders a unified diff between two versions of a file's source.
5
+ #
6
+ # RuboCop has no diffing dependency and this output is meant to be read by
7
+ # people (and occasionally piped into `git apply`), so the goal is a diff
8
+ # that is correct and readable, not one that matches `diff -u` byte for byte.
9
+ #
10
+ # @api private
11
+ class UnifiedDiff
12
+ CONTEXT_LINES = 3
13
+ NO_NEWLINE_MARKER = "\\n"
14
+
15
+ # Finding a minimal diff costs time and memory proportional to the square
16
+ # of the number of edits. Past this many edits the file was rewritten
17
+ # rather than corrected, so the changed region is reported as a single
18
+ # replacement instead.
19
+ MAX_EDIT_DISTANCE = 400
20
+
21
+ def initialize(path, old_source, new_source)
22
+ @path = path
23
+ @old_lines = old_source.lines
24
+ @new_lines = new_source.lines
25
+ end
26
+
27
+ # @return [String] the diff, or an empty string when the sources are identical
28
+ def to_s
29
+ return '' if @old_lines == @new_lines
30
+
31
+ hunks = hunks_for(edit_script)
32
+ return '' if hunks.empty?
33
+
34
+ ["--- a/#{@path}\n", "+++ b/#{@path}\n", *hunks].join
35
+ end
36
+
37
+ private
38
+
39
+ def edit_script
40
+ prefix = common_prefix_length
41
+ suffix = common_suffix_length(prefix)
42
+ old_last = @old_lines.length - suffix
43
+ new_last = @new_lines.length - suffix
44
+
45
+ [
46
+ *@old_lines[0...prefix].map { |line| [:equal, line] },
47
+ *middle_script(@old_lines[prefix...old_last], @new_lines[prefix...new_last]),
48
+ *@old_lines[old_last..].map { |line| [:equal, line] }
49
+ ]
50
+ end
51
+
52
+ def common_prefix_length
53
+ length = 0
54
+ length += 1 while length < @old_lines.length && @old_lines[length] == @new_lines[length]
55
+ length
56
+ end
57
+
58
+ def common_suffix_length(prefix)
59
+ length = 0
60
+ max = [@old_lines.length, @new_lines.length].min - prefix
61
+ while length < max &&
62
+ @old_lines[@old_lines.length - 1 - length] == @new_lines[@new_lines.length - 1 - length]
63
+ length += 1
64
+ end
65
+ length
66
+ end
67
+
68
+ def middle_script(old_lines, new_lines)
69
+ # The region that actually differs is diffed on its own, so the rest of
70
+ # the algorithm works on these two slices rather than the whole file.
71
+ @from_lines = old_lines
72
+ @to_lines = new_lines
73
+
74
+ myers_script ||
75
+ [*old_lines.map { |line| [:delete, line] }, *new_lines.map { |line| [:insert, line] }]
76
+ end
77
+
78
+ # Myers' diff algorithm. Each round `d` extends the furthest reaching path
79
+ # for every diagonal `k`; the first path to reach the end of both sources
80
+ # is a shortest edit script, which is then reconstructed from the saved
81
+ # rounds. Returns `nil` when the sources are too different to bother.
82
+ def myers_script
83
+ trace = []
84
+ furthest = Hash.new(0)
85
+ max_distance = [@from_lines.length + @to_lines.length, MAX_EDIT_DISTANCE].min
86
+
87
+ 0.upto(max_distance) do |distance|
88
+ trace << furthest.dup
89
+
90
+ (-distance).step(distance, 2) do |diagonal|
91
+ furthest[diagonal] = advance(furthest, diagonal, distance)
92
+
93
+ return backtrack(trace) if reached_end?(furthest[diagonal], diagonal)
94
+ end
95
+ end
96
+
97
+ nil
98
+ end
99
+
100
+ def reached_end?(old_index, diagonal)
101
+ old_index >= @from_lines.length && old_index - diagonal >= @to_lines.length
102
+ end
103
+
104
+ # Picks the better of the two paths reaching this diagonal, then follows
105
+ # the diagonal as far as the lines match.
106
+ def advance(furthest, diagonal, distance)
107
+ old_index = start_of_path(furthest, diagonal, distance)
108
+
109
+ follow_diagonal(old_index, old_index - diagonal)
110
+ end
111
+
112
+ # A path arrives at this diagonal either from the one above it (having
113
+ # inserted a line) or the one below it (having deleted one); whichever
114
+ # reached further wins.
115
+ def previous_diagonal(furthest, diagonal, distance)
116
+ if diagonal == -distance ||
117
+ (diagonal != distance && furthest[diagonal - 1] < furthest[diagonal + 1])
118
+ diagonal + 1
119
+ else
120
+ diagonal - 1
121
+ end
122
+ end
123
+
124
+ def start_of_path(furthest, diagonal, distance)
125
+ previous = previous_diagonal(furthest, diagonal, distance)
126
+
127
+ previous > diagonal ? furthest[previous] : furthest[previous] + 1
128
+ end
129
+
130
+ # Matching lines cost nothing, so the path slides along them for free.
131
+ def follow_diagonal(old_index, new_index)
132
+ while old_index < @from_lines.length && new_index < @to_lines.length &&
133
+ @from_lines[old_index] == @to_lines[new_index]
134
+ old_index += 1
135
+ new_index += 1
136
+ end
137
+
138
+ old_index
139
+ end
140
+
141
+ def backtrack(trace)
142
+ script = []
143
+ position = [@from_lines.length, @to_lines.length]
144
+
145
+ trace.each_with_index.reverse_each do |furthest, distance|
146
+ previous = previous_position(furthest, distance, *position)
147
+ position = walk_diagonal(script, position, previous)
148
+ next if distance.zero?
149
+
150
+ position = record_edit(script, position, previous)
151
+ end
152
+
153
+ script
154
+ end
155
+
156
+ # Both sides step back together for as long as their lines match.
157
+ def walk_diagonal(script, position, previous)
158
+ old_index, new_index = position
159
+
160
+ while old_index > previous[0] && new_index > previous[1]
161
+ old_index -= 1
162
+ new_index -= 1
163
+ script.unshift([:equal, @from_lines[old_index]])
164
+ end
165
+
166
+ [old_index, new_index]
167
+ end
168
+
169
+ def record_edit(script, position, previous)
170
+ old_index, new_index = position
171
+
172
+ if old_index == previous[0]
173
+ new_index -= 1
174
+ script.unshift([:insert, @to_lines[new_index]])
175
+ else
176
+ old_index -= 1
177
+ script.unshift([:delete, @from_lines[old_index]])
178
+ end
179
+
180
+ [old_index, new_index]
181
+ end
182
+
183
+ def previous_position(furthest, distance, old_index, new_index)
184
+ previous = previous_diagonal(furthest, old_index - new_index, distance)
185
+ previous_old = furthest[previous]
186
+
187
+ [previous_old, previous_old - previous]
188
+ end
189
+
190
+ def hunks_for(script)
191
+ changed = script.each_index.reject { |index| script[index].first == :equal }
192
+ return [] if changed.empty?
193
+
194
+ ranges_for(changed, script.length).map { |range| hunk(script, range) }
195
+ end
196
+
197
+ # Every change is shown with a few lines of context around it, and changes
198
+ # whose context would overlap are shown as a single hunk.
199
+ def ranges_for(changed, script_length)
200
+ ranges = []
201
+
202
+ changed.each do |index|
203
+ first = [index - CONTEXT_LINES, 0].max
204
+ last = [index + CONTEXT_LINES, script_length - 1].min
205
+
206
+ if ranges.last && first <= ranges.last.last + 1
207
+ ranges[-1] = (ranges.last.first..last)
208
+ else
209
+ ranges << (first..last)
210
+ end
211
+ end
212
+
213
+ ranges
214
+ end
215
+
216
+ def hunk(script, range)
217
+ old_start, new_start = start_positions(script, range.first)
218
+ old_count = script[range].count { |kind, _| kind != :insert }
219
+ new_count = script[range].count { |kind, _| kind != :delete }
220
+ body = script[range].map { |kind, line| formatted_line(kind, line) }
221
+
222
+ [
223
+ "@@ -#{position(old_start, old_count)} +#{position(new_start, new_count)} @@\n",
224
+ *body
225
+ ].join
226
+ end
227
+
228
+ def start_positions(script, index)
229
+ old_line = 1
230
+ new_line = 1
231
+
232
+ script[0...index].each do |entry|
233
+ old_line += 1 unless entry.first == :insert
234
+ new_line += 1 unless entry.first == :delete
235
+ end
236
+
237
+ [old_line, new_line]
238
+ end
239
+
240
+ # An empty side is anchored to the line it follows, which is how `diff`
241
+ # reports a pure insertion or deletion, and a single line drops the count.
242
+ def position(start, count)
243
+ case count
244
+ when 0 then "#{start - 1},0"
245
+ when 1 then start.to_s
246
+ else "#{start},#{count}"
247
+ end
248
+ end
249
+
250
+ def formatted_line(kind, line)
251
+ marker = { equal: ' ', delete: '-', insert: '+' }.fetch(kind)
252
+ return "#{marker}#{line}" if line.end_with?("\n")
253
+
254
+ "#{marker}#{line}\n#{NO_NEWLINE_MARKER}"
255
+ end
256
+ end
257
+ end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.89.0'
6
+ STRING = '1.91.0'
7
7
 
8
8
  MSG = '%<version>s (using %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
@@ -23,7 +23,7 @@ module RuboCop
23
23
 
24
24
  # NOTE: Marked as private but used by gems like standard.
25
25
  # @api private
26
- # rubocop:disable Metrics/MethodLength
26
+ # rubocop:disable-next Metrics/MethodLength
27
27
  def self.version(debug: false, env: nil)
28
28
  if debug
29
29
  target_ruby_version = target_ruby_version(env)
@@ -48,7 +48,6 @@ module RuboCop
48
48
  STRING
49
49
  end
50
50
  end
51
- # rubocop:enable Metrics/MethodLength
52
51
 
53
52
  # @api private
54
53
  def self.verbose(env: nil)
@@ -72,7 +71,7 @@ module RuboCop
72
71
  end
73
72
 
74
73
  # @api private
75
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
74
+ # rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
76
75
  def self.extension_versions(env)
77
76
  plugins = config_for_pwd(env).loaded_plugins
78
77
  plugin_versions = plugins.filter_map do |plugin|
@@ -108,7 +107,6 @@ module RuboCop
108
107
 
109
108
  plugin_versions + feature_versions
110
109
  end
111
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
112
110
 
113
111
  # @api private
114
112
  def self.target_ruby_version(env)
data/lib/rubocop.rb CHANGED
@@ -27,6 +27,7 @@ require_relative 'rubocop/ext/regexp_parser'
27
27
  require_relative 'rubocop/core_ext/string'
28
28
  require_relative 'rubocop/ext/processed_source'
29
29
 
30
+ require_relative 'rubocop/changed_files'
30
31
  require_relative 'rubocop/error'
31
32
  require_relative 'rubocop/file_finder'
32
33
  require_relative 'rubocop/file_patterns'
@@ -34,10 +35,11 @@ require_relative 'rubocop/name_similarity'
34
35
  require_relative 'rubocop/path_util'
35
36
  require_relative 'rubocop/platform'
36
37
  require_relative 'rubocop/string_interpreter'
38
+ require_relative 'rubocop/unified_diff'
37
39
  require_relative 'rubocop/util'
38
40
  require_relative 'rubocop/warning'
39
41
 
40
- # rubocop:disable Style/RequireOrder
42
+ # rubocop:disable Style/RequireOrder -- ordered by load dependency, not alphabetically
41
43
 
42
44
  require_relative 'rubocop/project_index_loader'
43
45
  require_relative 'rubocop/cop/util'
@@ -110,6 +112,9 @@ require_relative 'rubocop/lockfile'
110
112
  require_relative 'rubocop/lsp'
111
113
  require_relative 'rubocop/target_finder'
112
114
  require_relative 'rubocop/directive_comment'
115
+ require_relative 'rubocop/comment_config/directive_range'
116
+ require_relative 'rubocop/comment_config/disable_next'
117
+ require_relative 'rubocop/comment_config/push_pop'
113
118
  require_relative 'rubocop/comment_config'
114
119
  require_relative 'rubocop/result_cache'
115
120
  require_relative 'rubocop/runner'
@@ -128,6 +133,7 @@ require_relative 'rubocop/cli/command/show_docs_url'
128
133
  require_relative 'rubocop/cli/command/suggest_extensions'
129
134
  require_relative 'rubocop/cli/command/version'
130
135
  require_relative 'rubocop/config_regeneration'
136
+ require_relative 'rubocop/todo_audit'
131
137
  require_relative 'rubocop/options'
132
138
  require_relative 'rubocop/remote_config'
133
139
  require_relative 'rubocop/target_ruby'
@@ -41,7 +41,7 @@ module RubyLsp
41
41
  @runtime_adapter = nil
42
42
  end
43
43
 
44
- # rubocop:disable Metrics/MethodLength
44
+ # rubocop:disable-next Metrics/MethodLength
45
45
  def register_additional_file_watchers(global_state, message_queue)
46
46
  return unless global_state.supports_watching_files
47
47
 
@@ -66,7 +66,6 @@ module RubyLsp
66
66
  )
67
67
  )
68
68
  end
69
- # rubocop:enable Metrics/MethodLength
70
69
 
71
70
  def workspace_did_change_watched_files(changes)
72
71
  if (changed_config_file = changed_config_file(changes))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.89.0
4
+ version: 1.91.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -15,14 +15,14 @@ dependencies:
15
15
  name: json
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "~>"
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
20
  version: '2.3'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - "~>"
25
+ - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: '2.3'
28
28
  - !ruby/object:Gem::Dependency
@@ -201,6 +201,7 @@ files:
201
201
  - lib/rubocop/ast_aliases.rb
202
202
  - lib/rubocop/cache_config.rb
203
203
  - lib/rubocop/cached_data.rb
204
+ - lib/rubocop/changed_files.rb
204
205
  - lib/rubocop/cli.rb
205
206
  - lib/rubocop/cli/command.rb
206
207
  - lib/rubocop/cli/command/auto_generate_config.rb
@@ -216,6 +217,9 @@ files:
216
217
  - lib/rubocop/cli/command/version.rb
217
218
  - lib/rubocop/cli/environment.rb
218
219
  - lib/rubocop/comment_config.rb
220
+ - lib/rubocop/comment_config/directive_range.rb
221
+ - lib/rubocop/comment_config/disable_next.rb
222
+ - lib/rubocop/comment_config/push_pop.rb
219
223
  - lib/rubocop/config.rb
220
224
  - lib/rubocop/config_finder.rb
221
225
  - lib/rubocop/config_loader.rb
@@ -438,6 +442,7 @@ files:
438
442
  - lib/rubocop/cop/lint/ambiguous_operator_precedence.rb
439
443
  - lib/rubocop/cop/lint/ambiguous_range.rb
440
444
  - lib/rubocop/cop/lint/ambiguous_regexp_literal.rb
445
+ - lib/rubocop/cop/lint/argument_mismatch.rb
441
446
  - lib/rubocop/cop/lint/array_literal_in_regexp.rb
442
447
  - lib/rubocop/cop/lint/assignment_in_condition.rb
443
448
  - lib/rubocop/cop/lint/big_decimal_new.rb
@@ -499,6 +504,7 @@ files:
499
504
  - lib/rubocop/cop/lint/literal_assignment_in_condition.rb
500
505
  - lib/rubocop/cop/lint/literal_in_interpolation.rb
501
506
  - lib/rubocop/cop/lint/loop.rb
507
+ - lib/rubocop/cop/lint/misplaced_magic_comment.rb
502
508
  - lib/rubocop/cop/lint/missing_cop_enable_directive.rb
503
509
  - lib/rubocop/cop/lint/missing_super.rb
504
510
  - lib/rubocop/cop/lint/mixed_case_range.rb
@@ -553,6 +559,7 @@ files:
553
559
  - lib/rubocop/cop/lint/shadowing_outer_local_variable.rb
554
560
  - lib/rubocop/cop/lint/shared_mutable_default.rb
555
561
  - lib/rubocop/cop/lint/struct_new_override.rb
562
+ - lib/rubocop/cop/lint/super_argument_mismatch.rb
556
563
  - lib/rubocop/cop/lint/suppressed_exception.rb
557
564
  - lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb
558
565
  - lib/rubocop/cop/lint/symbol_conversion.rb
@@ -650,6 +657,7 @@ files:
650
657
  - lib/rubocop/cop/mixin/hash_transform_method.rb
651
658
  - lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb
652
659
  - lib/rubocop/cop/mixin/heredoc.rb
660
+ - lib/rubocop/cop/mixin/indexed_method_arity.rb
653
661
  - lib/rubocop/cop/mixin/integer_node.rb
654
662
  - lib/rubocop/cop/mixin/interpolation.rb
655
663
  - lib/rubocop/cop/mixin/line_length_help.rb
@@ -775,11 +783,11 @@ files:
775
783
  - lib/rubocop/cop/style/dig_chain.rb
776
784
  - lib/rubocop/cop/style/dir.rb
777
785
  - lib/rubocop/cop/style/dir_empty.rb
786
+ - lib/rubocop/cop/style/directive_scope.rb
778
787
  - lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb
779
788
  - lib/rubocop/cop/style/document_dynamic_eval_definition.rb
780
789
  - lib/rubocop/cop/style/documentation.rb
781
790
  - lib/rubocop/cop/style/documentation_method.rb
782
- - lib/rubocop/cop/style/double_cop_disable_directive.rb
783
791
  - lib/rubocop/cop/style/double_negation.rb
784
792
  - lib/rubocop/cop/style/each_for_simple_loop.rb
785
793
  - lib/rubocop/cop/style/each_with_object.rb
@@ -1001,6 +1009,7 @@ files:
1001
1009
  - lib/rubocop/cop/style/symbol_proc.rb
1002
1010
  - lib/rubocop/cop/style/tally_method.rb
1003
1011
  - lib/rubocop/cop/style/ternary_parentheses.rb
1012
+ - lib/rubocop/cop/style/time_now.rb
1004
1013
  - lib/rubocop/cop/style/top_level_method_definition.rb
1005
1014
  - lib/rubocop/cop/style/trailing_body_on_class.rb
1006
1015
  - lib/rubocop/cop/style/trailing_body_on_method_definition.rb
@@ -1066,6 +1075,7 @@ files:
1066
1075
  - lib/rubocop/formatter/pacman_formatter.rb
1067
1076
  - lib/rubocop/formatter/progress_formatter.rb
1068
1077
  - lib/rubocop/formatter/quiet_formatter.rb
1078
+ - lib/rubocop/formatter/sarif_formatter.rb
1069
1079
  - lib/rubocop/formatter/simple_text_formatter.rb
1070
1080
  - lib/rubocop/formatter/tap_formatter.rb
1071
1081
  - lib/rubocop/formatter/text_util.rb
@@ -1123,6 +1133,8 @@ files:
1123
1133
  - lib/rubocop/string_interpreter.rb
1124
1134
  - lib/rubocop/target_finder.rb
1125
1135
  - lib/rubocop/target_ruby.rb
1136
+ - lib/rubocop/todo_audit.rb
1137
+ - lib/rubocop/unified_diff.rb
1126
1138
  - lib/rubocop/util.rb
1127
1139
  - lib/rubocop/version.rb
1128
1140
  - lib/rubocop/warning.rb
@@ -1134,9 +1146,9 @@ licenses:
1134
1146
  - MIT
1135
1147
  metadata:
1136
1148
  homepage_uri: https://rubocop.org/
1137
- changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.89.0
1149
+ changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.91.0
1138
1150
  source_code_uri: https://github.com/rubocop/rubocop/
1139
- documentation_uri: https://docs.rubocop.org/rubocop/1.89/
1151
+ documentation_uri: https://docs.rubocop.org/rubocop/1.91/
1140
1152
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
1141
1153
  rubygems_mfa_required: 'true'
1142
1154
  rdoc_options: []