rubocop 1.37.1 → 1.39.0

Sign up to get free protection for your applications and to get access to all the features.
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: