rubocop 1.57.2 → 1.62.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +4 -4
  4. data/assets/output.css.erb +159 -0
  5. data/assets/output.html.erb +1 -160
  6. data/config/default.yml +87 -15
  7. data/lib/rubocop/cli/command/auto_generate_config.rb +12 -3
  8. data/lib/rubocop/cli/command/lsp.rb +2 -2
  9. data/lib/rubocop/cli.rb +6 -1
  10. data/lib/rubocop/config.rb +4 -2
  11. data/lib/rubocop/config_finder.rb +12 -2
  12. data/lib/rubocop/config_loader.rb +0 -1
  13. data/lib/rubocop/config_obsoletion.rb +11 -8
  14. data/lib/rubocop/config_validator.rb +14 -7
  15. data/lib/rubocop/cop/autocorrect_logic.rb +6 -1
  16. data/lib/rubocop/cop/base.rb +17 -2
  17. data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
  18. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
  19. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
  20. data/lib/rubocop/cop/exclude_limit.rb +1 -1
  21. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
  22. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +5 -1
  23. data/lib/rubocop/cop/internal_affairs/example_description.rb +4 -4
  24. data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
  25. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
  26. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
  27. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +123 -29
  28. data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
  29. data/lib/rubocop/cop/internal_affairs.rb +2 -0
  30. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  31. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +14 -7
  32. data/lib/rubocop/cop/layout/end_alignment.rb +8 -2
  33. data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
  34. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +22 -7
  35. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  36. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  37. data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
  38. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +1 -1
  39. data/lib/rubocop/cop/layout/redundant_line_break.rb +16 -3
  40. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
  41. data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
  42. data/lib/rubocop/cop/layout/space_around_operators.rb +50 -20
  43. data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
  44. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
  45. data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -4
  46. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
  47. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  48. data/lib/rubocop/cop/lint/debugger.rb +2 -1
  49. data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
  50. data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
  51. data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -3
  52. data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
  53. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
  54. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
  55. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +85 -0
  56. data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
  57. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
  58. data/lib/rubocop/cop/lint/number_conversion.rb +9 -4
  59. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +54 -6
  60. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -2
  61. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  62. data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
  63. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -4
  64. data/lib/rubocop/cop/lint/script_permission.rb +3 -3
  65. data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
  66. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
  67. data/lib/rubocop/cop/lint/symbol_conversion.rb +7 -2
  68. data/lib/rubocop/cop/lint/syntax.rb +6 -3
  69. data/lib/rubocop/cop/lint/to_enum_arguments.rb +7 -2
  70. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
  71. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
  72. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  73. data/lib/rubocop/cop/lint/useless_times.rb +2 -2
  74. data/lib/rubocop/cop/lint/void.rb +20 -2
  75. data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
  76. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  77. data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -0
  78. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  79. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
  80. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  81. data/lib/rubocop/cop/naming/block_forwarding.rb +12 -4
  82. data/lib/rubocop/cop/naming/constant_name.rb +1 -2
  83. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  84. data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
  85. data/lib/rubocop/cop/registry.rb +1 -1
  86. data/lib/rubocop/cop/security/open.rb +2 -2
  87. data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -2
  88. data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
  89. data/lib/rubocop/cop/style/arguments_forwarding.rb +152 -21
  90. data/lib/rubocop/cop/style/array_first_last.rb +64 -0
  91. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
  92. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
  93. data/lib/rubocop/cop/style/case_like_if.rb +5 -5
  94. data/lib/rubocop/cop/style/class_check.rb +1 -0
  95. data/lib/rubocop/cop/style/class_vars.rb +3 -3
  96. data/lib/rubocop/cop/style/collection_compact.rb +18 -8
  97. data/lib/rubocop/cop/style/combinable_loops.rb +13 -7
  98. data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
  99. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -0
  100. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -7
  101. data/lib/rubocop/cop/style/date_time.rb +5 -4
  102. data/lib/rubocop/cop/style/each_for_simple_loop.rb +7 -7
  103. data/lib/rubocop/cop/style/each_with_object.rb +2 -2
  104. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  105. data/lib/rubocop/cop/style/eval_with_location.rb +3 -14
  106. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -1
  107. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
  108. data/lib/rubocop/cop/style/for.rb +2 -0
  109. data/lib/rubocop/cop/style/hash_each_methods.rb +105 -11
  110. data/lib/rubocop/cop/style/hash_except.rb +2 -1
  111. data/lib/rubocop/cop/style/hash_syntax.rb +6 -2
  112. data/lib/rubocop/cop/style/identical_conditional_branches.rb +4 -1
  113. data/lib/rubocop/cop/style/inverse_methods.rb +14 -13
  114. data/lib/rubocop/cop/style/invertible_unless_condition.rb +44 -2
  115. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +8 -10
  116. data/lib/rubocop/cop/style/map_to_hash.rb +17 -7
  117. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +14 -5
  118. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -4
  119. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
  120. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  121. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
  122. data/lib/rubocop/cop/style/multiline_method_signature.rb +10 -1
  123. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +5 -3
  124. data/lib/rubocop/cop/style/next.rb +1 -1
  125. data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
  126. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
  127. data/lib/rubocop/cop/style/object_then.rb +5 -3
  128. data/lib/rubocop/cop/style/operator_method_call.rb +2 -2
  129. data/lib/rubocop/cop/style/parallel_assignment.rb +3 -5
  130. data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -0
  131. data/lib/rubocop/cop/style/raise_args.rb +4 -1
  132. data/lib/rubocop/cop/style/redundant_argument.rb +4 -3
  133. data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
  134. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +4 -3
  135. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +3 -3
  136. data/lib/rubocop/cop/style/redundant_each.rb +7 -4
  137. data/lib/rubocop/cop/style/redundant_fetch_block.rb +3 -3
  138. data/lib/rubocop/cop/style/redundant_line_continuation.rb +27 -7
  139. data/lib/rubocop/cop/style/redundant_parentheses.rb +33 -10
  140. data/lib/rubocop/cop/style/redundant_return.rb +7 -1
  141. data/lib/rubocop/cop/style/redundant_self.rb +17 -2
  142. data/lib/rubocop/cop/style/redundant_sort.rb +9 -8
  143. data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
  144. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -1
  145. data/lib/rubocop/cop/style/sample.rb +3 -4
  146. data/lib/rubocop/cop/style/select_by_regexp.rb +7 -6
  147. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  148. data/lib/rubocop/cop/style/semicolon.rb +8 -0
  149. data/lib/rubocop/cop/style/single_argument_dig.rb +5 -2
  150. data/lib/rubocop/cop/style/slicing_with_range.rb +76 -10
  151. data/lib/rubocop/cop/style/string_chars.rb +1 -0
  152. data/lib/rubocop/cop/style/strip.rb +7 -4
  153. data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
  154. data/lib/rubocop/cop/style/symbol_proc.rb +36 -0
  155. data/lib/rubocop/cop/style/unpack_first.rb +11 -14
  156. data/lib/rubocop/cop/utils/regexp_ranges.rb +1 -1
  157. data/lib/rubocop/cops_documentation_generator.rb +15 -3
  158. data/lib/rubocop/directive_comment.rb +10 -8
  159. data/lib/rubocop/ext/regexp_node.rb +9 -4
  160. data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
  161. data/lib/rubocop/formatter/html_formatter.rb +31 -12
  162. data/lib/rubocop/formatter/json_formatter.rb +0 -1
  163. data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
  164. data/lib/rubocop/formatter.rb +1 -1
  165. data/lib/rubocop/lsp/logger.rb +1 -1
  166. data/lib/rubocop/lsp/routes.rb +2 -2
  167. data/lib/rubocop/lsp/runtime.rb +1 -1
  168. data/lib/rubocop/lsp/server.rb +5 -2
  169. data/lib/rubocop/lsp/severity.rb +1 -1
  170. data/lib/rubocop/lsp.rb +29 -0
  171. data/lib/rubocop/magic_comment.rb +1 -1
  172. data/lib/rubocop/options.rb +11 -8
  173. data/lib/rubocop/path_util.rb +6 -2
  174. data/lib/rubocop/result_cache.rb +0 -1
  175. data/lib/rubocop/rspec/cop_helper.rb +8 -2
  176. data/lib/rubocop/rspec/expect_offense.rb +8 -8
  177. data/lib/rubocop/rspec/shared_contexts.rb +40 -15
  178. data/lib/rubocop/rspec/support.rb +2 -0
  179. data/lib/rubocop/runner.rb +10 -3
  180. data/lib/rubocop/server/cache.rb +1 -2
  181. data/lib/rubocop/server/client_command/exec.rb +0 -1
  182. data/lib/rubocop/server/server_command/exec.rb +0 -1
  183. data/lib/rubocop/target_finder.rb +84 -78
  184. data/lib/rubocop/target_ruby.rb +82 -80
  185. data/lib/rubocop/version.rb +18 -3
  186. data/lib/rubocop.rb +4 -0
  187. metadata +18 -10
  188. /data/lib/rubocop/formatter/{git_hub_actions_formatter.rb → github_actions_formatter.rb} +0 -0
@@ -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
- 'Enabled' => true, # in case it is 'pending'
105
- 'AutoCorrect' => true # in case defaults set it to false
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,50 +128,75 @@ RSpec.shared_context 'mock console output' do
128
128
  end
129
129
  end
130
130
 
131
+ RSpec.shared_context 'lsp' do
132
+ before do
133
+ RuboCop::LSP.enable
134
+ end
135
+
136
+ after do
137
+ RuboCop::LSP.disable
138
+ end
139
+ end
140
+
131
141
  RSpec.shared_context 'ruby 2.0' do
132
- let(:ruby_version) { 2.0 }
142
+ # Prism supports parsing Ruby 3.3+.
143
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.0 }
133
144
  end
134
145
 
135
146
  RSpec.shared_context 'ruby 2.1' do
136
- let(:ruby_version) { 2.1 }
147
+ # Prism supports parsing Ruby 3.3+.
148
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.1 }
137
149
  end
138
150
 
139
151
  RSpec.shared_context 'ruby 2.2' do
140
- let(:ruby_version) { 2.2 }
152
+ # Prism supports parsing Ruby 3.3+.
153
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.2 }
141
154
  end
142
155
 
143
156
  RSpec.shared_context 'ruby 2.3' do
144
- let(:ruby_version) { 2.3 }
157
+ # Prism supports parsing Ruby 3.3+.
158
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.3 }
145
159
  end
146
160
 
147
161
  RSpec.shared_context 'ruby 2.4' do
148
- let(:ruby_version) { 2.4 }
162
+ # Prism supports parsing Ruby 3.3+.
163
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.4 }
149
164
  end
150
165
 
151
166
  RSpec.shared_context 'ruby 2.5' do
152
- let(:ruby_version) { 2.5 }
167
+ # Prism supports parsing Ruby 3.3+.
168
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.5 }
153
169
  end
154
170
 
155
171
  RSpec.shared_context 'ruby 2.6' do
156
- let(:ruby_version) { 2.6 }
172
+ # Prism supports parsing Ruby 3.3+.
173
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.6 }
157
174
  end
158
175
 
159
176
  RSpec.shared_context 'ruby 2.7' do
160
- let(:ruby_version) { 2.7 }
177
+ # Prism supports parsing Ruby 3.3+.
178
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.7 }
161
179
  end
162
180
 
163
181
  RSpec.shared_context 'ruby 3.0' do
164
- let(:ruby_version) { 3.0 }
182
+ # Prism supports parsing Ruby 3.3+.
183
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 3.0 }
165
184
  end
166
185
 
167
186
  RSpec.shared_context 'ruby 3.1' do
168
- let(:ruby_version) { 3.1 }
187
+ # Prism supports parsing Ruby 3.3+.
188
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 3.1 }
169
189
  end
170
190
 
171
191
  RSpec.shared_context 'ruby 3.2' do
172
- let(:ruby_version) { 3.2 }
192
+ # Prism supports parsing Ruby 3.3+.
193
+ let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 3.2 }
173
194
  end
174
195
 
175
196
  RSpec.shared_context 'ruby 3.3' do
176
197
  let(:ruby_version) { 3.3 }
177
198
  end
199
+
200
+ RSpec.shared_context 'ruby 3.4' do
201
+ let(:ruby_version) { 3.4 }
202
+ end
@@ -13,6 +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', :lsp
16
17
  config.include_context 'maintain registry', :restore_registry
17
18
  config.include_context 'ruby 2.0', :ruby20
18
19
  config.include_context 'ruby 2.1', :ruby21
@@ -26,4 +27,5 @@ RSpec.configure do |config|
26
27
  config.include_context 'ruby 3.1', :ruby31
27
28
  config.include_context 'ruby 3.2', :ruby32
28
29
  config.include_context 'ruby 3.3', :ruby33
30
+ config.include_context 'ruby 3.4', :ruby34
29
31
  end
@@ -20,7 +20,7 @@ module RuboCop
20
20
  message = 'Infinite loop detected'
21
21
  message += " in #{path}" if path
22
22
  message += " and caused by #{root_cause}" if root_cause
23
- super message
23
+ super(message)
24
24
  end
25
25
  end
26
26
 
@@ -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(@options[:stdin], ruby_version, file)
477
+ ProcessedSource.new(
478
+ @options[:stdin], ruby_version, file, parser_engine: parser_engine
479
+ )
476
480
  else
477
481
  begin
478
- ProcessedSource.from_file(file, ruby_version)
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,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'fileutils'
4
3
  require 'pathname'
5
4
  require_relative '../cache_config'
6
5
  require_relative '../config_finder'
@@ -117,7 +116,7 @@ module RuboCop
117
116
 
118
117
  def pid_running?
119
118
  Process.kill(0, pid_path.read.to_i) == 1
120
- rescue Errno::ESRCH, Errno::ENOENT, Errno::EACCES
119
+ rescue Errno::ESRCH, Errno::ENOENT, Errno::EACCES, Errno::EROFS
121
120
  false
122
121
  end
123
122
 
@@ -17,7 +17,6 @@ module RuboCop
17
17
  class Exec < Base
18
18
  def run
19
19
  ensure_server!
20
- Cache.status_path.delete if Cache.status_path.file?
21
20
  read_stdin = ARGV.include?('-s') || ARGV.include?('--stdin')
22
21
  send_request(
23
22
  command: 'exec',
@@ -16,7 +16,6 @@ module RuboCop
16
16
  # @api private
17
17
  class Exec < Base
18
18
  def run
19
- Cache.status_path.delete if Cache.status_path.file?
20
19
  # RuboCop output is colorized by default where there is a TTY.
21
20
  # We must pass the --color option to preserve this behavior.
22
21
  @args.unshift('--color') unless %w[--color --no-color].any? { |f| @args.include?(f) }
@@ -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
- def force_exclusion?
16
- @options[:force_exclusion]
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
- # directory. A Ruby source file is defined as a file with the `.rb`
49
- # extension or a file with no extension that has a ruby shebang line
50
- # as its first line.
51
- # It is possible to specify includes and excludes using the config file,
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
- def to_inspect?(file, hidden_files, base_dir_config)
70
- return false if base_dir_config.file_to_exclude?(file)
71
- return true if !hidden_files.bsearch do |hidden_file|
72
- file <=> hidden_file
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 ruby_executable?(file)
154
- return false unless File.extname(file).empty? && File.exist?(file)
124
+ def process_explicit_path(path, mode)
125
+ files = path.include?('*') ? Dir[path] : [path]
155
126
 
156
- first_line = File.open(file, &:readline)
157
- /#!.*(#{ruby_interpreters(file).join('|')})/.match?(first_line)
158
- rescue EOFError, ArgumentError => e
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
- false
131
+ force_exclusion? ? without_excluded(files) : files
162
132
  end
163
133
 
164
- def ruby_interpreters(file)
165
- @config_store.for(file).for_all_cops['RubyInterpreters']
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 stdin?
169
- @options.key?(:stdin)
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 configured_include?(file)
177
- @config_store.for_pwd.file_to_include?(file)
153
+ def stdin?
154
+ @options.key?(:stdin)
178
155
  end
179
156
 
180
- def included_file?(file)
181
- ruby_file?(file) || configured_include?(file)
157
+ def ruby_extension?(file)
158
+ ruby_extensions.include?(File.extname(file))
182
159
  end
183
160
 
184
- def process_explicit_path(path, mode)
185
- files = path.include?('*') ? Dir[path] : [path]
186
-
187
- if mode == :only_recognized_file_types || force_exclusion?
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
- return files unless force_exclusion?
168
+ def ruby_filename?(file)
169
+ ruby_filenames.include?(File.basename(file))
170
+ end
192
171
 
193
- files.reject do |file|
194
- config = @config_store.for(file)
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
- private
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
@@ -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? && right_hand_side.children.all?(&:str_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
 
@@ -3,9 +3,9 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.57.2'
6
+ STRING = '1.62.1'
7
7
 
8
- MSG = '%<version>s (using Parser %<parser_version>s, ' \
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: 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