rubocop 1.35.1 → 1.37.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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +32 -1
  4. data/lib/rubocop/arguments_env.rb +17 -0
  5. data/lib/rubocop/arguments_file.rb +17 -0
  6. data/lib/rubocop/cli/command/execute_runner.rb +7 -7
  7. data/lib/rubocop/cop/generator.rb +1 -2
  8. data/lib/rubocop/cop/layout/block_alignment.rb +14 -12
  9. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
  10. data/lib/rubocop/cop/layout/indentation_width.rb +4 -2
  11. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
  12. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +25 -9
  13. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +28 -3
  14. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -2
  15. data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
  16. data/lib/rubocop/cop/lint/duplicate_methods.rb +11 -1
  17. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
  18. data/lib/rubocop/cop/lint/duplicate_require.rb +1 -1
  19. data/lib/rubocop/cop/lint/empty_class.rb +3 -1
  20. data/lib/rubocop/cop/lint/empty_conditional_body.rb +46 -4
  21. data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
  22. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  23. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
  24. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
  25. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
  26. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
  27. data/lib/rubocop/cop/lint/redundant_require_statement.rb +29 -9
  28. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
  29. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -2
  30. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -11
  31. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +17 -2
  32. data/lib/rubocop/cop/lint/unreachable_loop.rb +2 -2
  33. data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
  34. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  35. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +1 -1
  36. data/lib/rubocop/cop/mixin/allowed_methods.rb +10 -5
  37. data/lib/rubocop/cop/mixin/allowed_pattern.rb +13 -5
  38. data/lib/rubocop/cop/mixin/comments_help.rb +12 -0
  39. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
  40. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +6 -3
  41. data/lib/rubocop/cop/mixin/hash_transform_method.rb +9 -5
  42. data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
  43. data/lib/rubocop/cop/mixin/surrounding_space.rb +6 -5
  44. data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
  45. data/lib/rubocop/cop/style/access_modifier_declarations.rb +97 -1
  46. data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
  47. data/lib/rubocop/cop/style/block_delimiters.rb +1 -1
  48. data/lib/rubocop/cop/style/case_equality.rb +40 -10
  49. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  50. data/lib/rubocop/cop/style/collection_compact.rb +6 -1
  51. data/lib/rubocop/cop/style/each_for_simple_loop.rb +40 -5
  52. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  53. data/lib/rubocop/cop/style/endless_method.rb +1 -1
  54. data/lib/rubocop/cop/style/explicit_block_argument.rb +4 -0
  55. data/lib/rubocop/cop/style/format_string_token.rb +1 -1
  56. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  57. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -2
  58. data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
  59. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
  60. data/lib/rubocop/cop/style/operator_method_call.rb +39 -0
  61. data/lib/rubocop/cop/style/perl_backrefs.rb +22 -1
  62. data/lib/rubocop/cop/style/redundant_begin.rb +1 -0
  63. data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
  64. data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
  65. data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -0
  66. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
  67. data/lib/rubocop/cop/style/redundant_string_escape.rb +173 -0
  68. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
  69. data/lib/rubocop/cop/style/static_class.rb +32 -1
  70. data/lib/rubocop/cop/style/symbol_array.rb +2 -0
  71. data/lib/rubocop/cop/style/symbol_proc.rb +6 -5
  72. data/lib/rubocop/cop/style/word_array.rb +2 -0
  73. data/lib/rubocop/formatter/disabled_config_formatter.rb +8 -2
  74. data/lib/rubocop/options.rb +13 -13
  75. data/lib/rubocop/rspec/shared_contexts.rb +13 -1
  76. data/lib/rubocop/runner.rb +4 -0
  77. data/lib/rubocop/server/cache.rb +5 -1
  78. data/lib/rubocop/server/cli.rb +9 -2
  79. data/lib/rubocop/server/client_command/exec.rb +5 -0
  80. data/lib/rubocop/server/core.rb +2 -1
  81. data/lib/rubocop/server/socket_reader.rb +5 -1
  82. data/lib/rubocop/server.rb +1 -1
  83. data/lib/rubocop/version.rb +8 -2
  84. data/lib/rubocop.rb +3 -0
  85. metadata +10 -5
@@ -0,0 +1,173 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for redundant escapes in string literals.
7
+ #
8
+ # @example
9
+ # # bad - no need to escape # without following {/$/@
10
+ # "\#foo"
11
+ #
12
+ # # bad - no need to escape single quotes inside double quoted string
13
+ # "\'foo\'"
14
+ #
15
+ # # bad - heredocs are also checked for unnecessary escapes
16
+ # <<~STR
17
+ # \#foo \"foo\"
18
+ # STR
19
+ #
20
+ # # good
21
+ # "#foo"
22
+ #
23
+ # # good
24
+ # "\#{no_interpolation}"
25
+ #
26
+ # # good
27
+ # "'foo'"
28
+ #
29
+ # # good
30
+ # "foo\
31
+ # bar"
32
+ #
33
+ # # good
34
+ # <<~STR
35
+ # #foo "foo"
36
+ # STR
37
+ class RedundantStringEscape < Base
38
+ include MatchRange
39
+ include RangeHelp
40
+ extend AutoCorrector
41
+
42
+ MSG = 'Redundant escape of %<char>s inside string literal.'
43
+
44
+ def on_str(node)
45
+ return if node.parent&.regexp_type? || node.parent&.xstr_type?
46
+
47
+ str_contents_range = str_contents_range(node)
48
+ return unless str_contents_range.source.include?('\\')
49
+
50
+ each_match_range(str_contents_range, /(\\.)/) do |range|
51
+ next if allowed_escape?(node, range.resize(3))
52
+
53
+ add_offense(range) do |corrector|
54
+ corrector.remove_leading(range, 1)
55
+ end
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def message(range)
62
+ format(MSG, char: range.source.chars.last)
63
+ end
64
+
65
+ def str_contents_range(node)
66
+ if heredoc?(node)
67
+ node.loc.heredoc_body
68
+ elsif begin_loc_present?(node)
69
+ contents_range(node)
70
+ else
71
+ node.loc.expression
72
+ end
73
+ end
74
+
75
+ def begin_loc_present?(node)
76
+ # e.g. a __FILE__ literal has no begin loc so we can't query if it's nil
77
+ node.loc.to_hash.key?(:begin) && !node.loc.begin.nil?
78
+ end
79
+
80
+ def allowed_escape?(node, range)
81
+ escaped = range.source[(1..-1)]
82
+
83
+ # Inside a single-quoted string, escapes (except \\ and \') do not have special meaning,
84
+ # and so are not redundant, as they are a literal backslash.
85
+ return true if interpolation_not_enabled?(node)
86
+
87
+ # Strictly speaking a few single-letter chars are currently unnecessary to "escape", e.g.
88
+ # d, but enumerating them is rather difficult, and their behavior could change over time
89
+ # with different versions of Ruby so that e.g. /\d/ != /d/
90
+ return true if /[\n\\[[:alnum:]]]/.match?(escaped[0])
91
+
92
+ return true if escaped[0] == ' ' && percent_array_literal?(node)
93
+
94
+ # Allow #{foo}, #$foo, #@foo, and #@@foo for escaping local, global, instance and class
95
+ # variable interpolations inside
96
+ return true if /\A#[{$@]/.match?(escaped)
97
+ return true if delimiter?(node, escaped[0])
98
+
99
+ false
100
+ end
101
+
102
+ def interpolation_not_enabled?(node)
103
+ single_quoted?(node) ||
104
+ percent_w_literal?(node) ||
105
+ percent_q_literal?(node) ||
106
+ heredoc_with_disabled_interpolation?(node)
107
+ end
108
+
109
+ def single_quoted?(node)
110
+ delimiter?(node, "'")
111
+ end
112
+
113
+ def percent_q_literal?(node)
114
+ if literal_in_interpolated_or_multiline_string?(node)
115
+ percent_q_literal?(node.parent)
116
+ else
117
+ node.source.start_with?('%q')
118
+ end
119
+ end
120
+
121
+ def array_literal?(node, prefix)
122
+ if literal_in_interpolated_or_multiline_string?(node)
123
+ array_literal?(node.parent, prefix)
124
+ else
125
+ node.parent&.array_type? && node.parent.source.start_with?(prefix)
126
+ end
127
+ end
128
+
129
+ def percent_w_literal?(node)
130
+ array_literal?(node, '%w')
131
+ end
132
+
133
+ def percent_w_upper_literal?(node)
134
+ array_literal?(node, '%W')
135
+ end
136
+
137
+ def percent_array_literal?(node)
138
+ (percent_w_literal?(node) || percent_w_upper_literal?(node))
139
+ end
140
+
141
+ def heredoc_with_disabled_interpolation?(node)
142
+ if heredoc?(node)
143
+ node.loc.expression.source.end_with?("'")
144
+ elsif node.parent&.dstr_type?
145
+ heredoc_with_disabled_interpolation?(node.parent)
146
+ else
147
+ false
148
+ end
149
+ end
150
+
151
+ def heredoc?(node)
152
+ (node.str_type? || node.dstr_type?) && node.heredoc?
153
+ end
154
+
155
+ def delimiter?(node, char)
156
+ return false if heredoc?(node)
157
+
158
+ if literal_in_interpolated_or_multiline_string?(node) || percent_array_literal?(node)
159
+ return delimiter?(node.parent, char)
160
+ end
161
+
162
+ delimiters = [node.loc.begin.source[-1], node.loc.end.source[0]]
163
+
164
+ delimiters.include?(char)
165
+ end
166
+
167
+ def literal_in_interpolated_or_multiline_string?(node)
168
+ node.str_type? && !begin_loc_present?(node) && node.parent&.dstr_type?
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
@@ -9,7 +9,7 @@ module RuboCop
9
9
  # reasons:
10
10
  #
11
11
  # * The syntax of modifier form `rescue` can be misleading because it
12
- # might led us to believe that `rescue` handles the given exception
12
+ # might lead us to believe that `rescue` handles the given exception
13
13
  # but it actually rescue all exceptions to return the given rescue
14
14
  # block. In this case, value returned by handle_error or
15
15
  # SomeException.
@@ -44,18 +44,49 @@ module RuboCop
44
44
  # end
45
45
  #
46
46
  class StaticClass < Base
47
+ include RangeHelp
47
48
  include VisibilityHelp
49
+ extend AutoCorrector
48
50
 
49
51
  MSG = 'Prefer modules to classes with only class methods.'
50
52
 
51
53
  def on_class(class_node)
52
54
  return if class_node.parent_class
55
+ return unless class_convertible_to_module?(class_node)
53
56
 
54
- add_offense(class_node) if class_convertible_to_module?(class_node)
57
+ add_offense(class_node) do |corrector|
58
+ autocorrect(corrector, class_node)
59
+ end
55
60
  end
56
61
 
57
62
  private
58
63
 
64
+ def autocorrect(corrector, class_node)
65
+ corrector.replace(class_node.loc.keyword, 'module')
66
+ corrector.insert_after(class_node.loc.name, "\nmodule_function\n")
67
+
68
+ class_elements(class_node).each do |node|
69
+ if node.defs_type?
70
+ autocorrect_def(corrector, node)
71
+ elsif node.sclass_type?
72
+ autocorrect_sclass(corrector, node)
73
+ end
74
+ end
75
+ end
76
+
77
+ def autocorrect_def(corrector, node)
78
+ corrector.remove(
79
+ range_between(node.receiver.source_range.begin_pos, node.loc.name.begin_pos)
80
+ )
81
+ end
82
+
83
+ def autocorrect_sclass(corrector, node)
84
+ corrector.remove(
85
+ range_between(node.loc.keyword.begin_pos, node.identifier.source_range.end_pos)
86
+ )
87
+ corrector.remove(node.loc.end)
88
+ end
89
+
59
90
  def class_convertible_to_module?(class_node)
60
91
  nodes = class_elements(class_node)
61
92
  return false if nodes.empty?
@@ -65,6 +65,8 @@ module RuboCop
65
65
  end
66
66
 
67
67
  def build_bracketed_array(node)
68
+ return '[]' if node.children.empty?
69
+
68
70
  syms = node.children.map do |c|
69
71
  if c.dsym_type?
70
72
  string_literal = to_string_literal(c.source)
@@ -11,10 +11,11 @@ module RuboCop
11
11
  # These are customizable with `AllowedMethods` option.
12
12
  #
13
13
  # @safety
14
- # This cop is unsafe because `proc`s and blocks work differently
15
- # when additional arguments are passed in. A block will silently
16
- # allow additional arguments, but a `proc` will raise
17
- # an `ArgumentError`.
14
+ # This cop is unsafe because there is a difference that a `Proc`
15
+ # generated from `Symbol#to_proc` behaves as a lambda, while
16
+ # a `Proc` generated from a block does not.
17
+ # For example, a lambda will raise an `ArgumentError` if the
18
+ # number of arguments is wrong, but a non-lambda `Proc` will not.
18
19
  #
19
20
  # For example:
20
21
  #
@@ -81,7 +82,7 @@ module RuboCop
81
82
  # # bad
82
83
  # something.map { |s| s.upcase }
83
84
  #
84
- # @example AllowedPatterns: [/map/] (default)
85
+ # @example AllowedPatterns: ['map'] (default)
85
86
  # # good
86
87
  # something.map { |s| s.upcase }
87
88
  #
@@ -83,6 +83,8 @@ module RuboCop
83
83
  end
84
84
 
85
85
  def build_bracketed_array(node)
86
+ return '[]' if node.children.empty?
87
+
86
88
  words = node.children.map do |word|
87
89
  if word.dstr_type?
88
90
  string_literal = to_string_literal(word.source)
@@ -70,7 +70,9 @@ module RuboCop
70
70
 
71
71
  command += ' --auto-gen-only-exclude' if @options[:auto_gen_only_exclude]
72
72
 
73
- if @exclude_limit_option
73
+ if no_exclude_limit?
74
+ command += ' --no-exclude-limit'
75
+ elsif @exclude_limit_option
74
76
  command += format(' --exclude-limit %<limit>d', limit: Integer(@exclude_limit_option))
75
77
  end
76
78
  command += ' --no-offense-counts' unless show_offense_counts?
@@ -187,7 +189,7 @@ module RuboCop
187
189
  return unless cfg.empty?
188
190
 
189
191
  offending_files = @files_with_offenses[cop_name].sort
190
- if offending_files.count > @exclude_limit
192
+ if !no_exclude_limit? && offending_files.count > @exclude_limit
191
193
  output_buffer.puts ' Enabled: false'
192
194
  else
193
195
  output_exclude_list(output_buffer, offending_files, cop_name)
@@ -245,6 +247,10 @@ module RuboCop
245
247
  def safe_autocorrect?(config)
246
248
  config.fetch('Safe', true) && config.fetch('SafeAutoCorrect', true)
247
249
  end
250
+
251
+ def no_exclude_limit?
252
+ @options[:no_exclude_limit] == false
253
+ end
248
254
  end
249
255
  end
250
256
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'optparse'
4
- require 'shellwords'
4
+ require_relative 'arguments_env'
5
+ require_relative 'arguments_file'
5
6
 
6
7
  module RuboCop
7
8
  class IncorrectCopNameError < StandardError; end
@@ -24,7 +25,10 @@ module RuboCop
24
25
  end
25
26
 
26
27
  def parse(command_line_args)
28
+ args_from_file = ArgumentsFile.read_as_arguments
29
+ args_from_env = ArgumentsEnv.read_as_arguments
27
30
  args = args_from_file.concat(args_from_env).concat(command_line_args)
31
+
28
32
  define_options.parse!(args)
29
33
 
30
34
  @validator.validate_compatibility
@@ -45,18 +49,6 @@ module RuboCop
45
49
 
46
50
  private
47
51
 
48
- def args_from_file
49
- if File.exist?('.rubocop') && !File.directory?('.rubocop')
50
- File.read('.rubocop').shellsplit
51
- else
52
- []
53
- end
54
- end
55
-
56
- def args_from_env
57
- Shellwords.split(ENV.fetch('RUBOCOP_OPTS', ''))
58
- end
59
-
60
52
  def define_options
61
53
  OptionParser.new do |opts|
62
54
  opts.banner = rainbow.wrap('Usage: rubocop [options] [file1, file2, ...]').bright
@@ -169,6 +161,7 @@ module RuboCop
169
161
  end
170
162
 
171
163
  option(opts, '--exclude-limit COUNT') { @validator.validate_exclude_limit_option }
164
+ option(opts, '--no-exclude-limit')
172
165
 
173
166
  option(opts, '--[no-]offense-counts')
174
167
  option(opts, '--[no-]auto-gen-only-exclude')
@@ -400,6 +393,12 @@ module RuboCop
400
393
  end
401
394
 
402
395
  def validate_autocorrect
396
+ if @options.key?(:safe_autocorrect) && @options.key?(:autocorrect_all)
397
+ message = Rainbow(<<~MESSAGE).red
398
+ Error: Both safe and unsafe autocorrect options are specified, use only one.
399
+ MESSAGE
400
+ raise OptionArgumentError, message
401
+ end
403
402
  return if @options.key?(:autocorrect)
404
403
  return unless @options.key?(:disable_uncorrectable)
405
404
 
@@ -497,6 +496,7 @@ module RuboCop
497
496
  disable_uncorrectable: ['Used with --autocorrect to annotate any',
498
497
  'offenses that do not support autocorrect',
499
498
  'with `rubocop:todo` comments.'],
499
+ no_exclude_limit: ['Do not set the limit for how many files to exclude.'],
500
500
  force_exclusion: ['Any files excluded by `Exclude` in configuration',
501
501
  'files will be excluded, even if given explicitly',
502
502
  'as arguments.'],
@@ -2,7 +2,15 @@
2
2
 
3
3
  require 'tmpdir'
4
4
 
5
- RSpec.shared_context 'isolated environment' do
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
+
6
14
  around do |example|
7
15
  Dir.mktmpdir do |tmpdir|
8
16
  original_home = Dir.home
@@ -32,6 +40,10 @@ RSpec.shared_context 'isolated environment' do
32
40
  ENV['HOME'] = original_home
33
41
  ENV['XDG_CONFIG_HOME'] = original_xdg_config_home
34
42
 
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
35
47
  RuboCop::FileFinder.root_level = nil
36
48
  end
37
49
  end
@@ -64,6 +64,10 @@ module RuboCop
64
64
  # instances that each inspects its allotted group of files.
65
65
  def warm_cache(target_files)
66
66
  saved_options = @options.dup
67
+ if target_files.length <= 1
68
+ puts 'Skipping parallel inspection: only a single file needs inspection' if @options[:debug]
69
+ return
70
+ end
67
71
  puts 'Running parallel inspection' if @options[:debug]
68
72
  %i[autocorrect safe_autocorrect].each { |opt| @options[opt] = false }
69
73
  Parallel.each(target_files) { |target_file| file_offenses(target_file) }
@@ -103,9 +103,13 @@ module RuboCop
103
103
  dir.join('version')
104
104
  end
105
105
 
106
+ def stderr_path
107
+ dir.join('stderr')
108
+ end
109
+
106
110
  def pid_running?
107
111
  Process.kill(0, pid_path.read.to_i) == 1
108
- rescue Errno::ESRCH
112
+ rescue Errno::ESRCH, Errno::ENOENT
109
113
  false
110
114
  end
111
115
 
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rainbow'
4
+ require_relative '../arguments_env'
5
+ require_relative '../arguments_file'
4
6
 
5
7
  #
6
8
  # This code is based on https://github.com/fohte/rubocop-daemon.
@@ -29,7 +31,7 @@ module RuboCop
29
31
  @exit = false
30
32
  end
31
33
 
32
- # rubocop:disable Metrics/MethodLength
34
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
33
35
  def run(argv = ARGV)
34
36
  unless Server.support_server?
35
37
  return error('RuboCop server is not supported by this Ruby.') if use_server_option?(argv)
@@ -50,11 +52,16 @@ module RuboCop
50
52
  return error("#{server_command} cannot be combined with other options.")
51
53
  end
52
54
 
55
+ if server_command.nil?
56
+ server_command = ArgumentsEnv.read_as_arguments.delete('--server') ||
57
+ ArgumentsFile.read_as_arguments.delete('--server')
58
+ end
59
+
53
60
  run_command(server_command)
54
61
 
55
62
  STATUS_SUCCESS
56
63
  end
57
- # rubocop:enable Metrics/MethodLength
64
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
58
65
 
59
66
  def exit?
60
67
  @exit
@@ -23,6 +23,7 @@ module RuboCop
23
23
  args: ARGV.dup,
24
24
  body: $stdin.tty? ? '' : $stdin.read
25
25
  )
26
+ warn stderr unless stderr.empty?
26
27
  status
27
28
  end
28
29
 
@@ -43,6 +44,10 @@ module RuboCop
43
44
  RuboCop::Version::STRING != Cache.version_path.read
44
45
  end
45
46
 
47
+ def stderr
48
+ Cache.stderr_path.read
49
+ end
50
+
46
51
  def status
47
52
  unless Cache.status_path.file?
48
53
  raise "RuboCop server: Could not find status file at: #{Cache.status_path}"
@@ -56,7 +56,8 @@ module RuboCop
56
56
  def start_server(host, port)
57
57
  @server = TCPServer.open(host, port)
58
58
 
59
- puts "RuboCop server starting on #{@server.addr[3]}:#{@server.addr[1]}."
59
+ output_stream = ARGV.include?('--stderr') ? $stderr : $stdout
60
+ output_stream.puts "RuboCop server starting on #{@server.addr[3]}:#{@server.addr[1]}."
60
61
  end
61
62
 
62
63
  def read_socket(socket)
@@ -24,13 +24,17 @@ module RuboCop
24
24
  def read!
25
25
  request = parse_request(@socket.read)
26
26
 
27
+ stderr = StringIO.new
27
28
  Helper.redirect(
28
29
  stdin: StringIO.new(request.body),
29
30
  stdout: @socket,
30
- stderr: @socket
31
+ stderr: stderr
31
32
  ) do
32
33
  create_command_instance(request).run
33
34
  end
35
+ ensure
36
+ Cache.stderr_path.write(stderr.string)
37
+ @socket.close
34
38
  end
35
39
 
36
40
  private
@@ -33,7 +33,7 @@ module RuboCop
33
33
  def running?
34
34
  return false unless support_server? # Never running.
35
35
 
36
- Cache.dir.exist? && Cache.pid_path.file? && Cache.pid_running?
36
+ Cache.pid_running?
37
37
  end
38
38
 
39
39
  def wait_for_running_status!(expected)
@@ -3,11 +3,11 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.35.1'
6
+ STRING = '1.37.0'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
10
- 'running on %<ruby_engine>s %<ruby_version>s %<ruby_platform>s)'
10
+ 'running on %<ruby_engine>s %<ruby_version>s)%<server_mode>s [%<ruby_platform>s]'
11
11
 
12
12
  CANONICAL_FEATURE_NAMES = { 'Rspec' => 'RSpec', 'Graphql' => 'GraphQL', 'Md' => 'Markdown',
13
13
  'Thread_safety' => 'ThreadSafety' }.freeze
@@ -19,6 +19,7 @@ module RuboCop
19
19
  verbose_version = format(MSG, version: STRING, parser_version: Parser::VERSION,
20
20
  rubocop_ast_version: RuboCop::AST::Version::STRING,
21
21
  ruby_engine: RUBY_ENGINE, ruby_version: RUBY_VERSION,
22
+ server_mode: server_mode,
22
23
  ruby_platform: RUBY_PLATFORM)
23
24
  return verbose_version unless env
24
25
 
@@ -88,5 +89,10 @@ module RuboCop
88
89
  def self.document_version
89
90
  STRING.match('\d+\.\d+').to_s
90
91
  end
92
+
93
+ # @api private
94
+ def self.server_mode
95
+ RuboCop.const_defined?(:Server) && Server.running? ? ' +server' : ''
96
+ end
91
97
  end
92
98
  end
data/lib/rubocop.rb CHANGED
@@ -292,6 +292,7 @@ require_relative 'rubocop/cop/lint/duplicate_branch'
292
292
  require_relative 'rubocop/cop/lint/duplicate_case_condition'
293
293
  require_relative 'rubocop/cop/lint/duplicate_elsif_condition'
294
294
  require_relative 'rubocop/cop/lint/duplicate_hash_key'
295
+ require_relative 'rubocop/cop/lint/duplicate_magic_comment'
295
296
  require_relative 'rubocop/cop/lint/duplicate_methods'
296
297
  require_relative 'rubocop/cop/lint/duplicate_regexp_character_class_element'
297
298
  require_relative 'rubocop/cop/lint/duplicate_require'
@@ -537,6 +538,7 @@ require_relative 'rubocop/cop/style/method_call_with_args_parentheses'
537
538
  require_relative 'rubocop/cop/style/multiline_in_pattern_then'
538
539
  require_relative 'rubocop/cop/style/numbered_parameters'
539
540
  require_relative 'rubocop/cop/style/open_struct_use'
541
+ require_relative 'rubocop/cop/style/operator_method_call'
540
542
  require_relative 'rubocop/cop/style/redundant_assignment'
541
543
  require_relative 'rubocop/cop/style/redundant_fetch_block'
542
544
  require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
@@ -612,6 +614,7 @@ require_relative 'rubocop/cop/style/redundant_return'
612
614
  require_relative 'rubocop/cop/style/redundant_self'
613
615
  require_relative 'rubocop/cop/style/redundant_sort'
614
616
  require_relative 'rubocop/cop/style/redundant_sort_by'
617
+ require_relative 'rubocop/cop/style/redundant_string_escape'
615
618
  require_relative 'rubocop/cop/style/regexp_literal'
616
619
  require_relative 'rubocop/cop/style/rescue_modifier'
617
620
  require_relative 'rubocop/cop/style/rescue_standard_error'
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.35.1
4
+ version: 1.37.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-08-22 00:00:00.000000000 Z
13
+ date: 2022-10-20 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -120,7 +120,7 @@ dependencies:
120
120
  requirements:
121
121
  - - ">="
122
122
  - !ruby/object:Gem::Version
123
- version: 1.20.1
123
+ version: 1.22.0
124
124
  - - "<"
125
125
  - !ruby/object:Gem::Version
126
126
  version: '2.0'
@@ -130,7 +130,7 @@ dependencies:
130
130
  requirements:
131
131
  - - ">="
132
132
  - !ruby/object:Gem::Version
133
- version: 1.20.1
133
+ version: 1.22.0
134
134
  - - "<"
135
135
  - !ruby/object:Gem::Version
136
136
  version: '2.0'
@@ -207,6 +207,8 @@ files:
207
207
  - config/obsoletion.yml
208
208
  - exe/rubocop
209
209
  - lib/rubocop.rb
210
+ - lib/rubocop/arguments_env.rb
211
+ - lib/rubocop/arguments_file.rb
210
212
  - lib/rubocop/ast_aliases.rb
211
213
  - lib/rubocop/cache_config.rb
212
214
  - lib/rubocop/cached_data.rb
@@ -430,6 +432,7 @@ files:
430
432
  - lib/rubocop/cop/lint/duplicate_case_condition.rb
431
433
  - lib/rubocop/cop/lint/duplicate_elsif_condition.rb
432
434
  - lib/rubocop/cop/lint/duplicate_hash_key.rb
435
+ - lib/rubocop/cop/lint/duplicate_magic_comment.rb
433
436
  - lib/rubocop/cop/lint/duplicate_methods.rb
434
437
  - lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb
435
438
  - lib/rubocop/cop/lint/duplicate_require.rb
@@ -795,6 +798,7 @@ files:
795
798
  - lib/rubocop/cop/style/object_then.rb
796
799
  - lib/rubocop/cop/style/one_line_conditional.rb
797
800
  - lib/rubocop/cop/style/open_struct_use.rb
801
+ - lib/rubocop/cop/style/operator_method_call.rb
798
802
  - lib/rubocop/cop/style/option_hash.rb
799
803
  - lib/rubocop/cop/style/optional_arguments.rb
800
804
  - lib/rubocop/cop/style/optional_boolean_parameter.rb
@@ -831,6 +835,7 @@ files:
831
835
  - lib/rubocop/cop/style/redundant_self_assignment_branch.rb
832
836
  - lib/rubocop/cop/style/redundant_sort.rb
833
837
  - lib/rubocop/cop/style/redundant_sort_by.rb
838
+ - lib/rubocop/cop/style/redundant_string_escape.rb
834
839
  - lib/rubocop/cop/style/regexp_literal.rb
835
840
  - lib/rubocop/cop/style/rescue_modifier.rb
836
841
  - lib/rubocop/cop/style/rescue_standard_error.rb
@@ -977,7 +982,7 @@ metadata:
977
982
  homepage_uri: https://rubocop.org/
978
983
  changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
979
984
  source_code_uri: https://github.com/rubocop/rubocop/
980
- documentation_uri: https://docs.rubocop.org/rubocop/1.35/
985
+ documentation_uri: https://docs.rubocop.org/rubocop/1.37/
981
986
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
982
987
  rubygems_mfa_required: 'true'
983
988
  post_install_message: