rubocop 1.41.1 → 1.43.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +33 -2
  5. data/lib/rubocop/cli.rb +1 -1
  6. data/lib/rubocop/config.rb +7 -7
  7. data/lib/rubocop/config_loader_resolver.rb +5 -1
  8. data/lib/rubocop/cop/base.rb +62 -61
  9. data/lib/rubocop/cop/cop.rb +28 -28
  10. data/lib/rubocop/cop/corrector.rb +23 -11
  11. data/lib/rubocop/cop/gemspec/dependency_version.rb +16 -18
  12. data/lib/rubocop/cop/layout/class_structure.rb +32 -10
  13. data/lib/rubocop/cop/layout/comment_indentation.rb +3 -1
  14. data/lib/rubocop/cop/layout/indentation_style.rb +4 -1
  15. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +6 -6
  16. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
  17. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  18. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -2
  19. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +19 -0
  20. data/lib/rubocop/cop/lint/regexp_as_condition.rb +6 -0
  21. data/lib/rubocop/cop/lint/require_parentheses.rb +3 -1
  22. data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -1
  23. data/lib/rubocop/cop/lint/useless_rescue.rb +71 -0
  24. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +5 -3
  25. data/lib/rubocop/cop/metrics/parameter_lists.rb +27 -0
  26. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  27. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -4
  28. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  29. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +9 -1
  30. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
  31. data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -0
  32. data/lib/rubocop/cop/registry.rb +22 -22
  33. data/lib/rubocop/cop/security/compound_hash.rb +2 -1
  34. data/lib/rubocop/cop/style/block_comments.rb +1 -1
  35. data/lib/rubocop/cop/style/concat_array_literals.rb +22 -2
  36. data/lib/rubocop/cop/style/guard_clause.rb +11 -7
  37. data/lib/rubocop/cop/style/hash_each_methods.rb +13 -1
  38. data/lib/rubocop/cop/style/hash_syntax.rb +11 -7
  39. data/lib/rubocop/cop/style/identical_conditional_branches.rb +15 -0
  40. data/lib/rubocop/cop/style/map_to_set.rb +61 -0
  41. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +12 -9
  42. data/lib/rubocop/cop/style/method_def_parentheses.rb +11 -4
  43. data/lib/rubocop/cop/style/min_max_comparison.rb +73 -0
  44. data/lib/rubocop/cop/style/missing_else.rb +13 -1
  45. data/lib/rubocop/cop/style/operator_method_call.rb +15 -1
  46. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +1 -1
  47. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
  48. data/lib/rubocop/cop/style/redundant_string_escape.rb +4 -2
  49. data/lib/rubocop/cop/style/require_order.rb +4 -2
  50. data/lib/rubocop/cop/style/select_by_regexp.rb +6 -2
  51. data/lib/rubocop/cop/style/signal_exception.rb +8 -6
  52. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -1
  53. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -4
  54. data/lib/rubocop/cop/style/word_array.rb +41 -0
  55. data/lib/rubocop/cop/style/yoda_expression.rb +81 -0
  56. data/lib/rubocop/cop/style/zero_length_predicate.rb +31 -14
  57. data/lib/rubocop/cop/team.rb +29 -29
  58. data/lib/rubocop/cop/variable_force.rb +0 -3
  59. data/lib/rubocop/path_util.rb +17 -7
  60. data/lib/rubocop/result_cache.rb +1 -1
  61. data/lib/rubocop/runner.rb +10 -3
  62. data/lib/rubocop/target_ruby.rb +0 -1
  63. data/lib/rubocop/version.rb +1 -1
  64. data/lib/rubocop.rb +4 -0
  65. metadata +13 -9
@@ -34,43 +34,55 @@ module RuboCop
34
34
  class ZeroLengthPredicate < Base
35
35
  extend AutoCorrector
36
36
 
37
- ZERO_MSG = 'Use `empty?` instead of `%<lhs>s %<opr>s %<rhs>s`.'
38
- NONZERO_MSG = 'Use `!empty?` instead of `%<lhs>s %<opr>s %<rhs>s`.'
37
+ ZERO_MSG = 'Use `empty?` instead of `%<current>s`.'
38
+ NONZERO_MSG = 'Use `!empty?` instead of `%<current>s`.'
39
39
 
40
40
  RESTRICT_ON_SEND = %i[size length].freeze
41
41
 
42
42
  def on_send(node)
43
43
  check_zero_length_predicate(node)
44
- check_nonzero_length_predicate(node)
44
+ check_zero_length_comparison(node)
45
+ check_nonzero_length_comparison(node)
45
46
  end
46
47
 
47
48
  private
48
49
 
49
50
  def check_zero_length_predicate(node)
50
- zero_length_predicate = zero_length_predicate(node.parent)
51
- return unless zero_length_predicate
51
+ return unless (length_method = zero_length_predicate(node.parent))
52
52
 
53
- lhs, opr, rhs = zero_length_predicate
53
+ offense = node.loc.selector.join(node.parent.source_range.end)
54
+ message = format(ZERO_MSG, current: "#{length_method}.zero?")
55
+
56
+ add_offense(offense, message: message) do |corrector|
57
+ corrector.replace(offense, 'empty?')
58
+ end
59
+ end
60
+
61
+ def check_zero_length_comparison(node)
62
+ zero_length_comparison = zero_length_comparison(node.parent)
63
+ return unless zero_length_comparison
64
+
65
+ lhs, opr, rhs = zero_length_comparison
54
66
 
55
67
  return if non_polymorphic_collection?(node.parent)
56
68
 
57
69
  add_offense(
58
- node.parent, message: format(ZERO_MSG, lhs: lhs, opr: opr, rhs: rhs)
70
+ node.parent, message: format(ZERO_MSG, current: "#{lhs} #{opr} #{rhs}")
59
71
  ) do |corrector|
60
72
  corrector.replace(node.parent, replacement(node.parent))
61
73
  end
62
74
  end
63
75
 
64
- def check_nonzero_length_predicate(node)
65
- nonzero_length_predicate = nonzero_length_predicate(node.parent)
66
- return unless nonzero_length_predicate
76
+ def check_nonzero_length_comparison(node)
77
+ nonzero_length_comparison = nonzero_length_comparison(node.parent)
78
+ return unless nonzero_length_comparison
67
79
 
68
- lhs, opr, rhs = nonzero_length_predicate
80
+ lhs, opr, rhs = nonzero_length_comparison
69
81
 
70
82
  return if non_polymorphic_collection?(node.parent)
71
83
 
72
84
  add_offense(
73
- node.parent, message: format(NONZERO_MSG, lhs: lhs, opr: opr, rhs: rhs)
85
+ node.parent, message: format(NONZERO_MSG, current: "#{lhs} #{opr} #{rhs}")
74
86
  ) do |corrector|
75
87
  corrector.replace(node.parent, replacement(node.parent))
76
88
  end
@@ -78,14 +90,19 @@ module RuboCop
78
90
 
79
91
  # @!method zero_length_predicate(node)
80
92
  def_node_matcher :zero_length_predicate, <<~PATTERN
93
+ (send (send (...) ${:length :size}) :zero?)
94
+ PATTERN
95
+
96
+ # @!method zero_length_comparison(node)
97
+ def_node_matcher :zero_length_comparison, <<~PATTERN
81
98
  {(send (send (...) ${:length :size}) $:== (int $0))
82
99
  (send (int $0) $:== (send (...) ${:length :size}))
83
100
  (send (send (...) ${:length :size}) $:< (int $1))
84
101
  (send (int $1) $:> (send (...) ${:length :size}))}
85
102
  PATTERN
86
103
 
87
- # @!method nonzero_length_predicate(node)
88
- def_node_matcher :nonzero_length_predicate, <<~PATTERN
104
+ # @!method nonzero_length_comparison(node)
105
+ def_node_matcher :nonzero_length_comparison, <<~PATTERN
89
106
  {(send (send (...) ${:length :size}) ${:> :!=} (int $0))
90
107
  (send (int $0) ${:< :!=} (send (...) ${:length :size}))}
91
108
  PATTERN
@@ -10,20 +10,6 @@ module RuboCop
10
10
  # first the ones needed for autocorrection (if any), then the rest
11
11
  # (unless autocorrections happened).
12
12
  class Team
13
- attr_reader :errors, :warnings, :updated_source_file, :cops
14
-
15
- alias updated_source_file? updated_source_file
16
-
17
- def initialize(cops, config = nil, options = {})
18
- @cops = cops
19
- @config = config
20
- @options = options
21
- reset
22
- @ready = true
23
-
24
- validate_config
25
- end
26
-
27
13
  # @return [Team]
28
14
  def self.new(cop_or_classes, config, options = {})
29
15
  # Support v0 api:
@@ -47,6 +33,35 @@ module RuboCop
47
33
  end
48
34
  end
49
35
 
36
+ # @return [Array<Force>] needed for the given cops
37
+ def self.forces_for(cops)
38
+ needed = Hash.new { |h, k| h[k] = [] }
39
+ cops.each do |cop|
40
+ forces = cop.class.joining_forces
41
+ if forces.is_a?(Array)
42
+ forces.each { |force| needed[force] << cop }
43
+ elsif forces
44
+ needed[forces] << cop
45
+ end
46
+ end
47
+
48
+ needed.map { |force_class, joining_cops| force_class.new(joining_cops) }
49
+ end
50
+
51
+ attr_reader :errors, :warnings, :updated_source_file, :cops
52
+
53
+ alias updated_source_file? updated_source_file
54
+
55
+ def initialize(cops, config = nil, options = {})
56
+ @cops = cops
57
+ @config = config
58
+ @options = options
59
+ reset
60
+ @ready = true
61
+
62
+ validate_config
63
+ end
64
+
50
65
  def autocorrect?
51
66
  @options[:autocorrect]
52
67
  end
@@ -94,21 +109,6 @@ module RuboCop
94
109
  @forces ||= self.class.forces_for(cops)
95
110
  end
96
111
 
97
- # @return [Array<Force>] needed for the given cops
98
- def self.forces_for(cops)
99
- needed = Hash.new { |h, k| h[k] = [] }
100
- cops.each do |cop|
101
- forces = cop.class.joining_forces
102
- if forces.is_a?(Array)
103
- forces.each { |force| needed[force] << cop }
104
- elsif forces
105
- needed[forces] << cop
106
- end
107
- end
108
-
109
- needed.map { |force_class, joining_cops| force_class.new(joining_cops) }
110
- end
111
-
112
112
  def external_dependency_checksum
113
113
  keys = cops.map(&:external_dependency_checksum).compact
114
114
  Digest::SHA1.hexdigest(keys.join)
@@ -108,7 +108,6 @@ module RuboCop
108
108
  :skip_children
109
109
  end
110
110
 
111
- # rubocop:disable Layout/ClassStructure
112
111
  NODE_HANDLER_METHOD_NAMES = [
113
112
  [VARIABLE_ASSIGNMENT_TYPE, :process_variable_assignment],
114
113
  [REGEXP_NAMED_CAPTURE_TYPE, :process_regexp_named_captures],
@@ -123,8 +122,6 @@ module RuboCop
123
122
  *SCOPE_TYPES.product([:process_scope])
124
123
  ].to_h.freeze
125
124
  private_constant :NODE_HANDLER_METHOD_NAMES
126
- # rubocop:enable Layout/ClassStructure
127
-
128
125
  def node_handler_method_name(node)
129
126
  NODE_HANDLER_METHOD_NAMES[node.type]
130
127
  end
@@ -28,14 +28,19 @@ module RuboCop
28
28
  end
29
29
  end
30
30
 
31
+ SMART_PATH_CACHE = {} # rubocop:disable Style/MutableConstant
32
+ private_constant :SMART_PATH_CACHE
33
+
31
34
  def smart_path(path)
32
- # Ideally, we calculate this relative to the project root.
33
- base_dir = Dir.pwd
35
+ SMART_PATH_CACHE[path] ||= begin
36
+ # Ideally, we calculate this relative to the project root.
37
+ base_dir = Dir.pwd
34
38
 
35
- if path.start_with? base_dir
36
- relative_path(path, base_dir)
37
- else
38
- path
39
+ if path.start_with? base_dir
40
+ relative_path(path, base_dir)
41
+ else
42
+ path
43
+ end
39
44
  end
40
45
  end
41
46
 
@@ -46,7 +51,7 @@ module RuboCop
46
51
  matches =
47
52
  if pattern == path
48
53
  true
49
- elsif pattern.match?(/[*{\[?]/)
54
+ elsif glob?(pattern)
50
55
  File.fnmatch?(pattern, path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
51
56
  end
52
57
 
@@ -68,6 +73,11 @@ module RuboCop
68
73
  %r{\A([A-Z]:)?/}i.match?(path)
69
74
  end
70
75
 
76
+ # Returns true for a glob
77
+ def glob?(path)
78
+ path.match?(/[*{\[?]/)
79
+ end
80
+
71
81
  def hidden_file_in_not_hidden_dir?(pattern, path)
72
82
  hidden_file?(path) &&
73
83
  File.fnmatch?(
@@ -53,7 +53,7 @@ module RuboCop
53
53
  def remove_oldest_files(files, dirs, cache_root, verbose)
54
54
  # Add 1 to half the number of files, so that we remove the file if
55
55
  # there's only 1 left.
56
- remove_count = 1 + (files.length / 2)
56
+ remove_count = (files.length / 2) + 1
57
57
  puts "Removing the #{remove_count} oldest files from #{cache_root}" if verbose
58
58
  sorted = files.sort_by { |path| File.mtime(path) }
59
59
  remove_files(sorted, dirs, remove_count)
@@ -27,6 +27,11 @@ module RuboCop
27
27
  # @api private
28
28
  MAX_ITERATIONS = 200
29
29
 
30
+ # @api private
31
+ REDUNDANT_COP_DISABLE_DIRECTIVE_RULES = %w[
32
+ Lint/RedundantCopDisableDirective RedundantCopDisableDirective Lint
33
+ ].freeze
34
+
30
35
  attr_reader :errors, :warnings
31
36
  attr_writer :aborting
32
37
 
@@ -194,7 +199,9 @@ module RuboCop
194
199
  end
195
200
 
196
201
  def check_for_redundant_disables?(source)
197
- !source.disabled_line_ranges.empty? && !filtered_run?
202
+ return false if source.disabled_line_ranges.empty? || except_redundant_cop_disable_directive?
203
+
204
+ !@options[:only]
198
205
  end
199
206
 
200
207
  def redundant_cop_disable_directive(file)
@@ -205,8 +212,8 @@ module RuboCop
205
212
  yield cop if cop.relevant_file?(file)
206
213
  end
207
214
 
208
- def filtered_run?
209
- @options[:except] || @options[:only]
215
+ def except_redundant_cop_disable_directive?
216
+ @options[:except] && (@options[:except] & REDUNDANT_COP_DISABLE_DIRECTIVE_RULES).any?
210
217
  end
211
218
 
212
219
  def file_started(file)
@@ -244,7 +244,6 @@ module RuboCop
244
244
  ].freeze
245
245
 
246
246
  private_constant :SOURCES
247
-
248
247
  def initialize(config)
249
248
  @config = config
250
249
  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.41.1'
6
+ STRING = '1.43.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
@@ -399,6 +399,7 @@ require_relative 'rubocop/cop/lint/useless_access_modifier'
399
399
  require_relative 'rubocop/cop/lint/useless_assignment'
400
400
  require_relative 'rubocop/cop/lint/useless_else_without_rescue'
401
401
  require_relative 'rubocop/cop/lint/useless_method_definition'
402
+ require_relative 'rubocop/cop/lint/useless_rescue'
402
403
  require_relative 'rubocop/cop/lint/useless_ruby2_keywords'
403
404
  require_relative 'rubocop/cop/lint/useless_setter_call'
404
405
  require_relative 'rubocop/cop/lint/useless_times'
@@ -538,8 +539,10 @@ require_relative 'rubocop/cop/style/lambda_call'
538
539
  require_relative 'rubocop/cop/style/line_end_concatenation'
539
540
  require_relative 'rubocop/cop/style/magic_comment_format'
540
541
  require_relative 'rubocop/cop/style/map_to_hash'
542
+ require_relative 'rubocop/cop/style/map_to_set'
541
543
  require_relative 'rubocop/cop/style/method_call_without_args_parentheses'
542
544
  require_relative 'rubocop/cop/style/method_call_with_args_parentheses'
545
+ require_relative 'rubocop/cop/style/min_max_comparison'
543
546
  require_relative 'rubocop/cop/style/multiline_in_pattern_then'
544
547
  require_relative 'rubocop/cop/style/numbered_parameters'
545
548
  require_relative 'rubocop/cop/style/open_struct_use'
@@ -675,6 +678,7 @@ require_relative 'rubocop/cop/style/while_until_do'
675
678
  require_relative 'rubocop/cop/style/while_until_modifier'
676
679
  require_relative 'rubocop/cop/style/word_array'
677
680
  require_relative 'rubocop/cop/style/yoda_condition'
681
+ require_relative 'rubocop/cop/style/yoda_expression'
678
682
  require_relative 'rubocop/cop/style/zero_length_predicate'
679
683
 
680
684
  require_relative 'rubocop/cop/security/compound_hash'
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.41.1
4
+ version: 1.43.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-12-22 00:00:00.000000000 Z
13
+ date: 2023-01-10 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -46,14 +46,14 @@ dependencies:
46
46
  requirements:
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: 3.1.2.1
49
+ version: 3.2.0.0
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
54
  - - ">="
55
55
  - !ruby/object:Gem::Version
56
- version: 3.1.2.1
56
+ version: 3.2.0.0
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: rainbow
59
59
  requirement: !ruby/object:Gem::Requirement
@@ -120,7 +120,7 @@ dependencies:
120
120
  requirements:
121
121
  - - ">="
122
122
  - !ruby/object:Gem::Version
123
- version: 1.23.0
123
+ version: 1.24.1
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.23.0
133
+ version: 1.24.1
134
134
  - - "<"
135
135
  - !ruby/object:Gem::Version
136
136
  version: '2.0'
@@ -154,7 +154,7 @@ dependencies:
154
154
  requirements:
155
155
  - - ">="
156
156
  - !ruby/object:Gem::Version
157
- version: 1.4.0
157
+ version: 2.4.0
158
158
  - - "<"
159
159
  - !ruby/object:Gem::Version
160
160
  version: '3.0'
@@ -164,7 +164,7 @@ dependencies:
164
164
  requirements:
165
165
  - - ">="
166
166
  - !ruby/object:Gem::Version
167
- version: 1.4.0
167
+ version: 2.4.0
168
168
  - - "<"
169
169
  - !ruby/object:Gem::Version
170
170
  version: '3.0'
@@ -539,6 +539,7 @@ files:
539
539
  - lib/rubocop/cop/lint/useless_assignment.rb
540
540
  - lib/rubocop/cop/lint/useless_else_without_rescue.rb
541
541
  - lib/rubocop/cop/lint/useless_method_definition.rb
542
+ - lib/rubocop/cop/lint/useless_rescue.rb
542
543
  - lib/rubocop/cop/lint/useless_ruby2_keywords.rb
543
544
  - lib/rubocop/cop/lint/useless_setter_call.rb
544
545
  - lib/rubocop/cop/lint/useless_times.rb
@@ -760,6 +761,7 @@ files:
760
761
  - lib/rubocop/cop/style/magic_comment_format.rb
761
762
  - lib/rubocop/cop/style/map_compact_with_conditional_block.rb
762
763
  - lib/rubocop/cop/style/map_to_hash.rb
764
+ - lib/rubocop/cop/style/map_to_set.rb
763
765
  - lib/rubocop/cop/style/method_call_with_args_parentheses.rb
764
766
  - lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb
765
767
  - lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb
@@ -767,6 +769,7 @@ files:
767
769
  - lib/rubocop/cop/style/method_called_on_do_end_block.rb
768
770
  - lib/rubocop/cop/style/method_def_parentheses.rb
769
771
  - lib/rubocop/cop/style/min_max.rb
772
+ - lib/rubocop/cop/style/min_max_comparison.rb
770
773
  - lib/rubocop/cop/style/missing_else.rb
771
774
  - lib/rubocop/cop/style/missing_respond_to_missing.rb
772
775
  - lib/rubocop/cop/style/mixin_grouping.rb
@@ -898,6 +901,7 @@ files:
898
901
  - lib/rubocop/cop/style/while_until_modifier.rb
899
902
  - lib/rubocop/cop/style/word_array.rb
900
903
  - lib/rubocop/cop/style/yoda_condition.rb
904
+ - lib/rubocop/cop/style/yoda_expression.rb
901
905
  - lib/rubocop/cop/style/zero_length_predicate.rb
902
906
  - lib/rubocop/cop/team.rb
903
907
  - lib/rubocop/cop/util.rb
@@ -992,7 +996,7 @@ metadata:
992
996
  homepage_uri: https://rubocop.org/
993
997
  changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
994
998
  source_code_uri: https://github.com/rubocop/rubocop/
995
- documentation_uri: https://docs.rubocop.org/rubocop/1.41/
999
+ documentation_uri: https://docs.rubocop.org/rubocop/1.43/
996
1000
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
997
1001
  rubygems_mfa_required: 'true'
998
1002
  post_install_message: