rubocop-rails 2.8.1 → 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 +33 -1
  4. data/lib/rubocop/cop/mixin/active_record_helper.rb +4 -3
  5. data/lib/rubocop/cop/mixin/enforce_superclass.rb +40 -0
  6. data/lib/rubocop/cop/mixin/index_method.rb +8 -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 +17 -12
  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 +1 -1
  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 +16 -16
  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 +11 -4
  27. data/lib/rubocop/cop/rails/delegate.rb +9 -9
  28. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +7 -8
  29. data/lib/rubocop/cop/rails/dynamic_find_by.rb +12 -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 +4 -3
  35. data/lib/rubocop/cop/rails/find_by.rb +13 -13
  36. data/lib/rubocop/cop/rails/find_by_id.rb +12 -21
  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 +3 -2
  40. data/lib/rubocop/cop/rails/helper_instance_variable.rb +2 -2
  41. data/lib/rubocop/cop/rails/http_positional_arguments.rb +19 -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 +2 -1
  45. data/lib/rubocop/cop/rails/index_with.rb +2 -1
  46. data/lib/rubocop/cop/rails/inquiry.rb +4 -3
  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 -22
  50. data/lib/rubocop/cop/rails/mailer_name.rb +19 -13
  51. data/lib/rubocop/cop/rails/match_route.rb +14 -13
  52. data/lib/rubocop/cop/rails/negate_include.rb +10 -8
  53. data/lib/rubocop/cop/rails/not_null_column.rb +2 -1
  54. data/lib/rubocop/cop/rails/order_by_id.rb +1 -2
  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 +14 -12
  58. data/lib/rubocop/cop/rails/pluck.rb +6 -9
  59. data/lib/rubocop/cop/rails/pluck_id.rb +4 -6
  60. data/lib/rubocop/cop/rails/pluck_in_where.rb +7 -7
  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 +8 -10
  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 +3 -2
  70. data/lib/rubocop/cop/rails/refute_methods.rb +9 -10
  71. data/lib/rubocop/cop/rails/relative_date_constant.rb +16 -8
  72. data/lib/rubocop/cop/rails/render_inline.rb +2 -1
  73. data/lib/rubocop/cop/rails/render_plain_text.rb +9 -14
  74. data/lib/rubocop/cop/rails/request_referer.rb +7 -7
  75. data/lib/rubocop/cop/rails/reversible_migration.rb +2 -6
  76. data/lib/rubocop/cop/rails/safe_navigation.rb +11 -10
  77. data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +5 -10
  78. data/lib/rubocop/cop/rails/save_bang.rb +17 -20
  79. data/lib/rubocop/cop/rails/scope_args.rb +2 -1
  80. data/lib/rubocop/cop/rails/short_i18n.rb +7 -9
  81. data/lib/rubocop/cop/rails/skips_model_validations.rb +4 -4
  82. data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +5 -6
  83. data/lib/rubocop/cop/rails/time_zone.rb +22 -20
  84. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +4 -6
  85. data/lib/rubocop/cop/rails/unique_validation_without_index.rb +2 -2
  86. data/lib/rubocop/cop/rails/unknown_env.rb +2 -2
  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 +8 -13
  90. data/lib/rubocop/cop/rails/where_not.rb +5 -16
  91. data/lib/rubocop/cop/rails_cops.rb +4 -0
  92. data/lib/rubocop/rails/schema_loader.rb +4 -4
  93. data/lib/rubocop/rails/schema_loader/schema.rb +1 -1
  94. data/lib/rubocop/rails/version.rb +5 -1
  95. metadata +19 -9
@@ -16,10 +16,12 @@ module RuboCop
16
16
  # # good
17
17
  # User.find(id)
18
18
  #
19
- class FindById < Cop
19
+ class FindById < Base
20
20
  include RangeHelp
21
+ extend AutoCorrector
21
22
 
22
23
  MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
24
+ RESTRICT_ON_SEND = %i[take! find_by_id! find_by!].freeze
23
25
 
24
26
  def_node_matcher :where_take?, <<~PATTERN
25
27
  (send
@@ -38,41 +40,30 @@ module RuboCop
38
40
  def on_send(node)
39
41
  where_take?(node) do |where, id_value|
40
42
  range = where_take_offense_range(node, where)
41
-
42
- good_method = build_good_method(id_value)
43
43
  bad_method = build_where_take_bad_method(id_value)
44
- message = format(MSG, good_method: good_method, bad_method: bad_method)
45
44
 
46
- add_offense(node, location: range, message: message)
45
+ register_offense(range, id_value, bad_method)
47
46
  end
48
47
 
49
48
  find_by?(node) do |id_value|
50
49
  range = find_by_offense_range(node)
51
-
52
- good_method = build_good_method(id_value)
53
50
  bad_method = build_find_by_bad_method(node, id_value)
54
- message = format(MSG, good_method: good_method, bad_method: bad_method)
55
51
 
56
- add_offense(node, location: range, message: message)
52
+ register_offense(range, id_value, bad_method)
57
53
  end
58
54
  end
59
55
 
60
- def autocorrect(node)
61
- if (matches = where_take?(node))
62
- where, id_value = *matches
63
- range = where_take_offense_range(node, where)
64
- elsif (id_value = find_by?(node))
65
- range = find_by_offense_range(node)
66
- end
56
+ private
57
+
58
+ def register_offense(range, id_value, bad_method)
59
+ good_method = build_good_method(id_value)
60
+ message = format(MSG, good_method: good_method, bad_method: bad_method)
67
61
 
68
- lambda do |corrector|
69
- replacement = build_good_method(id_value)
70
- corrector.replace(range, replacement)
62
+ add_offense(range, message: message) do |corrector|
63
+ corrector.replace(range, good_method)
71
64
  end
72
65
  end
73
66
 
74
- private
75
-
76
67
  def where_take_offense_range(node, where)
77
68
  range_between(where.loc.selector.begin_pos, node.loc.expression.end_pos)
78
69
  end
@@ -12,27 +12,30 @@ module RuboCop
12
12
  #
13
13
  # # good
14
14
  # User.all.find_each
15
- class FindEach < Cop
15
+ #
16
+ # @example IgnoredMethods: ['order']
17
+ # # good
18
+ # User.order(:foo).each
19
+ class FindEach < Base
20
+ extend AutoCorrector
21
+
16
22
  MSG = 'Use `find_each` instead of `each`.'
23
+ RESTRICT_ON_SEND = %i[each].freeze
17
24
 
18
25
  SCOPE_METHODS = %i[
19
26
  all eager_load includes joins left_joins left_outer_joins not preload
20
27
  references unscoped where
21
28
  ].freeze
22
- IGNORED_METHODS = %i[order limit select].freeze
23
29
 
24
30
  def on_send(node)
25
- return unless node.receiver&.send_type? &&
26
- node.method?(:each)
27
-
31
+ return unless node.receiver&.send_type?
28
32
  return unless SCOPE_METHODS.include?(node.receiver.method_name)
29
- return if method_chain(node).any? { |m| ignored_by_find_each?(m) }
30
-
31
- add_offense(node, location: :selector)
32
- end
33
+ return if method_chain(node).any? { |m| ignored?(m) }
33
34
 
34
- def autocorrect(node)
35
- ->(corrector) { corrector.replace(node.loc.selector, 'find_each') }
35
+ range = node.loc.selector
36
+ add_offense(range) do |corrector|
37
+ corrector.replace(range, 'find_each')
38
+ end
36
39
  end
37
40
 
38
41
  private
@@ -41,9 +44,8 @@ module RuboCop
41
44
  node.each_node(:send).map(&:method_name)
42
45
  end
43
46
 
44
- def ignored_by_find_each?(relation_method)
45
- # Active Record's #find_each ignores various extra parameters
46
- IGNORED_METHODS.include?(relation_method)
47
+ def ignored?(relation_method)
48
+ cop_config['IgnoredMethods'].include?(relation_method)
47
49
  end
48
50
  end
49
51
  end
@@ -11,13 +11,14 @@ module RuboCop
11
11
  #
12
12
  # # good
13
13
  # # has_many :ingredients, through: :recipe_ingredients
14
- class HasAndBelongsToMany < Cop
14
+ class HasAndBelongsToMany < Base
15
15
  MSG = 'Prefer `has_many :through` to `has_and_belongs_to_many`.'
16
+ RESTRICT_ON_SEND = %i[has_and_belongs_to_many].freeze
16
17
 
17
18
  def on_send(node)
18
19
  return unless node.command?(:has_and_belongs_to_many)
19
20
 
20
- add_offense(node, location: :selector)
21
+ add_offense(node.loc.selector)
21
22
  end
22
23
  end
23
24
  end
@@ -20,8 +20,9 @@ module RuboCop
20
20
  # has_one :avatar, dependent: :destroy
21
21
  # has_many :patients, through: :appointments
22
22
  # end
23
- class HasManyOrHasOneDependent < Cop
23
+ class HasManyOrHasOneDependent < Base
24
24
  MSG = 'Specify a `:dependent` option.'
25
+ RESTRICT_ON_SEND = %i[has_many has_one].freeze
25
26
 
26
27
  def_node_search :active_resource_class?, <<~PATTERN
27
28
  (const (const nil? :ActiveResource) :Base)
@@ -55,7 +56,7 @@ module RuboCop
55
56
  return if !association_without_options?(node) && valid_options?(association_with_options?(node))
56
57
  return if valid_options_in_with_options_block?(node)
57
58
 
58
- add_offense(node, location: :selector)
59
+ add_offense(node.loc.selector)
59
60
  end
60
61
 
61
62
  private
@@ -23,7 +23,7 @@ module RuboCop
23
23
  # def welcome_message(user)
24
24
  # "Hello #{user.name}"
25
25
  # end
26
- class HelperInstanceVariable < Cop
26
+ class HelperInstanceVariable < Base
27
27
  MSG = 'Do not use instance variables in helpers.'
28
28
 
29
29
  def on_ivar(node)
@@ -33,7 +33,7 @@ module RuboCop
33
33
  def on_ivasgn(node)
34
34
  return if node.parent.or_asgn_type?
35
35
 
36
- add_offense(node, location: :name)
36
+ add_offense(node.loc.name)
37
37
  end
38
38
  end
39
39
  end
@@ -17,7 +17,8 @@ module RuboCop
17
17
  # # good
18
18
  # get :new, params: { user_id: 1 }
19
19
  # get :new, **options
20
- class HttpPositionalArguments < Cop
20
+ class HttpPositionalArguments < Base
21
+ extend AutoCorrector
21
22
  extend TargetRailsVersion
22
23
 
23
24
  MSG = 'Use keyword arguments instead of ' \
@@ -25,12 +26,12 @@ module RuboCop
25
26
  KEYWORD_ARGS = %i[
26
27
  method params session body flash xhr as headers env to
27
28
  ].freeze
28
- HTTP_METHODS = %i[get post put patch delete head].freeze
29
+ RESTRICT_ON_SEND = %i[get post put patch delete head].freeze
29
30
 
30
31
  minimum_target_rails_version 5.0
31
32
 
32
33
  def_node_matcher :http_request?, <<~PATTERN
33
- (send nil? {#{HTTP_METHODS.map(&:inspect).join(' ')}} !nil? $_ ...)
34
+ (send nil? {#{RESTRICT_ON_SEND.map(&:inspect).join(' ')}} !nil? $_ ...)
34
35
  PATTERN
35
36
 
36
37
  def_node_matcher :kwsplat_hash?, <<~PATTERN
@@ -41,24 +42,21 @@ module RuboCop
41
42
  http_request?(node) do |data|
42
43
  return unless needs_conversion?(data)
43
44
 
44
- add_offense(node, location: :selector,
45
- message: format(MSG, verb: node.method_name))
46
- end
47
- end
48
-
49
- # given a pre Rails 5 method: get :new, {user_id: @user.id}, {}
50
- #
51
- # @return lambda of auto correct procedure
52
- # the result should look like:
53
- # get :new, params: { user_id: @user.id }, session: {}
54
- # the http_method is the method used to call the controller
55
- # the controller node can be a symbol, method, object or string
56
- # that represents the path/action on the Rails controller
57
- # the data is the http parameters and environment sent in
58
- # the Rails 5 http call
59
- def autocorrect(node)
60
- lambda do |corrector|
61
- corrector.replace(node.loc.expression, correction(node))
45
+ message = format(MSG, verb: node.method_name)
46
+
47
+ add_offense(node.loc.selector, message: message) do |corrector|
48
+ # given a pre Rails 5 method: get :new, {user_id: @user.id}, {}
49
+ #
50
+ # @return lambda of auto correct procedure
51
+ # the result should look like:
52
+ # get :new, params: { user_id: @user.id }, session: {}
53
+ # the http_method is the method used to call the controller
54
+ # the controller node can be a symbol, method, object or string
55
+ # that represents the path/action on the Rails controller
56
+ # the data is the http parameters and environment sent in
57
+ # the Rails 5 http call
58
+ corrector.replace(node.loc.expression, correction(node))
59
+ end
62
60
  end
63
61
  end
64
62
 
@@ -31,8 +31,11 @@ module RuboCop
31
31
  # render plain: 'foo/bar', status: 304
32
32
  # redirect_to root_url, status: 301
33
33
  #
34
- class HttpStatus < Cop
34
+ class HttpStatus < Base
35
35
  include ConfigurableEnforcedStyle
36
+ extend AutoCorrector
37
+
38
+ RESTRICT_ON_SEND = %i[render redirect_to].freeze
36
39
 
37
40
  def_node_matcher :http_status, <<~PATTERN
38
41
  {
@@ -53,14 +56,9 @@ module RuboCop
53
56
  checker = checker_class.new(status)
54
57
  return unless checker.offensive?
55
58
 
56
- add_offense(checker.node, message: checker.message)
57
- end
58
- end
59
-
60
- def autocorrect(node)
61
- lambda do |corrector|
62
- checker = checker_class.new(node)
63
- corrector.replace(node.loc.expression, checker.preferred_style)
59
+ add_offense(checker.node, message: checker.message) do |corrector|
60
+ corrector.replace(checker.node.loc.expression, checker.preferred_style)
61
+ end
64
62
  end
65
63
  end
66
64
 
@@ -37,18 +37,20 @@ module RuboCop
37
37
  # end
38
38
  #
39
39
  # @see https://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html#method-i-_normalize_callback_options
40
- class IgnoredSkipActionFilterOption < Cop
40
+ class IgnoredSkipActionFilterOption < Base
41
41
  MSG = <<~MSG.chomp.freeze
42
42
  `%<ignore>s` option will be ignored when `%<prefer>s` and `%<ignore>s` are used together.
43
43
  MSG
44
44
 
45
- FILTERS = %w[
46
- :skip_after_action
47
- :skip_around_action
48
- :skip_before_action
49
- :skip_action_callback
45
+ RESTRICT_ON_SEND = %i[
46
+ skip_after_action
47
+ skip_around_action
48
+ skip_before_action
49
+ skip_action_callback
50
50
  ].freeze
51
51
 
52
+ FILTERS = RESTRICT_ON_SEND.map { |method_name| ":#{method_name}" }
53
+
52
54
  def_node_matcher :filter_options, <<~PATTERN
53
55
  (send
54
56
  nil?
@@ -17,8 +17,9 @@ module RuboCop
17
17
  #
18
18
  # # good
19
19
  # [1, 2, 3].index_by { |el| foo(el) }
20
- class IndexBy < Cop
20
+ class IndexBy < Base
21
21
  include IndexMethod
22
+ extend AutoCorrector
22
23
 
23
24
  def_node_matcher :on_bad_each_with_object, <<~PATTERN
24
25
  (block
@@ -17,7 +17,8 @@ module RuboCop
17
17
  #
18
18
  # # good
19
19
  # [1, 2, 3].index_with { |el| foo(el) }
20
- class IndexWith < Cop
20
+ class IndexWith < Base
21
+ extend AutoCorrector
21
22
  extend TargetRailsVersion
22
23
  include IndexMethod
23
24
 
@@ -22,15 +22,16 @@ module RuboCop
22
22
  # pets = %w(cat dog)
23
23
  # pets.include? 'cat'
24
24
  #
25
- class Inquiry < Cop
25
+ class Inquiry < Base
26
26
  MSG = "Prefer Ruby's comparison operators over Active Support's `inquiry`."
27
+ RESTRICT_ON_SEND = %i[inquiry].freeze
27
28
 
28
29
  def on_send(node)
29
- return unless node.method?(:inquiry) && node.arguments.empty?
30
+ return unless node.arguments.empty?
30
31
  return unless (receiver = node.receiver)
31
32
  return if !receiver.str_type? && !receiver.array_type?
32
33
 
33
- add_offense(node, location: :selector)
34
+ add_offense(node.loc.selector)
34
35
  end
35
36
  end
36
37
  end
@@ -128,10 +128,11 @@ module RuboCop
128
128
  #
129
129
  # @see https://guides.rubyonrails.org/association_basics.html#bi-directional-associations
130
130
  # @see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses
131
- class InverseOf < Cop
131
+ class InverseOf < Base
132
132
  SPECIFY_MSG = 'Specify an `:inverse_of` option.'
133
133
  NIL_MSG = 'You specified `inverse_of: nil`, you probably meant to ' \
134
134
  'use `inverse_of: false`.'
135
+ RESTRICT_ON_SEND = %i[has_many has_one belongs_to].freeze
135
136
 
136
137
  def_node_matcher :association_recv_arguments, <<~PATTERN
137
138
  (send $_ {:has_many :has_one :belongs_to} _ $...)
@@ -185,7 +186,7 @@ module RuboCop
185
186
 
186
187
  return if options_contain_inverse_of?(options)
187
188
 
188
- add_offense(node, message: message(options), location: :selector)
189
+ add_offense(node.loc.selector, message: message(options))
189
190
  end
190
191
 
191
192
  def scope?(arguments)
@@ -82,25 +82,27 @@ module RuboCop
82
82
  # @content = Article.find(params[:article_id])
83
83
  # end
84
84
  # end
85
- class LexicallyScopedActionFilter < Cop
85
+ class LexicallyScopedActionFilter < Base
86
86
  MSG = '%<action>s not explicitly defined on the %<type>s.'
87
87
 
88
- FILTERS = %w[
89
- :after_action
90
- :append_after_action
91
- :append_around_action
92
- :append_before_action
93
- :around_action
94
- :before_action
95
- :prepend_after_action
96
- :prepend_around_action
97
- :prepend_before_action
98
- :skip_after_action
99
- :skip_around_action
100
- :skip_before_action
101
- :skip_action_callback
88
+ RESTRICT_ON_SEND = %i[
89
+ after_action
90
+ append_after_action
91
+ append_around_action
92
+ append_before_action
93
+ around_action
94
+ before_action
95
+ prepend_after_action
96
+ prepend_around_action
97
+ prepend_before_action
98
+ skip_after_action
99
+ skip_around_action
100
+ skip_before_action
101
+ skip_action_callback
102
102
  ].freeze
103
103
 
104
+ FILTERS = RESTRICT_ON_SEND.map { |method_name| ":#{method_name}" }
105
+
104
106
  def_node_matcher :only_or_except_filter_methods, <<~PATTERN
105
107
  (send
106
108
  nil?
@@ -20,8 +20,11 @@ module RuboCop
20
20
  #
21
21
  # # good
22
22
  # link_to 'Click here', url, target: '_blank', rel: 'noreferrer'
23
- class LinkToBlank < Cop
23
+ class LinkToBlank < Base
24
+ extend AutoCorrector
25
+
24
26
  MSG = 'Specify a `:rel` option containing noopener.'
27
+ RESTRICT_ON_SEND = %i[link_to].freeze
25
28
 
26
29
  def_node_matcher :blank_target?, <<~PATTERN
27
30
  (pair {(sym :target) (str "target")} {(str "_blank") (sym :_blank)})
@@ -35,39 +38,34 @@ module RuboCop
35
38
  (pair {(sym :rel) (str "rel")} (str _))
36
39
  PATTERN
37
40
 
38
- # rubocop:disable Metrics/CyclomaticComplexity
39
41
  def on_send(node)
40
- return unless node.method?(:link_to)
41
-
42
42
  option_nodes = node.each_child_node(:hash)
43
43
 
44
44
  option_nodes.map(&:children).each do |options|
45
45
  blank = options.find { |o| blank_target?(o) }
46
- add_offense(blank) if blank && options.none? { |o| includes_noopener?(o) }
46
+ next unless blank && options.none? { |o| includes_noopener?(o) }
47
+
48
+ add_offense(blank) do |corrector|
49
+ autocorrect(corrector, node, blank, option_nodes)
50
+ end
47
51
  end
48
52
  end
49
- # rubocop:enable Metrics/CyclomaticComplexity
50
53
 
51
- def autocorrect(node)
52
- lambda do |corrector|
53
- send_node = node.parent.parent
54
+ private
54
55
 
55
- option_nodes = send_node.each_child_node(:hash)
56
- rel_node = nil
57
- option_nodes.map(&:children).each do |options|
58
- rel_node ||= options.find { |o| rel_node?(o) }
59
- end
56
+ def autocorrect(corrector, send_node, node, option_nodes)
57
+ rel_node = nil
58
+ option_nodes.map(&:children).each do |options|
59
+ rel_node ||= options.find { |o| rel_node?(o) }
60
+ end
60
61
 
61
- if rel_node
62
- append_to_rel(rel_node, corrector)
63
- else
64
- add_rel(send_node, node, corrector)
65
- end
62
+ if rel_node
63
+ append_to_rel(rel_node, corrector)
64
+ else
65
+ add_rel(send_node, node, corrector)
66
66
  end
67
67
  end
68
68
 
69
- private
70
-
71
69
  def append_to_rel(rel_node, corrector)
72
70
  existing_rel = rel_node.children.last.value
73
71
  str_range = rel_node.children.last.loc.expression.adjust(
@@ -89,7 +87,7 @@ module RuboCop
89
87
  def contains_noopener?(value)
90
88
  return false unless value
91
89
 
92
- rel_array = value.to_s.split(' ')
90
+ rel_array = value.to_s.split
93
91
  rel_array.include?('noopener') || rel_array.include?('noreferrer')
94
92
  end
95
93
  end