rubocop 0.71.0 → 0.72.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -8
  3. data/config/default.yml +42 -484
  4. data/lib/rubocop.rb +5 -53
  5. data/lib/rubocop/ast/builder.rb +2 -0
  6. data/lib/rubocop/ast/node.rb +1 -1
  7. data/lib/rubocop/ast/node/float_node.rb +12 -0
  8. data/lib/rubocop/ast/node/int_node.rb +12 -0
  9. data/lib/rubocop/ast/node/mixin/numeric_node.rb +21 -0
  10. data/lib/rubocop/ast/node/resbody_node.rb +1 -6
  11. data/lib/rubocop/cached_data.rb +1 -1
  12. data/lib/rubocop/config.rb +34 -5
  13. data/lib/rubocop/config_loader.rb +2 -6
  14. data/lib/rubocop/config_loader_resolver.rb +0 -14
  15. data/lib/rubocop/cop/cop.rb +0 -4
  16. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +55 -0
  17. data/lib/rubocop/cop/layout/class_structure.rb +1 -1
  18. data/lib/rubocop/cop/layout/indent_first_argument.rb +6 -2
  19. data/lib/rubocop/cop/layout/indent_first_parameter.rb +7 -3
  20. data/lib/rubocop/cop/layout/indent_heredoc.rb +0 -1
  21. data/lib/rubocop/cop/layout/indentation_consistency.rb +13 -12
  22. data/lib/rubocop/cop/layout/indentation_width.rb +8 -4
  23. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  24. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +21 -20
  25. data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
  26. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -1
  27. data/lib/rubocop/cop/style/float_division.rb +94 -0
  28. data/lib/rubocop/cop/style/format_string.rb +7 -3
  29. data/lib/rubocop/cop/style/if_inside_else.rb +42 -0
  30. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -1
  31. data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
  32. data/lib/rubocop/cop/style/ternary_parentheses.rb +12 -2
  33. data/lib/rubocop/cop/style/word_array.rb +2 -2
  34. data/lib/rubocop/cop/style/zero_length_predicate.rb +1 -1
  35. data/lib/rubocop/options.rb +0 -2
  36. data/lib/rubocop/processed_source.rb +2 -1
  37. data/lib/rubocop/rspec/cop_helper.rb +0 -1
  38. data/lib/rubocop/rspec/shared_contexts.rb +0 -17
  39. data/lib/rubocop/rspec/support.rb +0 -1
  40. data/lib/rubocop/runner.rb +0 -17
  41. data/lib/rubocop/version.rb +1 -1
  42. data/lib/rubocop/yaml_duplication_checker.rb +8 -2
  43. metadata +8 -91
  44. data/lib/rubocop/cop/mixin/target_rails_version.rb +0 -16
  45. data/lib/rubocop/cop/rails/action_filter.rb +0 -117
  46. data/lib/rubocop/cop/rails/active_record_aliases.rb +0 -48
  47. data/lib/rubocop/cop/rails/active_record_override.rb +0 -82
  48. data/lib/rubocop/cop/rails/active_support_aliases.rb +0 -69
  49. data/lib/rubocop/cop/rails/application_job.rb +0 -40
  50. data/lib/rubocop/cop/rails/application_record.rb +0 -40
  51. data/lib/rubocop/cop/rails/assert_not.rb +0 -44
  52. data/lib/rubocop/cop/rails/belongs_to.rb +0 -102
  53. data/lib/rubocop/cop/rails/blank.rb +0 -164
  54. data/lib/rubocop/cop/rails/bulk_change_table.rb +0 -289
  55. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +0 -91
  56. data/lib/rubocop/cop/rails/date.rb +0 -161
  57. data/lib/rubocop/cop/rails/delegate.rb +0 -132
  58. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +0 -37
  59. data/lib/rubocop/cop/rails/dynamic_find_by.rb +0 -91
  60. data/lib/rubocop/cop/rails/enum_uniqueness.rb +0 -45
  61. data/lib/rubocop/cop/rails/environment_comparison.rb +0 -68
  62. data/lib/rubocop/cop/rails/exit.rb +0 -67
  63. data/lib/rubocop/cop/rails/file_path.rb +0 -108
  64. data/lib/rubocop/cop/rails/find_by.rb +0 -55
  65. data/lib/rubocop/cop/rails/find_each.rb +0 -51
  66. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +0 -25
  67. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +0 -106
  68. data/lib/rubocop/cop/rails/http_positional_arguments.rb +0 -117
  69. data/lib/rubocop/cop/rails/http_status.rb +0 -179
  70. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +0 -94
  71. data/lib/rubocop/cop/rails/inverse_of.rb +0 -246
  72. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +0 -175
  73. data/lib/rubocop/cop/rails/link_to_blank.rb +0 -98
  74. data/lib/rubocop/cop/rails/not_null_column.rb +0 -67
  75. data/lib/rubocop/cop/rails/output.rb +0 -49
  76. data/lib/rubocop/cop/rails/output_safety.rb +0 -99
  77. data/lib/rubocop/cop/rails/pluralization_grammar.rb +0 -107
  78. data/lib/rubocop/cop/rails/presence.rb +0 -124
  79. data/lib/rubocop/cop/rails/present.rb +0 -153
  80. data/lib/rubocop/cop/rails/read_write_attribute.rb +0 -74
  81. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +0 -111
  82. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +0 -136
  83. data/lib/rubocop/cop/rails/reflection_class_name.rb +0 -37
  84. data/lib/rubocop/cop/rails/refute_methods.rb +0 -76
  85. data/lib/rubocop/cop/rails/relative_date_constant.rb +0 -93
  86. data/lib/rubocop/cop/rails/request_referer.rb +0 -56
  87. data/lib/rubocop/cop/rails/reversible_migration.rb +0 -286
  88. data/lib/rubocop/cop/rails/safe_navigation.rb +0 -87
  89. data/lib/rubocop/cop/rails/save_bang.rb +0 -316
  90. data/lib/rubocop/cop/rails/scope_args.rb +0 -29
  91. data/lib/rubocop/cop/rails/skips_model_validations.rb +0 -87
  92. data/lib/rubocop/cop/rails/time_zone.rb +0 -238
  93. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +0 -105
  94. data/lib/rubocop/cop/rails/unknown_env.rb +0 -63
  95. data/lib/rubocop/cop/rails/validation.rb +0 -109
  96. 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