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,94 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Rails
6
- # This cop checks that `if` and `only` (or `except`) are not used together
7
- # as options of `skip_*` action filter.
8
- #
9
- # The `if` option will be ignored when `if` and `only` are used together.
10
- # Similarly, the `except` option will be ignored when `if` and `except`
11
- # are used together.
12
- #
13
- # @example
14
- # # bad
15
- # class MyPageController < ApplicationController
16
- # skip_before_action :login_required,
17
- # only: :show, if: :trusted_origin?
18
- # end
19
- #
20
- # # good
21
- # class MyPageController < ApplicationController
22
- # skip_before_action :login_required,
23
- # if: -> { trusted_origin? && action_name == "show" }
24
- # end
25
- #
26
- # @example
27
- # # bad
28
- # class MyPageController < ApplicationController
29
- # skip_before_action :login_required,
30
- # except: :admin, if: :trusted_origin?
31
- # end
32
- #
33
- # # good
34
- # class MyPageController < ApplicationController
35
- # skip_before_action :login_required,
36
- # if: -> { trusted_origin? && action_name != "admin" }
37
- # end
38
- #
39
- # @see https://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html#method-i-_normalize_callback_options
40
- class IgnoredSkipActionFilterOption < Cop
41
- MSG = <<~MSG.chomp.freeze
42
- `%<ignore>s` option will be ignored when `%<prefer>s` and `%<ignore>s` are used together.
43
- MSG
44
-
45
- FILTERS = %w[
46
- :skip_after_action
47
- :skip_around_action
48
- :skip_before_action
49
- :skip_action_callback
50
- ].freeze
51
-
52
- def_node_matcher :filter_options, <<-PATTERN
53
- (send
54
- nil?
55
- {#{FILTERS.join(' ')}}
56
- _
57
- $_)
58
- PATTERN
59
-
60
- def on_send(node)
61
- options = filter_options(node)
62
- return unless options
63
- return unless options.hash_type?
64
-
65
- options = options_hash(options)
66
-
67
- if if_and_only?(options)
68
- add_offense(options[:if],
69
- message: format(MSG, prefer: :only, ignore: :if))
70
- elsif if_and_except?(options)
71
- add_offense(options[:except],
72
- message: format(MSG, prefer: :if, ignore: :except))
73
- end
74
- end
75
-
76
- private
77
-
78
- def options_hash(options)
79
- options.pairs
80
- .select { |pair| pair.key.sym_type? }
81
- .map { |pair| [pair.key.value, pair] }.to_h
82
- end
83
-
84
- def if_and_only?(options)
85
- options.key?(:if) && options.key?(:only)
86
- end
87
-
88
- def if_and_except?(options)
89
- options.key?(:if) && options.key?(:except)
90
- end
91
- end
92
- end
93
- end
94
- end
@@ -1,246 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Rails
6
- # This cop looks for has_(one|many) and belongs_to associations where
7
- # Active Record can't automatically determine the inverse association
8
- # because of a scope or the options used. Using the blog with order scope
9
- # example below, traversing the a Blog's association in both directions
10
- # with `blog.posts.first.blog` would cause the `blog` to be loaded from
11
- # the database twice.
12
- #
13
- # `:inverse_of` must be manually specified for Active Record to use the
14
- # associated object in memory, or set to `false` to opt-out. Note that
15
- # setting `nil` does not stop Active Record from trying to determine the
16
- # inverse automatically, and is not considered a valid value for this.
17
- #
18
- # @example
19
- # # good
20
- # class Blog < ApplicationRecord
21
- # has_many :posts
22
- # end
23
- #
24
- # class Post < ApplicationRecord
25
- # belongs_to :blog
26
- # end
27
- #
28
- # @example
29
- # # bad
30
- # class Blog < ApplicationRecord
31
- # has_many :posts, -> { order(published_at: :desc) }
32
- # end
33
- #
34
- # class Post < ApplicationRecord
35
- # belongs_to :blog
36
- # end
37
- #
38
- # # good
39
- # class Blog < ApplicationRecord
40
- # has_many(:posts,
41
- # -> { order(published_at: :desc) },
42
- # inverse_of: :blog)
43
- # end
44
- #
45
- # class Post < ApplicationRecord
46
- # belongs_to :blog
47
- # end
48
- #
49
- # # good
50
- # class Blog < ApplicationRecord
51
- # with_options inverse_of: :blog do
52
- # has_many :posts, -> { order(published_at: :desc) }
53
- # end
54
- # end
55
- #
56
- # class Post < ApplicationRecord
57
- # belongs_to :blog
58
- # end
59
- #
60
- # # good
61
- # # When you don't want to use the inverse association.
62
- # class Blog < ApplicationRecord
63
- # has_many(:posts,
64
- # -> { order(published_at: :desc) },
65
- # inverse_of: false)
66
- # end
67
- #
68
- # @example
69
- # # bad
70
- # class Picture < ApplicationRecord
71
- # belongs_to :imageable, polymorphic: true
72
- # end
73
- #
74
- # class Employee < ApplicationRecord
75
- # has_many :pictures, as: :imageable
76
- # end
77
- #
78
- # class Product < ApplicationRecord
79
- # has_many :pictures, as: :imageable
80
- # end
81
- #
82
- # # good
83
- # class Picture < ApplicationRecord
84
- # belongs_to :imageable, polymorphic: true
85
- # end
86
- #
87
- # class Employee < ApplicationRecord
88
- # has_many :pictures, as: :imageable, inverse_of: :imageable
89
- # end
90
- #
91
- # class Product < ApplicationRecord
92
- # has_many :pictures, as: :imageable, inverse_of: :imageable
93
- # end
94
- #
95
- # @example
96
- # # bad
97
- # # However, RuboCop can not detect this pattern...
98
- # class Physician < ApplicationRecord
99
- # has_many :appointments
100
- # has_many :patients, through: :appointments
101
- # end
102
- #
103
- # class Appointment < ApplicationRecord
104
- # belongs_to :physician
105
- # belongs_to :patient
106
- # end
107
- #
108
- # class Patient < ApplicationRecord
109
- # has_many :appointments
110
- # has_many :physicians, through: :appointments
111
- # end
112
- #
113
- # # good
114
- # class Physician < ApplicationRecord
115
- # has_many :appointments
116
- # has_many :patients, through: :appointments
117
- # end
118
- #
119
- # class Appointment < ApplicationRecord
120
- # belongs_to :physician, inverse_of: :appointments
121
- # belongs_to :patient, inverse_of: :appointments
122
- # end
123
- #
124
- # class Patient < ApplicationRecord
125
- # has_many :appointments
126
- # has_many :physicians, through: :appointments
127
- # end
128
- #
129
- # @see https://guides.rubyonrails.org/association_basics.html#bi-directional-associations
130
- # @see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses
131
- class InverseOf < Cop
132
- extend TargetRailsVersion
133
-
134
- minimum_target_rails_version 4.1
135
-
136
- SPECIFY_MSG = 'Specify an `:inverse_of` option.'
137
- NIL_MSG = 'You specified `inverse_of: nil`, you probably meant to ' \
138
- 'use `inverse_of: false`.'
139
-
140
- def_node_matcher :association_recv_arguments, <<-PATTERN
141
- (send $_ {:has_many :has_one :belongs_to} _ $...)
142
- PATTERN
143
-
144
- def_node_matcher :options_from_argument, <<-PATTERN
145
- (hash $...)
146
- PATTERN
147
-
148
- def_node_matcher :conditions_option?, <<-PATTERN
149
- (pair (sym :conditions) !nil)
150
- PATTERN
151
-
152
- def_node_matcher :through_option?, <<-PATTERN
153
- (pair (sym :through) !nil)
154
- PATTERN
155
-
156
- def_node_matcher :polymorphic_option?, <<-PATTERN
157
- (pair (sym :polymorphic) !nil)
158
- PATTERN
159
-
160
- def_node_matcher :as_option?, <<-PATTERN
161
- (pair (sym :as) !nil)
162
- PATTERN
163
-
164
- def_node_matcher :foreign_key_option?, <<-PATTERN
165
- (pair (sym :foreign_key) !nil)
166
- PATTERN
167
-
168
- def_node_matcher :inverse_of_option?, <<-PATTERN
169
- (pair (sym :inverse_of) !nil)
170
- PATTERN
171
-
172
- def_node_matcher :inverse_of_nil_option?, <<-PATTERN
173
- (pair (sym :inverse_of) nil)
174
- PATTERN
175
-
176
- def on_send(node)
177
- recv, arguments = association_recv_arguments(node)
178
- return unless arguments
179
-
180
- with_options = with_options_arguments(recv, node)
181
-
182
- options = arguments.concat(with_options).flat_map do |arg|
183
- options_from_argument(arg)
184
- end
185
- return if options_ignoring_inverse_of?(options)
186
-
187
- return unless scope?(arguments) ||
188
- options_requiring_inverse_of?(options)
189
-
190
- return if options_contain_inverse_of?(options)
191
-
192
- add_offense(node, message: message(options), location: :selector)
193
- end
194
-
195
- def scope?(arguments)
196
- arguments.any?(&:block_type?)
197
- end
198
-
199
- def options_requiring_inverse_of?(options)
200
- required = options.any? do |opt|
201
- conditions_option?(opt) ||
202
- foreign_key_option?(opt)
203
- end
204
-
205
- return required if target_rails_version >= 5.2
206
-
207
- required || options.any? { |opt| as_option?(opt) }
208
- end
209
-
210
- def options_ignoring_inverse_of?(options)
211
- options.any? do |opt|
212
- through_option?(opt) || polymorphic_option?(opt)
213
- end
214
- end
215
-
216
- def options_contain_inverse_of?(options)
217
- options.any? { |opt| inverse_of_option?(opt) }
218
- end
219
-
220
- def with_options_arguments(recv, node)
221
- blocks = node.each_ancestor(:block).select do |block|
222
- block.send_node.command?(:with_options) &&
223
- same_context_in_with_options?(block.arguments.first, recv)
224
- end
225
- blocks.flat_map { |n| n.send_node.arguments }
226
- end
227
-
228
- def same_context_in_with_options?(arg, recv)
229
- return true if arg.nil? && recv.nil?
230
-
231
- arg && recv && arg.children[0] == recv.children[0]
232
- end
233
-
234
- private
235
-
236
- def message(options)
237
- if options.any? { |opt| inverse_of_nil_option?(opt) }
238
- NIL_MSG
239
- else
240
- SPECIFY_MSG
241
- end
242
- end
243
- end
244
- end
245
- end
246
- end
@@ -1,175 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Rails
6
- # This cop checks that methods specified in the filter's `only` or
7
- # `except` options are defined within the same class or module.
8
- #
9
- # You can technically specify methods of superclass or methods added by
10
- # mixins on the filter, but these can confuse developers. If you specify
11
- # methods that are defined in other classes or modules, you should
12
- # define the filter in that class or module.
13
- #
14
- # If you rely on behaviour defined in the superclass actions, you must
15
- # remember to invoke `super` in the subclass actions.
16
- #
17
- # @example
18
- # # bad
19
- # class LoginController < ApplicationController
20
- # before_action :require_login, only: %i[index settings logout]
21
- #
22
- # def index
23
- # end
24
- # end
25
- #
26
- # # good
27
- # class LoginController < ApplicationController
28
- # before_action :require_login, only: %i[index settings logout]
29
- #
30
- # def index
31
- # end
32
- #
33
- # def settings
34
- # end
35
- #
36
- # def logout
37
- # end
38
- # end
39
- #
40
- # @example
41
- # # bad
42
- # module FooMixin
43
- # extend ActiveSupport::Concern
44
- #
45
- # included do
46
- # before_action proc { authenticate }, only: :foo
47
- # end
48
- # end
49
- #
50
- # # good
51
- # module FooMixin
52
- # extend ActiveSupport::Concern
53
- #
54
- # included do
55
- # before_action proc { authenticate }, only: :foo
56
- # end
57
- #
58
- # def foo
59
- # # something
60
- # end
61
- # end
62
- #
63
- # @example
64
- # class ContentController < ApplicationController
65
- # def update
66
- # @content.update(content_attributes)
67
- # end
68
- # end
69
- #
70
- # class ArticlesController < ContentController
71
- # before_action :load_article, only: [:update]
72
- #
73
- # # the cop requires this method, but it relies on behaviour defined
74
- # # in the superclass, so needs to invoke `super`
75
- # def update
76
- # super
77
- # end
78
- #
79
- # private
80
- #
81
- # def load_article
82
- # @content = Article.find(params[:article_id])
83
- # end
84
- # end
85
- class LexicallyScopedActionFilter < Cop
86
- MSG = '%<action>s not explicitly defined on the %<type>s.'
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
102
- ].freeze
103
-
104
- def_node_matcher :only_or_except_filter_methods, <<-PATTERN
105
- (send
106
- nil?
107
- {#{FILTERS.join(' ')}}
108
- _
109
- (hash
110
- (pair
111
- (sym {:only :except})
112
- $_)))
113
- PATTERN
114
-
115
- def on_send(node)
116
- methods_node = only_or_except_filter_methods(node)
117
- return unless methods_node
118
-
119
- parent = node.each_ancestor(:class, :module).first
120
- return unless parent
121
-
122
- block = parent.each_child_node(:begin).first
123
- return unless block
124
-
125
- defined_methods = block.each_child_node(:def).map(&:method_name)
126
- methods = array_values(methods_node).reject do |method|
127
- defined_methods.include?(method)
128
- end
129
-
130
- message = message(methods, parent)
131
- add_offense(node, message: message) unless methods.empty?
132
- end
133
-
134
- private
135
-
136
- # @param node [RuboCop::AST::Node]
137
- # @return [Array<Symbol>]
138
- def array_values(node) # rubocop:disable Metrics/MethodLength
139
- case node.type
140
- when :str
141
- [node.str_content.to_sym]
142
- when :sym
143
- [node.value]
144
- when :array
145
- node.values.map do |v|
146
- case v.type
147
- when :str
148
- v.str_content.to_sym
149
- when :sym
150
- v.value
151
- end
152
- end.compact
153
- else
154
- []
155
- end
156
- end
157
-
158
- # @param methods [Array<String>]
159
- # @param parent [RuboCop::AST::Node]
160
- # @return [String]
161
- def message(methods, parent)
162
- if methods.size == 1
163
- format(MSG,
164
- action: "`#{methods[0]}` is",
165
- type: parent.type)
166
- else
167
- format(MSG,
168
- action: "`#{methods.join('`, `')}` are",
169
- type: parent.type)
170
- end
171
- end
172
- end
173
- end
174
- end
175
- end