rubocop-rails 2.9.1 → 2.11.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +4 -4
  4. data/config/default.yml +111 -5
  5. data/config/obsoletion.yml +7 -0
  6. data/lib/rubocop/cop/mixin/active_record_helper.rb +11 -0
  7. data/lib/rubocop/cop/rails/add_column_index.rb +64 -0
  8. data/lib/rubocop/cop/rails/attribute_default_block_value.rb +1 -1
  9. data/lib/rubocop/cop/rails/belongs_to.rb +1 -1
  10. data/lib/rubocop/cop/rails/blank.rb +4 -0
  11. data/lib/rubocop/cop/rails/bulk_change_table.rb +5 -1
  12. data/lib/rubocop/cop/rails/content_tag.rb +18 -3
  13. data/lib/rubocop/cop/rails/date.rb +17 -6
  14. data/lib/rubocop/cop/rails/dynamic_find_by.rb +4 -2
  15. data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +78 -0
  16. data/lib/rubocop/cop/rails/environment_comparison.rb +1 -2
  17. data/lib/rubocop/cop/rails/environment_variable_access.rb +67 -0
  18. data/lib/rubocop/cop/rails/expanded_date_range.rb +86 -0
  19. data/lib/rubocop/cop/rails/file_path.rb +2 -4
  20. data/lib/rubocop/cop/rails/find_by.rb +31 -12
  21. data/lib/rubocop/cop/rails/find_each.rb +2 -0
  22. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +34 -4
  23. data/lib/rubocop/cop/rails/http_positional_arguments.rb +8 -1
  24. data/lib/rubocop/cop/rails/http_status.rb +12 -3
  25. data/lib/rubocop/cop/rails/i18n_locale_assignment.rb +37 -0
  26. data/lib/rubocop/cop/rails/inverse_of.rb +1 -2
  27. data/lib/rubocop/cop/rails/link_to_blank.rb +5 -1
  28. data/lib/rubocop/cop/rails/reflection_class_name.rb +14 -1
  29. data/lib/rubocop/cop/rails/relative_date_constant.rb +18 -19
  30. data/lib/rubocop/cop/rails/require_dependency.rb +38 -0
  31. data/lib/rubocop/cop/rails/reversible_migration.rb +1 -1
  32. data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +75 -0
  33. data/lib/rubocop/cop/rails/safe_navigation.rb +20 -2
  34. data/lib/rubocop/cop/rails/time_zone.rb +22 -22
  35. data/lib/rubocop/cop/rails/time_zone_assignment.rb +37 -0
  36. data/lib/rubocop/cop/rails/unknown_env.rb +1 -1
  37. data/lib/rubocop/cop/rails/unused_ignored_columns.rb +69 -0
  38. data/lib/rubocop/cop/rails/where_exists.rb +11 -0
  39. data/lib/rubocop/cop/rails/where_not.rb +5 -1
  40. data/lib/rubocop/cop/rails_cops.rb +9 -0
  41. data/lib/rubocop/rails.rb +2 -0
  42. data/lib/rubocop/rails/schema_loader/schema.rb +2 -4
  43. data/lib/rubocop/rails/version.rb +1 -1
  44. metadata +21 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a4f37840f94de73bdcc15533ef3e5e95ee265a79fd0486b5e813ee926421d17
4
- data.tar.gz: b2fee8ee1727d8cf33c1d0568f12378f1115d1ae00aa52295656d232de8c59af
3
+ metadata.gz: 70f7044795da60c3d19962181ad6e9bc1914c1ae9c46f5072f4c2bc9c6115add
4
+ data.tar.gz: d1130053b86d468d25b114694dca3d56eea533aafdbff9ff8dc33f3fdc306fbb
5
5
  SHA512:
6
- metadata.gz: d4ceba3963546eaa994918f85d1558223de162f66de58ac48d1e466c2b126facf7548053c00fcbfcd4d05e2d1225eed32e15e6ff921627cfb2a14014119df757
7
- data.tar.gz: af84d0f778766239432a0b599e21c0e6671b02739769570b2c8655df5f32770f796978747d02a321a5ad1ea2c009d60b7ec3e93b09f669106ad9305a4cc50c3e
6
+ metadata.gz: 49d18f985b54c2a8beefe8f00ad758b2cabed80d463315e10c994eeb348af4f1e6db1f53ac7a73434105d210db831b98ddb8f5ae44e849346888ff427c4eabcc
7
+ data.tar.gz: 291ad9f2cafe1c8ce146bf9e311e5bf84c667e087596050076d9fa560ef0612c41a425beb8d314386f98e4f2eeb4f31bdb50f134eebad52b44efca82ea4299ba
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-20 Bozhidar Batsov
1
+ Copyright (c) 2012-21 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
@@ -1,9 +1,9 @@
1
1
  # RuboCop Rails
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/rubocop-rails.svg)](https://badge.fury.io/rb/rubocop-rails)
4
- [![CircleCI](https://circleci.com/gh/rubocop-hq/rubocop-rails.svg?style=svg)](https://circleci.com/gh/rubocop-hq/rubocop-rails)
4
+ [![CircleCI](https://circleci.com/gh/rubocop/rubocop-rails.svg?style=svg)](https://circleci.com/gh/rubocop/rubocop-rails)
5
5
 
6
- A [RuboCop](https://github.com/rubocop-hq/rubocop) extension focused on enforcing Rails best practices and coding conventions.
6
+ A [RuboCop](https://github.com/rubocop/rubocop) extension focused on enforcing Rails best practices and coding conventions.
7
7
 
8
8
  Note: This repository manages rubocop-rails gem (>= 2.0.0). rubocop-rails gem (<= 1.5.0) has been renamed to [rubocop-rails_config](https://rubygems.org/gems/rubocop-rails_config) gem.
9
9
 
@@ -90,14 +90,14 @@ Rails cops support the following versions:
90
90
 
91
91
  If you use RuboCop Rails in your project, you can include one of these badges in your readme to let people know that your code is written following the community Rails Style Guide.
92
92
 
93
- [![Rails Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop-hq/rubocop-rails)
93
+ [![Rails Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop/rubocop-rails)
94
94
 
95
95
  [![Rails Style Guide](https://img.shields.io/badge/code_style-community-brightgreen.svg)](https://rails.rubystyle.guide)
96
96
 
97
97
  Here are the Markdown snippets for the two badges:
98
98
 
99
99
  ``` markdown
100
- [![Rails Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop-hq/rubocop-rails)
100
+ [![Rails Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop/rubocop-rails)
101
101
 
102
102
  [![Rails Style Guide](https://img.shields.io/badge/code_style-community-brightgreen.svg)](https://rails.rubystyle.guide)
103
103
  ```
data/config/default.yml CHANGED
@@ -17,6 +17,27 @@ AllCops:
17
17
  # as the default.
18
18
  TargetRailsVersion: ~
19
19
 
20
+ Lint/NumberConversion:
21
+ # Add Rails' duration methods to the ignore list for `Lint/NumberConversion`
22
+ # so that calling `to_i` on one of these does not register an offense.
23
+ # See: https://github.com/rubocop/rubocop/issues/8950
24
+ IgnoredMethods:
25
+ - ago
26
+ - from_now
27
+ - second
28
+ - seconds
29
+ - minute
30
+ - minutes
31
+ - hour
32
+ - hours
33
+ - day
34
+ - days
35
+ - week
36
+ - weeks
37
+ - fortnight
38
+ - fortnights
39
+ - in_milliseconds
40
+
20
41
  Rails/ActionFilter:
21
42
  Description: 'Enforces consistent use of action filter methods.'
22
43
  Enabled: true
@@ -62,6 +83,16 @@ Rails/ActiveSupportAliases:
62
83
  Enabled: true
63
84
  VersionAdded: '0.48'
64
85
 
86
+ Rails/AddColumnIndex:
87
+ Description: >-
88
+ Rails migrations don't make use of a given `index` key, but also
89
+ doesn't given an error when it's used, so it makes it seem like an
90
+ index might be used.
91
+ Enabled: pending
92
+ VersionAdded: '2.11'
93
+ Include:
94
+ - db/migrate/*.rb
95
+
65
96
  Rails/AfterCommitOverride:
66
97
  Description: >-
67
98
  This cop enforces that there is only one call to `after_commit`
@@ -128,8 +159,9 @@ Rails/BelongsTo:
128
159
  Rails/Blank:
129
160
  Description: 'Enforces use of `blank?`.'
130
161
  Enabled: true
162
+ SafeAutoCorrect: false
131
163
  VersionAdded: '0.48'
132
- VersionChanged: '0.67'
164
+ VersionChanged: '2.10'
133
165
  # Convert usages of `nil? || empty?` to `blank?`
134
166
  NilOrEmpty: true
135
167
  # Convert usages of `!present?` to `blank?`
@@ -171,7 +203,7 @@ Rails/Date:
171
203
  such as Date.today, Date.current etc.
172
204
  Enabled: true
173
205
  VersionAdded: '0.30'
174
- VersionChanged: '0.33'
206
+ VersionChanged: '2.11'
175
207
  # The value `strict` disallows usage of `Date.today`, `Date.current`,
176
208
  # `Date#to_time` etc.
177
209
  # The value `flexible` allows usage of `Date.current`, `Date.yesterday`, etc
@@ -181,6 +213,7 @@ Rails/Date:
181
213
  SupportedStyles:
182
214
  - strict
183
215
  - flexible
216
+ AllowToTime: true
184
217
 
185
218
  Rails/DefaultScope:
186
219
  Description: 'Avoid use of `default_scope`.'
@@ -207,8 +240,9 @@ Rails/DynamicFindBy:
207
240
  Description: 'Use `find_by` instead of dynamic `find_by_*`.'
208
241
  StyleGuide: 'https://rails.rubystyle.guide#find_by'
209
242
  Enabled: true
243
+ Safe: false
210
244
  VersionAdded: '0.44'
211
- VersionChanged: '2.6'
245
+ VersionChanged: '2.10'
212
246
  # The `Whitelist` has been deprecated, Please use `AllowedMethods` instead.
213
247
  Whitelist:
214
248
  - find_by_sql
@@ -217,6 +251,12 @@ Rails/DynamicFindBy:
217
251
  AllowedReceivers:
218
252
  - Gem::Specification
219
253
 
254
+ Rails/EagerEvaluationLogMessage:
255
+ Description: 'Checks that blocks are used for interpolated strings passed to `Rails.logger.debug`.'
256
+ Reference: 'https://guides.rubyonrails.org/debugging_rails_applications.html#impact-of-logs-on-performance'
257
+ Enabled: pending
258
+ VersionAdded: '2.11'
259
+
220
260
  Rails/EnumHash:
221
261
  Description: 'Prefer hash syntax over array syntax when defining enums.'
222
262
  StyleGuide: 'https://rails.rubystyle.guide#enums'
@@ -237,6 +277,20 @@ Rails/EnvironmentComparison:
237
277
  Enabled: true
238
278
  VersionAdded: '0.52'
239
279
 
280
+ Rails/EnvironmentVariableAccess:
281
+ Description: 'Do not access `ENV` directly after initialization.'
282
+ # TODO: Set to `pending` status in RuboCop Rails 2 series when migration doc will be written.
283
+ Enabled: false
284
+ VersionAdded: '2.10'
285
+ VersionChanged: '2.11'
286
+ Include:
287
+ - app/**/*.rb
288
+ - lib/**/*.rb
289
+ Exclude:
290
+ - lib/**/*.rake
291
+ AllowReads: false
292
+ AllowWrites: false
293
+
240
294
  Rails/Exit:
241
295
  Description: >-
242
296
  Favor `fail`, `break`, `return`, etc. over `exit` in
@@ -251,6 +305,11 @@ Rails/Exit:
251
305
  Exclude:
252
306
  - lib/**/*.rake
253
307
 
308
+ Rails/ExpandedDateRange:
309
+ Description: 'Checks for expanded date range.'
310
+ Enabled: pending
311
+ VersionAdded: '2.11'
312
+
254
313
  Rails/FilePath:
255
314
  Description: 'Use `Rails.root.join` for file path joining.'
256
315
  Enabled: true
@@ -266,6 +325,8 @@ Rails/FindBy:
266
325
  StyleGuide: 'https://rails.rubystyle.guide#find_by'
267
326
  Enabled: true
268
327
  VersionAdded: '0.30'
328
+ VersionChanged: '2.11'
329
+ IgnoreWhereFirst: true
269
330
  Include:
270
331
  - app/models/**/*.rb
271
332
 
@@ -327,11 +388,20 @@ Rails/HttpStatus:
327
388
  Description: 'Enforces use of symbolic or numeric value to define HTTP status.'
328
389
  Enabled: true
329
390
  VersionAdded: '0.54'
391
+ VersionChanged: '2.11'
330
392
  EnforcedStyle: symbolic
331
393
  SupportedStyles:
332
394
  - numeric
333
395
  - symbolic
334
396
 
397
+ Rails/I18nLocaleAssignment:
398
+ Description: 'Prefer the usage of `I18n.with_locale` instead of manually updating `I18n.locale` value.'
399
+ Enabled: 'pending'
400
+ VersionAdded: '2.11'
401
+ Include:
402
+ - spec/**/*.rb
403
+ - test/**/*.rb
404
+
335
405
  Rails/IgnoredSkipActionFilterOption:
336
406
  Description: 'Checks that `if` and `only` (or `except`) are not used together as options of `skip_*` action filter.'
337
407
  Reference: 'https://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html#method-i-_normalize_callback_options'
@@ -540,7 +610,9 @@ Rails/RedundantReceiverInWithOptions:
540
610
  Rails/ReflectionClassName:
541
611
  Description: 'Use a string for `class_name` option value in the definition of a reflection.'
542
612
  Enabled: true
613
+ Safe: false
543
614
  VersionAdded: '0.64'
615
+ VersionChanged: '2.10'
544
616
 
545
617
  Rails/RefuteMethods:
546
618
  Description: 'Use `assert_not` methods instead of `refute` methods.'
@@ -583,6 +655,12 @@ Rails/RequestReferer:
583
655
  - referer
584
656
  - referrer
585
657
 
658
+ Rails/RequireDependency:
659
+ Description: 'Do not use `require_dependency` when running in Zeitwerk mode. `require_dependency` is for autoloading in classic mode.'
660
+ Reference: 'https://guides.rubyonrails.org/autoloading_and_reloading_constants.html'
661
+ Enabled: false
662
+ VersionAdded: '2.10'
663
+
586
664
  Rails/ReversibleMigration:
587
665
  Description: 'Checks whether the change method of the migration file is reversible.'
588
666
  StyleGuide: 'https://rails.rubystyle.guide#reversible-migration'
@@ -592,6 +670,13 @@ Rails/ReversibleMigration:
592
670
  Include:
593
671
  - db/migrate/*.rb
594
672
 
673
+ Rails/ReversibleMigrationMethodDefinition:
674
+ Description: 'Checks whether the migration implements either a `change` method or both an `up` and a `down` method.'
675
+ Enabled: false
676
+ VersionAdded: '2.10'
677
+ Include:
678
+ - db/migrate/*.rb
679
+
595
680
  Rails/SafeNavigation:
596
681
  Description: "Use Ruby's safe navigation operator (`&.`) instead of `try!`."
597
682
  Enabled: true
@@ -687,13 +772,24 @@ Rails/TimeZone:
687
772
  Enabled: true
688
773
  Safe: false
689
774
  VersionAdded: '0.30'
690
- VersionChanged: '0.68'
775
+ VersionChanged: '2.10'
691
776
  # The value `strict` means that `Time` should be used with `zone`.
692
777
  # The value `flexible` allows usage of `in_time_zone` instead of `zone`.
693
778
  EnforcedStyle: flexible
694
779
  SupportedStyles:
695
780
  - strict
696
781
  - flexible
782
+ Exclude:
783
+ - '**/*.gemspec'
784
+
785
+ Rails/TimeZoneAssignment:
786
+ Description: 'Prefer the usage of `Time.use_zone` instead of manually updating `Time.zone` value.'
787
+ Reference: 'https://thoughtbot.com/blog/its-about-time-zones'
788
+ Enabled: 'pending'
789
+ VersionAdded: '2.10'
790
+ Include:
791
+ - spec/**/*.rb
792
+ - test/**/*.rb
697
793
 
698
794
  Rails/UniqBeforePluck:
699
795
  Description: 'Prefer the use of uniq or distinct before pluck.'
@@ -723,6 +819,13 @@ Rails/UnknownEnv:
723
819
  - test
724
820
  - production
725
821
 
822
+ Rails/UnusedIgnoredColumns:
823
+ Description: 'Remove a column that does not exist from `ignored_columns`.'
824
+ Enabled: pending
825
+ VersionAdded: '2.11'
826
+ Include:
827
+ - app/models/**/*.rb
828
+
726
829
  Rails/Validation:
727
830
  Description: 'Use validates :attribute, hash of validations.'
728
831
  Enabled: true
@@ -735,17 +838,20 @@ Rails/WhereEquals:
735
838
  Description: 'Pass conditions to `where` as a hash instead of manually constructing SQL.'
736
839
  StyleGuide: 'https://rails.rubystyle.guide/#hash-conditions'
737
840
  Enabled: 'pending'
841
+ SafeAutoCorrect: false
738
842
  VersionAdded: '2.9'
843
+ VersionChanged: '2.10'
739
844
 
740
845
  Rails/WhereExists:
741
846
  Description: 'Prefer `exists?(...)` over `where(...).exists?`.'
742
847
  Enabled: 'pending'
848
+ SafeAutoCorrect: false
743
849
  EnforcedStyle: exists
744
850
  SupportedStyles:
745
851
  - exists
746
852
  - where
747
853
  VersionAdded: '2.7'
748
- VersionChanged: '2.8'
854
+ VersionChanged: '2.10'
749
855
 
750
856
  Rails/WhereNot:
751
857
  Description: 'Use `where.not(...)` instead of manually constructing negated SQL in `where`.'
@@ -0,0 +1,7 @@
1
+ #
2
+ # Configuration for obsoletion.
3
+ #
4
+ # See: https://docs.rubocop.org/rubocop/extensions.html#config-obsoletions
5
+ #
6
+ extracted:
7
+ Rails/*: ~
@@ -8,6 +8,13 @@ module RuboCop
8
8
 
9
9
  WHERE_METHODS = %i[where rewhere].freeze
10
10
 
11
+ def_node_matcher :active_record?, <<~PATTERN
12
+ {
13
+ (const nil? :ApplicationRecord)
14
+ (const (const nil? :ActiveRecord) :Base)
15
+ }
16
+ PATTERN
17
+
11
18
  def_node_search :find_set_table_name, <<~PATTERN
12
19
  (send self :table_name= {str sym})
13
20
  PATTERN
@@ -16,6 +23,10 @@ module RuboCop
16
23
  (send nil? :belongs_to {str sym} ...)
17
24
  PATTERN
18
25
 
26
+ def inherit_active_record_base?(node)
27
+ node.each_ancestor(:class).any? { |class_node| active_record?(class_node.parent_class) }
28
+ end
29
+
19
30
  def external_dependency_checksum
20
31
  return @external_dependency_checksum if defined?(@external_dependency_checksum)
21
32
 
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop checks for migrations using `add_column` that have an `index`
7
+ # key. `add_column` does not accept `index`, but also does not raise an
8
+ # error for extra keys, so it is possible to mistakenly add the key without
9
+ # realizing it will not actually add an index.
10
+ #
11
+ # @example
12
+ # # bad (will not add an index)
13
+ # add_column :table, :column, :integer, index: true
14
+ #
15
+ # # good
16
+ # add_column :table, :column, :integer
17
+ # add_index :table, :column
18
+ #
19
+ class AddColumnIndex < Base
20
+ extend AutoCorrector
21
+ include RangeHelp
22
+
23
+ MSG = '`add_column` does not accept an `index` key, use `add_index` instead.'
24
+ RESTRICT_ON_SEND = %i[add_column].freeze
25
+
26
+ # @!method add_column_with_index(node)
27
+ def_node_matcher :add_column_with_index, <<~PATTERN
28
+ (
29
+ send nil? :add_column $_table $_column
30
+ <(hash <$(pair {(sym :index) (str "index")} $_) ...>) ...>
31
+ )
32
+ PATTERN
33
+
34
+ def on_send(node)
35
+ table, column, pair, value = add_column_with_index(node)
36
+ return unless pair
37
+
38
+ add_offense(pair) do |corrector|
39
+ corrector.remove(index_range(pair))
40
+
41
+ add_index = "add_index #{table.source}, #{column.source}"
42
+ add_index_opts = ''
43
+
44
+ if value.hash_type?
45
+ hash = value.loc.expression.adjust(begin_pos: 1, end_pos: -1).source.strip
46
+ add_index_opts = ", #{hash}"
47
+ end
48
+
49
+ corrector.insert_after(node, "\n#{add_index}#{add_index_opts}")
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def index_range(pair_node)
56
+ range_with_surrounding_comma(
57
+ range_with_surrounding_space(range: pair_node.loc.expression, side: :left),
58
+ :left
59
+ )
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -75,7 +75,7 @@ module RuboCop
75
75
  def on_send(node)
76
76
  default_attribute(node) do |attribute|
77
77
  value = attribute.children.last
78
- return unless TYPE_OFFENDERS.any? { |type| value.type == type }
78
+ return unless TYPE_OFFENDERS.any?(value.type)
79
79
 
80
80
  add_offense(value) do |corrector|
81
81
  expression = default_attribute(node).children.last
@@ -68,7 +68,7 @@ module RuboCop
68
68
  RESTRICT_ON_SEND = %i[belongs_to].freeze
69
69
 
70
70
  def_node_matcher :match_belongs_to_with_options, <<~PATTERN
71
- (send _ :belongs_to _
71
+ (send _ :belongs_to ...
72
72
  (hash <$(pair (sym :required) ${true false}) ...>)
73
73
  )
74
74
  PATTERN
@@ -6,6 +6,10 @@ module RuboCop
6
6
  # This cop checks for code that can be written with simpler conditionals
7
7
  # using `Object#blank?` defined by Active Support.
8
8
  #
9
+ # This cop is marked as unsafe auto-correction, because `' '.empty?` returns false,
10
+ # but `' '.blank?` returns true. Therefore, auto-correction is not compatible
11
+ # if the receiver is a non-empty blank string, tab, or newline meta characters.
12
+ #
9
13
  # Interaction with `Style/UnlessElse`:
10
14
  # The configuration of `NotPresent` will not produce an offense in the
11
15
  # context of `unless else` if `Style/UnlessElse` is inabled. This is
@@ -194,7 +194,11 @@ module RuboCop
194
194
  def database_yaml
195
195
  return nil unless File.exist?('config/database.yml')
196
196
 
197
- yaml = YAML.load_file('config/database.yml')
197
+ yaml = if YAML.respond_to?(:unsafe_load_file)
198
+ YAML.unsafe_load_file('config/database.yml')
199
+ else
200
+ YAML.load_file('config/database.yml')
201
+ end
198
202
  return nil unless yaml.is_a? Hash
199
203
 
200
204
  config = yaml['development']
@@ -28,19 +28,34 @@ module RuboCop
28
28
  MSG = 'Use `tag` instead of `content_tag`.'
29
29
  RESTRICT_ON_SEND = %i[content_tag].freeze
30
30
 
31
+ def on_new_investigation
32
+ @corrected_nodes = nil
33
+ end
34
+
31
35
  def on_send(node)
32
36
  first_argument = node.first_argument
33
- return unless first_argument
34
-
35
- return if first_argument.variable? || first_argument.send_type? || first_argument.const_type?
37
+ return if !first_argument ||
38
+ allowed_argument?(first_argument) ||
39
+ corrected_ancestor?(node)
36
40
 
37
41
  add_offense(node) do |corrector|
38
42
  autocorrect(corrector, node)
43
+
44
+ @corrected_nodes ||= Set.new.compare_by_identity
45
+ @corrected_nodes.add(node)
39
46
  end
40
47
  end
41
48
 
42
49
  private
43
50
 
51
+ def corrected_ancestor?(node)
52
+ node.each_ancestor(:send).any? { |ancestor| @corrected_nodes&.include?(ancestor) }
53
+ end
54
+
55
+ def allowed_argument?(argument)
56
+ argument.variable? || argument.send_type? || argument.const_type? || argument.splat_type?
57
+ end
58
+
44
59
  def autocorrect(corrector, node)
45
60
  if method_name?(node.first_argument)
46
61
  range = correction_range(node)