rubocop 1.24.1 → 1.25.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2e7d2cbe48c6ff81a071b353132db29ed017af57a32bcd142038e2e551f3a5b
4
- data.tar.gz: 8ae72a3ce8b6ab13b4d451bbdb1dbcdf54f898711a3009dae81450a49fb037e0
3
+ metadata.gz: 0e565e6065561954dc1aa6db221e2f6cf7753a96b40bf863a571243a2b567d84
4
+ data.tar.gz: e489fdb8174dcc6f755ae18bf57091188808e3649db33ae0c282c507b0ec4f54
5
5
  SHA512:
6
- metadata.gz: d868781732056622d0f5157a50553c0b521f81f2ca14d2ede65b4c7372ef0e3b89be5146db8664fac5b28a39c82be52fc297a43d8280647b1b7426ce9ee87337
7
- data.tar.gz: e3d8f4dc8ab53859197eb3f05c62290cf72ba11c7e742869d619d6c4564e28f5c0fc70e4e15f90fc4f9bfe2d46cafdeedde8aa16d982adfc7d6eb482f7d20093
6
+ metadata.gz: 2c01d7352515c439403d4f479583d4099f4ac339ab8a26503ad6b6fd90db54d5a4bcddd6fc2d2e48f3de8faf2928f0f0930c938a5b22a7cfe1759199f68e873a
7
+ data.tar.gz: 3075cb42f837c728c31a936ddf1a61ba5d6aafcae9a984a97d05a519089ef7b9c4ff164cf9e3d45e1cd0ab6505a2348f4870bb6c0044e011c45eae04de123e45
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-21 Bozhidar Batsov
1
+ Copyright (c) 2012-22 Bozhidar Batsov
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
53
53
  in your `Gemfile`:
54
54
 
55
55
  ```rb
56
- gem 'rubocop', '~> 1.24', require: false
56
+ gem 'rubocop', '~> 1.25', require: false
57
57
  ```
58
58
 
59
59
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
@@ -244,5 +244,5 @@ RuboCop's changelog is available [here](CHANGELOG.md).
244
244
 
245
245
  ## Copyright
246
246
 
247
- Copyright (c) 2012-2021 Bozhidar Batsov. See [LICENSE.txt](LICENSE.txt) for
247
+ Copyright (c) 2012-2022 Bozhidar Batsov. See [LICENSE.txt](LICENSE.txt) for
248
248
  further details.
data/config/default.yml CHANGED
@@ -2496,6 +2496,7 @@ Naming/BlockForwarding:
2496
2496
  SupportedStyles:
2497
2497
  - anonymous
2498
2498
  - explicit
2499
+ BlockForwardingName: block
2499
2500
 
2500
2501
  Naming/BlockParameterName:
2501
2502
  Description: >-
@@ -3698,6 +3699,8 @@ Style/HashSyntax:
3698
3699
  - always
3699
3700
  # forces use of explicit hash literal value.
3700
3701
  - never
3702
+ # accepts both shorthand and explicit use of hash literal value.
3703
+ - either
3701
3704
  # Force hashes that have a symbol value to use hash rockets
3702
3705
  UseHashRocketsWithSymbolValues: false
3703
3706
  # Do not suggest { a?: 1 } over { :a? => 1 } in ruby19 style
@@ -68,8 +68,11 @@ module RuboCop
68
68
 
69
69
  # @!method defined_ruby_version(node)
70
70
  def_node_matcher :defined_ruby_version, <<~PATTERN
71
- {$(str _) $(array (str _) (str _))
72
- (send (const (const nil? :Gem) :Requirement) :new $(str _))}
71
+ {
72
+ $(str _)
73
+ $(array (str _) (str _))
74
+ (send (const (const nil? :Gem) :Requirement) :new $str+)
75
+ }
73
76
  PATTERN
74
77
 
75
78
  def on_new_investigation
@@ -97,7 +100,11 @@ module RuboCop
97
100
  def extract_ruby_version(required_ruby_version)
98
101
  return unless required_ruby_version
99
102
 
100
- if required_ruby_version.array_type?
103
+ if required_ruby_version.is_a?(Array)
104
+ required_ruby_version = required_ruby_version.detect do |v|
105
+ /[>=]/.match?(v.str_content)
106
+ end
107
+ elsif required_ruby_version.array_type?
101
108
  required_ruby_version = required_ruby_version.children.detect do |v|
102
109
  /[>=]/.match?(v.str_content)
103
110
  end
@@ -182,7 +182,8 @@ module RuboCop
182
182
  end
183
183
 
184
184
  def generate(template)
185
- format(template, department: badge.department, cop_name: badge.cop_name)
185
+ format(template, department: badge.department.to_s.gsub('/', '::'),
186
+ cop_name: badge.cop_name)
186
187
  end
187
188
 
188
189
  def spec_path
@@ -209,8 +210,8 @@ module RuboCop
209
210
  return 'rspec' if camel_case_string == 'RSpec'
210
211
 
211
212
  camel_case_string
212
- .gsub(/([^A-Z])([A-Z]+)/, '\1_\2')
213
- .gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2')
213
+ .gsub(%r{([^A-Z/])([A-Z]+)}, '\1_\2')
214
+ .gsub(%r{([A-Z])([A-Z][^A-Z\d/]+)}, '\1_\2')
214
215
  .downcase
215
216
  end
216
217
  end
@@ -53,23 +53,50 @@ module RuboCop
53
53
  'following the first line of a multi-line method call.'
54
54
 
55
55
  def on_send(node)
56
- first_arg = node.first_argument
57
- return if !multiple_arguments?(node, first_arg) || (node.send_type? && node.method?(:[]=))
56
+ return if !multiple_arguments?(node) || (node.send_type? && node.method?(:[]=))
58
57
 
59
- if first_arg.hash_type? && !first_arg.braces?
60
- pairs = first_arg.pairs
61
- check_alignment(pairs, base_column(node, pairs.first))
62
- else
63
- check_alignment(node.arguments, base_column(node, first_arg))
64
- end
58
+ items = flattened_arguments(node)
59
+
60
+ check_alignment(items, base_column(node, items.first))
65
61
  end
62
+
66
63
  alias on_csend on_send
67
64
 
68
65
  private
69
66
 
70
- def multiple_arguments?(node, first_argument)
67
+ def flattened_arguments(node)
68
+ if fixed_indentation?
69
+ arguments_with_last_arg_pairs(node)
70
+ else
71
+ arguments_or_first_arg_pairs(node)
72
+ end
73
+ end
74
+
75
+ def arguments_with_last_arg_pairs(node)
76
+ items = node.arguments[0..-2]
77
+ last_arg = node.arguments.last
78
+
79
+ if last_arg.hash_type? && !last_arg.braces?
80
+ items += last_arg.pairs
81
+ else
82
+ items << last_arg
83
+ end
84
+ items
85
+ end
86
+
87
+ def arguments_or_first_arg_pairs(node)
88
+ first_arg = node.first_argument
89
+ if first_arg.hash_type? && !first_arg.braces?
90
+ first_arg.pairs
91
+ else
92
+ node.arguments
93
+ end
94
+ end
95
+
96
+ def multiple_arguments?(node)
71
97
  return true if node.arguments.size >= 2
72
98
 
99
+ first_argument = node.first_argument
73
100
  first_argument&.hash_type? && first_argument.pairs.count >= 2
74
101
  end
75
102
 
@@ -30,7 +30,11 @@ module RuboCop
30
30
 
31
31
  def on_new_investigation
32
32
  processed_source.diagnostics.each do |diagnostic|
33
- next unless diagnostic.reason == :ambiguous_literal
33
+ if target_ruby_version >= 3.0
34
+ next unless diagnostic.reason == :ambiguous_regexp
35
+ else
36
+ next unless diagnostic.reason == :ambiguous_literal
37
+ end
34
38
 
35
39
  offense_node = find_offense_node_by(diagnostic)
36
40
 
@@ -33,11 +33,12 @@ module RuboCop
33
33
  # @!method io_select(node)
34
34
  def_node_matcher :io_select, <<~PATTERN
35
35
  (send
36
- (const {nil? cbase} :IO) :select $_ $_ {(array) nil} $...)
36
+ (const {nil? cbase} :IO) :select $...)
37
37
  PATTERN
38
38
 
39
39
  def on_send(node)
40
- return unless (read, write, timeout = io_select(node))
40
+ read, write, _excepts, timeout = *io_select(node)
41
+ return unless read
41
42
  return unless scheduler_compatible?(read, write) || scheduler_compatible?(write, read)
42
43
 
43
44
  preferred = preferred_method(read, write, timeout)
@@ -51,13 +52,13 @@ module RuboCop
51
52
  private
52
53
 
53
54
  def scheduler_compatible?(io1, io2)
54
- return false unless io1.array_type? && io1.values.size == 1
55
+ return false unless io1&.array_type? && io1.values.size == 1
55
56
 
56
- io2.array_type? ? io2.values.empty? : io2.nil_type?
57
+ io2&.array_type? ? io2.values.empty? : (io2.nil? || io2.nil_type?)
57
58
  end
58
59
 
59
60
  def preferred_method(read, write, timeout)
60
- timeout_argument = timeout.empty? ? '' : "(#{timeout[0].source})"
61
+ timeout_argument = timeout.nil? ? '' : "(#{timeout.source})"
61
62
 
62
63
  if read.array_type? && read.values[0]
63
64
  "#{read.values[0].source}.wait_readable#{timeout_argument}"
@@ -8,7 +8,7 @@ module RuboCop
8
8
  EXPLICIT_HASH_VALUE_MSG = 'Explicit the hash value.'
9
9
 
10
10
  def on_pair(node)
11
- return if target_ruby_version <= 3.0
11
+ return if target_ruby_version <= 3.0 || enforced_shorthand_syntax == 'either'
12
12
 
13
13
  hash_key_source = node.key.source
14
14
 
@@ -46,10 +46,22 @@ module RuboCop
46
46
 
47
47
  def without_parentheses_call_expr_follows?(node)
48
48
  return false unless (ancestor = node.parent.parent)
49
- return false unless (right_sibling = ancestor.right_sibling)
50
49
 
51
- ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized? &&
52
- right_sibling.respond_to?(:parenthesized?) && !right_sibling.parenthesized?
50
+ right_sibling = ancestor.right_sibling
51
+
52
+ return true if right_sibling.nil? && without_parentheses?(ancestor)
53
+ return false unless right_sibling
54
+ return true if node_with_block_and_arguments?(right_sibling)
55
+
56
+ without_parentheses?(ancestor) && without_parentheses?(right_sibling)
57
+ end
58
+
59
+ def without_parentheses?(node)
60
+ node.respond_to?(:parenthesized?) && !node.parenthesized?
61
+ end
62
+
63
+ def node_with_block_and_arguments?(node)
64
+ node.respond_to?(:block_type?) && node.block_type? && node.children&.first&.arguments?
53
65
  end
54
66
  end
55
67
  end
@@ -9,6 +9,9 @@ module RuboCop
9
9
  # by `do_something(&)`.
10
10
  #
11
11
  # It also supports the opposite style by alternative `explicit` option.
12
+ # You can specify the block variable name for auto-correction with `BlockForwardingName`.
13
+ # The default variable name is `block`. If the name is already in use, it will not be
14
+ # auto-corrected.
12
15
  #
13
16
  # @example EnforcedStyle: anonymous (default)
14
17
  #
@@ -50,12 +53,13 @@ module RuboCop
50
53
  last_argument = node.arguments.last
51
54
  return if expected_block_forwarding_style?(node, last_argument)
52
55
 
53
- register_offense(last_argument)
56
+ register_offense(last_argument, node)
54
57
 
55
58
  node.each_descendant(:block_pass) do |block_pass_node|
56
- next if block_pass_node.children.first&.sym_type?
59
+ next if block_pass_node.children.first&.sym_type? ||
60
+ last_argument.source != block_pass_node.source
57
61
 
58
- register_offense(block_pass_node)
62
+ register_offense(block_pass_node, node)
59
63
  end
60
64
  end
61
65
  alias on_defs on_def
@@ -66,7 +70,7 @@ module RuboCop
66
70
  if style == :anonymous
67
71
  !explicit_block_argument?(last_argument) ||
68
72
  use_kwarg_in_method_definition?(node) ||
69
- use_block_argument_as_local_variable?(node, last_argument)
73
+ use_block_argument_as_local_variable?(node, last_argument.source[1..-1])
70
74
  else
71
75
  !anonymous_block_argument?(last_argument)
72
76
  end
@@ -84,22 +88,32 @@ module RuboCop
84
88
  node.blockarg_type? && !node.name.nil?
85
89
  end
86
90
 
91
+ def register_offense(block_argument, node)
92
+ add_offense(block_argument, message: format(MSG, style: style)) do |corrector|
93
+ if style == :anonymous
94
+ corrector.replace(block_argument, '&')
95
+
96
+ arguments = block_argument.parent
97
+
98
+ add_parentheses(arguments, corrector) unless arguments.parenthesized_call?
99
+ else
100
+ unless use_block_argument_as_local_variable?(node, block_forwarding_name)
101
+ corrector.replace(block_argument, "&#{block_forwarding_name}")
102
+ end
103
+ end
104
+ end
105
+ end
106
+
87
107
  def use_block_argument_as_local_variable?(node, last_argument)
88
108
  return if node.body.nil?
89
109
 
90
110
  node.body.each_descendant(:lvar).any? do |lvar|
91
- !lvar.parent.block_pass_type? && lvar.source == last_argument.source[1..-1]
111
+ !lvar.parent.block_pass_type? && lvar.source == last_argument
92
112
  end
93
113
  end
94
114
 
95
- def register_offense(block_argument)
96
- add_offense(block_argument, message: format(MSG, style: style)) do |corrector|
97
- corrector.replace(block_argument, '&')
98
-
99
- arguments = block_argument.parent
100
-
101
- add_parentheses(arguments, corrector) unless arguments.parenthesized_call?
102
- end
115
+ def block_forwarding_name
116
+ cop_config.fetch('BlockForwardingName', 'block')
103
117
  end
104
118
  end
105
119
  end
@@ -41,7 +41,7 @@ module RuboCop
41
41
 
42
42
  # @!method reject_method_with_block_pass?(node)
43
43
  def_node_matcher :reject_method_with_block_pass?, <<~PATTERN
44
- (send _ {:reject :reject!}
44
+ (send !nil? {:reject :reject!}
45
45
  (block_pass
46
46
  (sym :nil?)))
47
47
  PATTERN
@@ -50,7 +50,7 @@ module RuboCop
50
50
  def_node_matcher :reject_method?, <<~PATTERN
51
51
  (block
52
52
  (send
53
- _ {:reject :reject!})
53
+ !nil? {:reject :reject!})
54
54
  $(args ...)
55
55
  (send
56
56
  $(lvar _) :nil?))
@@ -60,7 +60,7 @@ module RuboCop
60
60
  def_node_matcher :select_method?, <<~PATTERN
61
61
  (block
62
62
  (send
63
- _ {:select :select!})
63
+ !nil? {:select :select!})
64
64
  $(args ...)
65
65
  (send
66
66
  (send
@@ -23,6 +23,12 @@ module RuboCop
23
23
  # It can enforce either the use of the explicit hash value syntax or
24
24
  # the use of Ruby 3.1's hash value shorthand syntax.
25
25
  #
26
+ # The supported styles are:
27
+ #
28
+ # * always - forces use of the 3.1 syntax (e.g. {foo:})
29
+ # * never - forces use of explicit hash literal value
30
+ # * either - accepts both shorthand and explicit use of hash literal value
31
+ #
26
32
  # @example EnforcedStyle: ruby19 (default)
27
33
  # # bad
28
34
  # {:a => 2}
@@ -75,6 +81,14 @@ module RuboCop
75
81
  # # good
76
82
  # {foo: foo, bar: bar}
77
83
  #
84
+ # @example EnforcedShorthandSyntax: either
85
+ #
86
+ # # good
87
+ # {foo: foo, bar: bar}
88
+ #
89
+ # # good
90
+ # {foo:, bar:}
91
+ #
78
92
  class HashSyntax < Base
79
93
  include ConfigurableEnforcedStyle
80
94
  include HashShorthandSyntax
@@ -36,7 +36,7 @@ module RuboCop
36
36
  # # good (but potentially an unsafe correction)
37
37
  # foo.do_something?
38
38
  #
39
- # @example AllowedMethods: ['nonzero?']
39
+ # @example AllowedMethods: ['nonzero?'] (default)
40
40
  # # good
41
41
  # num.nonzero? ? true : false
42
42
  #
@@ -51,11 +51,12 @@ module RuboCop
51
51
  # Require hash value omission be enclosed in parentheses to prevent the following issue:
52
52
  # https://bugs.ruby-lang.org/issues/18396.
53
53
  def require_parentheses_for_hash_value_omission?(node)
54
- return unless (last_argument = node.last_argument)
54
+ return false unless (last_argument = node.last_argument)
55
55
 
56
- return false unless (right_sibling = node.right_sibling)
56
+ next_line = node.parent&.assignment? ? node.parent.right_sibling : node.right_sibling
57
+ return false unless next_line
57
58
 
58
- last_argument.hash_type? && last_argument.pairs.last&.value_omission? && right_sibling
59
+ last_argument.hash_type? && last_argument.pairs.last&.value_omission? && next_line
59
60
  end
60
61
 
61
62
  def syntax_like_method_call?(node)
@@ -47,7 +47,7 @@ module RuboCop
47
47
  # allowed when forwarding arguments with the triple-dot syntax introduced
48
48
  # in Ruby 2.7 as omitting them starts an endless range.
49
49
  # And Ruby 3.1's hash omission syntax has a case that requires parentheses
50
- # because the issue https://bugs.ruby-lang.org/issues/18396.
50
+ # because of the following issue: https://bugs.ruby-lang.org/issues/18396.
51
51
  #
52
52
  # @example EnforcedStyle: require_parentheses (default)
53
53
  #
@@ -91,11 +91,12 @@ module RuboCop
91
91
  second.int_type? ? second.to_a.first : :unknown
92
92
  end
93
93
 
94
- def range_size(range_node) # rubocop:todo Metrics/CyclomaticComplexity
94
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
95
+ def range_size(range_node)
95
96
  vals = range_node.to_a
96
- return :unknown unless vals.all?(&:int_type?)
97
+ return :unknown unless vals.all? { |val| val.nil? || val.int_type? }
97
98
 
98
- low, high = vals.map { |val| val.children[0] }
99
+ low, high = vals.map { |val| val.nil? ? 0 : val.children[0] }
99
100
  return :unknown unless low.zero? && high >= 0
100
101
 
101
102
  case range_node.type
@@ -105,6 +106,7 @@ module RuboCop
105
106
  (low..high).size
106
107
  end
107
108
  end
109
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
108
110
 
109
111
  def source_range(shuffle_node, node)
110
112
  Parser::Source::Range.new(shuffle_node.source_range.source_buffer,
@@ -67,7 +67,10 @@ module RuboCop
67
67
  MSG_COMPLEX = '%<command>s parentheses for ternary expressions with complex conditions.'
68
68
 
69
69
  def on_if(node)
70
- return if only_closing_parenthesis_is_last_line?(node.condition)
70
+ condition = node.condition
71
+
72
+ return if only_closing_parenthesis_is_last_line?(condition)
73
+ return if condition_as_parenthesized_one_line_pattern_matching?(condition)
71
74
  return unless node.ternary? && !infinite_loop? && offense?(node)
72
75
 
73
76
  message = message(node)
@@ -77,11 +80,22 @@ module RuboCop
77
80
  end
78
81
  end
79
82
 
83
+ private
84
+
80
85
  def only_closing_parenthesis_is_last_line?(condition)
81
86
  condition.source.split("\n").last == ')'
82
87
  end
83
88
 
84
- private
89
+ def condition_as_parenthesized_one_line_pattern_matching?(condition)
90
+ return false unless condition.parenthesized_call?
91
+ return false unless (first_child = condition.children.first)
92
+
93
+ if target_ruby_version >= 3.0
94
+ first_child.match_pattern_p_type?
95
+ else
96
+ first_child.match_pattern_type? # For Ruby 2.7's one line pattern matching AST.
97
+ end
98
+ end
85
99
 
86
100
  def autocorrect(corrector, node)
87
101
  condition = node.condition
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.24.1'
6
+ STRING = '1.25.0'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, '\
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
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.24.1
4
+ version: 1.25.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: 2021-12-31 00:00:00.000000000 Z
13
+ date: 2022-01-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: parallel
@@ -32,14 +32,14 @@ dependencies:
32
32
  requirements:
33
33
  - - ">="
34
34
  - !ruby/object:Gem::Version
35
- version: 3.0.0.0
35
+ version: 3.1.0.0
36
36
  type: :runtime
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 3.0.0.0
42
+ version: 3.1.0.0
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: rainbow
45
45
  requirement: !ruby/object:Gem::Requirement
@@ -911,7 +911,7 @@ metadata:
911
911
  homepage_uri: https://rubocop.org/
912
912
  changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
913
913
  source_code_uri: https://github.com/rubocop/rubocop/
914
- documentation_uri: https://docs.rubocop.org/rubocop/1.24/
914
+ documentation_uri: https://docs.rubocop.org/rubocop/1.25/
915
915
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
916
916
  rubygems_mfa_required: 'true'
917
917
  post_install_message: