rubocop 1.86.2 → 1.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +7 -0
  3. data/lib/rubocop/cli.rb +2 -0
  4. data/lib/rubocop/config_loader.rb +17 -2
  5. data/lib/rubocop/config_loader_resolver.rb +11 -3
  6. data/lib/rubocop/config_store.rb +1 -1
  7. data/lib/rubocop/cop/base.rb +8 -2
  8. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +33 -2
  9. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
  10. data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
  11. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
  12. data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
  13. data/lib/rubocop/cop/layout/class_structure.rb +1 -1
  14. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +14 -5
  15. data/lib/rubocop/cop/layout/end_alignment.rb +2 -2
  16. data/lib/rubocop/cop/layout/indentation_width.rb +13 -1
  17. data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -1
  18. data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -1
  19. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  20. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  21. data/lib/rubocop/cop/lint/constant_reassignment.rb +36 -4
  22. data/lib/rubocop/cop/lint/constant_resolution.rb +5 -5
  23. data/lib/rubocop/cop/lint/deprecated_constants.rb +1 -1
  24. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  25. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
  26. data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
  27. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
  28. data/lib/rubocop/cop/lint/number_conversion.rb +5 -5
  29. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  30. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  31. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +2 -2
  32. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +3 -3
  33. data/lib/rubocop/cop/lint/require_relative_self_path.rb +1 -1
  34. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  35. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -1
  36. data/lib/rubocop/cop/lint/unreachable_code.rb +2 -2
  37. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +1 -1
  38. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  39. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  40. data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
  41. data/lib/rubocop/cop/mixin/project_index_help.rb +48 -0
  42. data/lib/rubocop/cop/mixin.rb +1 -0
  43. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  44. data/lib/rubocop/cop/naming/predicate_method.rb +2 -2
  45. data/lib/rubocop/cop/naming/predicate_prefix.rb +1 -1
  46. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
  47. data/lib/rubocop/cop/registry.rb +28 -6
  48. data/lib/rubocop/cop/security/io_methods.rb +1 -1
  49. data/lib/rubocop/cop/style/alias.rb +10 -1
  50. data/lib/rubocop/cop/style/character_literal.rb +2 -2
  51. data/lib/rubocop/cop/style/class_and_module_children.rb +8 -0
  52. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +1 -1
  53. data/lib/rubocop/cop/style/file_write.rb +18 -16
  54. data/lib/rubocop/cop/style/format_string.rb +4 -3
  55. data/lib/rubocop/cop/style/hash_conversion.rb +1 -1
  56. data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
  57. data/lib/rubocop/cop/style/min_max_comparison.rb +1 -1
  58. data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
  59. data/lib/rubocop/cop/style/redundant_constant_base.rb +5 -5
  60. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +2 -2
  61. data/lib/rubocop/cop/style/regexp_literal.rb +2 -2
  62. data/lib/rubocop/cop/style/rescue_modifier.rb +3 -3
  63. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  64. data/lib/rubocop/cop/style/struct_inheritance.rb +13 -0
  65. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -2
  66. data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
  67. data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
  68. data/lib/rubocop/file_patterns.rb +9 -1
  69. data/lib/rubocop/options.rb +18 -0
  70. data/lib/rubocop/project_index_loader.rb +66 -0
  71. data/lib/rubocop/runner.rb +47 -3
  72. data/lib/rubocop/version.rb +20 -2
  73. data/lib/rubocop.rb +1 -0
  74. metadata +5 -3
@@ -91,6 +91,8 @@ module RuboCop
91
91
  option(opts, '-F', '--fail-fast')
92
92
  option(opts, '--disable-pending-cops')
93
93
  option(opts, '--enable-pending-cops')
94
+ option(opts, '--disable-all-cops')
95
+ option(opts, '--enable-all-cops')
94
96
  option(opts, '--ignore-disable-comments')
95
97
  option(opts, '--force-exclusion')
96
98
  option(opts, '--only-recognized-file-types')
@@ -396,6 +398,7 @@ module RuboCop
396
398
  validate_display_only_failed_and_display_only_correctable
397
399
  validate_display_only_correctable_and_autocorrect
398
400
  validate_lsp_and_editor_mode
401
+ validate_enable_all_cops_and_disable_all_cops
399
402
  disable_parallel_when_invalid_option_combo
400
403
 
401
404
  return if incompatible_options.size <= 1
@@ -449,6 +452,13 @@ module RuboCop
449
452
  raise OptionArgumentError, 'Do not specify `--editor-mode` as it is redundant in `--lsp`.'
450
453
  end
451
454
 
455
+ def validate_enable_all_cops_and_disable_all_cops
456
+ return if !@options.key?(:enable_all_cops) || !@options.key?(:disable_all_cops)
457
+
458
+ raise OptionArgumentError,
459
+ '--enable-all-cops cannot be used together with --disable-all-cops.'
460
+ end
461
+
452
462
  def validate_autocorrect
453
463
  if @options.key?(:safe_autocorrect) && @options.key?(:autocorrect_all)
454
464
  message = Rainbow(<<~MESSAGE).red
@@ -621,8 +631,16 @@ module RuboCop
621
631
  display_cop_names: ['Display cop names in offense messages.',
622
632
  'Default is true.'],
623
633
  disable_pending_cops: 'Run without pending cops.',
634
+ disable_all_cops: ['Run with all cops disabled by default,',
635
+ 'except `Lint/Syntax`. Overrides',
636
+ '`AllCops/EnabledByDefault` and',
637
+ '`AllCops/DisabledByDefault` in config files.'],
624
638
  display_style_guide: 'Display style guide URLs in offense messages.',
625
639
  enable_pending_cops: 'Run with pending cops.',
640
+ enable_all_cops: ['Run with all cops enabled, including those',
641
+ 'disabled by default. Overrides',
642
+ '`AllCops/EnabledByDefault` and',
643
+ '`AllCops/DisabledByDefault` in config files.'],
626
644
  extra_details: 'Display extra details in offense messages.',
627
645
  lint: 'Run only lint cops.',
628
646
  safe: 'Run only safe cops.',
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # Defensive loader for the optional `rubydex` gem.
5
+ #
6
+ # When `AllCops/UseProjectIndex` is enabled in the user's configuration, RuboCop builds
7
+ # a project-wide index using `Rubydex::Graph` and exposes it to cops that opt in.
8
+ # The gem is intentionally not a runtime dependency; if it is not installed,
9
+ # or if the running Ruby is older than what `rubydex` supports, RuboCop falls back to
10
+ # its standard file-local behavior.
11
+ module ProjectIndexLoader
12
+ MINIMUM_RUBY_VERSION = '3.2'
13
+
14
+ module_function
15
+
16
+ # Returns whether the `rubydex` gem can be loaded. The result is memoized
17
+ # for the lifetime of the process.
18
+ def available?
19
+ return @available if defined?(@available)
20
+
21
+ @available = supported_ruby? && try_require
22
+ end
23
+
24
+ def supported_ruby?
25
+ RUBY_VERSION >= MINIMUM_RUBY_VERSION
26
+ end
27
+
28
+ def warn_unavailable
29
+ return if @warned
30
+
31
+ @warned = true
32
+
33
+ if supported_ruby?
34
+ warn Rainbow(<<~MSG).yellow
35
+ `AllCops/UseProjectIndex` is enabled but the `rubydex` gem is not installed.
36
+ Analyses that use the project index will be skipped. Add `gem 'rubydex'` to your Gemfile.
37
+ MSG
38
+ else
39
+ warn Rainbow(<<~MSG).yellow
40
+ `AllCops/UseProjectIndex` is enabled but `rubydex` requires Ruby #{MINIMUM_RUBY_VERSION} or later (current: #{RUBY_VERSION}).
41
+ Analyses that use the project index will be skipped.
42
+ MSG
43
+ end
44
+ end
45
+
46
+ def try_require
47
+ require 'rubydex'
48
+ true
49
+ rescue LoadError
50
+ false
51
+ end
52
+
53
+ # Builds and resolves a `Rubydex::Graph` for the given file paths. Returns the resolved graph,
54
+ # or `nil` if the build fails. This is the only place in RuboCop that depends on the concrete
55
+ # `Rubydex::Graph` API, so callers (e.g. `Runner`) do not need to know which Rubydex classes
56
+ # or methods are involved.
57
+ def build_index(paths)
58
+ graph = Rubydex::Graph.new
59
+ graph.index_all(paths.map(&:to_s))
60
+ graph.resolve
61
+ graph
62
+ rescue StandardError => e
63
+ warn Rainbow("rubydex index build failed: #{e.message}. Continuing without it.").yellow
64
+ end
65
+ end
66
+ end
@@ -72,6 +72,8 @@ module RuboCop
72
72
  ResultCache.source_checksum
73
73
 
74
74
  target_files = find_target_files(paths)
75
+ @project_index = ProjectIndexLoader.build_index(target_files) if project_index_enabled?
76
+
75
77
  if @options[:list_target_files]
76
78
  list_files(target_files)
77
79
  else
@@ -102,6 +104,17 @@ module RuboCop
102
104
  target_files.each(&:freeze).freeze
103
105
  end
104
106
 
107
+ def project_index_enabled?
108
+ return false unless @config_store.for_pwd.for_all_cops['UseProjectIndex']
109
+
110
+ unless ProjectIndexLoader.available?
111
+ ProjectIndexLoader.warn_unavailable
112
+ return false
113
+ end
114
+
115
+ true
116
+ end
117
+
105
118
  def inspect_files(files) # rubocop:disable Metrics/AbcSize
106
119
  formatter_set.started(files)
107
120
  file_iterator(files) do |file|
@@ -171,7 +184,21 @@ module RuboCop
171
184
  return false
172
185
  end
173
186
 
187
+ return false if project_index_disables_parallel?
188
+
174
189
  puts 'Running parallel inspection' if @options[:debug]
190
+
191
+ true
192
+ end
193
+
194
+ def project_index_disables_parallel?
195
+ return false if @project_index.nil? || !Gem.win_platform?
196
+
197
+ if @options[:debug]
198
+ puts 'Skipping parallel inspection: the project index is enabled and parallel ' \
199
+ 'inspection is not yet supported on Windows.'
200
+ end
201
+
175
202
  true
176
203
  end
177
204
 
@@ -406,7 +433,15 @@ module RuboCop
406
433
 
407
434
  def mobilize_team(processed_source)
408
435
  config = @config_store.for_file(processed_source.path)
409
- Cop::Team.mobilize(mobilized_cop_classes(config), config, @options)
436
+ team = Cop::Team.mobilize(mobilized_cop_classes(config), config, @options)
437
+
438
+ if @project_index
439
+ team.cops.each do |cop|
440
+ cop.project_index = @project_index
441
+ end
442
+ end
443
+
444
+ team
410
445
  end
411
446
 
412
447
  def mobilized_cop_classes(config) # rubocop:disable Metrics/AbcSize
@@ -549,8 +584,17 @@ module RuboCop
549
584
  # level caching in ResultCache.
550
585
  def standby_team(config)
551
586
  @team_by_config ||= {}.compare_by_identity
552
- @team_by_config[config] ||=
553
- Cop::Team.mobilize(mobilized_cop_classes(config), config, @options)
587
+ @team_by_config[config] ||= begin
588
+ team = Cop::Team.mobilize(mobilized_cop_classes(config), config, @options)
589
+
590
+ if @project_index
591
+ team.cops.each do |cop|
592
+ cop.project_index = @project_index
593
+ end
594
+ end
595
+
596
+ team
597
+ end
554
598
  end
555
599
  end
556
600
  end
@@ -3,12 +3,13 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.86.2'
6
+ STRING = '1.87.0'
7
7
 
8
8
  MSG = '%<version>s (using %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
10
10
  'analyzing as Ruby %<target_ruby_version>s, ' \
11
- 'running on %<ruby_engine>s %<ruby_version>s)%<server_mode>s [%<ruby_platform>s]'
11
+ 'running on %<ruby_engine>s %<ruby_version>s)' \
12
+ '%<rubydex_indicator>s%<server_mode>s [%<ruby_platform>s]'
12
13
 
13
14
  MINIMUM_PARSABLE_PRISM_VERSION = 3.3
14
15
 
@@ -31,6 +32,7 @@ module RuboCop
31
32
  rubocop_ast_version: RuboCop::AST::Version::STRING,
32
33
  target_ruby_version: target_ruby_version,
33
34
  ruby_engine: RUBY_ENGINE, ruby_version: RUBY_VERSION,
35
+ rubydex_indicator: rubydex_indicator(env),
34
36
  server_mode: server_mode,
35
37
  ruby_platform: RUBY_PLATFORM)
36
38
  return verbose_version unless env
@@ -152,6 +154,22 @@ module RuboCop
152
154
  STRING.match('\d+\.\d+').to_s
153
155
  end
154
156
 
157
+ # @api private
158
+ def self.rubydex_indicator(env)
159
+ env && rubydex_enabled?(env) && ProjectIndexLoader.available? ? ' +Rubydex' : ''
160
+ end
161
+
162
+ # @api private
163
+ def self.rubydex_enabled?(env)
164
+ config_for_pwd(env).for_all_cops['UseProjectIndex']
165
+ rescue StandardError
166
+ # Keep `rubocop -V` usable when the config cannot be loaded (broken YAML,
167
+ # missing `inherit_from` target, etc). It is the first command users run to
168
+ # diagnose a broken setup, so the indicator just hides rather than letting
169
+ # the version banner crash.
170
+ false
171
+ end
172
+
155
173
  # @api private
156
174
  def self.server_mode
157
175
  RuboCop.const_defined?(:Server) && Server.running? ? ' +server' : ''
data/lib/rubocop.rb CHANGED
@@ -39,6 +39,7 @@ require_relative 'rubocop/warning'
39
39
 
40
40
  # rubocop:disable Style/RequireOrder
41
41
 
42
+ require_relative 'rubocop/project_index_loader'
42
43
  require_relative 'rubocop/cop/util'
43
44
  require_relative 'rubocop/cop/offense'
44
45
  require_relative 'rubocop/cop/message_annotator'
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.86.2
4
+ version: 1.87.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -660,6 +660,7 @@ files:
660
660
  - lib/rubocop/cop/mixin/percent_literal.rb
661
661
  - lib/rubocop/cop/mixin/preceding_following_alignment.rb
662
662
  - lib/rubocop/cop/mixin/preferred_delimiters.rb
663
+ - lib/rubocop/cop/mixin/project_index_help.rb
663
664
  - lib/rubocop/cop/mixin/range_help.rb
664
665
  - lib/rubocop/cop/mixin/rational_literal.rb
665
666
  - lib/rubocop/cop/mixin/require_library.rb
@@ -1076,6 +1077,7 @@ files:
1076
1077
  - lib/rubocop/plugin/load_error.rb
1077
1078
  - lib/rubocop/plugin/loader.rb
1078
1079
  - lib/rubocop/plugin/not_supported_error.rb
1080
+ - lib/rubocop/project_index_loader.rb
1079
1081
  - lib/rubocop/rake_task.rb
1080
1082
  - lib/rubocop/remote_config.rb
1081
1083
  - lib/rubocop/result_cache.rb
@@ -1117,9 +1119,9 @@ licenses:
1117
1119
  - MIT
1118
1120
  metadata:
1119
1121
  homepage_uri: https://rubocop.org/
1120
- changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.86.2
1122
+ changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.87.0
1121
1123
  source_code_uri: https://github.com/rubocop/rubocop/
1122
- documentation_uri: https://docs.rubocop.org/rubocop/1.86/
1124
+ documentation_uri: https://docs.rubocop.org/rubocop/1.87/
1123
1125
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
1124
1126
  rubygems_mfa_required: 'true'
1125
1127
  rdoc_options: []