rubocop 1.60.2 → 1.62.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/README.md +1 -1
- data/assets/output.css.erb +159 -0
- data/assets/output.html.erb +1 -160
- data/config/default.yml +41 -12
- data/lib/rubocop/cli/command/lsp.rb +2 -2
- data/lib/rubocop/cli.rb +6 -1
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_finder.rb +12 -2
- data/lib/rubocop/config_validator.rb +14 -5
- data/lib/rubocop/cop/autocorrect_logic.rb +6 -1
- data/lib/rubocop/cop/base.rb +17 -8
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +2 -0
- data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
- data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +3 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +14 -9
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
- data/lib/rubocop/cop/lint/script_permission.rb +3 -3
- data/lib/rubocop/cop/lint/syntax.rb +1 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +7 -2
- data/lib/rubocop/cop/lint/void.rb +6 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +29 -8
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +4 -5
- data/lib/rubocop/cop/style/hash_syntax.rb +6 -2
- data/lib/rubocop/cop/style/inverse_methods.rb +8 -8
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -5
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +5 -8
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +4 -0
- data/lib/rubocop/cop/style/object_then.rb +5 -3
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -3
- data/lib/rubocop/cop/style/raise_args.rb +3 -0
- data/lib/rubocop/cop/style/redundant_argument.rb +2 -2
- data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +17 -6
- data/lib/rubocop/cop/style/redundant_return.rb +6 -0
- data/lib/rubocop/cop/style/sample.rb +1 -3
- data/lib/rubocop/cops_documentation_generator.rb +4 -2
- data/lib/rubocop/formatter/html_formatter.rb +30 -10
- data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
- data/lib/rubocop/lsp/logger.rb +1 -1
- data/lib/rubocop/lsp/routes.rb +1 -1
- data/lib/rubocop/lsp/runtime.rb +1 -1
- data/lib/rubocop/lsp/server.rb +5 -2
- data/lib/rubocop/lsp/severity.rb +1 -1
- data/lib/rubocop/lsp.rb +29 -0
- data/lib/rubocop/magic_comment.rb +1 -1
- data/lib/rubocop/options.rb +11 -0
- data/lib/rubocop/path_util.rb +6 -2
- data/lib/rubocop/rspec/cop_helper.rb +8 -2
- data/lib/rubocop/rspec/expect_offense.rb +1 -1
- data/lib/rubocop/rspec/shared_contexts.rb +36 -17
- data/lib/rubocop/rspec/support.rb +2 -1
- data/lib/rubocop/runner.rb +9 -2
- data/lib/rubocop/target_finder.rb +84 -78
- data/lib/rubocop/target_ruby.rb +82 -80
- data/lib/rubocop/version.rb +18 -3
- metadata +9 -6
@@ -100,10 +100,10 @@ RSpec.shared_context 'config' do # rubocop:disable Metrics/BlockLength
|
|
100
100
|
let(:cur_cop_config) do
|
101
101
|
RuboCop::ConfigLoader
|
102
102
|
.default_configuration.for_cop(cop_class)
|
103
|
-
.merge(
|
104
|
-
|
105
|
-
|
106
|
-
|
103
|
+
.merge(
|
104
|
+
'Enabled' => true, # in case it is 'pending'
|
105
|
+
'AutoCorrect' => 'always' # in case defaults set it to 'disabled' or false
|
106
|
+
)
|
107
107
|
.merge(cop_config)
|
108
108
|
end
|
109
109
|
|
@@ -128,56 +128,75 @@ RSpec.shared_context 'mock console output' do
|
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
131
|
-
RSpec.shared_context 'lsp
|
131
|
+
RSpec.shared_context 'lsp' do
|
132
132
|
before do
|
133
|
-
|
133
|
+
RuboCop::LSP.enable
|
134
|
+
end
|
135
|
+
|
136
|
+
after do
|
137
|
+
RuboCop::LSP.disable
|
134
138
|
end
|
135
139
|
end
|
136
140
|
|
137
141
|
RSpec.shared_context 'ruby 2.0' do
|
138
|
-
|
142
|
+
# Prism supports parsing Ruby 3.3+.
|
143
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.0 }
|
139
144
|
end
|
140
145
|
|
141
146
|
RSpec.shared_context 'ruby 2.1' do
|
142
|
-
|
147
|
+
# Prism supports parsing Ruby 3.3+.
|
148
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.1 }
|
143
149
|
end
|
144
150
|
|
145
151
|
RSpec.shared_context 'ruby 2.2' do
|
146
|
-
|
152
|
+
# Prism supports parsing Ruby 3.3+.
|
153
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.2 }
|
147
154
|
end
|
148
155
|
|
149
156
|
RSpec.shared_context 'ruby 2.3' do
|
150
|
-
|
157
|
+
# Prism supports parsing Ruby 3.3+.
|
158
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.3 }
|
151
159
|
end
|
152
160
|
|
153
161
|
RSpec.shared_context 'ruby 2.4' do
|
154
|
-
|
162
|
+
# Prism supports parsing Ruby 3.3+.
|
163
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.4 }
|
155
164
|
end
|
156
165
|
|
157
166
|
RSpec.shared_context 'ruby 2.5' do
|
158
|
-
|
167
|
+
# Prism supports parsing Ruby 3.3+.
|
168
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.5 }
|
159
169
|
end
|
160
170
|
|
161
171
|
RSpec.shared_context 'ruby 2.6' do
|
162
|
-
|
172
|
+
# Prism supports parsing Ruby 3.3+.
|
173
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.6 }
|
163
174
|
end
|
164
175
|
|
165
176
|
RSpec.shared_context 'ruby 2.7' do
|
166
|
-
|
177
|
+
# Prism supports parsing Ruby 3.3+.
|
178
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.7 }
|
167
179
|
end
|
168
180
|
|
169
181
|
RSpec.shared_context 'ruby 3.0' do
|
170
|
-
|
182
|
+
# Prism supports parsing Ruby 3.3+.
|
183
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 3.0 }
|
171
184
|
end
|
172
185
|
|
173
186
|
RSpec.shared_context 'ruby 3.1' do
|
174
|
-
|
187
|
+
# Prism supports parsing Ruby 3.3+.
|
188
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 3.1 }
|
175
189
|
end
|
176
190
|
|
177
191
|
RSpec.shared_context 'ruby 3.2' do
|
178
|
-
|
192
|
+
# Prism supports parsing Ruby 3.3+.
|
193
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 3.2 }
|
179
194
|
end
|
180
195
|
|
181
196
|
RSpec.shared_context 'ruby 3.3' do
|
182
197
|
let(:ruby_version) { 3.3 }
|
183
198
|
end
|
199
|
+
|
200
|
+
RSpec.shared_context 'ruby 3.4' do
|
201
|
+
let(:ruby_version) { 3.4 }
|
202
|
+
end
|
@@ -13,7 +13,7 @@ RSpec.configure do |config|
|
|
13
13
|
config.include HostEnvironmentSimulatorHelper
|
14
14
|
config.include_context 'config', :config
|
15
15
|
config.include_context 'isolated environment', :isolated_environment
|
16
|
-
config.include_context 'lsp
|
16
|
+
config.include_context 'lsp', :lsp
|
17
17
|
config.include_context 'maintain registry', :restore_registry
|
18
18
|
config.include_context 'ruby 2.0', :ruby20
|
19
19
|
config.include_context 'ruby 2.1', :ruby21
|
@@ -27,4 +27,5 @@ RSpec.configure do |config|
|
|
27
27
|
config.include_context 'ruby 3.1', :ruby31
|
28
28
|
config.include_context 'ruby 3.2', :ruby32
|
29
29
|
config.include_context 'ruby 3.3', :ruby33
|
30
|
+
config.include_context 'ruby 3.4', :ruby34
|
30
31
|
end
|
data/lib/rubocop/runner.rb
CHANGED
@@ -467,15 +467,21 @@ module RuboCop
|
|
467
467
|
end
|
468
468
|
end
|
469
469
|
|
470
|
+
# rubocop:disable Metrics/MethodLength
|
470
471
|
def get_processed_source(file)
|
471
472
|
config = @config_store.for_file(file)
|
472
473
|
ruby_version = config.target_ruby_version
|
474
|
+
parser_engine = config.parser_engine
|
473
475
|
|
474
476
|
processed_source = if @options[:stdin]
|
475
|
-
ProcessedSource.new(
|
477
|
+
ProcessedSource.new(
|
478
|
+
@options[:stdin], ruby_version, file, parser_engine: parser_engine
|
479
|
+
)
|
476
480
|
else
|
477
481
|
begin
|
478
|
-
ProcessedSource.from_file(
|
482
|
+
ProcessedSource.from_file(
|
483
|
+
file, ruby_version, parser_engine: parser_engine
|
484
|
+
)
|
479
485
|
rescue Errno::ENOENT
|
480
486
|
raise RuboCop::Error, "No such file or directory: #{file}"
|
481
487
|
end
|
@@ -484,6 +490,7 @@ module RuboCop
|
|
484
490
|
processed_source.registry = mobilized_cop_classes(config)
|
485
491
|
processed_source
|
486
492
|
end
|
493
|
+
# rubocop:enable Metrics/MethodLength
|
487
494
|
|
488
495
|
# A Cop::Team instance is stateful and may change when inspecting.
|
489
496
|
# The "standby" team for a given config is an initialized but
|
@@ -1,8 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module RuboCop
|
4
|
-
# This class finds target files to inspect by scanning the directory tree
|
5
|
-
# and picking ruby files.
|
4
|
+
# This class finds target files to inspect by scanning the directory tree and picking ruby files.
|
6
5
|
# @api private
|
7
6
|
class TargetFinder
|
8
7
|
HIDDEN_PATH_SUBSTRING = "#{File::SEPARATOR}."
|
@@ -12,21 +11,8 @@ module RuboCop
|
|
12
11
|
@options = options
|
13
12
|
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
def debug?
|
20
|
-
@options[:debug]
|
21
|
-
end
|
22
|
-
|
23
|
-
def fail_fast?
|
24
|
-
@options[:fail_fast]
|
25
|
-
end
|
26
|
-
|
27
|
-
# Generate a list of target files by expanding globbing patterns
|
28
|
-
# (if any). If args is empty, recursively find all Ruby source
|
29
|
-
# files under the current directory
|
14
|
+
# Generate a list of target files by expanding globbing patterns (if any). If args is empty,
|
15
|
+
# recursively find all Ruby source files under the current directory
|
30
16
|
# @return [Array] array of file paths
|
31
17
|
def find(args, mode)
|
32
18
|
return target_files_in_dir if args.empty?
|
@@ -44,12 +30,11 @@ module RuboCop
|
|
44
30
|
files.map { |f| File.expand_path(f) }.uniq
|
45
31
|
end
|
46
32
|
|
47
|
-
# Finds all Ruby source files under the current or other supplied
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
# so you can include other Ruby files like Rakefiles and gemspecs.
|
33
|
+
# Finds all Ruby source files under the current or other supplied directory. A Ruby source file
|
34
|
+
# is defined as a file with the `.rb` extension or a file with no extension that has a ruby
|
35
|
+
# shebang line as its first line.
|
36
|
+
# It is possible to specify includes and excludes using the config file, so you can include
|
37
|
+
# other Ruby files like Rakefiles and gemspecs.
|
53
38
|
# @param base_dir Root directory under which to search for
|
54
39
|
# ruby source files
|
55
40
|
# @return [Array] Array of filenames
|
@@ -66,20 +51,10 @@ module RuboCop
|
|
66
51
|
target_files.sort_by!(&order)
|
67
52
|
end
|
68
53
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end && ruby_file?(file)
|
74
|
-
|
75
|
-
base_dir_config.file_to_include?(file)
|
76
|
-
end
|
77
|
-
|
78
|
-
# Search for files recursively starting at the given base directory using
|
79
|
-
# the given flags that determine how the match is made. Excluded files will
|
80
|
-
# be removed later by the caller, but as an optimization find_files removes
|
81
|
-
# the top level directories that are excluded in configuration in the
|
82
|
-
# normal way (dir/**/*).
|
54
|
+
# Search for files recursively starting at the given base directory using the given flags that
|
55
|
+
# determine how the match is made. Excluded files will be removed later by the caller, but as an
|
56
|
+
# optimization find_files removes the top level directories that are excluded in configuration
|
57
|
+
# in the normal way (dir/**/*).
|
83
58
|
def find_files(base_dir, flags)
|
84
59
|
# get all wanted directories first to improve speed of finding all files
|
85
60
|
exclude_pattern = combined_exclude_glob_patterns(base_dir)
|
@@ -93,6 +68,17 @@ module RuboCop
|
|
93
68
|
Dir.glob(patterns, flags).select { |path| FileTest.file?(path) }
|
94
69
|
end
|
95
70
|
|
71
|
+
private
|
72
|
+
|
73
|
+
def to_inspect?(file, hidden_files, base_dir_config)
|
74
|
+
return false if base_dir_config.file_to_exclude?(file)
|
75
|
+
return true if !hidden_files.bsearch do |hidden_file|
|
76
|
+
file <=> hidden_file
|
77
|
+
end && ruby_file?(file)
|
78
|
+
|
79
|
+
base_dir_config.file_to_include?(file)
|
80
|
+
end
|
81
|
+
|
96
82
|
def wanted_dir_patterns(base_dir, exclude_pattern, flags)
|
97
83
|
# Escape glob characters in base_dir to avoid unwanted behavior.
|
98
84
|
base_dir = base_dir.gsub(/[\\\{\}\[\]\*\?]/) do |reserved_glob_character|
|
@@ -124,21 +110,6 @@ module RuboCop
|
|
124
110
|
"#{base_dir}/{#{patterns.join(',')}}"
|
125
111
|
end
|
126
112
|
|
127
|
-
def ruby_extension?(file)
|
128
|
-
ruby_extensions.include?(File.extname(file))
|
129
|
-
end
|
130
|
-
|
131
|
-
def ruby_extensions
|
132
|
-
@ruby_extensions ||= begin
|
133
|
-
ext_patterns = all_cops_include.select { |pattern| pattern.start_with?('**/*.') }
|
134
|
-
ext_patterns.map { |pattern| pattern.sub('**/*', '') }
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def ruby_filename?(file)
|
139
|
-
ruby_filenames.include?(File.basename(file))
|
140
|
-
end
|
141
|
-
|
142
113
|
def ruby_filenames
|
143
114
|
@ruby_filenames ||= begin
|
144
115
|
file_patterns = all_cops_include.reject { |pattern| pattern.start_with?('**/*.') }
|
@@ -150,53 +121,72 @@ module RuboCop
|
|
150
121
|
@all_cops_include ||= @config_store.for_pwd.for_all_cops['Include'].map(&:to_s)
|
151
122
|
end
|
152
123
|
|
153
|
-
def
|
154
|
-
|
124
|
+
def process_explicit_path(path, mode)
|
125
|
+
files = path.include?('*') ? Dir[path] : [path]
|
155
126
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
warn("Unprocessable file #{file}: #{e.class}, #{e.message}") if debug?
|
127
|
+
if mode == :only_recognized_file_types || force_exclusion?
|
128
|
+
files.select! { |file| included_file?(file) }
|
129
|
+
end
|
160
130
|
|
161
|
-
|
131
|
+
force_exclusion? ? without_excluded(files) : files
|
162
132
|
end
|
163
133
|
|
164
|
-
def
|
165
|
-
|
134
|
+
def without_excluded(files)
|
135
|
+
files.reject do |file|
|
136
|
+
# When --ignore-parent-exclusion is given, we must look at the configuration associated with
|
137
|
+
# the file, but in the default case when --ignore-parent-exclusion is not given, can safely
|
138
|
+
# look only at the configuration for the current directory, since it's only the Exclude
|
139
|
+
# parameters we're going to check.
|
140
|
+
config = @config_store.for(ignore_parent_exclusion? ? file : '.')
|
141
|
+
config.file_to_exclude?(file)
|
142
|
+
end
|
166
143
|
end
|
167
144
|
|
168
|
-
def
|
169
|
-
|
145
|
+
def included_file?(file)
|
146
|
+
ruby_file?(file) || configured_include?(file)
|
170
147
|
end
|
171
148
|
|
172
149
|
def ruby_file?(file)
|
173
150
|
stdin? || ruby_extension?(file) || ruby_filename?(file) || ruby_executable?(file)
|
174
151
|
end
|
175
152
|
|
176
|
-
def
|
177
|
-
@
|
153
|
+
def stdin?
|
154
|
+
@options.key?(:stdin)
|
178
155
|
end
|
179
156
|
|
180
|
-
def
|
181
|
-
|
157
|
+
def ruby_extension?(file)
|
158
|
+
ruby_extensions.include?(File.extname(file))
|
182
159
|
end
|
183
160
|
|
184
|
-
def
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
files.select! { |file| included_file?(file) }
|
161
|
+
def ruby_extensions
|
162
|
+
@ruby_extensions ||= begin
|
163
|
+
ext_patterns = all_cops_include.select { |pattern| pattern.start_with?('**/*.') }
|
164
|
+
ext_patterns.map { |pattern| pattern.sub('**/*', '') }
|
189
165
|
end
|
166
|
+
end
|
190
167
|
|
191
|
-
|
168
|
+
def ruby_filename?(file)
|
169
|
+
ruby_filenames.include?(File.basename(file))
|
170
|
+
end
|
192
171
|
|
193
|
-
|
194
|
-
|
195
|
-
config.file_to_exclude?(file)
|
196
|
-
end
|
172
|
+
def configured_include?(file)
|
173
|
+
@config_store.for_pwd.file_to_include?(file)
|
197
174
|
end
|
198
175
|
|
199
|
-
|
176
|
+
def ruby_executable?(file)
|
177
|
+
return false unless File.extname(file).empty? && File.exist?(file)
|
178
|
+
|
179
|
+
first_line = File.open(file, &:readline)
|
180
|
+
/#!.*(#{ruby_interpreters(file).join('|')})/.match?(first_line)
|
181
|
+
rescue EOFError, ArgumentError => e
|
182
|
+
warn("Unprocessable file #{file}: #{e.class}, #{e.message}") if debug?
|
183
|
+
|
184
|
+
false
|
185
|
+
end
|
186
|
+
|
187
|
+
def ruby_interpreters(file)
|
188
|
+
@config_store.for(file).for_all_cops['RubyInterpreters']
|
189
|
+
end
|
200
190
|
|
201
191
|
def order
|
202
192
|
if fail_fast?
|
@@ -206,5 +196,21 @@ module RuboCop
|
|
206
196
|
:itself
|
207
197
|
end
|
208
198
|
end
|
199
|
+
|
200
|
+
def force_exclusion?
|
201
|
+
@options[:force_exclusion]
|
202
|
+
end
|
203
|
+
|
204
|
+
def ignore_parent_exclusion?
|
205
|
+
@options[:ignore_parent_exclusion]
|
206
|
+
end
|
207
|
+
|
208
|
+
def debug?
|
209
|
+
@options[:debug]
|
210
|
+
end
|
211
|
+
|
212
|
+
def fail_fast?
|
213
|
+
@options[:fail_fast]
|
214
|
+
end
|
209
215
|
end
|
210
216
|
end
|
data/lib/rubocop/target_ruby.rb
CHANGED
@@ -4,7 +4,7 @@ module RuboCop
|
|
4
4
|
# The kind of Ruby that code inspected by RuboCop is written in.
|
5
5
|
# @api private
|
6
6
|
class TargetRuby
|
7
|
-
KNOWN_RUBIES = [2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3].freeze
|
7
|
+
KNOWN_RUBIES = [2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4].freeze
|
8
8
|
DEFAULT_VERSION = 2.7
|
9
9
|
|
10
10
|
OBSOLETE_RUBIES = {
|
@@ -48,6 +48,86 @@ module RuboCop
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
# The target ruby version may be found in a .gemspec file.
|
52
|
+
# @api private
|
53
|
+
class GemspecFile < Source
|
54
|
+
extend NodePattern::Macros
|
55
|
+
|
56
|
+
GEMSPEC_EXTENSION = '.gemspec'
|
57
|
+
|
58
|
+
# @!method required_ruby_version(node)
|
59
|
+
def_node_search :required_ruby_version, <<~PATTERN
|
60
|
+
(send _ :required_ruby_version= $_)
|
61
|
+
PATTERN
|
62
|
+
|
63
|
+
# @!method gem_requirement_versions(node)
|
64
|
+
def_node_matcher :gem_requirement_versions, <<~PATTERN
|
65
|
+
(send (const(const _ :Gem):Requirement) :new
|
66
|
+
{$str+ | (send $str :freeze)+ | (array $str+) | (array (send $str :freeze)+)}
|
67
|
+
)
|
68
|
+
PATTERN
|
69
|
+
|
70
|
+
def name
|
71
|
+
"`required_ruby_version` parameter (in #{gemspec_filename})"
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def find_version
|
77
|
+
file = gemspec_filepath
|
78
|
+
return unless file && File.file?(file)
|
79
|
+
|
80
|
+
right_hand_side = version_from_gemspec_file(file)
|
81
|
+
return if right_hand_side.nil?
|
82
|
+
|
83
|
+
find_default_minimal_known_ruby(right_hand_side)
|
84
|
+
end
|
85
|
+
|
86
|
+
def gemspec_filename
|
87
|
+
@gemspec_filename ||= begin
|
88
|
+
basename = Pathname.new(@config.base_dir_for_path_parameters).basename.to_s
|
89
|
+
"#{basename}#{GEMSPEC_EXTENSION}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def gemspec_filepath
|
94
|
+
@gemspec_filepath ||=
|
95
|
+
@config.find_file_upwards(gemspec_filename, @config.base_dir_for_path_parameters)
|
96
|
+
end
|
97
|
+
|
98
|
+
def version_from_gemspec_file(file)
|
99
|
+
processed_source = ProcessedSource.from_file(
|
100
|
+
file, DEFAULT_VERSION, parser_engine: @config.parser_engine
|
101
|
+
)
|
102
|
+
required_ruby_version(processed_source.ast).first
|
103
|
+
end
|
104
|
+
|
105
|
+
def version_from_right_hand_side(right_hand_side)
|
106
|
+
gem_requirement_versions = gem_requirement_versions(right_hand_side)
|
107
|
+
|
108
|
+
if right_hand_side.array_type?
|
109
|
+
version_from_array(right_hand_side)
|
110
|
+
elsif gem_requirement_versions
|
111
|
+
gem_requirement_versions.map(&:value)
|
112
|
+
elsif right_hand_side.str_type?
|
113
|
+
right_hand_side.value
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def version_from_array(array)
|
118
|
+
array.children.map(&:value)
|
119
|
+
end
|
120
|
+
|
121
|
+
def find_default_minimal_known_ruby(right_hand_side)
|
122
|
+
version = version_from_right_hand_side(right_hand_side)
|
123
|
+
requirement = Gem::Requirement.new(version)
|
124
|
+
|
125
|
+
KNOWN_RUBIES.detect do |v|
|
126
|
+
v >= DEFAULT_VERSION && requirement.satisfied_by?(Gem::Version.new("#{v}.99"))
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
51
131
|
# The target ruby version may be found in a .ruby-version file.
|
52
132
|
# @api private
|
53
133
|
class RubyVersionFile < Source
|
@@ -143,84 +223,6 @@ module RuboCop
|
|
143
223
|
end
|
144
224
|
end
|
145
225
|
|
146
|
-
# The target ruby version may be found in a .gemspec file.
|
147
|
-
# @api private
|
148
|
-
class GemspecFile < Source
|
149
|
-
extend NodePattern::Macros
|
150
|
-
|
151
|
-
GEMSPEC_EXTENSION = '.gemspec'
|
152
|
-
|
153
|
-
# @!method required_ruby_version(node)
|
154
|
-
def_node_search :required_ruby_version, <<~PATTERN
|
155
|
-
(send _ :required_ruby_version= $_)
|
156
|
-
PATTERN
|
157
|
-
|
158
|
-
# @!method gem_requirement_versions(node)
|
159
|
-
def_node_matcher :gem_requirement_versions, <<~PATTERN
|
160
|
-
(send (const(const _ :Gem):Requirement) :new
|
161
|
-
{$str+ | (send $str :freeze)+ | (array $str+) | (array (send $str :freeze)+)}
|
162
|
-
)
|
163
|
-
PATTERN
|
164
|
-
|
165
|
-
def name
|
166
|
-
"`required_ruby_version` parameter (in #{gemspec_filename})"
|
167
|
-
end
|
168
|
-
|
169
|
-
private
|
170
|
-
|
171
|
-
def find_version
|
172
|
-
file = gemspec_filepath
|
173
|
-
return unless file && File.file?(file)
|
174
|
-
|
175
|
-
right_hand_side = version_from_gemspec_file(file)
|
176
|
-
return if right_hand_side.nil?
|
177
|
-
|
178
|
-
find_default_minimal_known_ruby(right_hand_side)
|
179
|
-
end
|
180
|
-
|
181
|
-
def gemspec_filename
|
182
|
-
@gemspec_filename ||= begin
|
183
|
-
basename = Pathname.new(@config.base_dir_for_path_parameters).basename.to_s
|
184
|
-
"#{basename}#{GEMSPEC_EXTENSION}"
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
def gemspec_filepath
|
189
|
-
@gemspec_filepath ||=
|
190
|
-
@config.find_file_upwards(gemspec_filename, @config.base_dir_for_path_parameters)
|
191
|
-
end
|
192
|
-
|
193
|
-
def version_from_gemspec_file(file)
|
194
|
-
processed_source = ProcessedSource.from_file(file, DEFAULT_VERSION)
|
195
|
-
required_ruby_version(processed_source.ast).first
|
196
|
-
end
|
197
|
-
|
198
|
-
def version_from_right_hand_side(right_hand_side)
|
199
|
-
gem_requirement_versions = gem_requirement_versions(right_hand_side)
|
200
|
-
|
201
|
-
if right_hand_side.array_type?
|
202
|
-
version_from_array(right_hand_side)
|
203
|
-
elsif gem_requirement_versions
|
204
|
-
gem_requirement_versions.map(&:value)
|
205
|
-
else
|
206
|
-
right_hand_side.value
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
def version_from_array(array)
|
211
|
-
array.children.map(&:value)
|
212
|
-
end
|
213
|
-
|
214
|
-
def find_default_minimal_known_ruby(right_hand_side)
|
215
|
-
version = version_from_right_hand_side(right_hand_side)
|
216
|
-
requirement = Gem::Requirement.new(version)
|
217
|
-
|
218
|
-
KNOWN_RUBIES.detect do |v|
|
219
|
-
v >= DEFAULT_VERSION && requirement.satisfied_by?(Gem::Version.new("#{v}.99"))
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
226
|
# If all else fails, a default version will be picked.
|
225
227
|
# @api private
|
226
228
|
class Default < Source
|
@@ -241,10 +243,10 @@ module RuboCop
|
|
241
243
|
|
242
244
|
SOURCES = [
|
243
245
|
RuboCopConfig,
|
246
|
+
GemspecFile,
|
244
247
|
RubyVersionFile,
|
245
248
|
ToolVersionsFile,
|
246
249
|
BundlerLockFile,
|
247
|
-
GemspecFile,
|
248
250
|
Default
|
249
251
|
].freeze
|
250
252
|
|
data/lib/rubocop/version.rb
CHANGED
@@ -3,9 +3,9 @@
|
|
3
3
|
module RuboCop
|
4
4
|
# This module holds the RuboCop version information.
|
5
5
|
module Version
|
6
|
-
STRING = '1.
|
6
|
+
STRING = '1.62.0'
|
7
7
|
|
8
|
-
MSG = '%<version>s (using
|
8
|
+
MSG = '%<version>s (using %<parser_version>s, ' \
|
9
9
|
'rubocop-ast %<rubocop_ast_version>s, ' \
|
10
10
|
'running on %<ruby_engine>s %<ruby_version>s)%<server_mode>s [%<ruby_platform>s]'
|
11
11
|
|
@@ -20,7 +20,7 @@ module RuboCop
|
|
20
20
|
# @api private
|
21
21
|
def self.version(debug: false, env: nil)
|
22
22
|
if debug
|
23
|
-
verbose_version = format(MSG, version: STRING, parser_version:
|
23
|
+
verbose_version = format(MSG, version: STRING, parser_version: parser_version,
|
24
24
|
rubocop_ast_version: RuboCop::AST::Version::STRING,
|
25
25
|
ruby_engine: RUBY_ENGINE, ruby_version: RUBY_VERSION,
|
26
26
|
server_mode: server_mode,
|
@@ -39,6 +39,21 @@ module RuboCop
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
# @api private
|
43
|
+
def self.parser_version
|
44
|
+
config_path = ConfigFinder.find_config_path(Dir.pwd)
|
45
|
+
yaml = YAML.safe_load(
|
46
|
+
File.read(config_path), permitted_classes: [Regexp, Symbol], aliases: true
|
47
|
+
)
|
48
|
+
|
49
|
+
if yaml.dig('AllCops', 'ParserEngine') == 'parser_prism'
|
50
|
+
require 'prism'
|
51
|
+
"Prism #{Prism::VERSION}"
|
52
|
+
else
|
53
|
+
"Parser #{Parser::VERSION}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
42
57
|
# @api private
|
43
58
|
def self.extension_versions(env)
|
44
59
|
features = Util.silence_warnings do
|