rubocop 1.8.1 → 1.9.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +34 -4
  4. data/lib/rubocop.rb +5 -0
  5. data/lib/rubocop/cli/command/auto_genenerate_config.rb +5 -4
  6. data/lib/rubocop/config.rb +2 -2
  7. data/lib/rubocop/config_loader.rb +7 -14
  8. data/lib/rubocop/config_store.rb +12 -1
  9. data/lib/rubocop/cop/base.rb +1 -1
  10. data/lib/rubocop/cop/generator.rb +1 -3
  11. data/lib/rubocop/cop/internal_affairs.rb +5 -1
  12. data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +68 -0
  13. data/lib/rubocop/cop/internal_affairs/example_description.rb +89 -0
  14. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +61 -0
  15. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +64 -0
  16. data/lib/rubocop/cop/layout/class_structure.rb +7 -2
  17. data/lib/rubocop/cop/lint/number_conversion.rb +41 -6
  18. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +47 -0
  19. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +39 -0
  20. data/lib/rubocop/cop/lint/symbol_conversion.rb +102 -0
  21. data/lib/rubocop/cop/lint/triple_quotes.rb +71 -0
  22. data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -0
  23. data/lib/rubocop/cop/mixin/comments_help.rb +0 -1
  24. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +38 -5
  25. data/lib/rubocop/cop/naming/variable_number.rb +1 -1
  26. data/lib/rubocop/cop/severity.rb +3 -3
  27. data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
  28. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +49 -9
  29. data/lib/rubocop/cop/style/eval_with_location.rb +63 -34
  30. data/lib/rubocop/cop/style/float_division.rb +3 -0
  31. data/lib/rubocop/cop/style/format_string_token.rb +18 -2
  32. data/lib/rubocop/cop/style/if_inside_else.rb +14 -7
  33. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +96 -0
  34. data/lib/rubocop/cop/style/nil_comparison.rb +1 -0
  35. data/lib/rubocop/cop/style/non_nil_check.rb +23 -13
  36. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  37. data/lib/rubocop/cop/style/sole_nested_conditional.rb +26 -2
  38. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  39. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -0
  40. data/lib/rubocop/magic_comment.rb +30 -1
  41. data/lib/rubocop/options.rb +1 -1
  42. data/lib/rubocop/rspec/expect_offense.rb +5 -2
  43. data/lib/rubocop/runner.rb +1 -0
  44. data/lib/rubocop/version.rb +2 -2
  45. metadata +12 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe7ec80b8cde2a075fee5a5658abf6dc74889091dae29e88482107983d2de270
4
- data.tar.gz: 7852fe6a6d0ba9cae98439cba0dfbfda659a5a434f62eca318bcd5bc45dfd3c4
3
+ metadata.gz: ec2d9f7ba4857375232c4e42ea44accdb38b2873c83315f3029a546e315622e0
4
+ data.tar.gz: 01df5c9957cca7c79cf8cab073c1bae675d684761561835d6d93f554f3743905
5
5
  SHA512:
6
- metadata.gz: 4239a27259a39584a544ed4bfc7c6025ece2198d463f8a2918a98e5560cec9a5a2ea5b978f0d253e61ea700446bb49f705627d8b8e41d4ead0fef35b23b14d98
7
- data.tar.gz: 59746b47f6bbe92dec5f6d79395ad6cd1a175d3a186005412953f0a849192673084b426bd14f6e9ac83e11dfaa0b27fc15718857b29ca6d359e2c9d387bca9c2
6
+ metadata.gz: 55a5a8deae643b6d76dc5220c7136a7c5413ecb93ca85ec61dcd3aa9ff0adb3c1ab356ec81f72273771ab3125317fc105bfcaf0c7e1e1ae07f6295c7fa33c26e
7
+ data.tar.gz: 642d925df9f18c6c42b532eb0193965c6a85a93bd9339523757882eb6e9029052161a32bbc4421e454a210fe2ab5318ae64459dc4a9d792ee0cb5e4b259568ff
data/README.md CHANGED
@@ -51,7 +51,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
51
51
  in your `Gemfile`:
52
52
 
53
53
  ```rb
54
- gem 'rubocop', '~> 1.8', require: false
54
+ gem 'rubocop', '~> 1.9', require: false
55
55
  ```
56
56
 
57
57
  See [versioning](https://docs.rubocop.org/rubocop/1.0/versioning.html) for further details.
@@ -1806,6 +1806,17 @@ Lint/NumberConversion:
1806
1806
  - Time
1807
1807
  - DateTime
1808
1808
 
1809
+ Lint/NumberedParameterAssignment:
1810
+ Description: 'Checks for uses of numbered parameter assignment.'
1811
+ Enabled: pending
1812
+ VersionAdded: '1.9'
1813
+
1814
+ Lint/OrAssignmentToConstant:
1815
+ Description: 'Checks unintended or-assignment to constant.'
1816
+ Enabled: pending
1817
+ Safe: false
1818
+ VersionAdded: '1.9'
1819
+
1809
1820
  Lint/OrderedMagicComments:
1810
1821
  Description: 'Checks the proper ordering of magic comments and whether a magic comment is not placed before a shebang.'
1811
1822
  Enabled: true
@@ -2032,12 +2043,16 @@ Lint/SuppressedException:
2032
2043
  VersionAdded: '0.9'
2033
2044
  VersionChanged: '0.81'
2034
2045
 
2046
+ Lint/SymbolConversion:
2047
+ Description: 'Checks for unnecessary symbol conversions.'
2048
+ Enabled: pending
2049
+ VersionAdded: '1.9'
2050
+
2035
2051
  Lint/Syntax:
2036
- Description: 'Checks syntax error.'
2052
+ Description: 'Checks for syntax errors.'
2037
2053
  Enabled: true
2038
2054
  VersionAdded: '0.9'
2039
2055
 
2040
-
2041
2056
  Lint/ToEnumArguments:
2042
2057
  Description: 'This cop ensures that `to_enum`/`enum_for`, called for the current method, has correct arguments.'
2043
2058
  Enabled: pending
@@ -2058,6 +2073,11 @@ Lint/TrailingCommaInAttributeDeclaration:
2058
2073
  Enabled: true
2059
2074
  VersionAdded: '0.90'
2060
2075
 
2076
+ Lint/TripleQuotes:
2077
+ Description: 'Checks for useless triple quote constructs.'
2078
+ Enabled: pending
2079
+ VersionAdded: '1.9'
2080
+
2061
2081
  Lint/UnderscorePrefixedVariableName:
2062
2082
  Description: 'Do not use prefix `_` for a variable that is used.'
2063
2083
  Enabled: true
@@ -2689,7 +2709,8 @@ Style/AsciiComments:
2689
2709
  Enabled: true
2690
2710
  VersionAdded: '0.9'
2691
2711
  VersionChanged: '0.52'
2692
- AllowedChars: []
2712
+ AllowedChars:
2713
+ - ©
2693
2714
 
2694
2715
  Style/Attr:
2695
2716
  Description: 'Checks for uses of Module#attr.'
@@ -3120,6 +3141,8 @@ Style/DisableCopsWithinSourceCodeDirective:
3120
3141
  Forbids disabling/enabling cops within source code.
3121
3142
  Enabled: false
3122
3143
  VersionAdded: '0.82'
3144
+ VersionChanged: '1.9'
3145
+ AllowedCops: []
3123
3146
 
3124
3147
  Style/DocumentDynamicEvalDefinition:
3125
3148
  Description: >-
@@ -3291,7 +3314,8 @@ Style/FloatDivision:
3291
3314
  Reference: 'https://blog.rubystyle.guide/ruby/2019/06/21/float-division.html'
3292
3315
  Enabled: true
3293
3316
  VersionAdded: '0.72'
3294
- VersionChanged: '1.6'
3317
+ VersionChanged: '1.9'
3318
+ Safe: false
3295
3319
  EnforcedStyle: single_coerce
3296
3320
  SupportedStyles:
3297
3321
  - left_coerce
@@ -3339,6 +3363,7 @@ Style/FormatStringToken:
3339
3363
  MaxUnannotatedPlaceholdersAllowed: 1
3340
3364
  VersionAdded: '0.49'
3341
3365
  VersionChanged: '1.0'
3366
+ IgnoredMethods: []
3342
3367
 
3343
3368
  Style/FrozenStringLiteralComment:
3344
3369
  Description: >-
@@ -3492,6 +3517,11 @@ Style/IfUnlessModifierOfIfUnless:
3492
3517
  VersionAdded: '0.39'
3493
3518
  VersionChanged: '0.87'
3494
3519
 
3520
+ Style/IfWithBooleanLiteralBranches:
3521
+ Description: 'Checks for redundant `if` with boolean literal branches.'
3522
+ Enabled: pending
3523
+ VersionAdded: '1.9'
3524
+
3495
3525
  Style/IfWithSemicolon:
3496
3526
  Description: 'Do not use if x; .... Use the ternary operator instead.'
3497
3527
  StyleGuide: '#no-semicolon-ifs'
@@ -312,6 +312,8 @@ require_relative 'rubocop/cop/lint/no_return_in_begin_end_blocks'
312
312
  require_relative 'rubocop/cop/lint/non_deterministic_require_order'
313
313
  require_relative 'rubocop/cop/lint/non_local_exit_from_iterator'
314
314
  require_relative 'rubocop/cop/lint/number_conversion'
315
+ require_relative 'rubocop/cop/lint/numbered_parameter_assignment'
316
+ require_relative 'rubocop/cop/lint/or_assignment_to_constant'
315
317
  require_relative 'rubocop/cop/lint/ordered_magic_comments'
316
318
  require_relative 'rubocop/cop/lint/out_of_range_regexp_ref'
317
319
  require_relative 'rubocop/cop/lint/parentheses_as_grouped_expression'
@@ -344,11 +346,13 @@ require_relative 'rubocop/cop/lint/shadowed_exception'
344
346
  require_relative 'rubocop/cop/lint/shadowing_outer_local_variable'
345
347
  require_relative 'rubocop/cop/lint/struct_new_override'
346
348
  require_relative 'rubocop/cop/lint/suppressed_exception'
349
+ require_relative 'rubocop/cop/lint/symbol_conversion'
347
350
  require_relative 'rubocop/cop/lint/syntax'
348
351
  require_relative 'rubocop/cop/lint/to_enum_arguments'
349
352
  require_relative 'rubocop/cop/lint/to_json'
350
353
  require_relative 'rubocop/cop/lint/top_level_return_with_argument'
351
354
  require_relative 'rubocop/cop/lint/trailing_comma_in_attribute_declaration'
355
+ require_relative 'rubocop/cop/lint/triple_quotes'
352
356
  require_relative 'rubocop/cop/lint/underscore_prefixed_variable_name'
353
357
  require_relative 'rubocop/cop/lint/unexpected_block_arity'
354
358
  require_relative 'rubocop/cop/lint/unified_integer'
@@ -477,6 +481,7 @@ require_relative 'rubocop/cop/style/identical_conditional_branches'
477
481
  require_relative 'rubocop/cop/style/if_inside_else'
478
482
  require_relative 'rubocop/cop/style/if_unless_modifier'
479
483
  require_relative 'rubocop/cop/style/if_unless_modifier_of_if_unless'
484
+ require_relative 'rubocop/cop/style/if_with_boolean_literal_branches'
480
485
  require_relative 'rubocop/cop/style/if_with_semicolon'
481
486
  require_relative 'rubocop/cop/style/implicit_runtime_error'
482
487
  require_relative 'rubocop/cop/style/infinite_loop'
@@ -9,6 +9,7 @@ module RuboCop
9
9
  self.command_name = :auto_gen_config
10
10
 
11
11
  AUTO_GENERATED_FILE = '.rubocop_todo.yml'
12
+ YAML_OPTIONAL_DOC_START = /\A---(\s+#|\s*\z)/.freeze
12
13
 
13
14
  PHASE_1 = 'Phase 1 of 2: run Layout/LineLength cop'
14
15
  PHASE_2 = 'Phase 2 of 2: run all cops'
@@ -130,10 +131,10 @@ module RuboCop
130
131
  end
131
132
 
132
133
  def write_config_file(file_name, file_string, rubocop_yml_contents)
133
- File.open(file_name, 'w') do |f|
134
- f.write "inherit_from:#{file_string}\n"
135
- f.write "\n#{rubocop_yml_contents}" if /\S/.match?(rubocop_yml_contents)
136
- end
134
+ lines = /\S/.match?(rubocop_yml_contents) ? rubocop_yml_contents.split("\n", -1) : []
135
+ doc_start_index = lines.index { |line| YAML_OPTIONAL_DOC_START.match?(line) } || -1
136
+ lines.insert(doc_start_index + 1, "inherit_from:#{file_string}\n")
137
+ File.open(file_name, 'w') { |f| f.write lines.join("\n") }
137
138
  end
138
139
  end
139
140
  end
@@ -33,8 +33,8 @@ module RuboCop
33
33
  @validator = ConfigValidator.new(self)
34
34
  end
35
35
 
36
- def self.create(hash, path)
37
- new(hash, path).check
36
+ def self.create(hash, path, check: true)
37
+ new(hash, path).tap { |config| config.check if check }
38
38
  end
39
39
 
40
40
  def loaded_features
@@ -25,17 +25,18 @@ module RuboCop
25
25
  attr_accessor :debug, :ignore_parent_exclusion,
26
26
  :disable_pending_cops, :enable_pending_cops
27
27
  attr_writer :default_configuration, :project_root
28
+ attr_reader :loaded_features
28
29
 
29
30
  alias debug? debug
30
31
  alias ignore_parent_exclusion? ignore_parent_exclusion
31
32
 
32
33
  def clear_options
33
34
  @debug = nil
34
- @loaded_features = []
35
+ @loaded_features = Set.new
35
36
  FileFinder.root_level = nil
36
37
  end
37
38
 
38
- def load_file(file)
39
+ def load_file(file, check: true)
39
40
  path = file_path(file)
40
41
 
41
42
  hash = load_yaml_configuration(path)
@@ -52,7 +53,7 @@ module RuboCop
52
53
 
53
54
  hash.delete('inherit_from')
54
55
 
55
- Config.create(hash, path)
56
+ Config.create(hash, path, check: check)
56
57
  end
57
58
 
58
59
  def load_yaml_configuration(absolute_path)
@@ -99,10 +100,10 @@ module RuboCop
99
100
  find_user_xdg_config || DEFAULT_FILE
100
101
  end
101
102
 
102
- def configuration_from_file(config_file)
103
+ def configuration_from_file(config_file, check: true)
103
104
  return default_configuration if config_file == DEFAULT_FILE
104
105
 
105
- config = load_file(config_file)
106
+ config = load_file(config_file, check: check)
106
107
  if ignore_parent_exclusion?
107
108
  print 'Ignoring AllCops/Exclude from parent folders' if debug?
108
109
  else
@@ -174,19 +175,11 @@ module RuboCop
174
175
  resolver.merge_with_default(config, config_file, unset_nil: unset_nil)
175
176
  end
176
177
 
177
- def loaded_features
178
- @loaded_features.flatten.compact.uniq
179
- end
180
-
181
178
  # @api private
182
179
  # Used to add features that were required inside a config or from
183
180
  # the CLI using `--require`.
184
181
  def add_loaded_features(loaded_features)
185
- if instance_variable_defined?(:@loaded_features)
186
- instance_variable_get(:@loaded_features) << loaded_features
187
- else
188
- instance_variable_set(:@loaded_features, [loaded_features])
189
- end
182
+ @loaded_features.merge(Array(loaded_features))
190
183
  end
191
184
 
192
185
  private
@@ -4,6 +4,9 @@ module RuboCop
4
4
  # Handles caching of configurations and association of inspected
5
5
  # ruby files to configurations.
6
6
  class ConfigStore
7
+ attr_reader :validated
8
+ alias validated? validated
9
+
7
10
  def initialize
8
11
  # @options_config stores a config that is specified in the command line.
9
12
  # This takes precedence over configs located in any directories
@@ -17,6 +20,9 @@ module RuboCop
17
20
  # @object_cache maps configuration file paths to
18
21
  # configuration objects so we only need to load them once.
19
22
  @object_cache = {}
23
+
24
+ # By default the config is validated before it can be used.
25
+ @validated = true
20
26
  end
21
27
 
22
28
  def options_config=(options_config)
@@ -29,6 +35,11 @@ module RuboCop
29
35
  @options_config = ConfigLoader.default_configuration
30
36
  end
31
37
 
38
+ def unvalidated
39
+ @validated = false
40
+ self
41
+ end
42
+
32
43
  def for_file(file)
33
44
  for_dir(File.dirname(file))
34
45
  end
@@ -55,7 +66,7 @@ module RuboCop
55
66
  path = @path_cache[dir]
56
67
  @object_cache[path] ||= begin
57
68
  print "For #{dir}: " if ConfigLoader.debug?
58
- ConfigLoader.configuration_from_file(path)
69
+ ConfigLoader.configuration_from_file(path, check: validated?)
59
70
  end
60
71
  end
61
72
  end
@@ -351,7 +351,7 @@ module RuboCop
351
351
  def use_corrector(range, corrector)
352
352
  if autocorrect?
353
353
  attempt_correction(range, corrector)
354
- elsif corrector
354
+ elsif corrector && cop_config.fetch('AutoCorrect', true)
355
355
  :uncorrected
356
356
  else
357
357
  :unsupported
@@ -81,9 +81,7 @@ module RuboCop
81
81
  SPEC_TEMPLATE = <<~SPEC
82
82
  # frozen_string_literal: true
83
83
 
84
- RSpec.describe RuboCop::Cop::%<department>s::%<cop_name>s do
85
- subject(:cop) { described_class.new(config) }
86
-
84
+ RSpec.describe RuboCop::Cop::%<department>s::%<cop_name>s, :config do
87
85
  let(:config) { RuboCop::Config.new }
88
86
 
89
87
  # TODO: Write test code
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'internal_affairs/empty_line_between_expect_offense_and_correction'
4
+ require_relative 'internal_affairs/example_description'
3
5
  require_relative 'internal_affairs/method_name_equal'
4
6
  require_relative 'internal_affairs/node_destructuring'
5
7
  require_relative 'internal_affairs/node_type_predicate'
6
8
  require_relative 'internal_affairs/offense_location_keyword'
7
- require_relative 'internal_affairs/redundant_message_argument'
9
+ require_relative 'internal_affairs/redundant_described_class_as_subject'
10
+ require_relative 'internal_affairs/redundant_let_rubocop_config_new'
8
11
  require_relative 'internal_affairs/redundant_location_argument'
12
+ require_relative 'internal_affairs/redundant_message_argument'
9
13
  require_relative 'internal_affairs/style_detected_api_use'
10
14
  require_relative 'internal_affairs/useless_message_assertion'
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # This cop checks whether `expect_offense` and correction expectation methods
7
+ # (i.e. `expect_correction` and `expect_no_corrections`) are separated by empty line.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # it 'registers and corrects an offense' do
12
+ # expect_offense(<<~RUBY)
13
+ # bad_method
14
+ # ^^^^^^^^^^ Use `good_method`.
15
+ # RUBY
16
+ # expect_correction(<<~RUBY)
17
+ # good_method
18
+ # RUBY
19
+ # end
20
+ #
21
+ # # good
22
+ # it 'registers and corrects an offense' do
23
+ # expect_offense(<<~RUBY)
24
+ # bad_method
25
+ # ^^^^^^^^^^ Use `good_method`.
26
+ # RUBY
27
+ #
28
+ # expect_correction(<<~RUBY)
29
+ # good_method
30
+ # RUBY
31
+ # end
32
+ #
33
+ class EmptyLineBetweenExpectOffenseAndCorrection < Base
34
+ extend AutoCorrector
35
+
36
+ MSG = 'Add empty line between `expect_offense` and `%<expect_correction>s`.'
37
+ RESTRICT_ON_SEND = %i[expect_offense].freeze
38
+ CORRECTION_EXPECTATION_METHODS = %i[expect_correction expect_no_corrections].freeze
39
+
40
+ def on_send(node)
41
+ return unless (next_sibling = node.right_sibling) && next_sibling.send_type?
42
+
43
+ method_name = next_sibling.method_name
44
+ return unless CORRECTION_EXPECTATION_METHODS.include?(method_name)
45
+
46
+ range = offense_range(node)
47
+ return unless range.last_line + 1 == next_sibling.loc.line
48
+
49
+ add_offense(range, message: format(MSG, expect_correction: method_name)) do |corrector|
50
+ corrector.insert_after(range, "\n")
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def offense_range(node)
57
+ first_argument = node.first_argument
58
+
59
+ if first_argument.respond_to?(:heredoc?) && first_argument.heredoc?
60
+ first_argument.loc.heredoc_end
61
+ else
62
+ node
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Checks that RSpec examples that use `expects_offense`
7
+ # or `expects_no_offenses` do not have conflicting
8
+ # descriptions.
9
+ #
10
+ # @example
11
+ # # bad
12
+ # it 'does not register an offense' do
13
+ # expect_offense('...')
14
+ # end
15
+ #
16
+ # it 'registers an offense' do
17
+ # expect_no_offenses('...')
18
+ # end
19
+ #
20
+ # # good
21
+ # it 'registers an offense' do
22
+ # expect_offense('...')
23
+ # end
24
+ #
25
+ # it 'does not register an offense' do
26
+ # expect_no_offenses('...')
27
+ # end
28
+ class ExampleDescription < Base
29
+ class << self
30
+ attr_accessor :descriptions
31
+ end
32
+
33
+ MSG = 'Description does not match use of `%<method_name>s`.'
34
+
35
+ RESTRICT_ON_SEND = %i[
36
+ expect_offense
37
+ expect_no_offenses
38
+ expect_correction
39
+ expect_no_corrections
40
+ ].to_set.freeze
41
+
42
+ EXPECT_NO_OFFENSES_INCORRECT_DESCRIPTIONS = [
43
+ /^(adds|registers|reports|finds) (an? )?offense/,
44
+ /^flags\b/
45
+ ].freeze
46
+
47
+ EXPECT_OFFENSE_INCORRECT_DESCRIPTIONS = [
48
+ /^(does not|doesn't) (register|find|flag|report)/,
49
+ /^(does not|doesn't) add (a|an|any )?offense/
50
+ ].freeze
51
+
52
+ EXPECT_NO_CORRECTIONS_INCORRECT_DESCRIPTIONS = [
53
+ /^(auto[- ]?)?correct/
54
+ ].freeze
55
+
56
+ EXPECT_CORRECTION_INCORRECT_DESCRIPTIONS = [
57
+ /\b(does not|doesn't) (auto[- ]?)?correct/
58
+ ].freeze
59
+
60
+ def_node_matcher :offense_example?, <<~PATTERN
61
+ (block
62
+ (send _ {:it :specify} $_description)
63
+ _args
64
+ `(send nil? %RESTRICT_ON_SEND ...)
65
+ )
66
+ PATTERN
67
+
68
+ def on_send(node)
69
+ parent = node.each_ancestor(:block).first
70
+ return unless parent && (description = offense_example?(parent))
71
+
72
+ method_name = node.method_name
73
+ message = format(MSG, method_name: method_name)
74
+
75
+ regexp_group = self.class.const_get("#{method_name}_incorrect_descriptions".upcase)
76
+ check_description(description, regexp_group, message)
77
+ end
78
+
79
+ private
80
+
81
+ def check_description(description, regexps, message)
82
+ return unless regexps.any? { |regexp| regexp.match?(description.value) }
83
+
84
+ add_offense(description, message: message)
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end