rubocop-rails 2.7.1 → 2.10.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.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +18 -2
- data/config/default.yml +144 -6
- data/config/obsoletion.yml +7 -0
- data/lib/rubocop/cop/mixin/active_record_helper.rb +16 -3
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +40 -0
- data/lib/rubocop/cop/mixin/index_method.rb +25 -11
- data/lib/rubocop/cop/rails/action_filter.rb +10 -14
- data/lib/rubocop/cop/rails/active_record_aliases.rb +13 -17
- data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +19 -16
- data/lib/rubocop/cop/rails/active_record_override.rb +1 -1
- data/lib/rubocop/cop/rails/active_support_aliases.rb +12 -21
- data/lib/rubocop/cop/rails/after_commit_override.rb +91 -0
- data/lib/rubocop/cop/rails/application_controller.rb +3 -7
- data/lib/rubocop/cop/rails/application_job.rb +2 -1
- data/lib/rubocop/cop/rails/application_mailer.rb +2 -7
- data/lib/rubocop/cop/rails/application_record.rb +2 -7
- data/lib/rubocop/cop/rails/arel_star.rb +41 -0
- data/lib/rubocop/cop/rails/assert_not.rb +8 -10
- data/lib/rubocop/cop/rails/attribute_default_block_value.rb +90 -0
- data/lib/rubocop/cop/rails/belongs_to.rb +10 -19
- data/lib/rubocop/cop/rails/blank.rb +31 -27
- data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -1
- data/lib/rubocop/cop/rails/content_tag.rb +34 -19
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +2 -1
- data/lib/rubocop/cop/rails/date.rb +10 -11
- data/lib/rubocop/cop/rails/default_scope.rb +11 -4
- data/lib/rubocop/cop/rails/delegate.rb +9 -9
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +7 -8
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +15 -12
- data/lib/rubocop/cop/rails/enum_hash.rb +11 -10
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -1
- data/lib/rubocop/cop/rails/environment_comparison.rb +18 -14
- data/lib/rubocop/cop/rails/environment_variable_access.rb +67 -0
- data/lib/rubocop/cop/rails/exit.rb +4 -10
- data/lib/rubocop/cop/rails/file_path.rb +7 -8
- data/lib/rubocop/cop/rails/find_by.rb +13 -13
- data/lib/rubocop/cop/rails/find_by_id.rb +12 -21
- data/lib/rubocop/cop/rails/find_each.rb +19 -18
- data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +3 -2
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +37 -10
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +30 -2
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +32 -21
- data/lib/rubocop/cop/rails/http_status.rb +7 -9
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +8 -6
- data/lib/rubocop/cop/rails/index_by.rb +11 -2
- data/lib/rubocop/cop/rails/index_with.rb +11 -2
- data/lib/rubocop/cop/rails/inquiry.rb +7 -2
- data/lib/rubocop/cop/rails/inverse_of.rb +3 -2
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +17 -15
- data/lib/rubocop/cop/rails/link_to_blank.rb +25 -23
- data/lib/rubocop/cop/rails/mailer_name.rb +19 -13
- data/lib/rubocop/cop/rails/match_route.rb +14 -13
- data/lib/rubocop/cop/rails/negate_include.rb +10 -8
- data/lib/rubocop/cop/rails/not_null_column.rb +2 -1
- data/lib/rubocop/cop/rails/order_by_id.rb +52 -0
- data/lib/rubocop/cop/rails/output.rb +5 -2
- data/lib/rubocop/cop/rails/output_safety.rb +3 -2
- data/lib/rubocop/cop/rails/pick.rb +14 -12
- data/lib/rubocop/cop/rails/pluck.rb +6 -9
- data/lib/rubocop/cop/rails/pluck_id.rb +4 -6
- data/lib/rubocop/cop/rails/pluck_in_where.rb +39 -5
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +10 -14
- data/lib/rubocop/cop/rails/presence.rb +12 -13
- data/lib/rubocop/cop/rails/present.rb +30 -24
- data/lib/rubocop/cop/rails/rake_environment.rb +8 -10
- data/lib/rubocop/cop/rails/read_write_attribute.rb +12 -11
- data/lib/rubocop/cop/rails/redundant_allow_nil.rb +29 -31
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +9 -12
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +11 -10
- data/lib/rubocop/cop/rails/reflection_class_name.rb +18 -4
- data/lib/rubocop/cop/rails/refute_methods.rb +9 -10
- data/lib/rubocop/cop/rails/relative_date_constant.rb +34 -22
- data/lib/rubocop/cop/rails/render_inline.rb +2 -1
- data/lib/rubocop/cop/rails/render_plain_text.rb +9 -14
- data/lib/rubocop/cop/rails/request_referer.rb +7 -7
- data/lib/rubocop/cop/rails/require_dependency.rb +38 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +83 -8
- data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +75 -0
- data/lib/rubocop/cop/rails/safe_navigation.rb +30 -11
- data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +5 -10
- data/lib/rubocop/cop/rails/save_bang.rb +19 -22
- data/lib/rubocop/cop/rails/scope_args.rb +2 -1
- data/lib/rubocop/cop/rails/short_i18n.rb +7 -9
- data/lib/rubocop/cop/rails/skips_model_validations.rb +4 -4
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +82 -0
- data/lib/rubocop/cop/rails/time_zone.rb +35 -25
- data/lib/rubocop/cop/rails/time_zone_assignment.rb +37 -0
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +6 -6
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +18 -8
- data/lib/rubocop/cop/rails/unknown_env.rb +3 -3
- data/lib/rubocop/cop/rails/validation.rb +15 -14
- data/lib/rubocop/cop/rails/where_equals.rb +98 -0
- data/lib/rubocop/cop/rails/where_exists.rb +85 -16
- data/lib/rubocop/cop/rails/where_not.rb +101 -0
- data/lib/rubocop/cop/rails_cops.rb +12 -0
- data/lib/rubocop/rails.rb +2 -0
- data/lib/rubocop/rails/schema_loader.rb +4 -4
- data/lib/rubocop/rails/schema_loader/schema.rb +4 -8
- data/lib/rubocop/rails/version.rb +5 -1
- metadata +33 -14
@@ -16,7 +16,8 @@ module RuboCop
|
|
16
16
|
# class MyMailer < ActionMailer::Base
|
17
17
|
# # ...
|
18
18
|
# end
|
19
|
-
class ApplicationMailer <
|
19
|
+
class ApplicationMailer < Base
|
20
|
+
extend AutoCorrector
|
20
21
|
extend TargetRailsVersion
|
21
22
|
|
22
23
|
minimum_target_rails_version 5.0
|
@@ -28,12 +29,6 @@ module RuboCop
|
|
28
29
|
# rubocop:disable Layout/ClassStructure
|
29
30
|
include RuboCop::Cop::EnforceSuperclass
|
30
31
|
# rubocop:enable Layout/ClassStructure
|
31
|
-
|
32
|
-
def autocorrect(node)
|
33
|
-
lambda do |corrector|
|
34
|
-
corrector.replace(node.source_range, self.class::SUPERCLASS)
|
35
|
-
end
|
36
|
-
end
|
37
32
|
end
|
38
33
|
end
|
39
34
|
end
|
@@ -16,7 +16,8 @@ module RuboCop
|
|
16
16
|
# class Rails4Model < ActiveRecord::Base
|
17
17
|
# # ...
|
18
18
|
# end
|
19
|
-
class ApplicationRecord <
|
19
|
+
class ApplicationRecord < Base
|
20
|
+
extend AutoCorrector
|
20
21
|
extend TargetRailsVersion
|
21
22
|
|
22
23
|
minimum_target_rails_version 5.0
|
@@ -28,12 +29,6 @@ module RuboCop
|
|
28
29
|
# rubocop:disable Layout/ClassStructure
|
29
30
|
include RuboCop::Cop::EnforceSuperclass
|
30
31
|
# rubocop:enable Layout/ClassStructure
|
31
|
-
|
32
|
-
def autocorrect(node)
|
33
|
-
lambda do |corrector|
|
34
|
-
corrector.replace(node.source_range, self.class::SUPERCLASS)
|
35
|
-
end
|
36
|
-
end
|
37
32
|
end
|
38
33
|
end
|
39
34
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop prevents usage of `"*"` on an Arel::Table column reference.
|
7
|
+
#
|
8
|
+
# Using `arel_table["*"]` causes the outputted string to be a literal
|
9
|
+
# quoted asterisk (e.g. <tt>`my_model`.`*`</tt>). This causes the
|
10
|
+
# database to look for a column named <tt>`*`</tt> (or `"*"`) as opposed
|
11
|
+
# to expanding the column list as one would likely expect.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# # bad
|
15
|
+
# MyTable.arel_table["*"]
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# MyTable.arel_table[Arel.star]
|
19
|
+
#
|
20
|
+
class ArelStar < Base
|
21
|
+
extend AutoCorrector
|
22
|
+
|
23
|
+
MSG = 'Use `Arel.star` instead of `"*"` for expanded column lists.'
|
24
|
+
|
25
|
+
RESTRICT_ON_SEND = %i[[]].freeze
|
26
|
+
|
27
|
+
def_node_matcher :star_bracket?, <<~PATTERN
|
28
|
+
(send {const (send _ :arel_table)} :[] $(str "*"))
|
29
|
+
PATTERN
|
30
|
+
|
31
|
+
def on_send(node)
|
32
|
+
return unless (star = star_bracket?(node))
|
33
|
+
|
34
|
+
add_offense(star) do |corrector|
|
35
|
+
corrector.replace(star.loc.expression, 'Arel.star')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -13,23 +13,21 @@ module RuboCop
|
|
13
13
|
# # good
|
14
14
|
# assert_not x
|
15
15
|
#
|
16
|
-
class AssertNot <
|
16
|
+
class AssertNot < Base
|
17
|
+
extend AutoCorrector
|
18
|
+
|
17
19
|
MSG = 'Prefer `assert_not` over `assert !`.'
|
20
|
+
RESTRICT_ON_SEND = %i[assert].freeze
|
18
21
|
|
19
22
|
def_node_matcher :offensive?, '(send nil? :assert (send ... :!) ...)'
|
20
23
|
|
21
24
|
def on_send(node)
|
22
|
-
|
23
|
-
end
|
25
|
+
return unless offensive?(node)
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
+
add_offense(node) do |corrector|
|
28
|
+
expression = node.loc.expression
|
27
29
|
|
28
|
-
|
29
|
-
corrector.replace(
|
30
|
-
expression,
|
31
|
-
corrected_source(expression.source)
|
32
|
-
)
|
30
|
+
corrector.replace(expression, corrected_source(expression.source))
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop looks for `attribute` class methods that specify a `:default` option
|
7
|
+
# which value is an array, string literal or method call without a block.
|
8
|
+
# It will accept all other values, such as string, symbol, integer and float literals
|
9
|
+
# as well as constants.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# class User < ApplicationRecord
|
14
|
+
# attribute :confirmed_at, :datetime, default: Time.zone.now
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# class User < ApplicationRecord
|
19
|
+
# attribute :confirmed_at, :datetime, default: -> { Time.zone.now }
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # bad
|
23
|
+
# class User < ApplicationRecord
|
24
|
+
# attribute :roles, :string, array: true, default: []
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# class User < ApplicationRecord
|
29
|
+
# attribute :roles, :string, array: true, default: -> { [] }
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # bad
|
33
|
+
# class User < ApplicationRecord
|
34
|
+
# attribute :configuration, default: {}
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# # good
|
38
|
+
# class User < ApplicationRecord
|
39
|
+
# attribute :configuration, default: -> { {} }
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # good
|
43
|
+
# class User < ApplicationRecord
|
44
|
+
# attribute :role, :string, default: :customer
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# # good
|
48
|
+
# class User < ApplicationRecord
|
49
|
+
# attribute :activated, :boolean, default: false
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# # good
|
53
|
+
# class User < ApplicationRecord
|
54
|
+
# attribute :login_count, :integer, default: 0
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# # good
|
58
|
+
# class User < ApplicationRecord
|
59
|
+
# FOO = 123
|
60
|
+
# attribute :custom_attribute, :integer, default: FOO
|
61
|
+
# end
|
62
|
+
class AttributeDefaultBlockValue < Base
|
63
|
+
extend AutoCorrector
|
64
|
+
|
65
|
+
MSG = 'Pass method in a block to `:default` option.'
|
66
|
+
RESTRICT_ON_SEND = %i[attribute].freeze
|
67
|
+
TYPE_OFFENDERS = %i[send array hash].freeze
|
68
|
+
|
69
|
+
def_node_matcher :default_attribute, <<~PATTERN
|
70
|
+
(send nil? :attribute _ ?_ (hash <$#attribute ...>))
|
71
|
+
PATTERN
|
72
|
+
|
73
|
+
def_node_matcher :attribute, '(pair (sym :default) $_)'
|
74
|
+
|
75
|
+
def on_send(node)
|
76
|
+
default_attribute(node) do |attribute|
|
77
|
+
value = attribute.children.last
|
78
|
+
return unless TYPE_OFFENDERS.any?(value.type)
|
79
|
+
|
80
|
+
add_offense(value) do |corrector|
|
81
|
+
expression = default_attribute(node).children.last
|
82
|
+
|
83
|
+
corrector.replace(value, "-> { #{expression.source} }")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -50,7 +50,8 @@ module RuboCop
|
|
50
50
|
#
|
51
51
|
# @see https://guides.rubyonrails.org/5_0_release_notes.html
|
52
52
|
# @see https://github.com/rails/rails/pull/18937
|
53
|
-
class BelongsTo <
|
53
|
+
class BelongsTo < Base
|
54
|
+
extend AutoCorrector
|
54
55
|
extend TargetRailsVersion
|
55
56
|
|
56
57
|
minimum_target_rails_version 5.0
|
@@ -64,35 +65,25 @@ module RuboCop
|
|
64
65
|
'option is deprecated and you want to use `optional: false`. ' \
|
65
66
|
'In most configurations, this is the default and you can omit ' \
|
66
67
|
'this option altogether'
|
68
|
+
RESTRICT_ON_SEND = %i[belongs_to].freeze
|
67
69
|
|
68
70
|
def_node_matcher :match_belongs_to_with_options, <<~PATTERN
|
69
|
-
(send _ :belongs_to
|
71
|
+
(send _ :belongs_to ...
|
70
72
|
(hash <$(pair (sym :required) ${true false}) ...>)
|
71
73
|
)
|
72
74
|
PATTERN
|
73
75
|
|
74
76
|
def on_send(node)
|
75
|
-
match_belongs_to_with_options(node) do |
|
76
|
-
message =
|
77
|
+
match_belongs_to_with_options(node) do |option_node, option_value|
|
78
|
+
message, replacement =
|
77
79
|
if option_value.true_type?
|
78
|
-
SUPERFLOUS_REQUIRE_TRUE_MSG
|
80
|
+
[SUPERFLOUS_REQUIRE_TRUE_MSG, 'optional: false']
|
79
81
|
elsif option_value.false_type?
|
80
|
-
SUPERFLOUS_REQUIRE_FALSE_MSG
|
82
|
+
[SUPERFLOUS_REQUIRE_FALSE_MSG, 'optional: true']
|
81
83
|
end
|
82
84
|
|
83
|
-
add_offense(node, message: message
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
def autocorrect(node)
|
88
|
-
option_node, option_value = match_belongs_to_with_options(node)
|
89
|
-
return unless option_node
|
90
|
-
|
91
|
-
lambda do |corrector|
|
92
|
-
if option_value.true_type?
|
93
|
-
corrector.replace(option_node.loc.expression, 'optional: false')
|
94
|
-
elsif option_value.false_type?
|
95
|
-
corrector.replace(option_node.loc.expression, 'optional: true')
|
85
|
+
add_offense(node.loc.selector, message: message) do |corrector|
|
86
|
+
corrector.replace(option_node.loc.expression, replacement)
|
96
87
|
end
|
97
88
|
end
|
98
89
|
end
|
@@ -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
|
@@ -53,11 +57,14 @@ module RuboCop
|
|
53
57
|
# def blank?
|
54
58
|
# !present?
|
55
59
|
# end
|
56
|
-
class Blank <
|
60
|
+
class Blank < Base
|
61
|
+
extend AutoCorrector
|
62
|
+
|
57
63
|
MSG_NIL_OR_EMPTY = 'Use `%<prefer>s` instead of `%<current>s`.'
|
58
64
|
MSG_NOT_PRESENT = 'Use `%<prefer>s` instead of `%<current>s`.'
|
59
65
|
MSG_UNLESS_PRESENT = 'Use `if %<prefer>s` instead of ' \
|
60
66
|
'`%<current>s`.'
|
67
|
+
RESTRICT_ON_SEND = %i[!].freeze
|
61
68
|
|
62
69
|
# `(send nil $_)` is not actually a valid match for an offense. Nodes
|
63
70
|
# that have a single method call on the left hand side
|
@@ -93,10 +100,10 @@ module RuboCop
|
|
93
100
|
# accepts !present? if its in the body of a `blank?` method
|
94
101
|
next if defining_blank?(node.parent)
|
95
102
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
103
|
+
message = format(MSG_NOT_PRESENT, prefer: replacement(receiver), current: node.source)
|
104
|
+
add_offense(node, message: message) do |corrector|
|
105
|
+
autocorrect(corrector, node)
|
106
|
+
end
|
100
107
|
end
|
101
108
|
end
|
102
109
|
|
@@ -106,10 +113,10 @@ module RuboCop
|
|
106
113
|
nil_or_empty?(node) do |var1, var2|
|
107
114
|
return unless var1 == var2
|
108
115
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
116
|
+
message = format(MSG_NIL_OR_EMPTY, prefer: replacement(var1), current: node.source)
|
117
|
+
add_offense(node, message: message) do |corrector|
|
118
|
+
autocorrect(corrector, node)
|
119
|
+
end
|
113
120
|
end
|
114
121
|
end
|
115
122
|
|
@@ -121,31 +128,28 @@ module RuboCop
|
|
121
128
|
unless_present?(node) do |method_call, receiver|
|
122
129
|
range = unless_condition(node, method_call)
|
123
130
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
current: range.source))
|
131
|
+
message = format(MSG_UNLESS_PRESENT, prefer: replacement(receiver), current: range.source)
|
132
|
+
add_offense(range, message: message) do |corrector|
|
133
|
+
autocorrect(corrector, node)
|
134
|
+
end
|
129
135
|
end
|
130
136
|
end
|
131
137
|
|
132
|
-
|
133
|
-
lambda do |corrector|
|
134
|
-
method_call, variable1 = unless_present?(node)
|
138
|
+
private
|
135
139
|
|
136
|
-
|
137
|
-
|
138
|
-
range = method_call.loc.expression
|
139
|
-
else
|
140
|
-
variable1, _variable2 = nil_or_empty?(node) || not_present?(node)
|
141
|
-
range = node.loc.expression
|
142
|
-
end
|
140
|
+
def autocorrect(corrector, node)
|
141
|
+
method_call, variable1 = unless_present?(node)
|
143
142
|
|
144
|
-
|
143
|
+
if method_call
|
144
|
+
corrector.replace(node.loc.keyword, 'if')
|
145
|
+
range = method_call.loc.expression
|
146
|
+
else
|
147
|
+
variable1, _variable2 = nil_or_empty?(node) || not_present?(node)
|
148
|
+
range = node.loc.expression
|
145
149
|
end
|
146
|
-
end
|
147
150
|
|
148
|
-
|
151
|
+
corrector.replace(range, replacement(variable1))
|
152
|
+
end
|
149
153
|
|
150
154
|
def unless_condition(node, method_call)
|
151
155
|
if node.modifier_form?
|
@@ -65,7 +65,7 @@ module RuboCop
|
|
65
65
|
#
|
66
66
|
# @see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-change_table
|
67
67
|
# @see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
|
68
|
-
class BulkChangeTable <
|
68
|
+
class BulkChangeTable < Base
|
69
69
|
MSG_FOR_CHANGE_TABLE = <<~MSG.chomp
|
70
70
|
You can combine alter queries using `bulk: true` options.
|
71
71
|
MSG
|
@@ -18,46 +18,61 @@ module RuboCop
|
|
18
18
|
# tag.p('Hello world!')
|
19
19
|
# tag.br
|
20
20
|
# content_tag(name, 'Hello world!')
|
21
|
-
class ContentTag <
|
21
|
+
class ContentTag < Base
|
22
22
|
include RangeHelp
|
23
|
+
extend AutoCorrector
|
23
24
|
extend TargetRailsVersion
|
24
25
|
|
25
26
|
minimum_target_rails_version 5.1
|
26
27
|
|
27
28
|
MSG = 'Use `tag` instead of `content_tag`.'
|
29
|
+
RESTRICT_ON_SEND = %i[content_tag].freeze
|
28
30
|
|
29
|
-
def
|
30
|
-
|
31
|
+
def on_new_investigation
|
32
|
+
@corrected_nodes = nil
|
33
|
+
end
|
31
34
|
|
35
|
+
def on_send(node)
|
32
36
|
first_argument = node.first_argument
|
33
|
-
return
|
37
|
+
return if !first_argument ||
|
38
|
+
allowed_argument?(first_argument) ||
|
39
|
+
corrected_ancestor?(node)
|
40
|
+
|
41
|
+
add_offense(node) do |corrector|
|
42
|
+
autocorrect(corrector, node)
|
43
|
+
|
44
|
+
@corrected_nodes ||= Set.new.compare_by_identity
|
45
|
+
@corrected_nodes.add(node)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
34
50
|
|
35
|
-
|
51
|
+
def corrected_ancestor?(node)
|
52
|
+
node.each_ancestor(:send).any? { |ancestor| @corrected_nodes&.include?(ancestor) }
|
53
|
+
end
|
36
54
|
|
37
|
-
|
55
|
+
def allowed_argument?(argument)
|
56
|
+
argument.variable? || argument.send_type? || argument.const_type? || argument.splat_type?
|
38
57
|
end
|
39
58
|
|
40
|
-
def autocorrect(node)
|
41
|
-
|
42
|
-
|
43
|
-
range = correction_range(node)
|
59
|
+
def autocorrect(corrector, node)
|
60
|
+
if method_name?(node.first_argument)
|
61
|
+
range = correction_range(node)
|
44
62
|
|
45
|
-
|
46
|
-
|
63
|
+
rest_args = node.arguments.drop(1)
|
64
|
+
replacement = "tag.#{node.first_argument.value.to_s.underscore}(#{rest_args.map(&:source).join(', ')})"
|
47
65
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
66
|
+
corrector.replace(range, replacement)
|
67
|
+
else
|
68
|
+
corrector.replace(node.loc.selector, 'tag')
|
52
69
|
end
|
53
70
|
end
|
54
71
|
|
55
|
-
private
|
56
|
-
|
57
72
|
def method_name?(node)
|
58
73
|
return false unless node.str_type? || node.sym_type?
|
59
74
|
|
60
|
-
/^[a-zA-Z_][a-zA-
|
75
|
+
/^[a-zA-Z_][a-zA-Z_\-0-9]*$/.match?(node.value)
|
61
76
|
end
|
62
77
|
|
63
78
|
def correction_range(node)
|