rubocop 1.37.1 → 1.39.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +10 -2
  4. data/lib/rubocop/comment_config.rb +36 -1
  5. data/lib/rubocop/cop/commissioner.rb +3 -1
  6. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  7. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +29 -8
  8. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  9. data/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb +3 -0
  10. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -0
  11. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +34 -0
  12. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +6 -2
  13. data/lib/rubocop/cop/lint/duplicate_methods.rb +17 -8
  14. data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
  15. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
  16. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +11 -0
  17. data/lib/rubocop/cop/lint/redundant_require_statement.rb +10 -2
  18. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  19. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  20. data/lib/rubocop/cop/mixin/range_help.rb +23 -0
  21. data/lib/rubocop/cop/mixin/surrounding_space.rb +4 -3
  22. data/lib/rubocop/cop/mixin/visibility_help.rb +40 -5
  23. data/lib/rubocop/cop/registry.rb +10 -4
  24. data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -25
  25. data/lib/rubocop/cop/style/block_delimiters.rb +1 -1
  26. data/lib/rubocop/cop/style/class_equality_comparison.rb +7 -5
  27. data/lib/rubocop/cop/style/collection_compact.rb +4 -2
  28. data/lib/rubocop/cop/style/guard_clause.rb +62 -21
  29. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -0
  30. data/lib/rubocop/cop/style/hash_each_methods.rb +32 -10
  31. data/lib/rubocop/cop/style/hash_except.rb +4 -0
  32. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +25 -2
  33. data/lib/rubocop/cop/style/module_function.rb +28 -6
  34. data/lib/rubocop/cop/style/object_then.rb +3 -0
  35. data/lib/rubocop/cop/style/operator_method_call.rb +13 -0
  36. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  37. data/lib/rubocop/cop/style/redundant_each.rb +116 -0
  38. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +12 -3
  39. data/lib/rubocop/cop/team.rb +3 -4
  40. data/lib/rubocop/cop/util.rb +1 -1
  41. data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
  42. data/lib/rubocop/cops_documentation_generator.rb +2 -1
  43. data/lib/rubocop/ext/processed_source.rb +2 -0
  44. data/lib/rubocop/formatter/offense_count_formatter.rb +8 -5
  45. data/lib/rubocop/formatter/worst_offenders_formatter.rb +6 -3
  46. data/lib/rubocop/options.rb +6 -2
  47. data/lib/rubocop/rspec/cop_helper.rb +21 -1
  48. data/lib/rubocop/rspec/shared_contexts.rb +13 -12
  49. data/lib/rubocop/runner.rb +15 -11
  50. data/lib/rubocop/server/core.rb +16 -0
  51. data/lib/rubocop/version.rb +1 -1
  52. data/lib/rubocop.rb +1 -0
  53. metadata +4 -3
@@ -122,7 +122,7 @@ module RuboCop
122
122
  string.inspect
123
123
  else
124
124
  # In a single-quoted strings, double quotes don't need to be escaped
125
- "'#{string.gsub('\"', '"').gsub('\\') { '\\\\' }}'"
125
+ "'#{string.gsub('\\') { '\\\\' }.gsub('\"', '"')}'"
126
126
  end
127
127
  end
128
128
 
@@ -109,7 +109,7 @@ module RuboCop
109
109
  end
110
110
 
111
111
  def accessible_variables
112
- scope_stack.reverse_each.each_with_object([]) do |scope, variables|
112
+ scope_stack.reverse_each.with_object([]) do |scope, variables|
113
113
  variables.concat(scope.variables.values)
114
114
  break variables unless scope.node.block_type?
115
115
  end
@@ -185,7 +185,8 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
185
185
  def to_table(header, content)
186
186
  table = ['|===', "| #{header.join(' | ')}\n\n"].join("\n")
187
187
  marked_contents = content.map do |plain_content|
188
- plain_content.map { |c| "| #{c}" }.join("\n")
188
+ # Escape `|` with backslash to prevent the regexp `|` is not used as a table separator.
189
+ plain_content.map { |c| "| #{c.gsub(/\|/, '\|')}" }.join("\n")
189
190
  end
190
191
  table << marked_contents.join("\n\n")
191
192
  table << "\n|===\n"
@@ -4,6 +4,8 @@ module RuboCop
4
4
  module Ext
5
5
  # Extensions to AST::ProcessedSource for our cached comment_config
6
6
  module ProcessedSource
7
+ attr_accessor :registry, :config
8
+
7
9
  def comment_config
8
10
  @comment_config ||= CommentConfig.new(self)
9
11
  end
@@ -12,13 +12,14 @@ module RuboCop
12
12
  # 26 LineLength
13
13
  # 3 OneLineConditional
14
14
  # --
15
- # 29 Total
15
+ # 29 Total in 5 files
16
16
  class OffenseCountFormatter < BaseFormatter
17
17
  attr_reader :offense_counts
18
18
 
19
19
  def started(target_files)
20
20
  super
21
21
  @offense_counts = Hash.new(0)
22
+ @offending_files_count = 0
22
23
  @style_guide_links = {}
23
24
 
24
25
  return unless output.tty?
@@ -43,26 +44,28 @@ module RuboCop
43
44
  if options[:display_style_guide]
44
45
  offenses.each { |o| @style_guide_links[o.cop_name] ||= o.message[/ \(http\S+\)\Z/] }
45
46
  end
47
+ @offending_files_count += 1 unless offenses.empty?
46
48
  @progressbar.increment if instance_variable_defined?(:@progressbar)
47
49
  end
48
50
 
49
51
  def finished(_inspected_files)
50
- report_summary(@offense_counts)
52
+ report_summary(@offense_counts, @offending_files_count)
51
53
  end
52
54
 
53
55
  # rubocop:disable Metrics/AbcSize
54
- def report_summary(offense_counts)
56
+ def report_summary(offense_counts, offending_files_count)
55
57
  per_cop_counts = ordered_offense_counts(offense_counts)
56
58
  total_count = total_offense_count(offense_counts)
57
59
 
58
60
  output.puts
59
61
 
62
+ column_width = total_count.to_s.length + 2
60
63
  per_cop_counts.each do |cop_name, count|
61
- output.puts "#{count.to_s.ljust(total_count.to_s.length + 2)}#{cop_name}" \
64
+ output.puts "#{count.to_s.ljust(column_width)}#{cop_name}" \
62
65
  "#{@style_guide_links[cop_name]}\n"
63
66
  end
64
67
  output.puts '--'
65
- output.puts "#{total_count} Total"
68
+ output.puts "#{total_count} Total in #{offending_files_count} files"
66
69
 
67
70
  output.puts
68
71
  end
@@ -12,7 +12,7 @@ module RuboCop
12
12
  # 26 this/file/is/really/bad.rb
13
13
  # 3 just/ok.rb
14
14
  # --
15
- # 29 Total
15
+ # 29 Total in 2 files
16
16
  class WorstOffendersFormatter < BaseFormatter
17
17
  attr_reader :offense_counts
18
18
 
@@ -36,14 +36,17 @@ module RuboCop
36
36
  def report_summary(offense_counts)
37
37
  per_file_counts = ordered_offense_counts(offense_counts)
38
38
  total_count = total_offense_count(offense_counts)
39
+ file_count = per_file_counts.size
39
40
 
40
41
  output.puts
41
42
 
43
+ column_width = total_count.to_s.length + 2
42
44
  per_file_counts.each do |file_name, count|
43
- output.puts "#{count.to_s.ljust(total_count.to_s.length + 2)}#{file_name}\n"
45
+ output.puts "#{count.to_s.ljust(column_width)}#{file_name}\n"
44
46
  end
47
+
45
48
  output.puts '--'
46
- output.puts "#{total_count} Total"
49
+ output.puts "#{total_count} Total in #{file_count} files"
47
50
 
48
51
  output.puts
49
52
  end
@@ -65,7 +65,7 @@ module RuboCop
65
65
  end
66
66
 
67
67
  def add_check_options(opts) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
68
- section(opts, 'Basic Options') do
68
+ section(opts, 'Basic Options') do # rubocop:disable Metrics/BlockLength
69
69
  option(opts, '-l', '--lint') do
70
70
  @options[:only] ||= []
71
71
  @options[:only] << 'Lint'
@@ -90,6 +90,7 @@ module RuboCop
90
90
  option(opts, '--force-default-config')
91
91
  option(opts, '-s', '--stdin FILE')
92
92
  option(opts, '-P', '--[no-]parallel')
93
+ option(opts, '--raise-cop-error')
93
94
  add_severity_option(opts)
94
95
  end
95
96
  end
@@ -589,7 +590,10 @@ module RuboCop
589
590
  restart_server: 'Restart server process.',
590
591
  start_server: 'Start server process.',
591
592
  stop_server: 'Stop server process.',
592
- server_status: 'Show server status.'
593
+ server_status: 'Show server status.',
594
+ raise_cop_error: ['Raise cop-related errors with cause and location.',
595
+ 'This is used to prevent cops from failing silently.',
596
+ 'Default is false.']
593
597
  }.freeze
594
598
  end
595
599
  end
@@ -28,7 +28,27 @@ module CopHelper
28
28
  file = file.path
29
29
  end
30
30
 
31
- RuboCop::ProcessedSource.new(source, ruby_version, file)
31
+ processed_source = RuboCop::ProcessedSource.new(source, ruby_version, file)
32
+ processed_source.config = configuration
33
+ processed_source.registry = registry
34
+ processed_source
35
+ end
36
+
37
+ def configuration
38
+ @configuration ||= if defined?(config)
39
+ config
40
+ else
41
+ RuboCop::Config.new({}, "#{Dir.pwd}/.rubocop.yml")
42
+ end
43
+ end
44
+
45
+ def registry
46
+ @registry ||= begin
47
+ cops = configuration.keys.map { |cop| RuboCop::Cop::Registry.global.find_by_cop_name(cop) }
48
+ cops << cop_class if defined?(cop_class) && !cops.include?(cop_class)
49
+ cops.compact!
50
+ RuboCop::Cop::Registry.new(cops)
51
+ end
32
52
  end
33
53
 
34
54
  def autocorrect_source_file(source)
@@ -3,14 +3,6 @@
3
3
  require 'tmpdir'
4
4
 
5
5
  RSpec.shared_context 'isolated environment' do # rubocop:disable Metrics/BlockLength
6
- before do
7
- if RuboCop.const_defined?(:Server)
8
- # Bust server cache to behave as an isolated environment
9
- RuboCop::Server::Cache.cache_root_path = nil
10
- RuboCop::Server::Cache.instance_variable_set(:@project_dir_cache_key, nil)
11
- end
12
- end
13
-
14
6
  around do |example|
15
7
  Dir.mktmpdir do |tmpdir|
16
8
  original_home = Dir.home
@@ -40,14 +32,23 @@ RSpec.shared_context 'isolated environment' do # rubocop:disable Metrics/BlockLe
40
32
  ENV['HOME'] = original_home
41
33
  ENV['XDG_CONFIG_HOME'] = original_xdg_config_home
42
34
 
43
- if RuboCop.const_defined?(:Server)
44
- RuboCop::Server::Cache.cache_root_path = nil
45
- RuboCop::Server::Cache.instance_variable_set(:@project_dir_cache_key, nil)
46
- end
47
35
  RuboCop::FileFinder.root_level = nil
48
36
  end
49
37
  end
50
38
  end
39
+
40
+ if RuboCop.const_defined?(:Server)
41
+ around do |example|
42
+ RuboCop::Server::Cache.cache_root_path = nil
43
+ RuboCop::Server::Cache.instance_variable_set(:@project_dir_cache_key, nil)
44
+ begin
45
+ example.run
46
+ ensure
47
+ RuboCop::Server::Cache.cache_root_path = nil
48
+ RuboCop::Server::Cache.instance_variable_set(:@project_dir_cache_key, nil)
49
+ end
50
+ end
51
+ end
51
52
  end
52
53
 
53
54
  RSpec.shared_context 'maintain registry' do
@@ -423,17 +423,21 @@ module RuboCop
423
423
  end
424
424
 
425
425
  def get_processed_source(file)
426
- ruby_version = @config_store.for_file(file).target_ruby_version
427
-
428
- if @options[:stdin]
429
- ProcessedSource.new(@options[:stdin], ruby_version, file)
430
- else
431
- begin
432
- ProcessedSource.from_file(file, ruby_version)
433
- rescue Errno::ENOENT
434
- raise RuboCop::Error, "No such file or directory: #{file}"
435
- end
436
- end
426
+ config = @config_store.for_file(file)
427
+ ruby_version = config.target_ruby_version
428
+
429
+ processed_source = if @options[:stdin]
430
+ ProcessedSource.new(@options[:stdin], ruby_version, file)
431
+ else
432
+ begin
433
+ ProcessedSource.from_file(file, ruby_version)
434
+ rescue Errno::ENOENT
435
+ raise RuboCop::Error, "No such file or directory: #{file}"
436
+ end
437
+ end
438
+ processed_source.config = config
439
+ processed_source.registry = mobilized_cop_classes(config)
440
+ processed_source
437
441
  end
438
442
 
439
443
  # A Cop::Team instance is stateful and may change when inspecting.
@@ -17,6 +17,8 @@ module RuboCop
17
17
  # The core of server process. It starts TCP server and perform socket communication.
18
18
  # @api private
19
19
  class Core
20
+ JSON_FORMATS = %w[json j].freeze
21
+
20
22
  def self.token
21
23
  @token ||= SecureRandom.hex(4)
22
24
  end
@@ -41,6 +43,7 @@ module RuboCop
41
43
 
42
44
  pid = fork do
43
45
  Process.daemon(true)
46
+ $stderr.reopen(Cache.stderr_path, 'w')
44
47
  Cache.write_pid_file do
45
48
  read_socket(@server.accept) until @server.closed?
46
49
  end
@@ -56,6 +59,10 @@ module RuboCop
56
59
  def start_server(host, port)
57
60
  @server = TCPServer.open(host, port)
58
61
 
62
+ # JSON format does not expected output message when IDE integration with server mode.
63
+ # See: https://github.com/rubocop/rubocop/issues/11164
64
+ return if use_json_format?
65
+
59
66
  output_stream = ARGV.include?('--stderr') ? $stderr : $stdout
60
67
  output_stream.puts "RuboCop server starting on #{@server.addr[3]}:#{@server.addr[1]}."
61
68
  end
@@ -75,6 +82,15 @@ module RuboCop
75
82
  ensure
76
83
  socket.close
77
84
  end
85
+
86
+ def use_json_format?
87
+ return true if ARGV.include?('--format=json') || ARGV.include?('--format=j')
88
+ return false unless (index = ARGV.index('--format'))
89
+
90
+ format = ARGV[index + 1]
91
+
92
+ JSON_FORMATS.include?(format)
93
+ end
78
94
  end
79
95
  end
80
96
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.37.1'
6
+ STRING = '1.39.0'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
data/lib/rubocop.rb CHANGED
@@ -540,6 +540,7 @@ require_relative 'rubocop/cop/style/numbered_parameters'
540
540
  require_relative 'rubocop/cop/style/open_struct_use'
541
541
  require_relative 'rubocop/cop/style/operator_method_call'
542
542
  require_relative 'rubocop/cop/style/redundant_assignment'
543
+ require_relative 'rubocop/cop/style/redundant_each'
543
544
  require_relative 'rubocop/cop/style/redundant_fetch_block'
544
545
  require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
545
546
  require_relative 'rubocop/cop/style/redundant_initialize'
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.37.1
4
+ version: 1.39.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2022-10-24 00:00:00.000000000 Z
13
+ date: 2022-11-14 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -821,6 +821,7 @@ files:
821
821
  - lib/rubocop/cop/style/redundant_capital_w.rb
822
822
  - lib/rubocop/cop/style/redundant_condition.rb
823
823
  - lib/rubocop/cop/style/redundant_conditional.rb
824
+ - lib/rubocop/cop/style/redundant_each.rb
824
825
  - lib/rubocop/cop/style/redundant_exception.rb
825
826
  - lib/rubocop/cop/style/redundant_fetch_block.rb
826
827
  - lib/rubocop/cop/style/redundant_file_extension_in_require.rb
@@ -984,7 +985,7 @@ metadata:
984
985
  homepage_uri: https://rubocop.org/
985
986
  changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
986
987
  source_code_uri: https://github.com/rubocop/rubocop/
987
- documentation_uri: https://docs.rubocop.org/rubocop/1.37/
988
+ documentation_uri: https://docs.rubocop.org/rubocop/1.39/
988
989
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
989
990
  rubygems_mfa_required: 'true'
990
991
  post_install_message: