rubocop 1.24.1 → 1.26.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +28 -15
  5. data/lib/rubocop/cli.rb +1 -1
  6. data/lib/rubocop/cop/badge.rb +7 -1
  7. data/lib/rubocop/cop/gemspec/require_mfa.rb +4 -3
  8. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +10 -3
  9. data/lib/rubocop/cop/generator.rb +6 -10
  10. data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +46 -0
  11. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  12. data/lib/rubocop/cop/layout/argument_alignment.rb +36 -9
  13. data/lib/rubocop/cop/layout/case_indentation.rb +1 -1
  14. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +5 -1
  15. data/lib/rubocop/cop/layout/hash_alignment.rb +6 -1
  16. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +7 -8
  17. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
  18. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +5 -1
  19. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +6 -5
  20. data/lib/rubocop/cop/lint/inherit_exception.rb +19 -28
  21. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -2
  22. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +5 -0
  23. data/lib/rubocop/cop/lint/useless_times.rb +13 -9
  24. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +32 -6
  25. data/lib/rubocop/cop/naming/block_forwarding.rb +27 -13
  26. data/lib/rubocop/cop/naming/method_parameter_name.rb +1 -1
  27. data/lib/rubocop/cop/security/yaml_load.rb +9 -3
  28. data/lib/rubocop/cop/style/collection_compact.rb +3 -3
  29. data/lib/rubocop/cop/style/def_with_parentheses.rb +16 -11
  30. data/lib/rubocop/cop/style/for.rb +4 -0
  31. data/lib/rubocop/cop/style/hash_syntax.rb +14 -0
  32. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
  33. data/lib/rubocop/cop/style/lambda_call.rb +12 -20
  34. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +12 -5
  35. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
  36. data/lib/rubocop/cop/style/nested_file_dirname.rb +66 -0
  37. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +3 -2
  38. data/lib/rubocop/cop/style/redundant_begin.rb +2 -6
  39. data/lib/rubocop/cop/style/sample.rb +5 -3
  40. data/lib/rubocop/cop/style/string_concatenation.rb +7 -1
  41. data/lib/rubocop/cop/style/swap_values.rb +2 -0
  42. data/lib/rubocop/cop/style/ternary_parentheses.rb +16 -2
  43. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +1 -1
  44. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +1 -1
  45. data/lib/rubocop/cop/variable_force.rb +1 -5
  46. data/lib/rubocop/cops_documentation_generator.rb +2 -2
  47. data/lib/rubocop/formatter/disabled_config_formatter.rb +16 -2
  48. data/lib/rubocop/options.rb +8 -2
  49. data/lib/rubocop/rspec/shared_contexts.rb +4 -0
  50. data/lib/rubocop/runner.rb +1 -1
  51. data/lib/rubocop/target_ruby.rb +1 -1
  52. data/lib/rubocop/version.rb +1 -1
  53. data/lib/rubocop.rb +1 -0
  54. metadata +9 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2e7d2cbe48c6ff81a071b353132db29ed017af57a32bcd142038e2e551f3a5b
4
- data.tar.gz: 8ae72a3ce8b6ab13b4d451bbdb1dbcdf54f898711a3009dae81450a49fb037e0
3
+ metadata.gz: 6f5e4905006f7a87c34929888b4f93424dfd0695f95542fcf04db5091e76f2b4
4
+ data.tar.gz: ca36431854888608b6f57b36eb5a1e04569b7c513585579f30e121f30b231705
5
5
  SHA512:
6
- metadata.gz: d868781732056622d0f5157a50553c0b521f81f2ca14d2ede65b4c7372ef0e3b89be5146db8664fac5b28a39c82be52fc297a43d8280647b1b7426ce9ee87337
7
- data.tar.gz: e3d8f4dc8ab53859197eb3f05c62290cf72ba11c7e742869d619d6c4564e28f5c0fc70e4e15f90fc4f9bfe2d46cafdeedde8aa16d982adfc7d6eb482f7d20093
6
+ metadata.gz: 76d8ae5e1506313617a01d9c7ddd4061b0ced25ad6a47287e199489dee9fe76126907a4193a2ec6b70e5fef1f0274af3b017557d2c2f904d931f9d41805f98cb
7
+ data.tar.gz: 78b0442c8baa4ae704a19e37df8e4490801238989ab880f888d1c355a7b488bab7086f68d1a8f5f3bafd691998b25d9c9dabcafb921b87b6ba5b781a9efba624
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.26', 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
@@ -262,7 +262,7 @@ Gemspec/OrderedDependencies:
262
262
  - '**/*.gemspec'
263
263
 
264
264
  Gemspec/RequireMFA:
265
- Description: 'Checks that the gemspec has metadata to require MFA from RubyGems.'
265
+ Description: 'Checks that the gemspec has metadata to require Multi-Factor Authentication from RubyGems.'
266
266
  Enabled: pending
267
267
  VersionAdded: '1.23'
268
268
  Reference:
@@ -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.'
@@ -1816,12 +1816,14 @@ Lint/IneffectiveAccessModifier:
1816
1816
  Lint/InheritException:
1817
1817
  Description: 'Avoid inheriting from the `Exception` class.'
1818
1818
  Enabled: true
1819
+ SafeAutoCorrect: false
1819
1820
  VersionAdded: '0.41'
1821
+ VersionChanged: '1.26'
1820
1822
  # The default base class in favour of `Exception`.
1821
- EnforcedStyle: runtime_error
1823
+ EnforcedStyle: standard_error
1822
1824
  SupportedStyles:
1823
- - runtime_error
1824
1825
  - standard_error
1826
+ - runtime_error
1825
1827
 
1826
1828
  Lint/InterpolationCheck:
1827
1829
  Description: 'Raise warning for interpolation in single q strs.'
@@ -1900,7 +1902,7 @@ Lint/NestedPercentLiteral:
1900
1902
  VersionAdded: '0.52'
1901
1903
 
1902
1904
  Lint/NextWithoutAccumulator:
1903
- Description: >-
1905
+ Description: >-
1904
1906
  Do not omit the accumulator when calling `next`
1905
1907
  in a `reduce`/`inject` block.
1906
1908
  Enabled: true
@@ -2011,6 +2013,8 @@ Lint/RedundantDirGlobSort:
2011
2013
  Description: 'Checks for redundant `sort` method to `Dir.glob` and `Dir[]`.'
2012
2014
  Enabled: pending
2013
2015
  VersionAdded: '1.8'
2016
+ VersionChanged: '1.26'
2017
+ SafeAutoCorrect: false
2014
2018
 
2015
2019
  Lint/RedundantRequireStatement:
2016
2020
  Description: 'Checks for unnecessary `require` statement.'
@@ -2496,6 +2500,7 @@ Naming/BlockForwarding:
2496
2500
  SupportedStyles:
2497
2501
  - anonymous
2498
2502
  - explicit
2503
+ BlockForwardingName: block
2499
2504
 
2500
2505
  Naming/BlockParameterName:
2501
2506
  Description: >-
@@ -3152,7 +3157,7 @@ Style/ClassMethodsDefinitions:
3152
3157
  StyleGuide: '#def-self-class-methods'
3153
3158
  Enabled: false
3154
3159
  VersionAdded: '0.89'
3155
- EnforcedStyle: def_self
3160
+ EnforcedStyle: def_self
3156
3161
  SupportedStyles:
3157
3162
  - def_self
3158
3163
  - self_class
@@ -3541,8 +3546,9 @@ Style/For:
3541
3546
  Description: 'Checks use of for or each in multiline loops.'
3542
3547
  StyleGuide: '#no-for-loops'
3543
3548
  Enabled: true
3549
+ SafeAutoCorrect: false
3544
3550
  VersionAdded: '0.13'
3545
- VersionChanged: '0.59'
3551
+ VersionChanged: '1.26'
3546
3552
  EnforcedStyle: each
3547
3553
  SupportedStyles:
3548
3554
  - each
@@ -3698,6 +3704,8 @@ Style/HashSyntax:
3698
3704
  - always
3699
3705
  # forces use of explicit hash literal value.
3700
3706
  - never
3707
+ # accepts both shorthand and explicit use of hash literal value.
3708
+ - either
3701
3709
  # Force hashes that have a symbol value to use hash rockets
3702
3710
  UseHashRocketsWithSymbolValues: false
3703
3711
  # Do not suggest { a?: 1 } over { :a? => 1 } in ruby19 style
@@ -3812,8 +3820,8 @@ Style/InverseMethods:
3812
3820
  :>: :<=
3813
3821
  # `ActiveSupport` defines some common inverse methods. They are listed below,
3814
3822
  # and not enabled by default.
3815
- #:present?: :blank?,
3816
- #:include?: :exclude?
3823
+ # :present?: :blank?,
3824
+ # :include?: :exclude?
3817
3825
  # `InverseBlocks` are methods that are inverted by inverting the return
3818
3826
  # of the block that is passed to the method
3819
3827
  InverseBlocks:
@@ -4119,6 +4127,11 @@ Style/NegatedWhile:
4119
4127
  Enabled: true
4120
4128
  VersionAdded: '0.20'
4121
4129
 
4130
+ Style/NestedFileDirname:
4131
+ Description: 'Checks for nested `File.dirname`.'
4132
+ Enabled: pending
4133
+ VersionAdded: '1.26'
4134
+
4122
4135
  Style/NestedModifier:
4123
4136
  Description: 'Avoid using nested modifiers.'
4124
4137
  StyleGuide: '#no-nested-modifiers'
data/lib/rubocop/cli.rb CHANGED
@@ -14,7 +14,7 @@ module RuboCop
14
14
  ignore_disable_comments lint only only_guide_cops require safe
15
15
  ].freeze
16
16
 
17
- class Finished < RuntimeError; end
17
+ class Finished < StandardError; end
18
18
 
19
19
  attr_reader :options, :config_store
20
20
 
@@ -19,7 +19,13 @@ module RuboCop
19
19
  end
20
20
 
21
21
  def self.parse(identifier)
22
- new(identifier.split('/'))
22
+ new(identifier.split('/').map { |i| camel_case(i) })
23
+ end
24
+
25
+ def self.camel_case(name_part)
26
+ return 'RSpec' if name_part == 'rspec'
27
+
28
+ name_part.gsub(/^\w|_\w/) { |match| match[-1, 1].upcase }
23
29
  end
24
30
 
25
31
  def initialize(class_name_parts)
@@ -5,9 +5,10 @@ module RuboCop
5
5
  module Gemspec
6
6
  # Requires a gemspec to have `rubygems_mfa_required` metadata set.
7
7
  #
8
- # This setting tells RubyGems that MFA is required for accounts to
9
- # be able perform privileged operations, such as (see
10
- # RubyGems' documentation for the full list of privileged operations):
8
+ # This setting tells RubyGems that MFA (Multi-Factor Authentication) is
9
+ # required for accounts to be able perform privileged operations, such as
10
+ # (see RubyGems' documentation for the full list of privileged
11
+ # operations):
11
12
  #
12
13
  # * `gem push`
13
14
  # * `gem yank`
@@ -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
@@ -8,13 +8,7 @@ module RuboCop
8
8
  # and spec file when given a valid qualified cop name.
9
9
  # @api private
10
10
  class Generator
11
- # NOTE: RDoc 5.1.0 or lower has the following issue.
12
- # https://github.com/rubocop/rubocop/issues/7043
13
- #
14
- # The following `String#gsub` can be replaced with
15
- # squiggly heredoc when RuboCop supports Ruby 2.5 or higher
16
- # (RDoc 6.0 or higher).
17
- SOURCE_TEMPLATE = <<-RUBY.gsub(/^ {8}/, '')
11
+ SOURCE_TEMPLATE = <<~RUBY
18
12
  # frozen_string_literal: true
19
13
 
20
14
  module RuboCop
@@ -68,6 +62,7 @@ module RuboCop
68
62
  # For example
69
63
  MSG = 'Use `#good_method` instead of `#bad_method`.'
70
64
 
65
+ # @!method bad_method?(node)
71
66
  def_node_matcher :bad_method?, <<~PATTERN
72
67
  (send nil? :bad_method ...)
73
68
  PATTERN
@@ -182,7 +177,8 @@ module RuboCop
182
177
  end
183
178
 
184
179
  def generate(template)
185
- format(template, department: badge.department, cop_name: badge.cop_name)
180
+ format(template, department: badge.department.to_s.gsub('/', '::'),
181
+ cop_name: badge.cop_name)
186
182
  end
187
183
 
188
184
  def spec_path
@@ -209,8 +205,8 @@ module RuboCop
209
205
  return 'rspec' if camel_case_string == 'RSpec'
210
206
 
211
207
  camel_case_string
212
- .gsub(/([^A-Z])([A-Z]+)/, '\1_\2')
213
- .gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2')
208
+ .gsub(%r{([^A-Z/])([A-Z]+)}, '\1_\2')
209
+ .gsub(%r{([A-Z])([A-Z][^A-Z\d/]+)}, '\1_\2')
214
210
  .downcase
215
211
  end
216
212
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Checks for redundant `:config` parameter in the `context` arguments.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # context 'foo', :config do
12
+ # end
13
+ #
14
+ # # good
15
+ # context 'foo' do
16
+ # end
17
+ #
18
+ class RedundantContextConfigParameter < Base
19
+ include RangeHelp
20
+ extend AutoCorrector
21
+
22
+ MSG = 'Remove the redundant `:config` parameter.'
23
+ RESTRICT_ON_SEND = %i[context].freeze
24
+
25
+ def on_send(node)
26
+ arguments = node.arguments
27
+ config_node = arguments.detect { |argument| argument.source == ':config' }
28
+ return unless config_node
29
+
30
+ add_offense(config_node) do |corrector|
31
+ dup_arguments = arguments.dup
32
+ dup_arguments.delete(config_node)
33
+
34
+ corrector.replace(offense_range(arguments), dup_arguments.map(&:source).join(', '))
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def offense_range(arguments)
41
+ range_between(arguments.first.source_range.begin_pos, arguments.last.source_range.end_pos)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -9,6 +9,7 @@ require_relative 'internal_affairs/node_destructuring'
9
9
  require_relative 'internal_affairs/node_matcher_directive'
10
10
  require_relative 'internal_affairs/node_type_predicate'
11
11
  require_relative 'internal_affairs/offense_location_keyword'
12
+ require_relative 'internal_affairs/redundant_context_config_parameter'
12
13
  require_relative 'internal_affairs/redundant_described_class_as_subject'
13
14
  require_relative 'internal_affairs/redundant_let_rubocop_config_new'
14
15
  require_relative 'internal_affairs/redundant_location_argument'
@@ -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
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # This cop checks how the `when` and `in`s of a `case` expression
6
+ # This cop checks how the `when` and ``in``s of a `case` expression
7
7
  # are indented in relation to its `case` or `end` keyword.
8
8
  #
9
9
  # It will register a separate offense for each misaligned `when` and `in`.
@@ -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] = {} }
@@ -3,27 +3,26 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # This cop checks the indentation of the right hand side operand in
7
- # binary operations that span more than one line.
6
+ # This cop checks the indentation of the right hand side operand in binary operations that
7
+ # span more than one line.
8
8
  #
9
- # The `aligned` style checks that operators are aligned if they are part
10
- # of an `if` or `while` condition, a `return` statement, etc. In other
11
- # contexts, the second operand should be indented regardless of enforced
12
- # style.
9
+ # The `aligned` style checks that operators are aligned if they are part of an `if` or `while`
10
+ # condition, an explicit `return` statement, etc. In other contexts, the second operand should
11
+ # be indented regardless of enforced style.
13
12
  #
14
13
  # @example EnforcedStyle: aligned (default)
15
14
  # # bad
16
15
  # if a +
17
16
  # b
18
17
  # something &&
19
- # something_else
18
+ # something_else
20
19
  # end
21
20
  #
22
21
  # # good
23
22
  # if a +
24
23
  # b
25
24
  # something &&
26
- # something_else
25
+ # something_else
27
26
  # end
28
27
  #
29
28
  # @example EnforcedStyle: indented
@@ -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}"
@@ -3,12 +3,16 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This cop looks for error classes inheriting from `Exception`
7
- # and its standard library subclasses, excluding subclasses of
8
- # `StandardError`. It is configurable to suggest using either
9
- # `RuntimeError` (default) or `StandardError` instead.
6
+ # This cop looks for error classes inheriting from `Exception`.
7
+ # It is configurable to suggest using either `StandardError` (default) or
8
+ # `RuntimeError` instead.
10
9
  #
11
- # @example EnforcedStyle: runtime_error (default)
10
+ # @safety
11
+ # This cop's autocorrection is unsafe because `rescue` that omit
12
+ # exception class handle `StandardError` and its subclasses,
13
+ # but not `Exception` and its subclasses.
14
+ #
15
+ # @example EnforcedStyle: standard_error (default)
12
16
  # # bad
13
17
  #
14
18
  # class C < Exception; end
@@ -17,11 +21,11 @@ module RuboCop
17
21
  #
18
22
  # # good
19
23
  #
20
- # class C < RuntimeError; end
24
+ # class C < StandardError; end
21
25
  #
22
- # C = Class.new(RuntimeError)
26
+ # C = Class.new(StandardError)
23
27
  #
24
- # @example EnforcedStyle: standard_error
28
+ # @example EnforcedStyle: runtime_error
25
29
  # # bad
26
30
  #
27
31
  # class C < Exception; end
@@ -30,31 +34,18 @@ module RuboCop
30
34
  #
31
35
  # # good
32
36
  #
33
- # class C < StandardError; end
37
+ # class C < RuntimeError; end
34
38
  #
35
- # C = Class.new(StandardError)
39
+ # C = Class.new(RuntimeError)
36
40
  class InheritException < Base
37
41
  include ConfigurableEnforcedStyle
38
42
  extend AutoCorrector
39
43
 
40
- MSG = 'Inherit from `%<prefer>s` instead of `%<current>s`.'
44
+ MSG = 'Inherit from `%<prefer>s` instead of `Exception`.'
41
45
  PREFERRED_BASE_CLASS = {
42
46
  runtime_error: 'RuntimeError',
43
47
  standard_error: 'StandardError'
44
48
  }.freeze
45
- ILLEGAL_CLASSES = %w[
46
- Exception
47
- SystemStackError
48
- NoMemoryError
49
- SecurityError
50
- NotImplementedError
51
- LoadError
52
- SyntaxError
53
- ScriptError
54
- Interrupt
55
- SignalException
56
- SystemExit
57
- ].freeze
58
49
 
59
50
  RESTRICT_ON_SEND = %i[new].freeze
60
51
 
@@ -66,7 +57,7 @@ module RuboCop
66
57
  PATTERN
67
58
 
68
59
  def on_class(node)
69
- return unless node.parent_class && illegal_class_name?(node.parent_class)
60
+ return unless node.parent_class && exception_class?(node.parent_class)
70
61
 
71
62
  message = message(node.parent_class)
72
63
 
@@ -77,7 +68,7 @@ module RuboCop
77
68
 
78
69
  def on_send(node)
79
70
  constant = class_new_call?(node)
80
- return unless constant && illegal_class_name?(constant)
71
+ return unless constant && exception_class?(constant)
81
72
 
82
73
  message = message(constant)
83
74
 
@@ -92,8 +83,8 @@ module RuboCop
92
83
  format(MSG, prefer: preferred_base_class, current: node.const_name)
93
84
  end
94
85
 
95
- def illegal_class_name?(class_node)
96
- ILLEGAL_CLASSES.include?(class_node.const_name)
86
+ def exception_class?(class_node)
87
+ class_node.const_name == 'Exception'
97
88
  end
98
89
 
99
90
  def preferred_base_class
@@ -19,7 +19,7 @@ module RuboCop
19
19
  include RangeHelp
20
20
  extend AutoCorrector
21
21
 
22
- MSG = '`(...)` interpreted as grouped expression.'
22
+ MSG = '`%<argument>s` interpreted as grouped expression.'
23
23
 
24
24
  def on_send(node)
25
25
  return if valid_context?(node)
@@ -28,8 +28,9 @@ module RuboCop
28
28
  return unless space_length.positive?
29
29
 
30
30
  range = space_range(node.first_argument.source_range, space_length)
31
+ message = format(MSG, argument: node.first_argument.source)
31
32
 
32
- add_offense(range) { |corrector| corrector.remove(range) }
33
+ add_offense(range, message: message) { |corrector| corrector.remove(range) }
33
34
  end
34
35
  alias on_csend on_send
35
36
 
@@ -6,6 +6,11 @@ module RuboCop
6
6
  # Sort globbed results by default in Ruby 3.0.
7
7
  # This cop checks for redundant `sort` method to `Dir.glob` and `Dir[]`.
8
8
  #
9
+ # @safety
10
+ # This cop is unsafe, in case of having a file and a directory with
11
+ # identical names, since directory will be loaded before the file, which
12
+ # will break `exe/files.rb` that rely on `exe.rb` file.
13
+ #
9
14
  # @example
10
15
  #
11
16
  # # bad