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,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