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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -10
  3. data/config/default.yml +50 -491
  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 +35 -6
  13. data/lib/rubocop/config_loader.rb +2 -2
  14. data/lib/rubocop/config_loader_resolver.rb +0 -6
  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/empty_lines_around_block_body.rb +3 -1
  19. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +4 -0
  20. data/lib/rubocop/cop/layout/indent_first_argument.rb +6 -2
  21. data/lib/rubocop/cop/layout/indent_first_parameter.rb +7 -3
  22. data/lib/rubocop/cop/layout/indent_heredoc.rb +0 -1
  23. data/lib/rubocop/cop/layout/indentation_consistency.rb +13 -12
  24. data/lib/rubocop/cop/layout/indentation_width.rb +8 -4
  25. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +2 -0
  26. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  27. data/lib/rubocop/cop/mixin/hash_alignment.rb +4 -0
  28. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +20 -22
  29. data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
  30. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -1
  31. data/lib/rubocop/cop/style/float_division.rb +94 -0
  32. data/lib/rubocop/cop/style/format_string.rb +7 -3
  33. data/lib/rubocop/cop/style/if_inside_else.rb +42 -0
  34. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -1
  35. data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
  36. data/lib/rubocop/cop/style/ternary_parentheses.rb +12 -2
  37. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -0
  38. data/lib/rubocop/cop/style/word_array.rb +2 -2
  39. data/lib/rubocop/cop/style/zero_length_predicate.rb +1 -1
  40. data/lib/rubocop/node_pattern.rb +84 -5
  41. data/lib/rubocop/options.rb +0 -2
  42. data/lib/rubocop/processed_source.rb +5 -1
  43. data/lib/rubocop/rspec/cop_helper.rb +0 -1
  44. data/lib/rubocop/rspec/shared_contexts.rb +0 -17
  45. data/lib/rubocop/rspec/support.rb +0 -1
  46. data/lib/rubocop/runner.rb +6 -7
  47. data/lib/rubocop/version.rb +1 -1
  48. data/lib/rubocop/yaml_duplication_checker.rb +8 -2
  49. metadata +7 -69
  50. data/lib/rubocop/cop/mixin/target_rails_version.rb +0 -16
  51. data/lib/rubocop/cop/rails/action_filter.rb +0 -117
  52. data/lib/rubocop/cop/rails/active_record_aliases.rb +0 -48
  53. data/lib/rubocop/cop/rails/active_record_override.rb +0 -82
  54. data/lib/rubocop/cop/rails/active_support_aliases.rb +0 -69
  55. data/lib/rubocop/cop/rails/application_job.rb +0 -40
  56. data/lib/rubocop/cop/rails/application_record.rb +0 -40
  57. data/lib/rubocop/cop/rails/assert_not.rb +0 -44
  58. data/lib/rubocop/cop/rails/belongs_to.rb +0 -102
  59. data/lib/rubocop/cop/rails/blank.rb +0 -164
  60. data/lib/rubocop/cop/rails/bulk_change_table.rb +0 -289
  61. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +0 -91
  62. data/lib/rubocop/cop/rails/date.rb +0 -161
  63. data/lib/rubocop/cop/rails/delegate.rb +0 -132
  64. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +0 -37
  65. data/lib/rubocop/cop/rails/dynamic_find_by.rb +0 -91
  66. data/lib/rubocop/cop/rails/enum_uniqueness.rb +0 -45
  67. data/lib/rubocop/cop/rails/environment_comparison.rb +0 -68
  68. data/lib/rubocop/cop/rails/exit.rb +0 -67
  69. data/lib/rubocop/cop/rails/file_path.rb +0 -108
  70. data/lib/rubocop/cop/rails/find_by.rb +0 -55
  71. data/lib/rubocop/cop/rails/find_each.rb +0 -51
  72. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +0 -25
  73. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +0 -106
  74. data/lib/rubocop/cop/rails/http_positional_arguments.rb +0 -117
  75. data/lib/rubocop/cop/rails/http_status.rb +0 -179
  76. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +0 -94
  77. data/lib/rubocop/cop/rails/inverse_of.rb +0 -246
  78. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +0 -175
  79. data/lib/rubocop/cop/rails/link_to_blank.rb +0 -98
  80. data/lib/rubocop/cop/rails/not_null_column.rb +0 -67
  81. data/lib/rubocop/cop/rails/output.rb +0 -49
  82. data/lib/rubocop/cop/rails/output_safety.rb +0 -99
  83. data/lib/rubocop/cop/rails/pluralization_grammar.rb +0 -107
  84. data/lib/rubocop/cop/rails/presence.rb +0 -124
  85. data/lib/rubocop/cop/rails/present.rb +0 -153
  86. data/lib/rubocop/cop/rails/read_write_attribute.rb +0 -74
  87. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +0 -111
  88. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +0 -136
  89. data/lib/rubocop/cop/rails/reflection_class_name.rb +0 -37
  90. data/lib/rubocop/cop/rails/refute_methods.rb +0 -76
  91. data/lib/rubocop/cop/rails/relative_date_constant.rb +0 -93
  92. data/lib/rubocop/cop/rails/request_referer.rb +0 -56
  93. data/lib/rubocop/cop/rails/reversible_migration.rb +0 -286
  94. data/lib/rubocop/cop/rails/safe_navigation.rb +0 -87
  95. data/lib/rubocop/cop/rails/save_bang.rb +0 -316
  96. data/lib/rubocop/cop/rails/scope_args.rb +0 -29
  97. data/lib/rubocop/cop/rails/skips_model_validations.rb +0 -87
  98. data/lib/rubocop/cop/rails/time_zone.rb +0 -238
  99. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +0 -105
  100. data/lib/rubocop/cop/rails/unknown_env.rb +0 -63
  101. data/lib/rubocop/cop/rails/validation.rb +0 -109
  102. data/lib/rubocop/rspec/shared_examples.rb +0 -59
@@ -1,87 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Rails
6
- # This cop converts usages of `try!` to `&.`. It can also be configured
7
- # to convert `try`. It will convert code to use safe navigation.
8
- #
9
- # @example
10
- # # ConvertTry: false
11
- # # bad
12
- # foo.try!(:bar)
13
- # foo.try!(:bar, baz)
14
- # foo.try!(:bar) { |e| e.baz }
15
- #
16
- # foo.try!(:[], 0)
17
- #
18
- # # good
19
- # foo.try(:bar)
20
- # foo.try(:bar, baz)
21
- # foo.try(:bar) { |e| e.baz }
22
- #
23
- # foo&.bar
24
- # foo&.bar(baz)
25
- # foo&.bar { |e| e.baz }
26
- #
27
- #
28
- # # ConvertTry: true
29
- # # bad
30
- # foo.try!(:bar)
31
- # foo.try!(:bar, baz)
32
- # foo.try!(:bar) { |e| e.baz }
33
- # foo.try(:bar)
34
- # foo.try(:bar, baz)
35
- # foo.try(:bar) { |e| e.baz }
36
- #
37
- # # good
38
- # foo&.bar
39
- # foo&.bar(baz)
40
- # foo&.bar { |e| e.baz }
41
- class SafeNavigation < Cop
42
- include RangeHelp
43
-
44
- MSG = 'Use safe navigation (`&.`) instead of `%<try>s`.'
45
-
46
- def_node_matcher :try_call, <<-PATTERN
47
- (send !nil? ${:try :try!} $_ ...)
48
- PATTERN
49
-
50
- def on_send(node)
51
- try_call(node) do |try_method, dispatch|
52
- return if try_method == :try && !cop_config['ConvertTry']
53
- return unless dispatch.sym_type? && dispatch.value =~ /\w+[=!?]?/
54
-
55
- add_offense(node, message: format(MSG, try: try_method))
56
- end
57
- end
58
-
59
- def autocorrect(node)
60
- method_node, *params = *node.arguments
61
- method = method_node.source[1..-1]
62
-
63
- range = range_between(node.loc.dot.begin_pos,
64
- node.loc.expression.end_pos)
65
-
66
- lambda do |corrector|
67
- corrector.replace(range, replacement(method, params))
68
- end
69
- end
70
-
71
- private
72
-
73
- def replacement(method, params)
74
- new_params = params.map(&:source).join(', ')
75
-
76
- if method.end_with?('=')
77
- "&.#{method[0...-1]} = #{new_params}"
78
- elsif params.empty?
79
- "&.#{method}"
80
- else
81
- "&.#{method}(#{new_params})"
82
- end
83
- end
84
- end
85
- end
86
- end
87
- end
@@ -1,316 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Rails
6
- # This cop identifies possible cases where Active Record save! or related
7
- # should be used instead of save because the model might have failed to
8
- # save and an exception is better than unhandled failure.
9
- #
10
- # This will allow:
11
- # - update or save calls, assigned to a variable,
12
- # or used as a condition in an if/unless/case statement.
13
- # - create calls, assigned to a variable that then has a
14
- # call to `persisted?`.
15
- # - calls if the result is explicitly returned from methods and blocks,
16
- # or provided as arguments.
17
- # - calls whose signature doesn't look like an ActiveRecord
18
- # persistence method.
19
- #
20
- # By default it will also allow implicit returns from methods and blocks.
21
- # that behavior can be turned off with `AllowImplicitReturn: false`.
22
- #
23
- # You can permit receivers that are giving false positives with
24
- # `AllowedReceivers: []`
25
- #
26
- # @example
27
- #
28
- # # bad
29
- # user.save
30
- # user.update(name: 'Joe')
31
- # user.find_or_create_by(name: 'Joe')
32
- # user.destroy
33
- #
34
- # # good
35
- # unless user.save
36
- # # ...
37
- # end
38
- # user.save!
39
- # user.update!(name: 'Joe')
40
- # user.find_or_create_by!(name: 'Joe')
41
- # user.destroy!
42
- #
43
- # user = User.find_or_create_by(name: 'Joe')
44
- # unless user.persisted?
45
- # # ...
46
- # end
47
- #
48
- # def save_user
49
- # return user.save
50
- # end
51
- #
52
- # @example AllowImplicitReturn: true (default)
53
- #
54
- # # good
55
- # users.each { |u| u.save }
56
- #
57
- # def save_user
58
- # user.save
59
- # end
60
- #
61
- # @example AllowImplicitReturn: false
62
- #
63
- # # bad
64
- # users.each { |u| u.save }
65
- # def save_user
66
- # user.save
67
- # end
68
- #
69
- # # good
70
- # users.each { |u| u.save! }
71
- #
72
- # def save_user
73
- # user.save!
74
- # end
75
- #
76
- # def save_user
77
- # return user.save
78
- # end
79
- #
80
- # @example AllowedReceivers: ['merchant.customers', 'Service::Mailer']
81
- #
82
- # # bad
83
- # merchant.create
84
- # customers.builder.save
85
- # Mailer.create
86
- #
87
- # module Service::Mailer
88
- # self.create
89
- # end
90
- #
91
- # # good
92
- # merchant.customers.create
93
- # MerchantService.merchant.customers.destroy
94
- # Service::Mailer.update(message: 'Message')
95
- # ::Service::Mailer.update
96
- # Services::Service::Mailer.update(message: 'Message')
97
- # Service::Mailer::update
98
- #
99
- class SaveBang < Cop
100
- include NegativeConditional
101
-
102
- MSG = 'Use `%<prefer>s` instead of `%<current>s` if the return ' \
103
- 'value is not checked.'
104
- CREATE_MSG = (MSG +
105
- ' Or check `persisted?` on model returned from ' \
106
- '`%<current>s`.').freeze
107
- CREATE_CONDITIONAL_MSG = '`%<current>s` returns a model which is ' \
108
- 'always truthy.'
109
-
110
- CREATE_PERSIST_METHODS = %i[create
111
- first_or_create find_or_create_by].freeze
112
- MODIFY_PERSIST_METHODS = %i[save
113
- update update_attributes destroy].freeze
114
- PERSIST_METHODS = (CREATE_PERSIST_METHODS +
115
- MODIFY_PERSIST_METHODS).freeze
116
-
117
- def join_force?(force_class)
118
- force_class == VariableForce
119
- end
120
-
121
- def after_leaving_scope(scope, _variable_table)
122
- scope.variables.each_value do |variable|
123
- variable.assignments.each do |assignment|
124
- check_assignment(assignment)
125
- end
126
- end
127
- end
128
-
129
- def check_assignment(assignment)
130
- node = right_assignment_node(assignment)
131
-
132
- return unless node&.send_type?
133
- return unless persist_method?(node, CREATE_PERSIST_METHODS)
134
- return if persisted_referenced?(assignment)
135
-
136
- add_offense_for_node(node, CREATE_MSG)
137
- end
138
-
139
- def on_send(node) # rubocop:disable Metrics/CyclomaticComplexity
140
- return unless persist_method?(node)
141
- return if return_value_assigned?(node)
142
- return if check_used_in_conditional(node)
143
- return if argument?(node)
144
- return if implicit_return?(node)
145
- return if explicit_return?(node)
146
-
147
- add_offense_for_node(node)
148
- end
149
- alias on_csend on_send
150
-
151
- def autocorrect(node)
152
- save_loc = node.loc.selector
153
- new_method = "#{node.method_name}!"
154
-
155
- ->(corrector) { corrector.replace(save_loc, new_method) }
156
- end
157
-
158
- private
159
-
160
- def add_offense_for_node(node, msg = MSG)
161
- name = node.method_name
162
- full_message = format(msg, prefer: "#{name}!", current: name.to_s)
163
-
164
- add_offense(node, location: :selector, message: full_message)
165
- end
166
-
167
- def right_assignment_node(assignment)
168
- node = assignment.node.child_nodes.first
169
-
170
- return node unless node&.block_type?
171
-
172
- node.send_node
173
- end
174
-
175
- def persisted_referenced?(assignment)
176
- return unless assignment.referenced?
177
-
178
- assignment.variable.references.any? do |reference|
179
- call_to_persisted?(reference.node.parent)
180
- end
181
- end
182
-
183
- def call_to_persisted?(node)
184
- node.send_type? && node.method?(:persisted?)
185
- end
186
-
187
- def assignable_node(node)
188
- assignable = node.block_node || node
189
- while node
190
- node = hash_parent(node) || array_parent(node)
191
- assignable = node if node
192
- end
193
- assignable
194
- end
195
-
196
- def hash_parent(node)
197
- pair = node.parent
198
- return unless pair&.pair_type?
199
-
200
- hash = pair.parent
201
- return unless hash&.hash_type?
202
-
203
- hash
204
- end
205
-
206
- def array_parent(node)
207
- array = node.parent
208
- return unless array&.array_type?
209
-
210
- array
211
- end
212
-
213
- def check_used_in_conditional(node)
214
- return false unless conditional?(node)
215
-
216
- unless MODIFY_PERSIST_METHODS.include?(node.method_name)
217
- add_offense_for_node(node, CREATE_CONDITIONAL_MSG)
218
- end
219
-
220
- true
221
- end
222
-
223
- def conditional?(node) # rubocop:disable Metrics/CyclomaticComplexity
224
- node = node.block_node || node
225
-
226
- condition = node.parent
227
- return false unless condition
228
-
229
- condition.if_type? || condition.case_type? ||
230
- condition.or_type? || condition.and_type? ||
231
- single_negative?(condition)
232
- end
233
-
234
- def allowed_receiver?(node)
235
- return false unless node.receiver
236
- return false unless cop_config['AllowedReceivers']
237
-
238
- cop_config['AllowedReceivers'].any? do |allowed_receiver|
239
- receiver_chain_matches?(node, allowed_receiver)
240
- end
241
- end
242
-
243
- def receiver_chain_matches?(node, allowed_receiver)
244
- allowed_receiver.split('.').reverse.all? do |receiver_part|
245
- node = node.receiver
246
- return false unless node
247
-
248
- if node.variable?
249
- node.node_parts.first == receiver_part.to_sym
250
- elsif node.send_type?
251
- node.method_name == receiver_part.to_sym
252
- elsif node.const_type?
253
- const_matches?(node.const_name, receiver_part)
254
- end
255
- end
256
- end
257
-
258
- # Const == Const
259
- # ::Const == ::Const
260
- # ::Const == Const
261
- # Const == ::Const
262
- # NameSpace::Const == Const
263
- # NameSpace::Const == NameSpace::Const
264
- # NameSpace::Const != ::Const
265
- # Const != NameSpace::Const
266
- def const_matches?(const, allowed_const)
267
- parts = allowed_const.split('::').reverse.zip(
268
- const.split('::').reverse
269
- )
270
- parts.all? do |(allowed_part, const_part)|
271
- allowed_part == const_part.to_s
272
- end
273
- end
274
-
275
- def implicit_return?(node)
276
- return false unless cop_config['AllowImplicitReturn']
277
-
278
- node = assignable_node(node)
279
- method = node.parent
280
- return unless method && (method.def_type? || method.block_type?)
281
-
282
- method.children.size == node.sibling_index + 1
283
- end
284
-
285
- def argument?(node)
286
- assignable_node(node).argument?
287
- end
288
-
289
- def explicit_return?(node)
290
- ret = assignable_node(node).parent
291
- ret && (ret.return_type? || ret.next_type?)
292
- end
293
-
294
- def return_value_assigned?(node)
295
- assignment = assignable_node(node).parent
296
- assignment&.lvasgn_type?
297
- end
298
-
299
- def persist_method?(node, methods = PERSIST_METHODS)
300
- methods.include?(node.method_name) &&
301
- expected_signature?(node) &&
302
- !allowed_receiver?(node)
303
- end
304
-
305
- # Check argument signature as no arguments or one hash
306
- def expected_signature?(node)
307
- !node.arguments? ||
308
- (node.arguments.one? &&
309
- node.method_name != :destroy &&
310
- (node.first_argument.hash_type? ||
311
- !node.first_argument.literal?))
312
- end
313
- end
314
- end
315
- end
316
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Rails
6
- # This cop checks for scope calls where it was passed
7
- # a method (usually a scope) instead of a lambda/proc.
8
- #
9
- # @example
10
- #
11
- # # bad
12
- # scope :something, where(something: true)
13
- #
14
- # # good
15
- # scope :something, -> { where(something: true) }
16
- class ScopeArgs < Cop
17
- MSG = 'Use `lambda`/`proc` instead of a plain method call.'
18
-
19
- def_node_matcher :scope?, '(send nil? :scope _ $send)'
20
-
21
- def on_send(node)
22
- scope?(node) do |second_arg|
23
- add_offense(second_arg)
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,87 +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 methods which skip
7
- # validations which are listed in
8
- # https://guides.rubyonrails.org/active_record_validations.html#skipping-validations
9
- #
10
- # Methods may be ignored from this rule by configuring a `Whitelist`.
11
- #
12
- # @example
13
- # # bad
14
- # Article.first.decrement!(:view_count)
15
- # DiscussionBoard.decrement_counter(:post_count, 5)
16
- # Article.first.increment!(:view_count)
17
- # DiscussionBoard.increment_counter(:post_count, 5)
18
- # person.toggle :active
19
- # product.touch
20
- # Billing.update_all("category = 'authorized', author = 'David'")
21
- # user.update_attribute(:website, 'example.com')
22
- # user.update_columns(last_request_at: Time.current)
23
- # Post.update_counters 5, comment_count: -1, action_count: 1
24
- #
25
- # # good
26
- # user.update(website: 'example.com')
27
- # FileUtils.touch('file')
28
- #
29
- # @example Whitelist: ["touch"]
30
- # # bad
31
- # DiscussionBoard.decrement_counter(:post_count, 5)
32
- # DiscussionBoard.increment_counter(:post_count, 5)
33
- # person.toggle :active
34
- #
35
- # # good
36
- # user.touch
37
- #
38
- class SkipsModelValidations < Cop
39
- MSG = 'Avoid using `%<method>s` because it skips validations.'
40
-
41
- METHODS_WITH_ARGUMENTS = %w[decrement!
42
- decrement_counter
43
- increment!
44
- increment_counter
45
- toggle!
46
- update_all
47
- update_attribute
48
- update_column
49
- update_columns
50
- update_counters].freeze
51
-
52
- def_node_matcher :good_touch?, <<-PATTERN
53
- (send (const nil? :FileUtils) :touch ...)
54
- PATTERN
55
-
56
- def on_send(node)
57
- return if whitelist.include?(node.method_name.to_s)
58
- return unless blacklist.include?(node.method_name.to_s)
59
- return if allowed_method?(node)
60
- return if good_touch?(node)
61
-
62
- add_offense(node, location: :selector)
63
- end
64
- alias on_csend on_send
65
-
66
- private
67
-
68
- def message(node)
69
- format(MSG, method: node.method_name)
70
- end
71
-
72
- def allowed_method?(node)
73
- METHODS_WITH_ARGUMENTS.include?(node.method_name.to_s) &&
74
- !node.arguments?
75
- end
76
-
77
- def blacklist
78
- cop_config['Blacklist'] || []
79
- end
80
-
81
- def whitelist
82
- cop_config['Whitelist'] || []
83
- end
84
- end
85
- end
86
- end
87
- end