rubocop 1.86.1 → 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.
- checksums.yaml +4 -4
- data/config/default.yml +15 -1
- data/lib/rubocop/cli/command/auto_generate_config.rb +27 -1
- data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
- data/lib/rubocop/cli/command/show_docs_url.rb +3 -7
- data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
- data/lib/rubocop/cli.rb +6 -7
- data/lib/rubocop/comment_config.rb +12 -15
- data/lib/rubocop/config_loader.rb +17 -2
- data/lib/rubocop/config_loader_resolver.rb +11 -3
- data/lib/rubocop/config_store.rb +1 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +2 -1
- data/lib/rubocop/cop/base.rb +8 -2
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -5
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +33 -2
- data/lib/rubocop/cop/correctors.rb +28 -0
- data/lib/rubocop/cop/exclude_limit.rb +31 -5
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
- data/lib/rubocop/cop/gemspec/require_mfa.rb +4 -4
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
- data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +14 -5
- data/lib/rubocop/cop/layout/end_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/indentation_width.rb +13 -1
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +26 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -1
- data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/constant_reassignment.rb +36 -4
- data/lib/rubocop/cop/lint/constant_resolution.rb +5 -5
- data/lib/rubocop/cop/lint/deprecated_constants.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +5 -5
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -13
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +3 -3
- data/lib/rubocop/cop/lint/require_relative_self_path.rb +3 -1
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -1
- data/lib/rubocop/cop/lint/unreachable_code.rb +2 -2
- data/lib/rubocop/cop/lint/useless_assignment.rb +3 -8
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +1 -1
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +18 -7
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
- data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
- data/lib/rubocop/cop/mixin/project_index_help.rb +48 -0
- data/lib/rubocop/cop/mixin.rb +86 -0
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_method.rb +2 -2
- data/lib/rubocop/cop/naming/predicate_prefix.rb +1 -1
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
- data/lib/rubocop/cop/offense.rb +8 -0
- data/lib/rubocop/cop/registry.rb +42 -25
- data/lib/rubocop/cop/security/io_methods.rb +1 -1
- data/lib/rubocop/cop/style/alias.rb +10 -1
- data/lib/rubocop/cop/style/character_literal.rb +2 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +8 -0
- data/lib/rubocop/cop/style/copyright.rb +21 -10
- data/lib/rubocop/cop/style/date_time.rb +2 -2
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +1 -1
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
- data/lib/rubocop/cop/style/file_write.rb +18 -16
- data/lib/rubocop/cop/style/format_string.rb +4 -3
- data/lib/rubocop/cop/style/hash_conversion.rb +1 -1
- data/lib/rubocop/cop/style/hash_lookup_method.rb +12 -7
- data/lib/rubocop/cop/style/if_inside_else.rb +15 -2
- data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
- data/lib/rubocop/cop/style/min_max_comparison.rb +1 -1
- data/lib/rubocop/cop/style/module_member_existence_check.rb +6 -3
- data/lib/rubocop/cop/style/reduce_to_hash.rb +16 -0
- data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
- data/lib/rubocop/cop/style/redundant_constant_base.rb +5 -5
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +2 -2
- data/lib/rubocop/cop/style/redundant_self.rb +2 -2
- data/lib/rubocop/cop/style/regexp_literal.rb +31 -2
- data/lib/rubocop/cop/style/rescue_modifier.rb +3 -3
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -2
- data/lib/rubocop/cop/style/struct_inheritance.rb +13 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +3 -3
- data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -2
- data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
- data/lib/rubocop/cop/style/while_until_modifier.rb +16 -0
- data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
- data/lib/rubocop/cop/team.rb +86 -35
- data/lib/rubocop/file_patterns.rb +9 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +4 -1
- data/lib/rubocop/lsp/runtime.rb +1 -2
- data/lib/rubocop/options.rb +26 -4
- data/lib/rubocop/project_index_loader.rb +66 -0
- data/lib/rubocop/rspec/shared_contexts.rb +21 -0
- data/lib/rubocop/runner.rb +123 -57
- data/lib/rubocop/target_finder.rb +13 -6
- data/lib/rubocop/version.rb +20 -2
- data/lib/rubocop.rb +8 -96
- metadata +8 -3
data/lib/rubocop/options.rb
CHANGED
|
@@ -16,7 +16,9 @@ module RuboCop
|
|
|
16
16
|
'root of the project. RuboCop will use this path to determine which ' \
|
|
17
17
|
'cops are enabled (via eg. Include/Exclude), and so that certain cops ' \
|
|
18
18
|
'like Naming/FileName can be checked.'
|
|
19
|
-
EXITING_OPTIONS = %i[
|
|
19
|
+
EXITING_OPTIONS = %i[
|
|
20
|
+
version verbose_version show_cops list_enabled_cops_for show_docs_url lsp mcp
|
|
21
|
+
].freeze
|
|
20
22
|
DEFAULT_MAXIMUM_EXCLUSION_ITEMS = 15
|
|
21
23
|
|
|
22
24
|
def initialize
|
|
@@ -89,6 +91,8 @@ module RuboCop
|
|
|
89
91
|
option(opts, '-F', '--fail-fast')
|
|
90
92
|
option(opts, '--disable-pending-cops')
|
|
91
93
|
option(opts, '--enable-pending-cops')
|
|
94
|
+
option(opts, '--disable-all-cops')
|
|
95
|
+
option(opts, '--enable-all-cops')
|
|
92
96
|
option(opts, '--ignore-disable-comments')
|
|
93
97
|
option(opts, '--force-exclusion')
|
|
94
98
|
option(opts, '--only-recognized-file-types')
|
|
@@ -236,6 +240,7 @@ module RuboCop
|
|
|
236
240
|
def add_additional_modes(opts)
|
|
237
241
|
section(opts, 'Additional Modes') do
|
|
238
242
|
option(opts, '-L', '--list-target-files')
|
|
243
|
+
option(opts, '--list-enabled-cops-for PATH')
|
|
239
244
|
option(opts, '--show-cops [COP1,COP2,...]') do |list|
|
|
240
245
|
@options[:show_cops] = list.nil? ? [] : list.split(',')
|
|
241
246
|
end
|
|
@@ -393,6 +398,7 @@ module RuboCop
|
|
|
393
398
|
validate_display_only_failed_and_display_only_correctable
|
|
394
399
|
validate_display_only_correctable_and_autocorrect
|
|
395
400
|
validate_lsp_and_editor_mode
|
|
401
|
+
validate_enable_all_cops_and_disable_all_cops
|
|
396
402
|
disable_parallel_when_invalid_option_combo
|
|
397
403
|
|
|
398
404
|
return if incompatible_options.size <= 1
|
|
@@ -446,6 +452,13 @@ module RuboCop
|
|
|
446
452
|
raise OptionArgumentError, 'Do not specify `--editor-mode` as it is redundant in `--lsp`.'
|
|
447
453
|
end
|
|
448
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
|
+
|
|
449
462
|
def validate_autocorrect
|
|
450
463
|
if @options.key?(:safe_autocorrect) && @options.key?(:autocorrect_all)
|
|
451
464
|
message = Rainbow(<<~MESSAGE).red
|
|
@@ -474,8 +487,7 @@ module RuboCop
|
|
|
474
487
|
end
|
|
475
488
|
|
|
476
489
|
def invalid_arguments_for_parallel
|
|
477
|
-
[('
|
|
478
|
-
('-F/--fail-fast' if @options.key?(:fail_fast)),
|
|
490
|
+
[('-F/--fail-fast' if @options.key?(:fail_fast)),
|
|
479
491
|
('--profile' if @options[:profile]),
|
|
480
492
|
('--memory' if @options[:memory]),
|
|
481
493
|
('--cache false' if @options > { cache: 'false' })].compact
|
|
@@ -599,7 +611,7 @@ module RuboCop
|
|
|
599
611
|
display_only_correctable: ['Only output correctable offense messages.'],
|
|
600
612
|
display_only_safe_correctable: ['Only output safe-correctable offense messages',
|
|
601
613
|
'when combined with --display-only-correctable.'],
|
|
602
|
-
show_cops: ['
|
|
614
|
+
show_cops: ['Show the given cops, or all cops by',
|
|
603
615
|
'default, and their configurations for the',
|
|
604
616
|
'current directory.',
|
|
605
617
|
'You can use `*` as a wildcard.'],
|
|
@@ -619,8 +631,16 @@ module RuboCop
|
|
|
619
631
|
display_cop_names: ['Display cop names in offense messages.',
|
|
620
632
|
'Default is true.'],
|
|
621
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.'],
|
|
622
638
|
display_style_guide: 'Display style guide URLs in offense messages.',
|
|
623
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.'],
|
|
624
644
|
extra_details: 'Display extra details in offense messages.',
|
|
625
645
|
lint: 'Run only lint cops.',
|
|
626
646
|
safe: 'Run only safe cops.',
|
|
@@ -628,6 +648,8 @@ module RuboCop
|
|
|
628
648
|
'autocorrected source. This is especially useful',
|
|
629
649
|
'when combined with --autocorrect and --stdin.'],
|
|
630
650
|
list_target_files: 'List all files RuboCop will inspect.',
|
|
651
|
+
list_enabled_cops_for: ['List which cops will inspect a given file or',
|
|
652
|
+
'directory.'],
|
|
631
653
|
autocorrect: 'Autocorrect offenses (only when it\'s safe).',
|
|
632
654
|
auto_correct: '(same, deprecated)',
|
|
633
655
|
safe_auto_correct: '(same, deprecated)',
|
|
@@ -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
|
|
@@ -212,6 +212,27 @@ RSpec.shared_context 'lsp' do
|
|
|
212
212
|
end
|
|
213
213
|
end
|
|
214
214
|
|
|
215
|
+
RSpec.shared_context 'with exclude limit tracking' do
|
|
216
|
+
around do |example|
|
|
217
|
+
Dir.mktmpdir('rubocop-exclude-limit') do |dir|
|
|
218
|
+
RuboCop::ExcludeLimit.tmp_dir = Pathname.new(dir)
|
|
219
|
+
example.run
|
|
220
|
+
ensure
|
|
221
|
+
RuboCop::ExcludeLimit.tmp_dir = nil
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Reads exclude_limit values from the tmp files written by ExcludeLimit.
|
|
226
|
+
# Returns a hash like { 'Max' => 81 } or nil if no values were written.
|
|
227
|
+
def read_exclude_limit(cop, parameter_name = nil)
|
|
228
|
+
if parameter_name
|
|
229
|
+
read_exclude_limit(cop)[parameter_name]
|
|
230
|
+
else
|
|
231
|
+
RuboCop::ExcludeLimit.read_limits(cop.class.badge.to_s)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
215
236
|
RSpec.shared_context 'ruby 2.0' do
|
|
216
237
|
# Prism supports parsing Ruby 3.3+.
|
|
217
238
|
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.0 }
|
data/lib/rubocop/runner.rb
CHANGED
|
@@ -62,6 +62,8 @@ module RuboCop
|
|
|
62
62
|
@errors = []
|
|
63
63
|
@warnings = []
|
|
64
64
|
@aborting = false
|
|
65
|
+
@inspected_files = []
|
|
66
|
+
@report_queue = {}
|
|
65
67
|
end
|
|
66
68
|
|
|
67
69
|
def run(paths)
|
|
@@ -70,10 +72,11 @@ module RuboCop
|
|
|
70
72
|
ResultCache.source_checksum
|
|
71
73
|
|
|
72
74
|
target_files = find_target_files(paths)
|
|
75
|
+
@project_index = ProjectIndexLoader.build_index(target_files) if project_index_enabled?
|
|
76
|
+
|
|
73
77
|
if @options[:list_target_files]
|
|
74
78
|
list_files(target_files)
|
|
75
79
|
else
|
|
76
|
-
warm_cache(target_files) if @options[:parallel]
|
|
77
80
|
inspect_files(target_files)
|
|
78
81
|
end
|
|
79
82
|
rescue Interrupt
|
|
@@ -90,21 +93,6 @@ module RuboCop
|
|
|
90
93
|
|
|
91
94
|
private
|
|
92
95
|
|
|
93
|
-
# Warms up the RuboCop cache by forking a suitable number of RuboCop
|
|
94
|
-
# instances that each inspects its allotted group of files.
|
|
95
|
-
def warm_cache(target_files)
|
|
96
|
-
saved_options = @options.dup
|
|
97
|
-
if target_files.length <= 1
|
|
98
|
-
puts 'Skipping parallel inspection: only a single file needs inspection' if @options[:debug]
|
|
99
|
-
return
|
|
100
|
-
end
|
|
101
|
-
puts 'Running parallel inspection' if @options[:debug]
|
|
102
|
-
%i[autocorrect safe_autocorrect].each { |opt| @options[opt] = false }
|
|
103
|
-
Parallel.each(target_files) { |target_file| file_offenses(target_file) }
|
|
104
|
-
ensure
|
|
105
|
-
@options = saved_options
|
|
106
|
-
end
|
|
107
|
-
|
|
108
96
|
def find_target_files(paths)
|
|
109
97
|
target_finder = TargetFinder.new(@config_store, @options)
|
|
110
98
|
mode = if @options[:only_recognized_file_types]
|
|
@@ -116,12 +104,26 @@ module RuboCop
|
|
|
116
104
|
target_files.each(&:freeze).freeze
|
|
117
105
|
end
|
|
118
106
|
|
|
119
|
-
def
|
|
120
|
-
|
|
107
|
+
def project_index_enabled?
|
|
108
|
+
return false unless @config_store.for_pwd.for_all_cops['UseProjectIndex']
|
|
121
109
|
|
|
110
|
+
unless ProjectIndexLoader.available?
|
|
111
|
+
ProjectIndexLoader.warn_unavailable
|
|
112
|
+
return false
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
true
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def inspect_files(files) # rubocop:disable Metrics/AbcSize
|
|
122
119
|
formatter_set.started(files)
|
|
120
|
+
file_iterator(files) do |file|
|
|
121
|
+
offenses = process_file(file)
|
|
122
|
+
succeeded = offenses.none? { |o| considered_failure?(o) && offense_displayed?(o) }
|
|
123
|
+
raise Parallel::Break if @options[:fail_fast] && !succeeded
|
|
123
124
|
|
|
124
|
-
|
|
125
|
+
[offenses, succeeded]
|
|
126
|
+
end
|
|
125
127
|
ensure
|
|
126
128
|
# OPTIMIZE: Calling `ResultCache.cleanup` takes time. This optimization
|
|
127
129
|
# mainly targets editors that integrates RuboCop. When RuboCop is run
|
|
@@ -129,23 +131,88 @@ module RuboCop
|
|
|
129
131
|
if files.size > 1 && cached_run?
|
|
130
132
|
ResultCache.cleanup(@config_store, @options[:debug], @options[:cache_root])
|
|
131
133
|
end
|
|
132
|
-
|
|
133
|
-
formatter_set.finished(inspected_files.freeze)
|
|
134
|
+
formatter_set.finished(@inspected_files.freeze)
|
|
134
135
|
formatter_set.close_output_files
|
|
135
136
|
end
|
|
136
137
|
|
|
137
|
-
def
|
|
138
|
-
|
|
139
|
-
offenses = process_file(file)
|
|
140
|
-
yield file
|
|
138
|
+
def file_iterator(files, &block)
|
|
139
|
+
all_passed = true
|
|
141
140
|
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
on_start = ->(file, _index) { file_started(file) }
|
|
142
|
+
on_finish = lambda do |file, index, (offenses, passed)|
|
|
143
|
+
all_passed &&= passed
|
|
144
|
+
finished_report(file, index, offenses)
|
|
145
|
+
end
|
|
144
146
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
+
if run_in_parallel?(files)
|
|
148
|
+
parallel_file_iterator(files, on_start, on_finish, &block)
|
|
149
|
+
else
|
|
150
|
+
serial_file_iterator(files, on_start, on_finish, &block)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
process_remaining_report_queue
|
|
154
|
+
|
|
155
|
+
all_passed
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def finished_report(file, index, offenses)
|
|
159
|
+
@report_queue[index] = [file, offenses]
|
|
160
|
+
@next_index_to_report ||= 0
|
|
161
|
+
while @report_queue.key?(@next_index_to_report)
|
|
162
|
+
process_report_queue_entry(@next_index_to_report)
|
|
163
|
+
@next_index_to_report += 1
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def process_report_queue_entry(index)
|
|
168
|
+
file, offenses = @report_queue.delete(index)
|
|
169
|
+
file_finished(file, offenses)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def process_remaining_report_queue
|
|
173
|
+
@report_queue.keys.sort.each do |index|
|
|
174
|
+
process_report_queue_entry(index)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
147
177
|
|
|
148
|
-
|
|
178
|
+
def run_in_parallel?(files)
|
|
179
|
+
return false if @options[:auto_gen_config]
|
|
180
|
+
return false unless @options[:parallel]
|
|
181
|
+
|
|
182
|
+
if files.size <= 1
|
|
183
|
+
puts 'Skipping parallel inspection: only a single file needs inspection' if @options[:debug]
|
|
184
|
+
return false
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
return false if project_index_disables_parallel?
|
|
188
|
+
|
|
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
|
+
|
|
202
|
+
true
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def parallel_file_iterator(files, on_start, on_finish, &block)
|
|
206
|
+
Parallel.each(files, start: on_start, finish: on_finish, &block)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def serial_file_iterator(files, on_start, on_finish, &block)
|
|
210
|
+
files.each_with_index do |file, index|
|
|
211
|
+
on_start.call(file, index)
|
|
212
|
+
result = yield file
|
|
213
|
+
on_finish.call(file, index, result)
|
|
214
|
+
rescue Parallel::Break
|
|
215
|
+
break
|
|
149
216
|
end
|
|
150
217
|
end
|
|
151
218
|
|
|
@@ -154,16 +221,13 @@ module RuboCop
|
|
|
154
221
|
end
|
|
155
222
|
|
|
156
223
|
def process_file(file)
|
|
157
|
-
|
|
158
|
-
offenses = file_offenses(file)
|
|
224
|
+
file_offenses(file)
|
|
159
225
|
rescue InfiniteCorrectionLoop => e
|
|
160
226
|
raise e if @options[:raise_cop_error]
|
|
161
227
|
|
|
162
228
|
errors << e
|
|
163
229
|
warn Rainbow(e.message).red
|
|
164
|
-
|
|
165
|
-
ensure
|
|
166
|
-
file_finished(file, offenses || [])
|
|
230
|
+
e.offenses.compact.sort.freeze
|
|
167
231
|
end
|
|
168
232
|
|
|
169
233
|
def file_offenses(file)
|
|
@@ -250,6 +314,7 @@ module RuboCop
|
|
|
250
314
|
end
|
|
251
315
|
|
|
252
316
|
def file_finished(file, offenses)
|
|
317
|
+
@inspected_files << file
|
|
253
318
|
offenses = offenses_to_report(offenses)
|
|
254
319
|
formatter_set.file_finished(file, offenses)
|
|
255
320
|
end
|
|
@@ -258,10 +323,6 @@ module RuboCop
|
|
|
258
323
|
@cached_run ||=
|
|
259
324
|
(@options[:cache] == 'true' ||
|
|
260
325
|
(@options[:cache] != 'false' && @config_store.for_pwd.for_all_cops['UseCache'])) &&
|
|
261
|
-
# When running --auto-gen-config, there's some processing done in the
|
|
262
|
-
# cops related to calculating the Max parameters for Metrics cops. We
|
|
263
|
-
# need to do that processing and cannot use caching.
|
|
264
|
-
!@options[:auto_gen_config] &&
|
|
265
326
|
# We can't cache results from code which is piped in to stdin
|
|
266
327
|
!@options[:stdin]
|
|
267
328
|
end
|
|
@@ -350,21 +411,9 @@ module RuboCop
|
|
|
350
411
|
|
|
351
412
|
def inspect_file(processed_source, team = mobilize_team(processed_source))
|
|
352
413
|
extracted_ruby_sources = extract_ruby_sources(processed_source)
|
|
353
|
-
offenses =
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
report = team.investigate(
|
|
357
|
-
extracted_ruby_source[:processed_source],
|
|
358
|
-
offset: extracted_ruby_source[:offset],
|
|
359
|
-
original: processed_source
|
|
360
|
-
)
|
|
361
|
-
@errors.concat(team.errors)
|
|
362
|
-
@warnings.concat(team.warnings)
|
|
363
|
-
offenses.concat(report.offenses)
|
|
364
|
-
|
|
365
|
-
break if team.updated_source_file?
|
|
366
|
-
end
|
|
367
|
-
|
|
414
|
+
offenses = team.investigate_fragments(extracted_ruby_sources, original: processed_source)
|
|
415
|
+
@errors.concat(team.errors)
|
|
416
|
+
@warnings.concat(team.warnings)
|
|
368
417
|
[offenses, team.updated_source_file?]
|
|
369
418
|
end
|
|
370
419
|
|
|
@@ -384,7 +433,15 @@ module RuboCop
|
|
|
384
433
|
|
|
385
434
|
def mobilize_team(processed_source)
|
|
386
435
|
config = @config_store.for_file(processed_source.path)
|
|
387
|
-
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
|
|
388
445
|
end
|
|
389
446
|
|
|
390
447
|
def mobilized_cop_classes(config) # rubocop:disable Metrics/AbcSize
|
|
@@ -527,8 +584,17 @@ module RuboCop
|
|
|
527
584
|
# level caching in ResultCache.
|
|
528
585
|
def standby_team(config)
|
|
529
586
|
@team_by_config ||= {}.compare_by_identity
|
|
530
|
-
@team_by_config[config] ||=
|
|
531
|
-
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
|
|
532
598
|
end
|
|
533
599
|
end
|
|
534
600
|
end
|
|
@@ -44,10 +44,10 @@ module RuboCop
|
|
|
44
44
|
all_files = find_files(base_dir, File::FNM_DOTMATCH)
|
|
45
45
|
base_dir_config = @config_store.for(base_dir)
|
|
46
46
|
|
|
47
|
-
target_files = if
|
|
47
|
+
target_files = if hidden_dir?(base_dir)
|
|
48
48
|
all_files.select { |file| ruby_file?(file) }
|
|
49
49
|
else
|
|
50
|
-
all_files.select { |file| to_inspect?(file, base_dir_config) }
|
|
50
|
+
all_files.select { |file| to_inspect?(file, base_dir, base_dir_config) }
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
target_files.sort_by!(&order)
|
|
@@ -72,15 +72,22 @@ module RuboCop
|
|
|
72
72
|
|
|
73
73
|
private
|
|
74
74
|
|
|
75
|
-
def to_inspect?(file, base_dir_config)
|
|
75
|
+
def to_inspect?(file, base_dir, base_dir_config)
|
|
76
76
|
return false if base_dir_config.file_to_exclude?(file)
|
|
77
|
-
return true if !
|
|
77
|
+
return true if !hidden_file_in_dir?(file, base_dir) && ruby_file?(file)
|
|
78
78
|
|
|
79
79
|
base_dir_config.file_to_include?(file)
|
|
80
80
|
end
|
|
81
81
|
|
|
82
|
-
def
|
|
83
|
-
|
|
82
|
+
def hidden_dir?(dir)
|
|
83
|
+
basename = File.basename(dir)
|
|
84
|
+
basename.start_with?('.') && basename != '.' && basename != '..'
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def hidden_file_in_dir?(file, base_dir)
|
|
88
|
+
base_dir = "#{base_dir}#{File::SEPARATOR}" unless base_dir.end_with?(File::SEPARATOR)
|
|
89
|
+
relative = file.delete_prefix(base_dir)
|
|
90
|
+
relative.start_with?('.') || relative.include?(HIDDEN_PATH_SUBSTRING)
|
|
84
91
|
end
|
|
85
92
|
|
|
86
93
|
def wanted_dir_patterns(base_dir, exclude_pattern, flags)
|
data/lib/rubocop/version.rb
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
# This module holds the RuboCop version information.
|
|
5
5
|
module Version
|
|
6
|
-
STRING = '1.
|
|
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)
|
|
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' : ''
|