rubocop 1.24.1 → 1.25.1

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: 54b88752efa8bb84dc034391460b9071f31179dcb279550a209d31829e7b8c93
4
+ data.tar.gz: 31115cff5fdbf562dee62cf7e07033205d150b61ac5fd11476708f21e67000cf
5
5
  SHA512:
6
- metadata.gz: d868781732056622d0f5157a50553c0b521f81f2ca14d2ede65b4c7372ef0e3b89be5146db8664fac5b28a39c82be52fc297a43d8280647b1b7426ce9ee87337
7
- data.tar.gz: e3d8f4dc8ab53859197eb3f05c62290cf72ba11c7e742869d619d6c4564e28f5c0fc70e4e15f90fc4f9bfe2d46cafdeedde8aa16d982adfc7d6eb482f7d20093
6
+ metadata.gz: acdaf069659a775853b20e05734e85cd65c0c8734b09e568d4360dc9a7440a49ec8e47928b0da78866e1326a588638d18f2564e6e94023bb17b2f39493555027
7
+ data.tar.gz: 2765d9c9c10966c485be6cd70190b69a25aa99800c8d483bd67c1fdfe3dc5d13bb97cb1ca7f9f663776869acda5a426bc797f3b40adda17e0241ff8b62a374f1
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
@@ -430,13 +430,13 @@ Layout/ClassStructure:
430
430
  - prepend
431
431
  - extend
432
432
  ExpectedOrder:
433
- - module_inclusion
434
- - constants
435
- - public_class_methods
436
- - initializer
437
- - public_methods
438
- - protected_methods
439
- - private_methods
433
+ - module_inclusion
434
+ - constants
435
+ - public_class_methods
436
+ - initializer
437
+ - public_methods
438
+ - protected_methods
439
+ - private_methods
440
440
 
441
441
  Layout/ClosingHeredocIndentation:
442
442
  Description: 'Checks the indentation of here document closings.'
@@ -1900,7 +1900,7 @@ Lint/NestedPercentLiteral:
1900
1900
  VersionAdded: '0.52'
1901
1901
 
1902
1902
  Lint/NextWithoutAccumulator:
1903
- Description: >-
1903
+ Description: >-
1904
1904
  Do not omit the accumulator when calling `next`
1905
1905
  in a `reduce`/`inject` block.
1906
1906
  Enabled: true
@@ -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: >-
@@ -3152,7 +3153,7 @@ Style/ClassMethodsDefinitions:
3152
3153
  StyleGuide: '#def-self-class-methods'
3153
3154
  Enabled: false
3154
3155
  VersionAdded: '0.89'
3155
- EnforcedStyle: def_self
3156
+ EnforcedStyle: def_self
3156
3157
  SupportedStyles:
3157
3158
  - def_self
3158
3159
  - self_class
@@ -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
@@ -3812,8 +3815,8 @@ Style/InverseMethods:
3812
3815
  :>: :<=
3813
3816
  # `ActiveSupport` defines some common inverse methods. They are listed below,
3814
3817
  # and not enabled by default.
3815
- #:present?: :blank?,
3816
- #:include?: :exclude?
3818
+ # :present?: :blank?,
3819
+ # :include?: :exclude?
3817
3820
  # `InverseBlocks` are methods that are inverted by inverting the return
3818
3821
  # of the block that is passed to the method
3819
3822
  InverseBlocks:
@@ -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
 
@@ -81,7 +81,7 @@ module RuboCop
81
81
 
82
82
  locations.each do |loc|
83
83
  line = loc.line
84
- next if line == line_of_def_or_kwbegin
84
+ next if line == line_of_def_or_kwbegin || last_rescue_and_end_on_same_line(body)
85
85
 
86
86
  keyword = loc.source
87
87
  # below the keyword
@@ -91,6 +91,10 @@ module RuboCop
91
91
  end
92
92
  end
93
93
 
94
+ def last_rescue_and_end_on_same_line(body)
95
+ body.rescue_type? && body.resbody_branches.last.loc.line == body.parent.loc.end.line
96
+ end
97
+
94
98
  def message(location, keyword)
95
99
  format(MSG, location: location, keyword: keyword)
96
100
  end
@@ -222,11 +222,16 @@ module RuboCop
222
222
  node.pairs.any? &&
223
223
  node.parent&.call_type?
224
224
 
225
+ left_sibling = argument_before_hash(node)
225
226
  parent_loc = node.parent.loc
226
- selector = parent_loc.selector || parent_loc.expression
227
+ selector = left_sibling || parent_loc.selector || parent_loc.expression
227
228
  same_line?(selector, node.pairs.first)
228
229
  end
229
230
 
231
+ def argument_before_hash(hash_node)
232
+ hash_node.left_sibling.respond_to?(:loc) ? hash_node.left_sibling : nil
233
+ end
234
+
230
235
  def reset!
231
236
  self.offenses_by = {}
232
237
  self.column_deltas = Hash.new { |hash, key| hash[key] = {} }
@@ -143,7 +143,7 @@ module RuboCop
143
143
  return true
144
144
  end
145
145
 
146
- do_keyword_line == selector.line && rescue_keyword_column == selector.column
146
+ do_keyword_line == selector&.line && rescue_keyword_column == selector.column
147
147
  end
148
148
 
149
149
  def aligned_with_leading_dot?(do_keyword_line, send_node_loc, rescue_keyword_column)
@@ -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 ignore_hash_shorthand_syntax?(node)
12
12
 
13
13
  hash_key_source = node.key.source
14
14
 
@@ -31,12 +31,17 @@ module RuboCop
31
31
 
32
32
  private
33
33
 
34
+ def ignore_hash_shorthand_syntax?(pair_node)
35
+ target_ruby_version <= 3.0 || enforced_shorthand_syntax == 'either' ||
36
+ !pair_node.parent.hash_type?
37
+ end
38
+
34
39
  def enforced_shorthand_syntax
35
40
  cop_config.fetch('EnforcedShorthandSyntax', 'always')
36
41
  end
37
42
 
38
43
  def require_hash_value?(hash_key_source, node)
39
- return true if without_parentheses_call_expr_follows?(node)
44
+ return true if require_hash_value_for_around_hash_literal?(node)
40
45
 
41
46
  hash_value = node.value
42
47
  return true unless hash_value.send_type? || hash_value.lvar_type?
@@ -44,12 +49,33 @@ module RuboCop
44
49
  hash_key_source != hash_value.source || hash_key_source.end_with?('!', '?')
45
50
  end
46
51
 
47
- def without_parentheses_call_expr_follows?(node)
52
+ def require_hash_value_for_around_hash_literal?(node)
48
53
  return false unless (ancestor = node.parent.parent)
49
- return false unless (right_sibling = ancestor.right_sibling)
54
+ return false if ancestor.send_type? && ancestor.method?(:[])
55
+
56
+ !node.parent.braces? && !use_element_of_hash_literal_as_receiver?(ancestor, node.parent) &&
57
+ (use_modifier_form_without_parenthesized_method_call?(ancestor) ||
58
+ without_parentheses_call_expr_follows?(ancestor))
59
+ end
60
+
61
+ def use_element_of_hash_literal_as_receiver?(ancestor, parent)
62
+ # `{value:}.do_something` is a valid syntax.
63
+ ancestor.send_type? && ancestor.receiver == parent
64
+ end
65
+
66
+ def use_modifier_form_without_parenthesized_method_call?(ancestor)
67
+ return false if ancestor.respond_to?(:parenthesized?) && ancestor.parenthesized?
68
+ return false unless (parent = ancestor.parent)
69
+
70
+ parent.respond_to?(:modifier_form?) && parent.modifier_form?
71
+ end
72
+
73
+ def without_parentheses_call_expr_follows?(ancestor)
74
+ right_sibling = ancestor.right_sibling
75
+ right_sibling ||= ancestor.each_ancestor.find(&:assignment?)&.right_sibling
76
+ return false unless right_sibling
50
77
 
51
- ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized? &&
52
- right_sibling.respond_to?(:parenthesized?) && !right_sibling.parenthesized?
78
+ ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized? && !!right_sibling
53
79
  end
54
80
  end
55
81
  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
@@ -26,7 +26,7 @@ module RuboCop
26
26
  # num1 * num2
27
27
  # end
28
28
  #
29
- # # With `MinArgNameLength` set to number greater than 1
29
+ # # With `MinNameLength` set to number greater than 1
30
30
  # def baz(a, b, c)
31
31
  # do_stuff(a, b, c)
32
32
  # 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
  #
@@ -48,14 +48,21 @@ module RuboCop
48
48
  node.each_ancestor(:def, :defs).any?(&:endless?) && node.arguments.any?
49
49
  end
50
50
 
51
- # Require hash value omission be enclosed in parentheses to prevent the following issue:
52
- # https://bugs.ruby-lang.org/issues/18396.
53
51
  def require_parentheses_for_hash_value_omission?(node)
54
- return unless (last_argument = node.last_argument)
52
+ return false unless (last_argument = node.last_argument)
53
+ return false if !last_argument.hash_type? || !last_argument.pairs.last&.value_omission?
55
54
 
56
- return false unless (right_sibling = node.right_sibling)
55
+ modifier_form?(node) || exist_next_line_expression?(node)
56
+ end
57
57
 
58
- last_argument.hash_type? && last_argument.pairs.last&.value_omission? && right_sibling
58
+ def modifier_form?(node)
59
+ node.parent.respond_to?(:modifier_form?) && node.parent.modifier_form?
60
+ end
61
+
62
+ # Require hash value omission be enclosed in parentheses to prevent the following issue:
63
+ # https://bugs.ruby-lang.org/issues/18396.
64
+ def exist_next_line_expression?(node)
65
+ node.parent&.assignment? ? node.parent.right_sibling : node.right_sibling
59
66
  end
60
67
 
61
68
  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
  #
@@ -97,7 +97,7 @@ module RuboCop
97
97
  offense_range = node.loc.begin
98
98
 
99
99
  add_offense(offense_range) do |corrector|
100
- if any_ancestor_assignment_node?(node)
100
+ if node.parent&.assignment?
101
101
  replace_begin_with_statement(corrector, offense_range, node)
102
102
  else
103
103
  corrector.remove(offense_range)
@@ -170,11 +170,7 @@ module RuboCop
170
170
  end
171
171
 
172
172
  def valid_begin_assignment?(node)
173
- any_ancestor_assignment_node?(node) && !node.children.one?
174
- end
175
-
176
- def any_ancestor_assignment_node?(node)
177
- node.each_ancestor.any?(&:assignment?)
173
+ node.parent&.assignment? && !node.children.one?
178
174
  end
179
175
  end
180
176
  end
@@ -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,
@@ -58,6 +58,8 @@ module RuboCop
58
58
  end
59
59
 
60
60
  def simple_assignment?(node)
61
+ return false unless node.respond_to?(:type)
62
+
61
63
  SIMPLE_ASSIGNMENT_TYPES.include?(node.type)
62
64
  end
63
65
 
@@ -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
@@ -121,9 +121,14 @@ module RuboCop
121
121
  output_buffer.puts "# Offense count: #{offense_count}" if show_offense_counts?
122
122
 
123
123
  cop_class = Cop::Registry.global.find_by_cop_name(cop_name)
124
- output_buffer.puts '# Cop supports --auto-correct.' if cop_class&.support_autocorrect?
125
-
126
124
  default_cfg = default_config(cop_name)
125
+
126
+ if supports_safe_auto_correct?(cop_class, default_cfg)
127
+ output_buffer.puts '# Cop supports --auto-correct.'
128
+ elsif supports_unsafe_autocorrect?(cop_class, default_cfg)
129
+ output_buffer.puts '# Cop supports --auto-correct-all.'
130
+ end
131
+
127
132
  return unless default_cfg
128
133
 
129
134
  params = cop_config_params(default_cfg, cfg)
@@ -132,6 +137,15 @@ module RuboCop
132
137
  output_cop_param_comments(output_buffer, params, default_cfg)
133
138
  end
134
139
 
140
+ def supports_safe_auto_correct?(cop_class, default_cfg)
141
+ cop_class&.support_autocorrect? &&
142
+ (default_cfg.nil? || default_cfg['Safe'] || default_cfg['Safe'].nil?)
143
+ end
144
+
145
+ def supports_unsafe_autocorrect?(cop_class, default_cfg)
146
+ cop_class&.support_autocorrect? && !default_cfg.nil? && default_cfg['Safe'] == false
147
+ end
148
+
135
149
  def cop_config_params(default_cfg, cfg)
136
150
  default_cfg.keys -
137
151
  %w[Description StyleGuide Reference Enabled Exclude Safe
@@ -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.1'
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.1
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-02-03 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: