rubocop-rails 2.26.2 → 2.32.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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +45 -7
  4. data/config/default.yml +87 -49
  5. data/lib/rubocop/cop/mixin/active_record_helper.rb +2 -2
  6. data/lib/rubocop/cop/mixin/active_record_migrations_helper.rb +2 -2
  7. data/lib/rubocop/cop/mixin/database_type_resolvable.rb +2 -2
  8. data/lib/rubocop/cop/mixin/enforce_superclass.rb +6 -1
  9. data/lib/rubocop/cop/mixin/index_method.rb +69 -61
  10. data/lib/rubocop/cop/mixin/routes_helper.rb +20 -0
  11. data/lib/rubocop/cop/mixin/target_rails_version.rb +3 -5
  12. data/lib/rubocop/cop/rails/add_column_index.rb +1 -0
  13. data/lib/rubocop/cop/rails/arel_star.rb +5 -5
  14. data/lib/rubocop/cop/rails/belongs_to.rb +1 -1
  15. data/lib/rubocop/cop/rails/blank.rb +1 -1
  16. data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -0
  17. data/lib/rubocop/cop/rails/content_tag.rb +1 -1
  18. data/lib/rubocop/cop/rails/dangerous_column_names.rb +2 -0
  19. data/lib/rubocop/cop/rails/delegate.rb +53 -7
  20. data/lib/rubocop/cop/rails/duplicate_association.rb +8 -4
  21. data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +1 -3
  22. data/lib/rubocop/cop/rails/enum_syntax.rb +2 -0
  23. data/lib/rubocop/cop/rails/env_local.rb +26 -3
  24. data/lib/rubocop/cop/rails/file_path.rb +61 -9
  25. data/lib/rubocop/cop/rails/http_positional_arguments.rb +7 -0
  26. data/lib/rubocop/cop/rails/index_by.rb +37 -12
  27. data/lib/rubocop/cop/rails/index_with.rb +37 -12
  28. data/lib/rubocop/cop/rails/inquiry.rb +1 -1
  29. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +11 -1
  30. data/lib/rubocop/cop/rails/match_route.rb +1 -9
  31. data/lib/rubocop/cop/rails/multiple_route_paths.rb +50 -0
  32. data/lib/rubocop/cop/rails/not_null_column.rb +6 -2
  33. data/lib/rubocop/cop/rails/output.rb +1 -2
  34. data/lib/rubocop/cop/rails/pluck.rb +30 -4
  35. data/lib/rubocop/cop/rails/pluralization_grammar.rb +1 -1
  36. data/lib/rubocop/cop/rails/presence.rb +1 -1
  37. data/lib/rubocop/cop/rails/present.rb +1 -1
  38. data/lib/rubocop/cop/rails/redundant_active_record_all_method.rb +1 -1
  39. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +6 -1
  40. data/lib/rubocop/cop/rails/reflection_class_name.rb +2 -2
  41. data/lib/rubocop/cop/rails/relative_date_constant.rb +1 -1
  42. data/lib/rubocop/cop/rails/reversible_migration.rb +4 -1
  43. data/lib/rubocop/cop/rails/root_pathname_methods.rb +6 -1
  44. data/lib/rubocop/cop/rails/save_bang.rb +8 -7
  45. data/lib/rubocop/cop/rails/schema_comment.rb +2 -1
  46. data/lib/rubocop/cop/rails/select_map.rb +3 -2
  47. data/lib/rubocop/cop/rails/skips_model_validations.rb +1 -1
  48. data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +1 -1
  49. data/lib/rubocop/cop/rails/strip_heredoc.rb +1 -1
  50. data/lib/rubocop/cop/rails/strong_parameters_expect.rb +104 -0
  51. data/lib/rubocop/cop/rails/three_state_boolean_column.rb +3 -2
  52. data/lib/rubocop/cop/rails/time_zone.rb +16 -7
  53. data/lib/rubocop/cop/rails/transaction_exit_statement.rb +7 -2
  54. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +10 -33
  55. data/lib/rubocop/cop/rails/unique_validation_without_index.rb +1 -1
  56. data/lib/rubocop/cop/rails/where_range.rb +1 -1
  57. data/lib/rubocop/cop/rails_cops.rb +3 -0
  58. data/lib/rubocop/rails/migration_file_skippable.rb +54 -0
  59. data/lib/rubocop/rails/plugin.rb +48 -0
  60. data/lib/rubocop/rails/version.rb +1 -1
  61. data/lib/rubocop/rails.rb +1 -8
  62. data/lib/rubocop-rails.rb +4 -5
  63. metadata +28 -12
  64. data/lib/rubocop/rails/inject.rb +0 -18
@@ -29,18 +29,34 @@ module RuboCop
29
29
  PATTERN
30
30
 
31
31
  def_node_matcher :on_bad_to_h, <<~PATTERN
32
- (block
33
- (call _ :to_h)
34
- (args (arg $_el))
35
- (array $_ (lvar _el)))
32
+ {
33
+ (block
34
+ (call _ :to_h)
35
+ (args (arg $_el))
36
+ (array $_ (lvar _el)))
37
+ (numblock
38
+ (call _ :to_h) $1
39
+ (array $_ (lvar :_1)))
40
+ (itblock
41
+ (call _ :to_h) $:it
42
+ (array $_ (lvar :it)))
43
+ }
36
44
  PATTERN
37
45
 
38
46
  def_node_matcher :on_bad_map_to_h, <<~PATTERN
39
47
  (call
40
- (block
41
- (call _ {:map :collect})
42
- (args (arg $_el))
43
- (array $_ (lvar _el)))
48
+ {
49
+ (block
50
+ (call _ {:map :collect})
51
+ (args (arg $_el))
52
+ (array $_ (lvar _el)))
53
+ (numblock
54
+ (call _ {:map :collect}) $1
55
+ (array $_ (lvar :_1)))
56
+ (itblock
57
+ (call _ {:map :collect}) $:it
58
+ (array $_ (lvar :it)))
59
+ }
44
60
  :to_h)
45
61
  PATTERN
46
62
 
@@ -48,10 +64,19 @@ module RuboCop
48
64
  (send
49
65
  (const {nil? cbase} :Hash)
50
66
  :[]
51
- (block
52
- (call _ {:map :collect})
53
- (args (arg $_el))
54
- (array $_ (lvar _el))))
67
+ {
68
+ (block
69
+ (call _ {:map :collect})
70
+ (args (arg $_el))
71
+ (array $_ (lvar _el)))
72
+ (numblock
73
+ (call _ {:map :collect}) $1
74
+ (array $_ (lvar :_1)))
75
+ (itblock
76
+ (call _ {:map :collect}) $:it
77
+ (array $_ (lvar :it)))
78
+ }
79
+ )
55
80
  PATTERN
56
81
 
57
82
  private
@@ -32,18 +32,34 @@ module RuboCop
32
32
  PATTERN
33
33
 
34
34
  def_node_matcher :on_bad_to_h, <<~PATTERN
35
- (block
36
- (call _ :to_h)
37
- (args (arg $_el))
38
- (array (lvar _el) $_))
35
+ {
36
+ (block
37
+ (call _ :to_h)
38
+ (args (arg $_el))
39
+ (array (lvar _el) $_))
40
+ (numblock
41
+ (call _ :to_h) $1
42
+ (array (lvar :_1) $_))
43
+ (itblock
44
+ (call _ :to_h) $:it
45
+ (array (lvar :it) $_))
46
+ }
39
47
  PATTERN
40
48
 
41
49
  def_node_matcher :on_bad_map_to_h, <<~PATTERN
42
50
  (call
43
- (block
44
- (call _ {:map :collect})
45
- (args (arg $_el))
46
- (array (lvar _el) $_))
51
+ {
52
+ (block
53
+ (call _ {:map :collect})
54
+ (args (arg $_el))
55
+ (array (lvar _el) $_))
56
+ (numblock
57
+ (call _ {:map :collect}) $1
58
+ (array (lvar :_1) $_))
59
+ (itblock
60
+ (call _ {:map :collect}) $:it
61
+ (array (lvar :it) $_))
62
+ }
47
63
  :to_h)
48
64
  PATTERN
49
65
 
@@ -51,10 +67,19 @@ module RuboCop
51
67
  (send
52
68
  (const {nil? cbase} :Hash)
53
69
  :[]
54
- (block
55
- (call _ {:map :collect})
56
- (args (arg $_el))
57
- (array (lvar _el) $_)))
70
+ {
71
+ (block
72
+ (call _ {:map :collect})
73
+ (args (arg $_el))
74
+ (array (lvar _el) $_))
75
+ (numblock
76
+ (call _ {:map :collect}) $1
77
+ (array (lvar :_1) $_))
78
+ (itblock
79
+ (call _ {:map :collect}) $:it
80
+ (array (lvar :it) $_))
81
+ }
82
+ )
58
83
  PATTERN
59
84
 
60
85
  private
@@ -29,7 +29,7 @@ module RuboCop
29
29
  def on_send(node)
30
30
  return unless node.arguments.empty?
31
31
  return unless (receiver = node.receiver)
32
- return if !receiver.str_type? && !receiver.array_type?
32
+ return unless receiver.type?(:str, :array)
33
33
 
34
34
  add_offense(node.loc.selector)
35
35
  end
@@ -115,6 +115,10 @@ module RuboCop
115
115
  $_)))
116
116
  PATTERN
117
117
 
118
+ def_node_matcher :delegated_methods, <<~PATTERN
119
+ (send nil? :delegate (sym $_)+ (hash <(pair (sym :to) _) ...>))
120
+ PATTERN
121
+
118
122
  def on_send(node)
119
123
  methods_node = only_or_except_filter_methods(node)
120
124
  return unless methods_node
@@ -139,7 +143,13 @@ module RuboCop
139
143
  return [] unless block
140
144
 
141
145
  defined_methods = block.each_child_node(:def).map(&:method_name)
142
- defined_methods + aliased_action_methods(block, defined_methods)
146
+ defined_methods + delegated_action_methods(block) + aliased_action_methods(block, defined_methods)
147
+ end
148
+
149
+ def delegated_action_methods(node)
150
+ node.each_child_node(:send).flat_map do |child_node|
151
+ delegated_methods(child_node) || []
152
+ end
143
153
  end
144
154
 
145
155
  def aliased_action_methods(node, defined_methods)
@@ -21,11 +21,11 @@ module RuboCop
21
21
  # match 'photos/:id', to: 'photos#show', via: :all
22
22
  #
23
23
  class MatchRoute < Base
24
+ include RoutesHelper
24
25
  extend AutoCorrector
25
26
 
26
27
  MSG = 'Use `%<http_method>s` instead of `match` to define a route.'
27
28
  RESTRICT_ON_SEND = %i[match].freeze
28
- HTTP_METHODS = %i[get post put patch delete].freeze
29
29
 
30
30
  def_node_matcher :match_method_call?, <<~PATTERN
31
31
  (send nil? :match $_ $(hash ...) ?)
@@ -60,14 +60,6 @@ module RuboCop
60
60
  end
61
61
  end
62
62
 
63
- def_node_matcher :routes_draw?, <<~PATTERN
64
- (send (send _ :routes) :draw)
65
- PATTERN
66
-
67
- def within_routes?(node)
68
- node.each_ancestor(:block).any? { |a| routes_draw?(a.send_node) }
69
- end
70
-
71
63
  def extract_via(node)
72
64
  via_pair = via_pair(node)
73
65
  return %i[get] unless via_pair
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # Checks for mapping a route with multiple paths, which is deprecated and will be removed in Rails 8.1.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # get '/users', '/other_path', to: 'users#index'
12
+ #
13
+ # # good
14
+ # get '/users', to: 'users#index'
15
+ # get '/other_path', to: 'users#index'
16
+ #
17
+ class MultipleRoutePaths < Base
18
+ include RoutesHelper
19
+ extend AutoCorrector
20
+
21
+ MSG = 'Use separate routes instead of combining multiple route paths in a single route.'
22
+ RESTRICT_ON_SEND = HTTP_METHODS
23
+
24
+ IGNORED_ARGUMENT_TYPES = %i[array hash].freeze
25
+
26
+ def on_send(node)
27
+ return unless within_routes?(node)
28
+
29
+ route_paths = node.arguments.reject { |argument| IGNORED_ARGUMENT_TYPES.include?(argument.type) }
30
+ return if route_paths.count < 2
31
+
32
+ add_offense(node) do |corrector|
33
+ corrector.replace(node, migrate_to_multiple_routes(node, route_paths))
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def migrate_to_multiple_routes(node, route_paths)
40
+ rest = route_paths.last.source_range.end.join(node.source_range.end).source
41
+ indentation = ' ' * node.source_range.column
42
+
43
+ route_paths.map do |route_path|
44
+ "#{node.method_name} #{route_path.source}#{rest}"
45
+ end.join("\n#{indentation}")
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -41,10 +41,14 @@ module RuboCop
41
41
  # change_column_null :products, :category_id, false
42
42
  class NotNullColumn < Base
43
43
  include DatabaseTypeResolvable
44
+ include MigrationsHelper
44
45
 
45
46
  MSG = 'Do not add a NOT NULL column without a default value.'
46
47
  RESTRICT_ON_SEND = %i[add_column add_reference].freeze
47
48
 
49
+ VIRTUAL_TYPE_VALUES = [:virtual, 'virtual'].freeze
50
+ TEXT_TYPE_VALUES = [:text, 'text'].freeze
51
+
48
52
  def_node_matcher :add_not_null_column?, <<~PATTERN
49
53
  (send nil? :add_column _ _ $_ (hash $...))
50
54
  PATTERN
@@ -91,8 +95,8 @@ module RuboCop
91
95
 
92
96
  def check_column(type, pairs)
93
97
  if type.respond_to?(:value)
94
- return if type.value == :virtual || type.value == 'virtual'
95
- return if (type.value == :text || type.value == 'text') && database == MYSQL
98
+ return if VIRTUAL_TYPE_VALUES.include?(type.value)
99
+ return if TEXT_TYPE_VALUES.include?(type.value) && database == MYSQL
96
100
  end
97
101
 
98
102
  check_pairs(pairs)
@@ -23,7 +23,6 @@ module RuboCop
23
23
 
24
24
  MSG = "Do not write to stdout. Use Rails's logger if you want to log."
25
25
  RESTRICT_ON_SEND = %i[ap p pp pretty_print print puts binwrite syswrite write write_nonblock].freeze
26
- ALLOWED_TYPES = %i[send csend block numblock].freeze
27
26
 
28
27
  def_node_matcher :output?, <<~PATTERN
29
28
  (send nil? {:ap :p :pp :pretty_print :print :puts} ...)
@@ -40,7 +39,7 @@ module RuboCop
40
39
  PATTERN
41
40
 
42
41
  def on_send(node)
43
- return if ALLOWED_TYPES.include?(node.parent&.type)
42
+ return if node.parent&.call_type? || node.block_node
44
43
  return if !output?(node) && !io_output?(node)
45
44
 
46
45
  range = offense_range(node)
@@ -9,6 +9,24 @@ module RuboCop
9
9
  # element in an enumerable. When called on an Active Record relation, it
10
10
  # results in a more efficient query that only selects the necessary key.
11
11
  #
12
+ # NOTE: If the receiver's relation is not loaded and `pluck` is used inside an iteration,
13
+ # it may result in N+1 queries because `pluck` queries the database on each iteration.
14
+ # This cop ignores offenses for `map/collect` when they are suspected to be part of an iteration
15
+ # to prevent such potential issues.
16
+ #
17
+ # [source,ruby]
18
+ # ----
19
+ # users = User.all
20
+ # 5.times do
21
+ # users.map { |user| user[:foo] } # Only one query is executed
22
+ # end
23
+ #
24
+ # users = User.all
25
+ # 5.times do
26
+ # users.pluck(:id) # A query is executed on every iteration
27
+ # end
28
+ # ----
29
+ #
12
30
  # @safety
13
31
  # This cop is unsafe because model can use column aliases.
14
32
  #
@@ -38,30 +56,38 @@ module RuboCop
38
56
  minimum_target_rails_version 5.0
39
57
 
40
58
  def_node_matcher :pluck_candidate?, <<~PATTERN
41
- ({block numblock} (call _ {:map :collect}) $_argument (send lvar :[] $_key))
59
+ (any_block (call _ {:map :collect}) $_argument (send lvar :[] $_key))
42
60
  PATTERN
43
61
 
62
+ # rubocop:disable Metrics/AbcSize
44
63
  def on_block(node)
64
+ return if node.each_ancestor(:any_block).any?
65
+
45
66
  pluck_candidate?(node) do |argument, key|
46
67
  next if key.regexp_type? || !use_one_block_argument?(argument)
47
68
 
48
69
  match = if node.block_type?
49
70
  block_argument = argument.children.first.source
50
71
  use_block_argument_in_key?(block_argument, key)
51
- else # numblock
52
- argument == 1 && use_block_argument_in_key?('_1', key)
72
+ elsif node.numblock_type?
73
+ use_block_argument_in_key?('_1', key)
74
+ else # itblock
75
+ use_block_argument_in_key?('it', key)
53
76
  end
54
77
  next unless match
55
78
 
56
79
  register_offense(node, key)
57
80
  end
58
81
  end
82
+ # rubocop:enable Metrics/AbcSize
59
83
  alias on_numblock on_block
84
+ alias on_itblock on_block
60
85
 
61
86
  private
62
87
 
63
88
  def use_one_block_argument?(argument)
64
- return true if argument == 1 # Checks for numbered argument `_1`.
89
+ # Checks for numbered argument `_1` or `it block parameter.
90
+ return true if [1, :it].include?(argument)
65
91
 
66
92
  argument.respond_to?(:one?) && argument.one?
67
93
  end
@@ -96,7 +96,7 @@ module RuboCop
96
96
  end
97
97
 
98
98
  def literal_number?(node)
99
- node && (node.int_type? || node.float_type?)
99
+ node&.type?(:int, :float)
100
100
  end
101
101
 
102
102
  def pluralize(method_name)
@@ -102,7 +102,7 @@ module RuboCop
102
102
  end
103
103
 
104
104
  def ignore_other_node?(node)
105
- node && (node.if_type? || node.rescue_type? || node.while_type?)
105
+ node&.type?(:if, :rescue, :while)
106
106
  end
107
107
 
108
108
  def message(node, receiver, other)
@@ -110,7 +110,7 @@ module RuboCop
110
110
  def on_if(node)
111
111
  return unless cop_config['UnlessBlank']
112
112
  return unless node.unless?
113
- return if node.else? && config.for_cop('Style/UnlessElse')['Enabled']
113
+ return if node.else? && config.cop_enabled?('Style/UnlessElse')
114
114
 
115
115
  unless_blank?(node) do |method_call, receiver|
116
116
  range = unless_condition(node, method_call)
@@ -174,7 +174,7 @@ module RuboCop
174
174
  parent = node.parent
175
175
  return false unless POSSIBLE_ENUMERABLE_BLOCK_METHODS.include?(parent.method_name)
176
176
 
177
- parent.parent&.block_type? || parent.parent&.numblock_type? || parent.first_argument&.block_pass_type?
177
+ parent.block_literal? || parent.first_argument&.block_pass_type?
178
178
  end
179
179
 
180
180
  def sensitive_association_method?(node)
@@ -85,18 +85,22 @@ module RuboCop
85
85
  end
86
86
 
87
87
  alias on_numblock on_block
88
+ alias on_itblock on_block
88
89
 
89
90
  private
90
91
 
91
92
  def autocorrect(corrector, send_node, node)
92
93
  corrector.remove(send_node.receiver)
93
94
  corrector.remove(send_node.loc.dot)
94
- corrector.remove(block_argument_range(send_node)) unless node.numblock_type?
95
+ corrector.remove(block_argument_range(send_node)) if node.block_type?
95
96
  end
96
97
 
98
+ # rubocop:disable Metrics/AbcSize
97
99
  def redundant_receiver?(send_nodes, node)
98
100
  proc = if node.numblock_type?
99
101
  ->(n) { n.receiver.lvar_type? && n.receiver.source == '_1' }
102
+ elsif node.itblock_type?
103
+ ->(n) { n.receiver.lvar_type? && n.receiver.source == 'it' }
100
104
  else
101
105
  return false if node.arguments.empty?
102
106
 
@@ -106,6 +110,7 @@ module RuboCop
106
110
 
107
111
  send_nodes.all?(&proc)
108
112
  end
113
+ # rubocop:enable Metrics/AbcSize
109
114
 
110
115
  def block_argument_range(node)
111
116
  block_node = node.each_ancestor(:block).first
@@ -40,7 +40,7 @@ module RuboCop
40
40
 
41
41
  def on_send(node)
42
42
  association_with_reflection(node) do |reflection_class_name|
43
- return if reflection_class_name.value.send_type? && reflection_class_name.value.receiver.nil?
43
+ return if reflection_class_name.value.send_type? && !reflection_class_name.value.receiver&.const_type?
44
44
  return if reflection_class_name.value.lvar_type? && str_assigned?(reflection_class_name)
45
45
 
46
46
  add_offense(reflection_class_name) do |corrector|
@@ -76,7 +76,7 @@ module RuboCop
76
76
  def autocorrect(corrector, class_config)
77
77
  class_value = class_config.value
78
78
  replacement = const_or_string(class_value)
79
- return unless replacement.present?
79
+ return unless replacement
80
80
 
81
81
  corrector.replace(class_value, replacement.source.inspect)
82
82
  end
@@ -90,7 +90,7 @@ module RuboCop
90
90
  end
91
91
 
92
92
  def nested_relative_date(node, &callback)
93
- return if node.nil? || node.block_type?
93
+ return if node.nil? || node.any_block_type?
94
94
 
95
95
  node.each_child_node do |child|
96
96
  nested_relative_date(child, &callback)
@@ -205,6 +205,7 @@ module RuboCop
205
205
  end
206
206
 
207
207
  alias on_numblock on_block
208
+ alias on_itblock on_block
208
209
 
209
210
  private
210
211
 
@@ -215,8 +216,10 @@ module RuboCop
215
216
  end
216
217
 
217
218
  def check_drop_table_node(node)
219
+ return unless (last_argument = node.last_argument)
220
+
218
221
  drop_table_call(node) do
219
- unless node.parent.block_type? || node.last_argument.block_pass_type?
222
+ unless node.parent.any_block_type? || last_argument.block_pass_type?
220
223
  add_offense(node, message: format(MSG, action: 'drop_table(without block)'))
221
224
  end
222
225
  end
@@ -237,7 +237,12 @@ module RuboCop
237
237
  end
238
238
 
239
239
  replacement = "#{path_replacement}.#{method}"
240
- replacement += "(#{args.map(&:source).join(', ')})" unless args.empty?
240
+
241
+ if args.any?
242
+ formatted_args = args.map { |arg| arg.array_type? ? "*#{arg.source}" : arg.source }
243
+ replacement += "(#{formatted_args.join(', ')})"
244
+ end
245
+
241
246
  replacement
242
247
  end
243
248
 
@@ -182,7 +182,7 @@ module RuboCop
182
182
  def right_assignment_node(assignment)
183
183
  node = assignment.node.child_nodes.first
184
184
 
185
- return node unless node&.block_type?
185
+ return node unless node&.any_block_type?
186
186
 
187
187
  node.send_node
188
188
  end
@@ -244,11 +244,11 @@ module RuboCop
244
244
  end
245
245
 
246
246
  def operator_or_single_negative?(node)
247
- node.or_type? || node.and_type? || single_negative?(node)
247
+ node.operator_keyword? || single_negative?(node)
248
248
  end
249
249
 
250
250
  def conditional?(parent)
251
- parent.if_type? || parent.case_type?
251
+ parent.type?(:if, :case)
252
252
  end
253
253
 
254
254
  def deparenthesize(node)
@@ -305,7 +305,7 @@ module RuboCop
305
305
 
306
306
  node = assignable_node(node)
307
307
  method, sibling_index = find_method_with_sibling_index(node.parent)
308
- return false unless method && (method.def_type? || method.block_type?)
308
+ return false unless method&.type?(:def, :any_block)
309
309
 
310
310
  method.children.size == node.sibling_index + sibling_index
311
311
  end
@@ -324,12 +324,13 @@ module RuboCop
324
324
 
325
325
  def explicit_return?(node)
326
326
  ret = assignable_node(node).parent
327
- ret && (ret.return_type? || ret.next_type?)
327
+ ret&.type?(:return, :next)
328
328
  end
329
329
 
330
330
  def return_value_assigned?(node)
331
- assignment = assignable_node(node).parent
332
- assignment&.lvasgn_type?
331
+ return false unless (assignment = assignable_node(node).parent)
332
+
333
+ assignment.assignment?
333
334
  end
334
335
 
335
336
  def persist_method?(node, methods = RESTRICT_ON_SEND)
@@ -23,6 +23,7 @@ module RuboCop
23
23
  #
24
24
  class SchemaComment < Base
25
25
  include ActiveRecordMigrationsHelper
26
+ include MigrationsHelper
26
27
 
27
28
  COLUMN_MSG = 'New database column without `comment`.'
28
29
  TABLE_MSG = 'New database table without `comment`.'
@@ -38,7 +39,7 @@ module RuboCop
38
39
 
39
40
  # @!method comment_present?(node)
40
41
  def_node_matcher :comment_present?, <<~PATTERN
41
- (hash <(pair {(sym :comment) (str "comment")} (_ [present?])) ...>)
42
+ (hash <(pair {(sym :comment) (str "comment")} !{nil (str blank?)}) ...>)
42
43
  PATTERN
43
44
 
44
45
  # @!method add_column?(node)
@@ -40,12 +40,13 @@ module RuboCop
40
40
  autocorrect(corrector, select_node, node, preferred_method)
41
41
  end
42
42
  end
43
+ alias on_csend on_send
43
44
 
44
45
  private
45
46
 
46
47
  def find_select_node(node, column_name)
47
48
  node.descendants.detect do |select_candidate|
48
- next if !select_candidate.send_type? || !select_candidate.method?(:select)
49
+ next if !select_candidate.call_type? || !select_candidate.method?(:select)
49
50
 
50
51
  match_column_name?(select_candidate, column_name)
51
52
  end
@@ -53,7 +54,7 @@ module RuboCop
53
54
 
54
55
  # rubocop:disable Metrics/AbcSize
55
56
  def autocorrect(corrector, select_node, node, preferred_method)
56
- corrector.remove(select_node.loc.dot || node.loc.dot)
57
+ corrector.remove(select_node.parent.loc.dot)
57
58
  corrector.remove(select_node.loc.selector.begin.join(select_node.source_range.end))
58
59
  corrector.replace(node.loc.selector.begin.join(node.source_range.end), preferred_method)
59
60
  end
@@ -61,7 +61,7 @@ module RuboCop
61
61
  def_node_matcher :good_touch?, <<~PATTERN
62
62
  {
63
63
  (send (const {nil? cbase} :FileUtils) :touch ...)
64
- (send _ :touch {true false})
64
+ (send _ :touch boolean)
65
65
  }
66
66
  PATTERN
67
67
 
@@ -68,7 +68,7 @@ module RuboCop
68
68
  end
69
69
 
70
70
  def using_squish?(node)
71
- node.parent&.send_type? && node.parent&.method?(:squish)
71
+ node.parent&.send_type? && node.parent.method?(:squish)
72
72
  end
73
73
 
74
74
  def singleline_comments_present?(node)
@@ -33,7 +33,7 @@ module RuboCop
33
33
 
34
34
  def on_send(node)
35
35
  return unless (receiver = node.receiver)
36
- return unless receiver.str_type? || receiver.dstr_type?
36
+ return unless receiver.type?(:str, :dstr)
37
37
  return unless receiver.respond_to?(:heredoc?) && receiver.heredoc?
38
38
 
39
39
  register_offense(node, receiver)