rubocop 0.70.0 → 0.72.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/README.md +5 -10
- data/config/default.yml +50 -491
- data/lib/rubocop.rb +5 -53
- data/lib/rubocop/ast/builder.rb +2 -0
- data/lib/rubocop/ast/node.rb +1 -1
- data/lib/rubocop/ast/node/float_node.rb +12 -0
- data/lib/rubocop/ast/node/int_node.rb +12 -0
- data/lib/rubocop/ast/node/mixin/numeric_node.rb +21 -0
- data/lib/rubocop/ast/node/resbody_node.rb +1 -6
- data/lib/rubocop/cached_data.rb +1 -1
- data/lib/rubocop/config.rb +35 -6
- data/lib/rubocop/config_loader.rb +2 -2
- data/lib/rubocop/config_loader_resolver.rb +0 -6
- data/lib/rubocop/cop/cop.rb +0 -4
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +55 -0
- data/lib/rubocop/cop/layout/class_structure.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +3 -1
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +4 -0
- data/lib/rubocop/cop/layout/indent_first_argument.rb +6 -2
- data/lib/rubocop/cop/layout/indent_first_parameter.rb +7 -3
- data/lib/rubocop/cop/layout/indent_heredoc.rb +0 -1
- data/lib/rubocop/cop/layout/indentation_consistency.rb +13 -12
- data/lib/rubocop/cop/layout/indentation_width.rb +8 -4
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +2 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_alignment.rb +4 -0
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +20 -22
- data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +2 -1
- data/lib/rubocop/cop/style/float_division.rb +94 -0
- data/lib/rubocop/cop/style/format_string.rb +7 -3
- data/lib/rubocop/cop/style/if_inside_else.rb +42 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
- data/lib/rubocop/cop/style/ternary_parentheses.rb +12 -2
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -0
- data/lib/rubocop/cop/style/word_array.rb +2 -2
- data/lib/rubocop/cop/style/zero_length_predicate.rb +1 -1
- data/lib/rubocop/node_pattern.rb +84 -5
- data/lib/rubocop/options.rb +0 -2
- data/lib/rubocop/processed_source.rb +5 -1
- data/lib/rubocop/rspec/cop_helper.rb +0 -1
- data/lib/rubocop/rspec/shared_contexts.rb +0 -17
- data/lib/rubocop/rspec/support.rb +0 -1
- data/lib/rubocop/runner.rb +6 -7
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop/yaml_duplication_checker.rb +8 -2
- metadata +7 -69
- data/lib/rubocop/cop/mixin/target_rails_version.rb +0 -16
- data/lib/rubocop/cop/rails/action_filter.rb +0 -117
- data/lib/rubocop/cop/rails/active_record_aliases.rb +0 -48
- data/lib/rubocop/cop/rails/active_record_override.rb +0 -82
- data/lib/rubocop/cop/rails/active_support_aliases.rb +0 -69
- data/lib/rubocop/cop/rails/application_job.rb +0 -40
- data/lib/rubocop/cop/rails/application_record.rb +0 -40
- data/lib/rubocop/cop/rails/assert_not.rb +0 -44
- data/lib/rubocop/cop/rails/belongs_to.rb +0 -102
- data/lib/rubocop/cop/rails/blank.rb +0 -164
- data/lib/rubocop/cop/rails/bulk_change_table.rb +0 -289
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +0 -91
- data/lib/rubocop/cop/rails/date.rb +0 -161
- data/lib/rubocop/cop/rails/delegate.rb +0 -132
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +0 -37
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +0 -91
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +0 -45
- data/lib/rubocop/cop/rails/environment_comparison.rb +0 -68
- data/lib/rubocop/cop/rails/exit.rb +0 -67
- data/lib/rubocop/cop/rails/file_path.rb +0 -108
- data/lib/rubocop/cop/rails/find_by.rb +0 -55
- data/lib/rubocop/cop/rails/find_each.rb +0 -51
- data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +0 -25
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +0 -106
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +0 -117
- data/lib/rubocop/cop/rails/http_status.rb +0 -179
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +0 -94
- data/lib/rubocop/cop/rails/inverse_of.rb +0 -246
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +0 -175
- data/lib/rubocop/cop/rails/link_to_blank.rb +0 -98
- data/lib/rubocop/cop/rails/not_null_column.rb +0 -67
- data/lib/rubocop/cop/rails/output.rb +0 -49
- data/lib/rubocop/cop/rails/output_safety.rb +0 -99
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +0 -107
- data/lib/rubocop/cop/rails/presence.rb +0 -124
- data/lib/rubocop/cop/rails/present.rb +0 -153
- data/lib/rubocop/cop/rails/read_write_attribute.rb +0 -74
- data/lib/rubocop/cop/rails/redundant_allow_nil.rb +0 -111
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +0 -136
- data/lib/rubocop/cop/rails/reflection_class_name.rb +0 -37
- data/lib/rubocop/cop/rails/refute_methods.rb +0 -76
- data/lib/rubocop/cop/rails/relative_date_constant.rb +0 -93
- data/lib/rubocop/cop/rails/request_referer.rb +0 -56
- data/lib/rubocop/cop/rails/reversible_migration.rb +0 -286
- data/lib/rubocop/cop/rails/safe_navigation.rb +0 -87
- data/lib/rubocop/cop/rails/save_bang.rb +0 -316
- data/lib/rubocop/cop/rails/scope_args.rb +0 -29
- data/lib/rubocop/cop/rails/skips_model_validations.rb +0 -87
- data/lib/rubocop/cop/rails/time_zone.rb +0 -238
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +0 -105
- data/lib/rubocop/cop/rails/unknown_env.rb +0 -63
- data/lib/rubocop/cop/rails/validation.rb +0 -109
- data/lib/rubocop/rspec/shared_examples.rb +0 -59
@@ -1,238 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RuboCop
|
4
|
-
module Cop
|
5
|
-
module Rails
|
6
|
-
# This cop checks for the use of Time methods without zone.
|
7
|
-
#
|
8
|
-
# Built on top of Ruby on Rails style guide (https://github.com/rubocop-hq/rails-style-guide#time)
|
9
|
-
# and the article http://danilenko.org/2012/7/6/rails_timezones/
|
10
|
-
#
|
11
|
-
# Two styles are supported for this cop. When EnforcedStyle is 'strict'
|
12
|
-
# then only use of Time.zone is allowed.
|
13
|
-
#
|
14
|
-
# When EnforcedStyle is 'flexible' then it's also allowed
|
15
|
-
# to use Time.in_time_zone.
|
16
|
-
#
|
17
|
-
# @example EnforcedStyle: strict
|
18
|
-
# # `strict` means that `Time` should be used with `zone`.
|
19
|
-
#
|
20
|
-
# # bad
|
21
|
-
# Time.now
|
22
|
-
# Time.parse('2015-03-02 19:05:37')
|
23
|
-
#
|
24
|
-
# # bad
|
25
|
-
# Time.current
|
26
|
-
# Time.at(timestamp).in_time_zone
|
27
|
-
#
|
28
|
-
# # good
|
29
|
-
# Time.zone.now
|
30
|
-
# Time.zone.parse('2015-03-02 19:05:37')
|
31
|
-
#
|
32
|
-
# @example EnforcedStyle: flexible (default)
|
33
|
-
# # `flexible` allows usage of `in_time_zone` instead of `zone`.
|
34
|
-
#
|
35
|
-
# # bad
|
36
|
-
# Time.now
|
37
|
-
# Time.parse('2015-03-02 19:05:37')
|
38
|
-
#
|
39
|
-
# # good
|
40
|
-
# Time.zone.now
|
41
|
-
# Time.zone.parse('2015-03-02 19:05:37')
|
42
|
-
#
|
43
|
-
# # good
|
44
|
-
# Time.current
|
45
|
-
# Time.at(timestamp).in_time_zone
|
46
|
-
class TimeZone < Cop
|
47
|
-
include ConfigurableEnforcedStyle
|
48
|
-
|
49
|
-
MSG = 'Do not use `%<current>s` without zone. Use `%<prefer>s` ' \
|
50
|
-
'instead.'
|
51
|
-
|
52
|
-
MSG_ACCEPTABLE = 'Do not use `%<current>s` without zone. ' \
|
53
|
-
'Use one of %<prefer>s instead.'
|
54
|
-
|
55
|
-
MSG_LOCALTIME = 'Do not use `Time.localtime` without ' \
|
56
|
-
'offset or zone.'
|
57
|
-
|
58
|
-
TIMECLASSES = %i[Time DateTime].freeze
|
59
|
-
|
60
|
-
GOOD_METHODS = %i[zone zone_default find_zone find_zone!].freeze
|
61
|
-
|
62
|
-
DANGEROUS_METHODS = %i[now local new parse at current].freeze
|
63
|
-
|
64
|
-
ACCEPTED_METHODS = %i[in_time_zone utc getlocal xmlschema iso8601
|
65
|
-
jisx0301 rfc3339 httpdate to_i to_f].freeze
|
66
|
-
|
67
|
-
def on_const(node)
|
68
|
-
mod, klass = *node
|
69
|
-
# we should only check core classes
|
70
|
-
# (`DateTime`, `Time`, `::DateTime` or `::Time`)
|
71
|
-
return unless (mod.nil? || mod.cbase_type?) && method_send?(node)
|
72
|
-
|
73
|
-
check_time_node(klass, node.parent) if TIMECLASSES.include?(klass)
|
74
|
-
end
|
75
|
-
|
76
|
-
def autocorrect(node)
|
77
|
-
lambda do |corrector|
|
78
|
-
# add `.zone`: `Time.at` => `Time.zone.at`
|
79
|
-
corrector.insert_after(node.children[0].source_range, '.zone')
|
80
|
-
# replace `Time.zone.current` => `Time.zone.now`
|
81
|
-
if node.method_name == :current
|
82
|
-
corrector.replace(node.loc.selector, 'now')
|
83
|
-
end
|
84
|
-
# prefer `Time` over `DateTime` class
|
85
|
-
if strict?
|
86
|
-
corrector.replace(node.children.first.source_range, 'Time')
|
87
|
-
end
|
88
|
-
remove_redundant_in_time_zone(corrector, node)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
private
|
93
|
-
|
94
|
-
# remove redundant `.in_time_zone` from `Time.zone.now.in_time_zone`
|
95
|
-
def remove_redundant_in_time_zone(corrector, node)
|
96
|
-
time_methods_called = extract_method_chain(node)
|
97
|
-
return unless time_methods_called.include?(:in_time_zone) ||
|
98
|
-
time_methods_called.include?(:zone)
|
99
|
-
|
100
|
-
while node&.send_type?
|
101
|
-
if node.children.last == :in_time_zone
|
102
|
-
in_time_zone_with_dot =
|
103
|
-
node.loc.selector.adjust(begin_pos: -1)
|
104
|
-
corrector.remove(in_time_zone_with_dot)
|
105
|
-
end
|
106
|
-
node = node.parent
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def check_time_node(klass, node)
|
111
|
-
chain = extract_method_chain(node)
|
112
|
-
return if not_danger_chain?(chain)
|
113
|
-
|
114
|
-
return check_localtime(node) if need_check_localtime?(chain)
|
115
|
-
|
116
|
-
method_name = (chain & DANGEROUS_METHODS).join('.')
|
117
|
-
|
118
|
-
return if offset_provided?(node)
|
119
|
-
|
120
|
-
message = build_message(klass, method_name, node)
|
121
|
-
|
122
|
-
add_offense(node, location: :selector, message: message)
|
123
|
-
end
|
124
|
-
|
125
|
-
def build_message(klass, method_name, node)
|
126
|
-
if flexible?
|
127
|
-
format(
|
128
|
-
MSG_ACCEPTABLE,
|
129
|
-
current: "#{klass}.#{method_name}",
|
130
|
-
prefer: acceptable_methods(klass, method_name, node).join(', ')
|
131
|
-
)
|
132
|
-
else
|
133
|
-
safe_method_name = safe_method(method_name, node)
|
134
|
-
format(MSG,
|
135
|
-
current: "#{klass}.#{method_name}",
|
136
|
-
prefer: "Time.zone.#{safe_method_name}")
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def extract_method_chain(node)
|
141
|
-
chain = []
|
142
|
-
while !node.nil? && node.send_type?
|
143
|
-
chain << node.method_name if method_from_time_class?(node)
|
144
|
-
node = node.parent
|
145
|
-
end
|
146
|
-
chain
|
147
|
-
end
|
148
|
-
|
149
|
-
# Only add the method to the chain if the method being
|
150
|
-
# called is part of the time class.
|
151
|
-
def method_from_time_class?(node)
|
152
|
-
receiver, method_name, *_args = *node
|
153
|
-
if (receiver.is_a? RuboCop::AST::Node) && !receiver.cbase_type?
|
154
|
-
method_from_time_class?(receiver)
|
155
|
-
else
|
156
|
-
TIMECLASSES.include?(method_name)
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
# checks that parent node of send_type
|
161
|
-
# and receiver is the given node
|
162
|
-
def method_send?(node)
|
163
|
-
return false unless node.parent&.send_type?
|
164
|
-
|
165
|
-
node.parent.receiver == node
|
166
|
-
end
|
167
|
-
|
168
|
-
def safe_method(method_name, node)
|
169
|
-
if %w[new current].include?(method_name)
|
170
|
-
node.arguments? ? 'local' : 'now'
|
171
|
-
else
|
172
|
-
method_name
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
def check_localtime(node)
|
177
|
-
selector_node = node
|
178
|
-
|
179
|
-
while node&.send_type?
|
180
|
-
break if node.method_name == :localtime
|
181
|
-
|
182
|
-
node = node.parent
|
183
|
-
end
|
184
|
-
|
185
|
-
return if node.arguments?
|
186
|
-
|
187
|
-
add_offense(selector_node,
|
188
|
-
location: :selector, message: MSG_LOCALTIME)
|
189
|
-
end
|
190
|
-
|
191
|
-
def not_danger_chain?(chain)
|
192
|
-
(chain & DANGEROUS_METHODS).empty? || !(chain & good_methods).empty?
|
193
|
-
end
|
194
|
-
|
195
|
-
def need_check_localtime?(chain)
|
196
|
-
flexible? && chain.include?(:localtime)
|
197
|
-
end
|
198
|
-
|
199
|
-
def flexible?
|
200
|
-
style == :flexible
|
201
|
-
end
|
202
|
-
|
203
|
-
def strict?
|
204
|
-
style == :strict
|
205
|
-
end
|
206
|
-
|
207
|
-
def good_methods
|
208
|
-
if strict?
|
209
|
-
GOOD_METHODS
|
210
|
-
else
|
211
|
-
GOOD_METHODS + [:current] + ACCEPTED_METHODS
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
def acceptable_methods(klass, method_name, node)
|
216
|
-
acceptable = [
|
217
|
-
"`Time.zone.#{safe_method(method_name, node)}`",
|
218
|
-
"`#{klass}.current`"
|
219
|
-
]
|
220
|
-
|
221
|
-
ACCEPTED_METHODS.each do |am|
|
222
|
-
acceptable << "`#{klass}.#{method_name}.#{am}`"
|
223
|
-
end
|
224
|
-
|
225
|
-
acceptable
|
226
|
-
end
|
227
|
-
|
228
|
-
# Time.new can be called with a time zone offset
|
229
|
-
# When it is, that should be considered safe
|
230
|
-
# Example:
|
231
|
-
# Time.new(1988, 3, 15, 3, 0, 0, "-05:00")
|
232
|
-
def offset_provided?(node)
|
233
|
-
node.arguments.size >= 7
|
234
|
-
end
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
@@ -1,105 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RuboCop
|
4
|
-
module Cop
|
5
|
-
module Rails
|
6
|
-
# Prefer the use of uniq (or distinct), before pluck instead of after.
|
7
|
-
#
|
8
|
-
# The use of uniq before pluck is preferred because it executes within
|
9
|
-
# the database.
|
10
|
-
#
|
11
|
-
# This cop has two different enforcement modes. When the EnforcedStyle
|
12
|
-
# is conservative (the default) then only calls to pluck on a constant
|
13
|
-
# (i.e. a model class) before uniq are added as offenses.
|
14
|
-
#
|
15
|
-
# When the EnforcedStyle is aggressive then all calls to pluck before
|
16
|
-
# uniq are added as offenses. This may lead to false positives as the cop
|
17
|
-
# cannot distinguish between calls to pluck on an ActiveRecord::Relation
|
18
|
-
# vs a call to pluck on an ActiveRecord::Associations::CollectionProxy.
|
19
|
-
#
|
20
|
-
# Autocorrect is disabled by default for this cop since it may generate
|
21
|
-
# false positives.
|
22
|
-
#
|
23
|
-
# @example EnforcedStyle: conservative (default)
|
24
|
-
# # bad
|
25
|
-
# Model.pluck(:id).uniq
|
26
|
-
#
|
27
|
-
# # good
|
28
|
-
# Model.uniq.pluck(:id)
|
29
|
-
#
|
30
|
-
# @example EnforcedStyle: aggressive
|
31
|
-
# # bad
|
32
|
-
# # this will return a Relation that pluck is called on
|
33
|
-
# Model.where(cond: true).pluck(:id).uniq
|
34
|
-
#
|
35
|
-
# # bad
|
36
|
-
# # an association on an instance will return a CollectionProxy
|
37
|
-
# instance.assoc.pluck(:id).uniq
|
38
|
-
#
|
39
|
-
# # bad
|
40
|
-
# Model.pluck(:id).uniq
|
41
|
-
#
|
42
|
-
# # good
|
43
|
-
# Model.uniq.pluck(:id)
|
44
|
-
#
|
45
|
-
class UniqBeforePluck < RuboCop::Cop::Cop
|
46
|
-
include ConfigurableEnforcedStyle
|
47
|
-
include RangeHelp
|
48
|
-
|
49
|
-
MSG = 'Use `%<method>s` before `pluck`.'
|
50
|
-
NEWLINE = "\n"
|
51
|
-
PATTERN = '[!^block (send (send %<type>s :pluck ...) ' \
|
52
|
-
'${:uniq :distinct} ...)]'
|
53
|
-
|
54
|
-
def_node_matcher :conservative_node_match,
|
55
|
-
format(PATTERN, type: 'const')
|
56
|
-
|
57
|
-
def_node_matcher :aggressive_node_match,
|
58
|
-
format(PATTERN, type: '_')
|
59
|
-
|
60
|
-
def on_send(node)
|
61
|
-
method = if style == :conservative
|
62
|
-
conservative_node_match(node)
|
63
|
-
else
|
64
|
-
aggressive_node_match(node)
|
65
|
-
end
|
66
|
-
|
67
|
-
return unless method
|
68
|
-
|
69
|
-
add_offense(node, location: :selector,
|
70
|
-
message: format(MSG, method: method))
|
71
|
-
end
|
72
|
-
|
73
|
-
def autocorrect(node)
|
74
|
-
lambda do |corrector|
|
75
|
-
method = node.method_name
|
76
|
-
|
77
|
-
corrector.remove(dot_method_with_whitespace(method, node))
|
78
|
-
corrector.insert_before(node.receiver.loc.dot.begin, ".#{method}")
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
private
|
83
|
-
|
84
|
-
def style_parameter_name
|
85
|
-
'EnforcedStyle'
|
86
|
-
end
|
87
|
-
|
88
|
-
def dot_method_with_whitespace(method, node)
|
89
|
-
range_between(dot_method_begin_pos(method, node),
|
90
|
-
node.loc.selector.end_pos)
|
91
|
-
end
|
92
|
-
|
93
|
-
def dot_method_begin_pos(method, node)
|
94
|
-
lines = node.source.split(NEWLINE)
|
95
|
-
|
96
|
-
if lines.last.strip == ".#{method}"
|
97
|
-
node.source.rindex(NEWLINE)
|
98
|
-
else
|
99
|
-
node.loc.dot.begin_pos
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RuboCop
|
4
|
-
module Cop
|
5
|
-
module Rails
|
6
|
-
# This cop checks that environments called with `Rails.env` predicates
|
7
|
-
# exist.
|
8
|
-
#
|
9
|
-
# @example
|
10
|
-
# # bad
|
11
|
-
# Rails.env.proudction?
|
12
|
-
#
|
13
|
-
# # good
|
14
|
-
# Rails.env.production?
|
15
|
-
class UnknownEnv < Cop
|
16
|
-
include NameSimilarity
|
17
|
-
|
18
|
-
MSG = 'Unknown environment `%<name>s`.'
|
19
|
-
MSG_SIMILAR = 'Unknown environment `%<name>s`. ' \
|
20
|
-
'Did you mean `%<similar>s`?'
|
21
|
-
|
22
|
-
def_node_matcher :unknown_environment?, <<-PATTERN
|
23
|
-
(send
|
24
|
-
(send
|
25
|
-
{(const nil? :Rails) (const (cbase) :Rails)}
|
26
|
-
:env)
|
27
|
-
$#unknown_env_name?)
|
28
|
-
PATTERN
|
29
|
-
|
30
|
-
def on_send(node)
|
31
|
-
unknown_environment?(node) do |name|
|
32
|
-
add_offense(node, location: :selector, message: message(name))
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def collect_variable_like_names(_scope)
|
39
|
-
environments.map { |env| env + '?' }
|
40
|
-
end
|
41
|
-
|
42
|
-
def message(name)
|
43
|
-
similar = find_similar_name(name.to_s, [])
|
44
|
-
if similar
|
45
|
-
format(MSG_SIMILAR, name: name, similar: similar)
|
46
|
-
else
|
47
|
-
format(MSG, name: name)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def unknown_env_name?(name)
|
52
|
-
name = name.to_s
|
53
|
-
name.end_with?('?') &&
|
54
|
-
!environments.include?(name[0..-2])
|
55
|
-
end
|
56
|
-
|
57
|
-
def environments
|
58
|
-
cop_config['Environments']
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,109 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RuboCop
|
4
|
-
module Cop
|
5
|
-
module Rails
|
6
|
-
# This cop checks for the use of old-style attribute validation macros.
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
# # bad
|
10
|
-
# validates_acceptance_of :foo
|
11
|
-
# validates_confirmation_of :foo
|
12
|
-
# validates_exclusion_of :foo
|
13
|
-
# validates_format_of :foo
|
14
|
-
# validates_inclusion_of :foo
|
15
|
-
# validates_length_of :foo
|
16
|
-
# validates_numericality_of :foo
|
17
|
-
# validates_presence_of :foo
|
18
|
-
# validates_absence_of :foo
|
19
|
-
# validates_size_of :foo
|
20
|
-
# validates_uniqueness_of :foo
|
21
|
-
#
|
22
|
-
# # good
|
23
|
-
# validates :foo, acceptance: true
|
24
|
-
# validates :foo, confirmation: true
|
25
|
-
# validates :foo, exclusion: true
|
26
|
-
# validates :foo, format: true
|
27
|
-
# validates :foo, inclusion: true
|
28
|
-
# validates :foo, length: true
|
29
|
-
# validates :foo, numericality: true
|
30
|
-
# validates :foo, presence: true
|
31
|
-
# validates :foo, absence: true
|
32
|
-
# validates :foo, size: true
|
33
|
-
# validates :foo, uniqueness: true
|
34
|
-
#
|
35
|
-
class Validation < Cop
|
36
|
-
MSG = 'Prefer the new style validations `%<prefer>s` over ' \
|
37
|
-
'`%<current>s`.'
|
38
|
-
|
39
|
-
TYPES = %w[
|
40
|
-
acceptance
|
41
|
-
confirmation
|
42
|
-
exclusion
|
43
|
-
format
|
44
|
-
inclusion
|
45
|
-
length
|
46
|
-
numericality
|
47
|
-
presence
|
48
|
-
absence
|
49
|
-
size
|
50
|
-
uniqueness
|
51
|
-
].freeze
|
52
|
-
|
53
|
-
DENYLIST = TYPES.map { |p| "validates_#{p}_of".to_sym }.freeze
|
54
|
-
ALLOWLIST = TYPES.map { |p| "validates :column, #{p}: value" }.freeze
|
55
|
-
|
56
|
-
def on_send(node)
|
57
|
-
return unless !node.receiver && DENYLIST.include?(node.method_name)
|
58
|
-
|
59
|
-
add_offense(node, location: :selector)
|
60
|
-
end
|
61
|
-
|
62
|
-
def autocorrect(node)
|
63
|
-
last_argument = node.arguments.last
|
64
|
-
return if !last_argument.literal? && !last_argument.splat_type?
|
65
|
-
|
66
|
-
lambda do |corrector|
|
67
|
-
corrector.replace(node.loc.selector, 'validates')
|
68
|
-
correct_validate_type(corrector, node)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
private
|
73
|
-
|
74
|
-
def message(node)
|
75
|
-
format(MSG, prefer: preferred_method(node.method_name),
|
76
|
-
current: node.method_name)
|
77
|
-
end
|
78
|
-
|
79
|
-
def preferred_method(method)
|
80
|
-
ALLOWLIST[DENYLIST.index(method.to_sym)]
|
81
|
-
end
|
82
|
-
|
83
|
-
def correct_validate_type(corrector, node)
|
84
|
-
last_argument = node.arguments.last
|
85
|
-
validate_type = node.method_name.to_s.split('_')[1]
|
86
|
-
|
87
|
-
if last_argument.hash_type?
|
88
|
-
corrector.replace(
|
89
|
-
last_argument.loc.expression,
|
90
|
-
"#{validate_type}: #{braced_options(last_argument)}"
|
91
|
-
)
|
92
|
-
else
|
93
|
-
range = last_argument.source_range
|
94
|
-
|
95
|
-
corrector.insert_after(range, ", #{validate_type}: true")
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def braced_options(options)
|
100
|
-
if options.braces?
|
101
|
-
options.source
|
102
|
-
else
|
103
|
-
"{ #{options.source} }"
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|