rubocop-rails 2.6.0 → 2.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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -0
  3. data/config/default.yml +189 -6
  4. data/lib/rubocop/cop/mixin/active_record_helper.rb +12 -3
  5. data/lib/rubocop/cop/mixin/enforce_superclass.rb +40 -0
  6. data/lib/rubocop/cop/mixin/index_method.rb +25 -11
  7. data/lib/rubocop/cop/rails/action_filter.rb +10 -14
  8. data/lib/rubocop/cop/rails/active_record_aliases.rb +13 -17
  9. data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +148 -0
  10. data/lib/rubocop/cop/rails/active_record_override.rb +1 -1
  11. data/lib/rubocop/cop/rails/active_support_aliases.rb +12 -21
  12. data/lib/rubocop/cop/rails/after_commit_override.rb +91 -0
  13. data/lib/rubocop/cop/rails/application_controller.rb +3 -7
  14. data/lib/rubocop/cop/rails/application_job.rb +2 -1
  15. data/lib/rubocop/cop/rails/application_mailer.rb +2 -7
  16. data/lib/rubocop/cop/rails/application_record.rb +2 -7
  17. data/lib/rubocop/cop/rails/arel_star.rb +41 -0
  18. data/lib/rubocop/cop/rails/assert_not.rb +8 -10
  19. data/lib/rubocop/cop/rails/attribute_default_block_value.rb +90 -0
  20. data/lib/rubocop/cop/rails/belongs_to.rb +9 -18
  21. data/lib/rubocop/cop/rails/blank.rb +27 -27
  22. data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -1
  23. data/lib/rubocop/cop/rails/content_tag.rb +20 -33
  24. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +2 -1
  25. data/lib/rubocop/cop/rails/date.rb +10 -11
  26. data/lib/rubocop/cop/rails/default_scope.rb +61 -0
  27. data/lib/rubocop/cop/rails/delegate.rb +10 -10
  28. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +7 -8
  29. data/lib/rubocop/cop/rails/dynamic_find_by.rb +13 -11
  30. data/lib/rubocop/cop/rails/enum_hash.rb +11 -10
  31. data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -1
  32. data/lib/rubocop/cop/rails/environment_comparison.rb +18 -14
  33. data/lib/rubocop/cop/rails/exit.rb +4 -10
  34. data/lib/rubocop/cop/rails/file_path.rb +5 -4
  35. data/lib/rubocop/cop/rails/find_by.rb +13 -13
  36. data/lib/rubocop/cop/rails/find_by_id.rb +94 -0
  37. data/lib/rubocop/cop/rails/find_each.rb +16 -14
  38. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +3 -2
  39. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +4 -7
  40. data/lib/rubocop/cop/rails/helper_instance_variable.rb +4 -2
  41. data/lib/rubocop/cop/rails/http_positional_arguments.rb +25 -21
  42. data/lib/rubocop/cop/rails/http_status.rb +7 -9
  43. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +8 -6
  44. data/lib/rubocop/cop/rails/index_by.rb +11 -2
  45. data/lib/rubocop/cop/rails/index_with.rb +11 -2
  46. data/lib/rubocop/cop/rails/inquiry.rb +39 -0
  47. data/lib/rubocop/cop/rails/inverse_of.rb +3 -2
  48. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +17 -15
  49. data/lib/rubocop/cop/rails/link_to_blank.rb +20 -20
  50. data/lib/rubocop/cop/rails/mailer_name.rb +86 -0
  51. data/lib/rubocop/cop/rails/match_route.rb +120 -0
  52. data/lib/rubocop/cop/rails/negate_include.rb +41 -0
  53. data/lib/rubocop/cop/rails/not_null_column.rb +2 -1
  54. data/lib/rubocop/cop/rails/order_by_id.rb +52 -0
  55. data/lib/rubocop/cop/rails/output.rb +5 -2
  56. data/lib/rubocop/cop/rails/output_safety.rb +3 -2
  57. data/lib/rubocop/cop/rails/pick.rb +21 -15
  58. data/lib/rubocop/cop/rails/pluck.rb +56 -0
  59. data/lib/rubocop/cop/rails/pluck_id.rb +56 -0
  60. data/lib/rubocop/cop/rails/pluck_in_where.rb +70 -0
  61. data/lib/rubocop/cop/rails/pluralization_grammar.rb +10 -14
  62. data/lib/rubocop/cop/rails/presence.rb +12 -13
  63. data/lib/rubocop/cop/rails/present.rb +30 -24
  64. data/lib/rubocop/cop/rails/rake_environment.rb +9 -11
  65. data/lib/rubocop/cop/rails/read_write_attribute.rb +12 -11
  66. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +29 -31
  67. data/lib/rubocop/cop/rails/redundant_foreign_key.rb +9 -12
  68. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +11 -10
  69. data/lib/rubocop/cop/rails/reflection_class_name.rb +4 -3
  70. data/lib/rubocop/cop/rails/refute_methods.rb +9 -10
  71. data/lib/rubocop/cop/rails/relative_date_constant.rb +20 -9
  72. data/lib/rubocop/cop/rails/render_inline.rb +41 -0
  73. data/lib/rubocop/cop/rails/render_plain_text.rb +71 -0
  74. data/lib/rubocop/cop/rails/request_referer.rb +7 -7
  75. data/lib/rubocop/cop/rails/reversible_migration.rb +82 -7
  76. data/lib/rubocop/cop/rails/safe_navigation.rb +12 -11
  77. data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +5 -10
  78. data/lib/rubocop/cop/rails/save_bang.rb +19 -22
  79. data/lib/rubocop/cop/rails/scope_args.rb +2 -1
  80. data/lib/rubocop/cop/rails/short_i18n.rb +74 -0
  81. data/lib/rubocop/cop/rails/skips_model_validations.rb +46 -11
  82. data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +82 -0
  83. data/lib/rubocop/cop/rails/time_zone.rb +22 -20
  84. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +10 -10
  85. data/lib/rubocop/cop/rails/unique_validation_without_index.rb +18 -8
  86. data/lib/rubocop/cop/rails/unknown_env.rb +15 -4
  87. data/lib/rubocop/cop/rails/validation.rb +15 -14
  88. data/lib/rubocop/cop/rails/where_equals.rb +94 -0
  89. data/lib/rubocop/cop/rails/where_exists.rb +126 -0
  90. data/lib/rubocop/cop/rails/where_not.rb +97 -0
  91. data/lib/rubocop/cop/rails_cops.rb +22 -0
  92. data/lib/rubocop/rails/schema_loader.rb +4 -4
  93. data/lib/rubocop/rails/schema_loader/schema.rb +5 -5
  94. data/lib/rubocop/rails/version.rb +5 -1
  95. metadata +37 -9
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop enforces the use of `ids` over `pluck(:id)` and `pluck(primary_key)`.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # User.pluck(:id)
11
+ # user.posts.pluck(:id)
12
+ #
13
+ # def self.user_ids
14
+ # pluck(primary_key)
15
+ # end
16
+ #
17
+ # # good
18
+ # User.ids
19
+ # user.posts.ids
20
+ #
21
+ # def self.user_ids
22
+ # ids
23
+ # end
24
+ #
25
+ class PluckId < Base
26
+ include RangeHelp
27
+ include ActiveRecordHelper
28
+ extend AutoCorrector
29
+
30
+ MSG = 'Use `ids` instead of `%<bad_method>s`.'
31
+ RESTRICT_ON_SEND = %i[pluck].freeze
32
+
33
+ def_node_matcher :pluck_id_call?, <<~PATTERN
34
+ (send _ :pluck {(sym :id) (send nil? :primary_key)})
35
+ PATTERN
36
+
37
+ def on_send(node)
38
+ return if !pluck_id_call?(node) || in_where?(node)
39
+
40
+ range = offense_range(node)
41
+ message = format(MSG, bad_method: range.source)
42
+
43
+ add_offense(range, message: message) do |corrector|
44
+ corrector.replace(offense_range(node), 'ids')
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def offense_range(node)
51
+ range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop identifies places where `pluck` is used in `where` query methods
7
+ # and can be replaced with `select`.
8
+ #
9
+ # Since `pluck` is an eager method and hits the database immediately,
10
+ # using `select` helps to avoid additional database queries.
11
+ #
12
+ # This cop has two different enforcement modes. When the EnforcedStyle
13
+ # is conservative (the default) then only calls to `pluck` on a constant
14
+ # (i.e. a model class) in the `where` is used as offenses.
15
+ #
16
+ # When the EnforcedStyle is aggressive then all calls to `pluck` in the
17
+ # `where` is used as offenses. This may lead to false positives
18
+ # as the cop cannot replace to `select` between calls to `pluck` on an
19
+ # `ActiveRecord::Relation` instance vs a call to `pluck` on an `Array` instance.
20
+ #
21
+ # @example
22
+ # # bad
23
+ # Post.where(user_id: User.active.pluck(:id))
24
+ #
25
+ # # good
26
+ # Post.where(user_id: User.active.select(:id))
27
+ # Post.where(user_id: active_users.select(:id))
28
+ #
29
+ # @example EnforcedStyle: conservative (default)
30
+ # # good
31
+ # Post.where(user_id: active_users.pluck(:id))
32
+ #
33
+ # @example EnforcedStyle: aggressive
34
+ # # bad
35
+ # Post.where(user_id: active_users.pluck(:id))
36
+ #
37
+ class PluckInWhere < Base
38
+ include ActiveRecordHelper
39
+ include ConfigurableEnforcedStyle
40
+ extend AutoCorrector
41
+
42
+ MSG = 'Use `select` instead of `pluck` within `where` query method.'
43
+ RESTRICT_ON_SEND = %i[pluck].freeze
44
+
45
+ def on_send(node)
46
+ return unless in_where?(node)
47
+ return if style == :conservative && !root_receiver(node)&.const_type?
48
+
49
+ range = node.loc.selector
50
+
51
+ add_offense(range) do |corrector|
52
+ corrector.replace(range, 'select')
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def root_receiver(node)
59
+ receiver = node.receiver
60
+
61
+ if receiver&.send_type?
62
+ root_receiver(receiver)
63
+ else
64
+ receiver
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -14,7 +14,9 @@ module RuboCop
14
14
  # # good
15
15
  # 3.days.ago
16
16
  # 1.month.ago
17
- class PluralizationGrammar < Cop
17
+ class PluralizationGrammar < Base
18
+ extend AutoCorrector
19
+
18
20
  SINGULAR_DURATION_METHODS = { second: :seconds,
19
21
  minute: :minutes,
20
22
  hour: :hours,
@@ -24,21 +26,18 @@ module RuboCop
24
26
  month: :months,
25
27
  year: :years }.freeze
26
28
 
29
+ RESTRICT_ON_SEND = SINGULAR_DURATION_METHODS.keys + SINGULAR_DURATION_METHODS.values
30
+
27
31
  PLURAL_DURATION_METHODS = SINGULAR_DURATION_METHODS.invert.freeze
28
32
 
29
33
  MSG = 'Prefer `%<number>s.%<correct>s`.'
30
34
 
31
35
  def on_send(node)
32
- return unless duration_method?(node.method_name)
33
- return unless literal_number?(node.receiver)
36
+ return unless duration_method?(node.method_name) && literal_number?(node.receiver) && offense?(node)
34
37
 
35
- return unless offense?(node)
36
-
37
- add_offense(node)
38
- end
38
+ number, = *node.receiver
39
39
 
40
- def autocorrect(node)
41
- lambda do |corrector|
40
+ add_offense(node, message: message(number, node.method_name)) do |corrector|
42
41
  method_name = node.loc.selector.source
43
42
 
44
43
  corrector.replace(node.loc.selector, correct_method(method_name))
@@ -47,11 +46,8 @@ module RuboCop
47
46
 
48
47
  private
49
48
 
50
- def message(node)
51
- number, = *node.receiver
52
-
53
- format(MSG, number: number,
54
- correct: correct_method(node.method_name.to_s))
49
+ def message(number, method_name)
50
+ format(MSG, number: number, correct: correct_method(method_name))
55
51
  end
56
52
 
57
53
  def correct_method(method_name)
@@ -37,8 +37,9 @@ module RuboCop
37
37
  #
38
38
  # # good
39
39
  # a.presence || b
40
- class Presence < Cop
40
+ class Presence < Base
41
41
  include RangeHelp
42
+ extend AutoCorrector
42
43
 
43
44
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
44
45
 
@@ -76,28 +77,26 @@ module RuboCop
76
77
  return if ignore_if_node?(node)
77
78
 
78
79
  redundant_receiver_and_other(node) do |receiver, other|
79
- add_offense(node, message: message(node, receiver, other)) unless ignore_other_node?(other) || receiver.nil?
80
+ return if ignore_other_node?(other) || receiver.nil?
81
+
82
+ register_offense(node, receiver, other)
80
83
  end
81
84
 
82
85
  redundant_negative_receiver_and_other(node) do |receiver, other|
83
- add_offense(node, message: message(node, receiver, other)) unless ignore_other_node?(other) || receiver.nil?
86
+ return if ignore_other_node?(other) || receiver.nil?
87
+
88
+ register_offense(node, receiver, other)
84
89
  end
85
90
  end
86
91
 
87
- def autocorrect(node)
88
- lambda do |corrector|
89
- redundant_receiver_and_other(node) do |receiver, other|
90
- corrector.replace(node.source_range, replacement(receiver, other))
91
- end
92
+ private
92
93
 
93
- redundant_negative_receiver_and_other(node) do |receiver, other|
94
- corrector.replace(node.source_range, replacement(receiver, other))
95
- end
94
+ def register_offense(node, receiver, other)
95
+ add_offense(node, message: message(node, receiver, other)) do |corrector|
96
+ corrector.replace(node.source_range, replacement(receiver, other))
96
97
  end
97
98
  end
98
99
 
99
- private
100
-
101
100
  def ignore_if_node?(node)
102
101
  node.elsif?
103
102
  end
@@ -43,12 +43,15 @@ module RuboCop
43
43
  #
44
44
  # # good
45
45
  # something if foo.present?
46
- class Present < Cop
46
+ class Present < Base
47
+ extend AutoCorrector
48
+
47
49
  MSG_NOT_BLANK = 'Use `%<prefer>s` instead of `%<current>s`.'
48
50
  MSG_EXISTS_AND_NOT_EMPTY = 'Use `%<prefer>s` instead of ' \
49
51
  '`%<current>s`.'
50
52
  MSG_UNLESS_BLANK = 'Use `if %<prefer>s` instead of ' \
51
53
  '`%<current>s`.'
54
+ RESTRICT_ON_SEND = %i[!].freeze
52
55
 
53
56
  def_node_matcher :exists_and_not_empty?, <<~PATTERN
54
57
  (and
@@ -74,10 +77,11 @@ module RuboCop
74
77
  return unless cop_config['NotBlank']
75
78
 
76
79
  not_blank?(node) do |receiver|
77
- add_offense(node,
78
- message: format(MSG_NOT_BLANK,
79
- prefer: replacement(receiver),
80
- current: node.source))
80
+ message = format(MSG_NOT_BLANK, prefer: replacement(receiver), current: node.source)
81
+
82
+ add_offense(node, message: message) do |corrector|
83
+ autocorrect(corrector, node)
84
+ end
81
85
  end
82
86
  end
83
87
 
@@ -87,10 +91,11 @@ module RuboCop
87
91
  exists_and_not_empty?(node) do |var1, var2|
88
92
  return unless var1 == var2
89
93
 
90
- add_offense(node,
91
- message: format(MSG_EXISTS_AND_NOT_EMPTY,
92
- prefer: replacement(var1),
93
- current: node.source))
94
+ message = format(MSG_EXISTS_AND_NOT_EMPTY, prefer: replacement(var1), current: node.source)
95
+
96
+ add_offense(node, message: message) do |corrector|
97
+ autocorrect(corrector, node)
98
+ end
94
99
  end
95
100
  end
96
101
 
@@ -100,7 +105,9 @@ module RuboCop
100
105
  exists_and_not_empty?(node) do |var1, var2|
101
106
  return unless var1 == var2
102
107
 
103
- add_offense(node, message: MSG_EXISTS_AND_NOT_EMPTY)
108
+ add_offense(node, message: MSG_EXISTS_AND_NOT_EMPTY) do |corrector|
109
+ autocorrect(corrector, node)
110
+ end
104
111
  end
105
112
  end
106
113
 
@@ -113,25 +120,24 @@ module RuboCop
113
120
  range = unless_condition(node, method_call)
114
121
  msg = format(MSG_UNLESS_BLANK, prefer: replacement(receiver),
115
122
  current: range.source)
116
- add_offense(node, location: range, message: msg)
123
+ add_offense(range, message: msg) do |corrector|
124
+ autocorrect(corrector, node)
125
+ end
117
126
  end
118
127
  end
119
128
 
120
- def autocorrect(node)
121
- lambda do |corrector|
122
- method_call, variable1 = unless_blank?(node)
123
-
124
- if method_call
125
- corrector.replace(node.loc.keyword, 'if')
126
- range = method_call.loc.expression
127
- else
128
- variable1, _variable2 =
129
- exists_and_not_empty?(node) || not_blank?(node)
130
- range = node.loc.expression
131
- end
129
+ def autocorrect(corrector, node)
130
+ method_call, variable1 = unless_blank?(node)
132
131
 
133
- corrector.replace(range, replacement(variable1))
132
+ if method_call
133
+ corrector.replace(node.loc.keyword, 'if')
134
+ range = method_call.loc.expression
135
+ else
136
+ variable1, _variable2 = exists_and_not_empty?(node) || not_blank?(node)
137
+ range = node.loc.expression
134
138
  end
139
+
140
+ corrector.replace(range, replacement(variable1))
135
141
  end
136
142
 
137
143
  private
@@ -25,7 +25,9 @@ module RuboCop
25
25
  # do_something
26
26
  # end
27
27
  #
28
- class RakeEnvironment < Cop
28
+ class RakeEnvironment < Base
29
+ extend AutoCorrector
30
+
29
31
  MSG = 'Include `:environment` task as a dependency for all Rake tasks.'
30
32
 
31
33
  def_node_matcher :task_definition?, <<~PATTERN
@@ -37,16 +39,12 @@ module RuboCop
37
39
  return if task_name(task_method) == :default
38
40
  return if with_dependencies?(task_method)
39
41
 
40
- add_offense(task_method)
41
- end
42
- end
42
+ add_offense(task_method) do |corrector|
43
+ task_name = task_method.arguments[0]
44
+ task_dependency = correct_task_dependency(task_name)
43
45
 
44
- def autocorrect(node)
45
- lambda do |corrector|
46
- task_name = node.arguments[0]
47
- task_dependency = correct_task_dependency(task_name)
48
-
49
- corrector.replace(task_name.loc.expression, task_dependency)
46
+ corrector.replace(task_name.loc.expression, task_dependency)
47
+ end
50
48
  end
51
49
  end
52
50
 
@@ -54,7 +52,7 @@ module RuboCop
54
52
 
55
53
  def correct_task_dependency(task_name)
56
54
  if task_name.sym_type?
57
- task_name.source.delete(':|\'|"') + ': :environment'
55
+ "#{task_name.source.delete(':|\'|"')}: :environment"
58
56
  else
59
57
  "#{task_name.source} => :environment"
60
58
  end
@@ -23,8 +23,11 @@ module RuboCop
23
23
  # # good
24
24
  # x = self[:attr]
25
25
  # self[:attr] = val
26
- class ReadWriteAttribute < Cop
26
+ class ReadWriteAttribute < Base
27
+ extend AutoCorrector
28
+
27
29
  MSG = 'Prefer `%<prefer>s` over `%<current>s`.'
30
+ RESTRICT_ON_SEND = %i[read_attribute write_attribute].freeze
28
31
 
29
32
  def_node_matcher :read_write_attribute?, <<~PATTERN
30
33
  {
@@ -36,18 +39,16 @@ module RuboCop
36
39
  def on_send(node)
37
40
  return unless read_write_attribute?(node)
38
41
 
39
- add_offense(node, location: :selector)
40
- end
42
+ add_offense(node.loc.selector, message: message(node)) do |corrector|
43
+ case node.method_name
44
+ when :read_attribute
45
+ replacement = read_attribute_replacement(node)
46
+ when :write_attribute
47
+ replacement = write_attribute_replacement(node)
48
+ end
41
49
 
42
- def autocorrect(node)
43
- case node.method_name
44
- when :read_attribute
45
- replacement = read_attribute_replacement(node)
46
- when :write_attribute
47
- replacement = write_attribute_replacement(node)
50
+ corrector.replace(node.source_range, replacement)
48
51
  end
49
-
50
- ->(corrector) { corrector.replace(node.source_range, replacement) }
51
52
  end
52
53
 
53
54
  private
@@ -26,8 +26,9 @@ module RuboCop
26
26
  # # Here, `nil` is valid but `''` is not
27
27
  # validates :x, length: { is: 5 }, allow_nil: true, allow_blank: false
28
28
  #
29
- class RedundantAllowNil < Cop
29
+ class RedundantAllowNil < Base
30
30
  include RangeHelp
31
+ extend AutoCorrector
31
32
 
32
33
  MSG_SAME =
33
34
  '`allow_nil` is redundant when `allow_blank` has the same value.'
@@ -35,59 +36,56 @@ module RuboCop
35
36
  MSG_ALLOW_NIL_FALSE =
36
37
  '`allow_nil: false` is redundant when `allow_blank` is true.'
37
38
 
38
- def on_send(node)
39
- return unless node.method?(:validates)
39
+ RESTRICT_ON_SEND = %i[validates].freeze
40
40
 
41
+ def on_send(node)
41
42
  allow_nil, allow_blank = find_allow_nil_and_allow_blank(node)
42
43
  return unless allow_nil && allow_blank
43
44
 
44
45
  allow_nil_val = allow_nil.children.last
45
46
  allow_blank_val = allow_blank.children.last
46
47
 
47
- offense(allow_nil_val, allow_blank_val, allow_nil)
48
+ if allow_nil_val.type == allow_blank_val.type
49
+ register_offense(allow_nil, MSG_SAME)
50
+ elsif allow_nil_val.false_type? && allow_blank_val.true_type?
51
+ register_offense(allow_nil, MSG_ALLOW_NIL_FALSE)
52
+ end
48
53
  end
49
54
 
50
- def autocorrect(node)
51
- prv_sib = previous_sibling(node)
52
- nxt_sib = next_sibling(node)
55
+ private
56
+
57
+ def register_offense(allow_nil, message)
58
+ add_offense(allow_nil, message: message) do |corrector|
59
+ prv_sib = previous_sibling(allow_nil)
60
+ nxt_sib = next_sibling(allow_nil)
53
61
 
54
- lambda do |corrector|
55
62
  if nxt_sib
56
- corrector.remove(range_between(node_beg(node), node_beg(nxt_sib)))
63
+ corrector.remove(range_between(node_beg(allow_nil), node_beg(nxt_sib)))
57
64
  elsif prv_sib
58
- corrector.remove(range_between(node_end(prv_sib), node_end(node)))
65
+ corrector.remove(range_between(node_end(prv_sib), node_end(allow_nil)))
59
66
  else
60
- corrector.remove(node.loc.expression)
67
+ corrector.remove(allow_nil.loc.expression)
61
68
  end
62
69
  end
63
70
  end
64
71
 
65
- private
66
-
67
- def offense(allow_nil_val, allow_blank_val, allow_nil)
68
- if allow_nil_val.type == allow_blank_val.type
69
- add_offense(allow_nil, message: MSG_SAME)
70
- elsif allow_nil_val.false_type? && allow_blank_val.true_type?
71
- add_offense(allow_nil, message: MSG_ALLOW_NIL_FALSE)
72
- end
73
- end
74
-
75
72
  def find_allow_nil_and_allow_blank(node)
76
- allow_nil = nil
77
- allow_blank = nil
73
+ allow_nil, allow_blank = nil
78
74
 
79
- node.each_descendant do |descendant|
80
- next unless descendant.pair_type?
75
+ node.each_child_node do |child_node|
76
+ if child_node.pair_type?
77
+ key = child_node.children.first.source
81
78
 
82
- key = descendant.children.first.source
83
-
84
- allow_nil = descendant if key == 'allow_nil'
85
- allow_blank = descendant if key == 'allow_blank'
79
+ allow_nil = child_node if key == 'allow_nil'
80
+ allow_blank = child_node if key == 'allow_blank'
81
+ end
82
+ return [allow_nil, allow_blank] if allow_nil && allow_blank
86
83
 
87
- break if allow_nil && allow_blank
84
+ found_in_children_nodes = find_allow_nil_and_allow_blank(child_node)
85
+ return found_in_children_nodes if found_in_children_nodes
88
86
  end
89
87
 
90
- [allow_nil, allow_blank]
88
+ nil
91
89
  end
92
90
 
93
91
  def previous_sibling(node)