rubocop 1.79.2 → 1.82.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 (142) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +35 -7
  4. data/config/obsoletion.yml +4 -0
  5. data/exe/rubocop +1 -8
  6. data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
  7. data/lib/rubocop/cli.rb +8 -3
  8. data/lib/rubocop/comment_config.rb +62 -17
  9. data/lib/rubocop/config_loader.rb +5 -2
  10. data/lib/rubocop/config_loader_resolver.rb +7 -6
  11. data/lib/rubocop/config_store.rb +5 -0
  12. data/lib/rubocop/cop/autocorrect_logic.rb +6 -4
  13. data/lib/rubocop/cop/correctors/alignment_corrector.rb +8 -7
  14. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
  15. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +10 -5
  16. data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
  17. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  18. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
  19. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  20. data/lib/rubocop/cop/layout/class_structure.rb +1 -1
  21. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  22. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -0
  23. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +30 -12
  24. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
  25. data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
  26. data/lib/rubocop/cop/layout/hash_alignment.rb +2 -5
  27. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  28. data/lib/rubocop/cop/layout/heredoc_indentation.rb +0 -4
  29. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  30. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  31. data/lib/rubocop/cop/layout/line_length.rb +16 -5
  32. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +8 -4
  33. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
  34. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  35. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  36. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
  37. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
  38. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
  39. data/lib/rubocop/cop/lint/debugger.rb +0 -2
  40. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
  41. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
  42. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  43. data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
  44. data/lib/rubocop/cop/lint/literal_as_condition.rb +4 -0
  45. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  46. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +17 -8
  47. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
  48. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
  49. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
  50. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -1
  51. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  52. data/lib/rubocop/cop/lint/self_assignment.rb +15 -6
  53. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  54. data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
  55. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
  56. data/lib/rubocop/cop/lint/useless_or.rb +15 -2
  57. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +1 -1
  58. data/lib/rubocop/cop/lint/void.rb +7 -0
  59. data/lib/rubocop/cop/message_annotator.rb +1 -1
  60. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  61. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  62. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +0 -4
  63. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  64. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
  65. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +1 -1
  66. data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
  67. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  68. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  69. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  70. data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
  71. data/lib/rubocop/cop/mixin/trailing_comma.rb +5 -6
  72. data/lib/rubocop/cop/naming/method_name.rb +5 -3
  73. data/lib/rubocop/cop/naming/predicate_method.rb +19 -6
  74. data/lib/rubocop/cop/security/json_load.rb +33 -11
  75. data/lib/rubocop/cop/style/array_intersect.rb +46 -12
  76. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
  77. data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -2
  78. data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
  79. data/lib/rubocop/cop/style/case_equality.rb +11 -13
  80. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -0
  81. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -14
  82. data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
  83. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  84. data/lib/rubocop/cop/style/empty_method.rb +0 -6
  85. data/lib/rubocop/cop/style/endless_method.rb +15 -2
  86. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  87. data/lib/rubocop/cop/style/float_division.rb +15 -1
  88. data/lib/rubocop/cop/style/guard_clause.rb +0 -11
  89. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  90. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  91. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  92. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +12 -1
  93. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
  94. data/lib/rubocop/cop/style/module_member_existence_check.rb +74 -0
  95. data/lib/rubocop/cop/style/multiline_method_signature.rb +0 -4
  96. data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
  97. data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
  98. data/lib/rubocop/cop/style/parallel_assignment.rb +2 -2
  99. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  100. data/lib/rubocop/cop/style/redundant_begin.rb +34 -0
  101. data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
  102. data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
  103. data/lib/rubocop/cop/style/redundant_format.rb +26 -5
  104. data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
  105. data/lib/rubocop/cop/style/redundant_parentheses.rb +14 -11
  106. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -2
  107. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
  108. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
  109. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  110. data/lib/rubocop/cop/style/safe_navigation.rb +18 -1
  111. data/lib/rubocop/cop/style/semicolon.rb +23 -7
  112. data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -1
  113. data/lib/rubocop/cop/style/string_concatenation.rb +17 -13
  114. data/lib/rubocop/cop/style/super_arguments.rb +2 -2
  115. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  116. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
  117. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
  118. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  119. data/lib/rubocop/cop/util.rb +2 -3
  120. data/lib/rubocop/cop/utils/format_string.rb +10 -0
  121. data/lib/rubocop/cop/variable_force/variable.rb +1 -1
  122. data/lib/rubocop/cop/variable_force.rb +9 -7
  123. data/lib/rubocop/cops_documentation_generator.rb +4 -4
  124. data/lib/rubocop/directive_comment.rb +46 -3
  125. data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -5
  126. data/lib/rubocop/lsp/diagnostic.rb +10 -14
  127. data/lib/rubocop/lsp/routes.rb +31 -2
  128. data/lib/rubocop/lsp/stdin_runner.rb +0 -16
  129. data/lib/rubocop/magic_comment.rb +20 -0
  130. data/lib/rubocop/rake_task.rb +1 -1
  131. data/lib/rubocop/remote_config.rb +7 -8
  132. data/lib/rubocop/result_cache.rb +1 -1
  133. data/lib/rubocop/rspec/shared_contexts.rb +2 -2
  134. data/lib/rubocop/rspec/support.rb +1 -1
  135. data/lib/rubocop/runner.rb +6 -4
  136. data/lib/rubocop/target_finder.rb +9 -9
  137. data/lib/rubocop/target_ruby.rb +11 -2
  138. data/lib/rubocop/version.rb +1 -1
  139. data/lib/rubocop.rb +2 -0
  140. data/lib/ruby_lsp/rubocop/addon.rb +23 -8
  141. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
  142. metadata +8 -6
@@ -51,7 +51,7 @@ module RuboCop
51
51
  capabilities: LanguageServer::Protocol::Interface::ServerCapabilities.new(
52
52
  document_formatting_provider: true,
53
53
  text_document_sync: LanguageServer::Protocol::Interface::TextDocumentSyncOptions.new(
54
- change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::FULL,
54
+ change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::INCREMENTAL,
55
55
  open_close: true
56
56
  )
57
57
  )
@@ -76,7 +76,12 @@ module RuboCop
76
76
 
77
77
  handle 'textDocument/didChange' do |request|
78
78
  params = request[:params]
79
- result = diagnostic(params[:textDocument][:uri], params[:contentChanges][0][:text])
79
+ file_uri = params[:textDocument][:uri]
80
+ text = @text_cache[file_uri]
81
+ params[:contentChanges].each do |content|
82
+ text = change_text(text, content[:text], content[:range])
83
+ end
84
+ result = diagnostic(file_uri, text)
80
85
  @server.write(result)
81
86
  end
82
87
 
@@ -219,6 +224,30 @@ module RuboCop
219
224
  }
220
225
  end
221
226
 
227
+ def change_text(orig_text, text, range)
228
+ return text unless range
229
+
230
+ start_pos = text_pos(orig_text, range[:start])
231
+ end_pos = text_pos(orig_text, range[:end])
232
+ text_bin = orig_text.b
233
+ text_bin[start_pos...end_pos] = text.b
234
+ text_bin.force_encoding(orig_text.encoding)
235
+ end
236
+
237
+ def text_pos(text, range)
238
+ line = range[:line]
239
+ char = range[:character]
240
+ pos = 0
241
+ text.each_line.with_index do |l, i|
242
+ if i == line
243
+ pos += l.encode('utf-16be').b[0, char * 2].encode('utf-8', 'utf-16be').bytesize
244
+ return pos
245
+ end
246
+ pos += l.bytesize
247
+ end
248
+ pos
249
+ end
250
+
222
251
  def convert_file_uri_to_path(uri)
223
252
  URI.decode_www_form_component(uri.delete_prefix('file://'))
224
253
  end
@@ -40,7 +40,6 @@ module RuboCop
40
40
  super(@options, config_store)
41
41
  end
42
42
 
43
- # rubocop:disable Metrics/MethodLength
44
43
  def run(path, contents, options, prism_result: nil)
45
44
  @options = options.merge(DEFAULT_RUBOCOP_OPTIONS)
46
45
  @options[:stdin] = contents
@@ -54,22 +53,7 @@ module RuboCop
54
53
  super([path])
55
54
 
56
55
  raise Interrupt if aborting?
57
- rescue RuboCop::Runner::InfiniteCorrectionLoop => e
58
- if defined?(::RubyLsp::Requests::Formatting::Error)
59
- raise ::RubyLsp::Requests::Formatting::Error, e.message
60
- end
61
-
62
- raise e
63
- rescue RuboCop::ValidationError => e
64
- raise ConfigurationError, e.message
65
- rescue StandardError => e
66
- if defined?(::RubyLsp::Requests::Formatting::Error)
67
- raise ::RubyLsp::Requests::Support::InternalRuboCopError, e
68
- end
69
-
70
- raise e
71
56
  end
72
- # rubocop:enable Metrics/MethodLength
73
57
 
74
58
  def formatted_source
75
59
  @options[:stdin]
@@ -11,6 +11,7 @@ module RuboCop
11
11
  KEYWORDS = {
12
12
  encoding: '(?:en)?coding',
13
13
  frozen_string_literal: 'frozen[_-]string[_-]literal',
14
+ rbs_inline: 'rbs_inline',
14
15
  shareable_constant_value: 'shareable[_-]constant[_-]value',
15
16
  typed: 'typed'
16
17
  }.freeze
@@ -36,6 +37,7 @@ module RuboCop
36
37
  def any?
37
38
  frozen_string_literal_specified? ||
38
39
  encoding_specified? ||
40
+ rbs_inline_specified? ||
39
41
  shareable_constant_value_specified? ||
40
42
  typed_specified?
41
43
  end
@@ -60,6 +62,10 @@ module RuboCop
60
62
  [true, false].include?(frozen_string_literal)
61
63
  end
62
64
 
65
+ def valid_rbs_inline_value?
66
+ %w[enabled disabled].include?(extract_rbs_inline_value)
67
+ end
68
+
63
69
  def valid_shareable_constant_value?
64
70
  %w[none literal experimental_everything experimental_copy].include?(shareable_constant_value)
65
71
  end
@@ -105,6 +111,10 @@ module RuboCop
105
111
  specified?(encoding)
106
112
  end
107
113
 
114
+ def rbs_inline_specified?
115
+ valid_rbs_inline_value?
116
+ end
117
+
108
118
  # Was the Sorbet `typed` sigil specified?
109
119
  #
110
120
  # @return [Boolean]
@@ -203,6 +213,9 @@ module RuboCop
203
213
  match(KEYWORDS[:frozen_string_literal])
204
214
  end
205
215
 
216
+ # Emacs comments cannot specify RBS::inline behavior.
217
+ def extract_rbs_inline_value; end
218
+
206
219
  def extract_shareable_constant_value
207
220
  match(KEYWORDS[:shareable_constant_value])
208
221
  end
@@ -242,6 +255,9 @@ module RuboCop
242
255
  # Vim comments cannot specify frozen string literal behavior.
243
256
  def frozen_string_literal; end
244
257
 
258
+ # Vim comments cannot specify RBS::inline behavior.
259
+ def extract_rbs_inline_value; end
260
+
245
261
  # Vim comments cannot specify shareable constant values behavior.
246
262
  def shareable_constant_value; end
247
263
 
@@ -296,6 +312,10 @@ module RuboCop
296
312
  extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s*#{TOKEN}\s*\z/io)
297
313
  end
298
314
 
315
+ def extract_rbs_inline_value
316
+ extract(/\A\s*#\s*#{KEYWORDS[:rbs_inline]}:\s*#{TOKEN}\s*\z/io)
317
+ end
318
+
299
319
  def extract_shareable_constant_value
300
320
  extract(/\A\s*#\s*#{KEYWORDS[:shareable_constant_value]}:\s*#{TOKEN}\s*\z/io)
301
321
  end
@@ -75,7 +75,7 @@ module RuboCop
75
75
  def setup_subtasks(name, *args, &task_block) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
76
76
  namespace(name) do
77
77
  # rubocop:todo Naming/InclusiveLanguage
78
- task(:auto_correct, *args) do
78
+ task(:auto_correct, *args) do |_, task_args|
79
79
  require 'rainbow'
80
80
  warn Rainbow(
81
81
  'rubocop:auto_correct task is deprecated; ' \
@@ -11,13 +11,13 @@ module RuboCop
11
11
 
12
12
  CACHE_LIFETIME = 24 * 60 * 60
13
13
 
14
- def initialize(url, base_dir)
14
+ def initialize(url, cache_root)
15
15
  begin
16
16
  @uri = URI.parse(url)
17
17
  rescue URI::InvalidURIError
18
18
  raise ConfigNotFoundError, "Failed to resolve configuration: '#{url}' is not a valid URI"
19
19
  end
20
- @base_dir = base_dir
20
+ @cache_root = cache_root
21
21
  end
22
22
 
23
23
  def file
@@ -27,16 +27,17 @@ module RuboCop
27
27
  next if response.is_a?(Net::HTTPNotModified)
28
28
  next if response.is_a?(SocketError)
29
29
 
30
+ FileUtils.mkdir_p(File.dirname(cache_path))
30
31
  File.write(cache_path, response.body)
31
32
  end
32
33
 
33
34
  cache_path
34
35
  end
35
36
 
36
- def inherit_from_remote(file, path)
37
+ def inherit_from_remote(file)
37
38
  new_uri = @uri.dup
38
39
  new_uri.path.gsub!(%r{/[^/]*$}, "/#{file.delete_prefix('./')}")
39
- RemoteConfig.new(new_uri.to_s, File.dirname(path))
40
+ RemoteConfig.new(new_uri.to_s, @cache_root)
40
41
  end
41
42
 
42
43
  private
@@ -80,7 +81,7 @@ module RuboCop
80
81
  end
81
82
 
82
83
  def cache_path
83
- File.expand_path(".rubocop-#{cache_name_from_uri}", @base_dir)
84
+ @cache_path ||= File.expand_path(".rubocop-remote-#{cache_name_from_uri}", @cache_root)
84
85
  end
85
86
 
86
87
  def cache_path_exists?
@@ -97,9 +98,7 @@ module RuboCop
97
98
  end
98
99
 
99
100
  def cache_name_from_uri
100
- uri = cloned_url
101
- uri.query = nil
102
- uri.to_s.gsub!(/[^0-9A-Za-z]/, '-')
101
+ "#{Digest::MD5.hexdigest(@uri.to_s)}.yml"
103
102
  end
104
103
 
105
104
  def cloned_url
@@ -9,7 +9,7 @@ module RuboCop
9
9
  # Provides functionality for caching RuboCop runs.
10
10
  # @api private
11
11
  class ResultCache
12
- NON_CHANGING = %i[color format formatters out debug fail_level
12
+ NON_CHANGING = %i[color format formatters out debug display_time fail_level
13
13
  fix_layout autocorrect safe_autocorrect autocorrect_all
14
14
  cache fail_fast stdin parallel].freeze
15
15
 
@@ -266,6 +266,6 @@ RSpec.shared_context 'ruby 3.4' do
266
266
  let(:ruby_version) { 3.4 }
267
267
  end
268
268
 
269
- RSpec.shared_context 'ruby 3.5' do
270
- let(:ruby_version) { 3.5 }
269
+ RSpec.shared_context 'ruby 4.0' do
270
+ let(:ruby_version) { 4.0 }
271
271
  end
@@ -30,5 +30,5 @@ RSpec.configure do |config|
30
30
  config.include_context 'ruby 3.2', :ruby32
31
31
  config.include_context 'ruby 3.3', :ruby33
32
32
  config.include_context 'ruby 3.4', :ruby34
33
- config.include_context 'ruby 3.5', :ruby35
33
+ config.include_context 'ruby 4.0', :ruby40
34
34
  end
@@ -273,7 +273,8 @@ module RuboCop
273
273
  end
274
274
 
275
275
  def do_inspection_loop(file)
276
- processed_source = get_processed_source(file)
276
+ # We can reuse the prism result since the source did not change yet.
277
+ processed_source = get_processed_source(file, @prism_result)
277
278
  # This variable is 2d array used to track corrected offenses after each
278
279
  # inspection iteration. This is used to output meaningful infinite loop
279
280
  # error message.
@@ -295,7 +296,8 @@ module RuboCop
295
296
  # loop if we find any.
296
297
  break unless updated_source_file
297
298
 
298
- processed_source = get_processed_source(file)
299
+ # Autocorrect has happened, don't use the prism result since it is stale.
300
+ processed_source = get_processed_source(file, nil)
299
301
  end
300
302
 
301
303
  # Return summary of corrected offenses after all iterations
@@ -482,7 +484,7 @@ module RuboCop
482
484
  end
483
485
 
484
486
  # rubocop:disable Metrics/MethodLength
485
- def get_processed_source(file)
487
+ def get_processed_source(file, prism_result)
486
488
  config = @config_store.for_file(file)
487
489
  ruby_version = config.target_ruby_version
488
490
  parser_engine = config.parser_engine
@@ -493,7 +495,7 @@ module RuboCop
493
495
  ruby_version,
494
496
  file,
495
497
  parser_engine: parser_engine,
496
- prism_result: @prism_result
498
+ prism_result: prism_result
497
499
  )
498
500
  else
499
501
  begin
@@ -42,14 +42,12 @@ module RuboCop
42
42
  # Support Windows: Backslashes from command-line -> forward slashes
43
43
  base_dir = base_dir.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
44
44
  all_files = find_files(base_dir, File::FNM_DOTMATCH)
45
- # use file.include? for performance optimization
46
- hidden_files = all_files.select { |file| file.include?(HIDDEN_PATH_SUBSTRING) }.sort
47
45
  base_dir_config = @config_store.for(base_dir)
48
46
 
49
- target_files = if base_dir.include?(HIDDEN_PATH_SUBSTRING)
47
+ target_files = if hidden_path?(base_dir)
50
48
  all_files.select { |file| ruby_file?(file) }
51
49
  else
52
- all_files.select { |file| to_inspect?(file, hidden_files, base_dir_config) }
50
+ all_files.select { |file| to_inspect?(file, base_dir_config) }
53
51
  end
54
52
 
55
53
  target_files.sort_by!(&order)
@@ -74,18 +72,20 @@ module RuboCop
74
72
 
75
73
  private
76
74
 
77
- def to_inspect?(file, hidden_files, base_dir_config)
75
+ def to_inspect?(file, base_dir_config)
78
76
  return false if base_dir_config.file_to_exclude?(file)
79
- return true if !hidden_files.bsearch do |hidden_file|
80
- file <=> hidden_file
81
- end && ruby_file?(file)
77
+ return true if !hidden_path?(file) && ruby_file?(file)
82
78
 
83
79
  base_dir_config.file_to_include?(file)
84
80
  end
85
81
 
82
+ def hidden_path?(path)
83
+ path.include?(HIDDEN_PATH_SUBSTRING)
84
+ end
85
+
86
86
  def wanted_dir_patterns(base_dir, exclude_pattern, flags)
87
87
  # Escape glob characters in base_dir to avoid unwanted behavior.
88
- base_dir = base_dir.gsub(/[\\\{\}\[\]\*\?]/) do |reserved_glob_character|
88
+ base_dir = base_dir.gsub(/[\\{}\[\]*?]/) do |reserved_glob_character|
89
89
  "\\#{reserved_glob_character}"
90
90
  end
91
91
 
@@ -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, 3.4, 3.5].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, 4.0].freeze
8
8
  DEFAULT_VERSION = 2.7
9
9
 
10
10
  OBSOLETE_RUBIES = {
@@ -110,8 +110,17 @@ module RuboCop
110
110
  end
111
111
 
112
112
  def version_from_gemspec_file(file)
113
+ # When using parser_prism, we need to use a Ruby version that Prism supports (3.3+)
114
+ # for parsing the gemspec file. This doesn't affect the detected Ruby version,
115
+ # it's just for the parsing step.
116
+ ruby_version_for_parsing = if @config.parser_engine == :parser_prism
117
+ 3.3
118
+ else
119
+ DEFAULT_VERSION
120
+ end
121
+
113
122
  processed_source = ProcessedSource.from_file(
114
- file, DEFAULT_VERSION, parser_engine: @config.parser_engine
123
+ file, ruby_version_for_parsing, parser_engine: @config.parser_engine
115
124
  )
116
125
  return unless processed_source.valid_syntax?
117
126
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.79.2'
6
+ STRING = '1.82.0'
7
7
 
8
8
  MSG = '%<version>s (using %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
data/lib/rubocop.rb CHANGED
@@ -489,6 +489,7 @@ require_relative 'rubocop/cop/style/arguments_forwarding'
489
489
  require_relative 'rubocop/cop/style/array_coercion'
490
490
  require_relative 'rubocop/cop/style/array_first_last'
491
491
  require_relative 'rubocop/cop/style/array_intersect'
492
+ require_relative 'rubocop/cop/style/array_intersect_with_single_element'
492
493
  require_relative 'rubocop/cop/style/array_join'
493
494
  require_relative 'rubocop/cop/style/ascii_comments'
494
495
  require_relative 'rubocop/cop/style/attr'
@@ -607,6 +608,7 @@ require_relative 'rubocop/cop/style/map_to_set'
607
608
  require_relative 'rubocop/cop/style/method_call_without_args_parentheses'
608
609
  require_relative 'rubocop/cop/style/method_call_with_args_parentheses'
609
610
  require_relative 'rubocop/cop/style/min_max_comparison'
611
+ require_relative 'rubocop/cop/style/module_member_existence_check'
610
612
  require_relative 'rubocop/cop/style/multiline_in_pattern_then'
611
613
  require_relative 'rubocop/cop/style/numbered_parameters'
612
614
  require_relative 'rubocop/cop/style/open_struct_use'
@@ -8,7 +8,10 @@ module RubyLsp
8
8
  module RuboCop
9
9
  # A Ruby LSP add-on for RuboCop.
10
10
  class Addon < RubyLsp::Addon
11
- def initializer
11
+ RESTART_WATCHERS = %w[.rubocop.yml .rubocop_todo.yml .rubocop].freeze
12
+
13
+ def initialize
14
+ super
12
15
  @runtime_adapter = nil
13
16
  end
14
17
 
@@ -16,12 +19,16 @@ module RubyLsp
16
19
  'RuboCop'
17
20
  end
18
21
 
22
+ def version
23
+ ::RuboCop::Version::STRING
24
+ end
25
+
19
26
  def activate(global_state, message_queue)
20
27
  ::RuboCop::LSP::Logger.log(
21
28
  "Activating RuboCop LSP addon #{::RuboCop::Version::STRING}.", prefix: '[RuboCop]'
22
29
  )
23
30
 
24
- @runtime_adapter = RuntimeAdapter.new
31
+ @runtime_adapter = RuntimeAdapter.new(message_queue)
25
32
  global_state.register_formatter('rubocop', @runtime_adapter)
26
33
  register_additional_file_watchers(global_state, message_queue)
27
34
 
@@ -49,7 +56,7 @@ module RubyLsp
49
56
  register_options: Interface::DidChangeWatchedFilesRegistrationOptions.new(
50
57
  watchers: [
51
58
  Interface::FileSystemWatcher.new(
52
- glob_pattern: '**/.rubocop{,_todo}.yml',
59
+ glob_pattern: "**/{#{RESTART_WATCHERS.join(',')}}",
53
60
  kind: Constant::WatchKind::CREATE | Constant::WatchKind::CHANGE | Constant::WatchKind::DELETE
54
61
  )
55
62
  ]
@@ -62,13 +69,21 @@ module RubyLsp
62
69
  # rubocop:enable Metrics/MethodLength
63
70
 
64
71
  def workspace_did_change_watched_files(changes)
65
- return unless changes.any? { |change| change[:uri].end_with?('.rubocop.yml') }
72
+ if (changed_config_file = changed_config_file(changes))
73
+ @runtime_adapter.reload_config
74
+
75
+ ::RuboCop::LSP::Logger.log(<<~MESSAGE, prefix: '[RuboCop]')
76
+ Re-initialized RuboCop LSP addon #{::RuboCop::Version::STRING} due to #{changed_config_file} change.
77
+ MESSAGE
78
+ end
79
+ end
66
80
 
67
- @runtime_adapter = RuntimeAdapter.new
81
+ private
68
82
 
69
- ::RuboCop::LSP::Logger.log(<<~MESSAGE, prefix: '[RuboCop]')
70
- Re-initialized RuboCop LSP addon #{::RuboCop::Version::STRING} due to .rubocop.yml file change.
71
- MESSAGE
83
+ def changed_config_file(changes)
84
+ RESTART_WATCHERS.find do |file_name|
85
+ changes.any? { |change| change[:uri].end_with?(file_name) }
86
+ end
72
87
  end
73
88
  end
74
89
  end
@@ -7,30 +7,45 @@ module RubyLsp
7
7
  # Provides an adapter to bridge RuboCop's built-in LSP runtime with Ruby LSP's add-on.
8
8
  # @api private
9
9
  class RuntimeAdapter
10
- include RubyLsp::Requests::Support::Formatter
10
+ def initialize(message_queue)
11
+ @message_queue = message_queue
12
+ reload_config
13
+ end
11
14
 
12
- def initialize
13
- config_store = ::RuboCop::ConfigStore.new
15
+ def reload_config
16
+ @runtime = nil
17
+ options, _paths = ::RuboCop::Options.new.parse([])
14
18
 
19
+ config_store = ::RuboCop::ConfigStore.new
20
+ config_store.apply_options!(options)
15
21
  @runtime = ::RuboCop::LSP::Runtime.new(config_store)
22
+ rescue ::RuboCop::Error => e
23
+ @message_queue << Notification.window_show_message(
24
+ "RuboCop configuration error: #{e.message}. Formatting will not be available.",
25
+ type: Constant::MessageType::ERROR
26
+ )
16
27
  end
17
28
 
18
29
  def run_diagnostic(uri, document)
19
- @runtime.offenses(
20
- uri_to_path(uri),
21
- document.source,
22
- document.encoding,
23
- prism_result: prism_result(document)
24
- )
30
+ with_error_handling do
31
+ @runtime.offenses(
32
+ uri_to_path(uri),
33
+ document.source,
34
+ document.encoding,
35
+ prism_result: prism_result(document)
36
+ )
37
+ end
25
38
  end
26
39
 
27
40
  def run_formatting(uri, document)
28
- @runtime.format(
29
- uri_to_path(uri),
30
- document.source,
31
- command: 'rubocop.formatAutocorrects',
32
- prism_result: prism_result(document)
33
- )
41
+ with_error_handling do
42
+ @runtime.format(
43
+ uri_to_path(uri),
44
+ document.source,
45
+ command: 'rubocop.formatAutocorrects',
46
+ prism_result: prism_result(document)
47
+ )
48
+ end
34
49
  end
35
50
 
36
51
  def run_range_formatting(_uri, _partial_source, _base_indentation)
@@ -43,6 +58,25 @@ module RubyLsp
43
58
 
44
59
  private
45
60
 
61
+ def with_error_handling
62
+ return unless @runtime
63
+
64
+ yield
65
+ rescue StandardError => e
66
+ ::RuboCop::LSP::Logger.log(e.full_message, prefix: '[RuboCop]')
67
+
68
+ message = if e.is_a?(::RuboCop::ErrorWithAnalyzedFileLocation)
69
+ "for the #{e.cop.name} cop"
70
+ else
71
+ "- #{e.message}"
72
+ end
73
+ raise Requests::Formatting::Error, <<~MSG
74
+ An internal error occurred #{message}.
75
+ Updating to a newer version of RuboCop may solve this.
76
+ For more details, run RuboCop on the command line.
77
+ MSG
78
+ end
79
+
46
80
  # duplicated from: lib/standard/lsp/routes.rb
47
81
  # modified to incorporate Ruby LSP's to_standardized_path method
48
82
  def uri_to_path(uri)
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.79.2
4
+ version: 1.82.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -9,7 +9,7 @@ authors:
9
9
  - Yuji Nakayama
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2025-08-05 00:00:00.000000000 Z
12
+ date: 2025-12-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
@@ -127,7 +127,7 @@ dependencies:
127
127
  requirements:
128
128
  - - ">="
129
129
  - !ruby/object:Gem::Version
130
- version: 1.46.0
130
+ version: 1.48.0
131
131
  - - "<"
132
132
  - !ruby/object:Gem::Version
133
133
  version: '2.0'
@@ -137,7 +137,7 @@ dependencies:
137
137
  requirements:
138
138
  - - ">="
139
139
  - !ruby/object:Gem::Version
140
- version: 1.46.0
140
+ version: 1.48.0
141
141
  - - "<"
142
142
  - !ruby/object:Gem::Version
143
143
  version: '2.0'
@@ -708,6 +708,7 @@ files:
708
708
  - lib/rubocop/cop/style/array_coercion.rb
709
709
  - lib/rubocop/cop/style/array_first_last.rb
710
710
  - lib/rubocop/cop/style/array_intersect.rb
711
+ - lib/rubocop/cop/style/array_intersect_with_single_element.rb
711
712
  - lib/rubocop/cop/style/array_join.rb
712
713
  - lib/rubocop/cop/style/ascii_comments.rb
713
714
  - lib/rubocop/cop/style/attr.rb
@@ -838,6 +839,7 @@ files:
838
839
  - lib/rubocop/cop/style/mixin_grouping.rb
839
840
  - lib/rubocop/cop/style/mixin_usage.rb
840
841
  - lib/rubocop/cop/style/module_function.rb
842
+ - lib/rubocop/cop/style/module_member_existence_check.rb
841
843
  - lib/rubocop/cop/style/multiline_block_chain.rb
842
844
  - lib/rubocop/cop/style/multiline_if_modifier.rb
843
845
  - lib/rubocop/cop/style/multiline_if_then.rb
@@ -1090,9 +1092,9 @@ licenses:
1090
1092
  - MIT
1091
1093
  metadata:
1092
1094
  homepage_uri: https://rubocop.org/
1093
- changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.79.2
1095
+ changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.82.0
1094
1096
  source_code_uri: https://github.com/rubocop/rubocop/
1095
- documentation_uri: https://docs.rubocop.org/rubocop/1.79/
1097
+ documentation_uri: https://docs.rubocop.org/rubocop/1.82/
1096
1098
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
1097
1099
  rubygems_mfa_required: 'true'
1098
1100
  rdoc_options: []