rubocop-rails 2.12.1 → 2.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +43 -8
  3. data/lib/rubocop/cop/mixin/active_record_migrations_helper.rb +34 -0
  4. data/lib/rubocop/cop/rails/active_record_aliases.rb +6 -2
  5. data/lib/rubocop/cop/rails/application_controller.rb +5 -1
  6. data/lib/rubocop/cop/rails/application_job.rb +5 -1
  7. data/lib/rubocop/cop/rails/application_mailer.rb +5 -1
  8. data/lib/rubocop/cop/rails/application_record.rb +6 -1
  9. data/lib/rubocop/cop/rails/arel_star.rb +6 -0
  10. data/lib/rubocop/cop/rails/blank.rb +5 -4
  11. data/lib/rubocop/cop/rails/compact_blank.rb +98 -0
  12. data/lib/rubocop/cop/rails/content_tag.rb +15 -8
  13. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +2 -7
  14. data/lib/rubocop/cop/rails/duration_arithmetic.rb +97 -0
  15. data/lib/rubocop/cop/rails/dynamic_find_by.rb +4 -0
  16. data/lib/rubocop/cop/rails/find_each.rb +13 -0
  17. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +1 -1
  18. data/lib/rubocop/cop/rails/http_positional_arguments.rb +1 -1
  19. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +8 -7
  20. data/lib/rubocop/cop/rails/mailer_name.rb +4 -0
  21. data/lib/rubocop/cop/rails/negate_include.rb +3 -2
  22. data/lib/rubocop/cop/rails/output.rb +4 -0
  23. data/lib/rubocop/cop/rails/pick.rb +7 -0
  24. data/lib/rubocop/cop/rails/pluck_id.rb +3 -0
  25. data/lib/rubocop/cop/rails/pluck_in_where.rb +7 -6
  26. data/lib/rubocop/cop/rails/rake_environment.rb +5 -0
  27. data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +192 -0
  28. data/lib/rubocop/cop/rails/reflection_class_name.rb +4 -2
  29. data/lib/rubocop/cop/rails/relative_date_constant.rb +4 -1
  30. data/lib/rubocop/cop/rails/reversible_migration.rb +11 -3
  31. data/lib/rubocop/cop/rails/root_join_chain.rb +72 -0
  32. data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +12 -3
  33. data/lib/rubocop/cop/rails/save_bang.rb +19 -0
  34. data/lib/rubocop/cop/rails/schema_comment.rb +104 -0
  35. data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +4 -2
  36. data/lib/rubocop/cop/rails/time_zone.rb +3 -0
  37. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +29 -35
  38. data/lib/rubocop/cop/rails/unique_validation_without_index.rb +1 -1
  39. data/lib/rubocop/cop/rails/where_equals.rb +4 -0
  40. data/lib/rubocop/cop/rails/where_exists.rb +9 -8
  41. data/lib/rubocop/cop/rails_cops.rb +6 -0
  42. data/lib/rubocop/rails/version.rb +1 -1
  43. metadata +11 -4
@@ -9,6 +9,13 @@ module RuboCop
9
9
  # `pick` avoids. When called on an Active Record relation, `pick` adds a
10
10
  # limit to the query so that only one value is fetched from the database.
11
11
  #
12
+ # @safety
13
+ # This cop is unsafe because `pluck` is defined on both `ActiveRecord::Relation` and `Enumerable`,
14
+ # whereas `pick` is only defined on `ActiveRecord::Relation` in Rails 6.0. This was addressed
15
+ # in Rails 6.1 via rails/rails#38760, at which point the cop is safe.
16
+ #
17
+ # See: https://github.com/rubocop/rubocop-rails/pull/249
18
+ #
12
19
  # @example
13
20
  # # bad
14
21
  # Model.pluck(:a).first
@@ -5,6 +5,9 @@ module RuboCop
5
5
  module Rails
6
6
  # This cop enforces the use of `ids` over `pluck(:id)` and `pluck(primary_key)`.
7
7
  #
8
+ # @safety
9
+ # This cop is unsafe if the receiver object is not an Active Record object.
10
+ #
8
11
  # @example
9
12
  # # bad
10
13
  # User.pluck(:id)
@@ -9,14 +9,15 @@ module RuboCop
9
9
  # Since `pluck` is an eager method and hits the database immediately,
10
10
  # using `select` helps to avoid additional database queries.
11
11
  #
12
- # This cop has two different enforcement modes. When the EnforcedStyle
13
- # is conservative (the default) then only calls to `pluck` on a constant
12
+ # This cop has two different enforcement modes. When the `EnforcedStyle`
13
+ # is `conservative` (the default) then only calls to `pluck` on a constant
14
14
  # (i.e. a model class) in the `where` is used as offenses.
15
15
  #
16
- # When the EnforcedStyle is aggressive then all calls to `pluck` in the
17
- # `where` is used as offenses. This may lead to false positives
18
- # as the cop cannot replace to `select` between calls to `pluck` on an
19
- # `ActiveRecord::Relation` instance vs a call to `pluck` on an `Array` instance.
16
+ # @safety
17
+ # When the `EnforcedStyle` is `aggressive` then all calls to `pluck` in the
18
+ # `where` is used as offenses. This may lead to false positives
19
+ # as the cop cannot replace to `select` between calls to `pluck` on an
20
+ # `ActiveRecord::Relation` instance vs a call to `pluck` on an `Array` instance.
20
21
  #
21
22
  # @example
22
23
  # # bad
@@ -14,6 +14,11 @@ module RuboCop
14
14
  # * The task does not need application code.
15
15
  # * The task invokes the `:environment` task.
16
16
  #
17
+ # @safety
18
+ # Probably not a problem in most cases, but it is possible that calling `:environment` task
19
+ # will break a behavior. It's also slower. E.g. some task that only needs one gem to be
20
+ # loaded to run will run significantly faster without loading the whole application.
21
+ #
17
22
  # @example
18
23
  # # bad
19
24
  # task :foo do
@@ -0,0 +1,192 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # Since Rails 5.0 the default for `belongs_to` is `optional: false`
7
+ # unless `config.active_record.belongs_to_required_by_default` is
8
+ # explicitly set to `false`. The presence validator is added
9
+ # automatically, and explicit presence validation is redundant.
10
+ #
11
+ # @example
12
+ # # bad
13
+ # belongs_to :user
14
+ # validates :user, presence: true
15
+ #
16
+ # # bad
17
+ # belongs_to :user
18
+ # validates :user_id, presence: true
19
+ #
20
+ # # bad
21
+ # belongs_to :author, foreign_key: :user_id
22
+ # validates :user_id, presence: true
23
+ #
24
+ # # good
25
+ # belongs_to :user
26
+ #
27
+ # # good
28
+ # belongs_to :author, foreign_key: :user_id
29
+ #
30
+ class RedundantPresenceValidationOnBelongsTo < Base
31
+ include RangeHelp
32
+ extend AutoCorrector
33
+ extend TargetRailsVersion
34
+
35
+ MSG = 'Remove explicit presence validation for `%<association>s`.'
36
+ RESTRICT_ON_SEND = %i[validates].freeze
37
+
38
+ minimum_target_rails_version 5.0
39
+
40
+ # @!method presence_validation?(node)
41
+ # Match a `validates` statement with a presence check
42
+ #
43
+ # @example source that matches - by association
44
+ # validates :user, presence: true
45
+ #
46
+ # @example source that matches - with presence options
47
+ # validates :user, presence: { message: 'duplicate' }
48
+ #
49
+ # @example source that matches - by a foreign key
50
+ # validates :user_id, presence: true
51
+ def_node_matcher :presence_validation?, <<~PATTERN
52
+ $(
53
+ send nil? :validates
54
+ (sym $_)
55
+ ...
56
+ $(hash <$(pair (sym :presence) {true hash}) ...>)
57
+ )
58
+ PATTERN
59
+
60
+ # @!method optional_option?(node)
61
+ # Match a `belongs_to` association with an optional option in a hash
62
+ def_node_matcher :optional?, <<~PATTERN
63
+ (send nil? :belongs_to _ ... #optional_option?)
64
+ PATTERN
65
+
66
+ # @!method optional_option?(node)
67
+ # Match an optional option in a hash
68
+ def_node_matcher :optional_option?, <<~PATTERN
69
+ {
70
+ (hash <(pair (sym :optional) true) ...>) # optional: true
71
+ (hash <(pair (sym :required) false) ...>) # required: false
72
+ }
73
+ PATTERN
74
+
75
+ # @!method any_belongs_to?(node, association:)
76
+ # Match a class with `belongs_to` with no regard to `foreign_key` option
77
+ #
78
+ # @example source that matches
79
+ # belongs_to :user
80
+ #
81
+ # @example source that matches - regardless of `foreign_key`
82
+ # belongs_to :author, foreign_key: :user_id
83
+ #
84
+ # @param node [RuboCop::AST::Node]
85
+ # @param association [Symbol]
86
+ # @return [Array<RuboCop::AST::Node>, nil] matching node
87
+ def_node_matcher :any_belongs_to?, <<~PATTERN
88
+ (begin
89
+ <
90
+ $(send nil? :belongs_to (sym %association) ...)
91
+ ...
92
+ >
93
+ )
94
+ PATTERN
95
+
96
+ # @!method belongs_to?(node, key:, fk:)
97
+ # Match a class with a matching association, either by name or an explicit
98
+ # `foreign_key` option
99
+ #
100
+ # @example source that matches - fk matches `foreign_key` option
101
+ # belongs_to :author, foreign_key: :user_id
102
+ #
103
+ # @example source that matches - key matches association name
104
+ # belongs_to :user
105
+ #
106
+ # @example source that does not match - explicit `foreign_key` does not match
107
+ # belongs_to :user, foreign_key: :account_id
108
+ #
109
+ # @param node [RuboCop::AST::Node]
110
+ # @param key [Symbol] e.g. `:user`
111
+ # @param fk [Symbol] e.g. `:user_id`
112
+ # @return [Array<RuboCop::AST::Node>] matching nodes
113
+ def_node_matcher :belongs_to?, <<~PATTERN
114
+ (begin
115
+ <
116
+ ${
117
+ #belongs_to_without_fk?(%key) # belongs_to :user
118
+ #belongs_to_with_a_matching_fk?(%fk) # belongs_to :author, foreign_key: :user_id
119
+ }
120
+ ...
121
+ >
122
+ )
123
+ PATTERN
124
+
125
+ # @!method belongs_to_without_fk?(node, fk)
126
+ # Match a matching `belongs_to` association, without an explicit `foreign_key` option
127
+ #
128
+ # @param node [RuboCop::AST::Node]
129
+ # @param key [Symbol] e.g. `:user`
130
+ # @return [Array<RuboCop::AST::Node>] matching nodes
131
+ def_node_matcher :belongs_to_without_fk?, <<~PATTERN
132
+ {
133
+ (send nil? :belongs_to (sym %1)) # belongs_to :user
134
+ (send nil? :belongs_to (sym %1) !hash) # belongs_to :user, -> { not_deleted }
135
+ (send nil? :belongs_to (sym %1) !(hash <(pair (sym :foreign_key) _) ...>))
136
+ }
137
+ PATTERN
138
+
139
+ # @!method belongs_to_with_a_matching_fk?(node, fk)
140
+ # Match a matching `belongs_to` association with a matching explicit `foreign_key` option
141
+ #
142
+ # @example source that matches
143
+ # belongs_to :author, foreign_key: :user_id
144
+ #
145
+ # @param node [RuboCop::AST::Node]
146
+ # @param fk [Symbol] e.g. `:user_id`
147
+ # @return [Array<RuboCop::AST::Node>] matching nodes
148
+ def_node_matcher :belongs_to_with_a_matching_fk?, <<~PATTERN
149
+ (send nil? :belongs_to ... (hash <(pair (sym :foreign_key) (sym %1)) ...>))
150
+ PATTERN
151
+
152
+ def on_send(node)
153
+ validation, key, options, presence = presence_validation?(node)
154
+ return unless validation
155
+
156
+ belongs_to = belongs_to_for(node.parent, key)
157
+ return unless belongs_to
158
+ return if optional?(belongs_to)
159
+
160
+ message = format(MSG, association: key.to_s)
161
+
162
+ add_offense(presence, message: message) do |corrector|
163
+ remove_presence_validation(corrector, node, options, presence)
164
+ end
165
+ end
166
+
167
+ private
168
+
169
+ def belongs_to_for(model_class_node, key)
170
+ if key.to_s.end_with?('_id')
171
+ normalized_key = key.to_s.delete_suffix('_id').to_sym
172
+ belongs_to?(model_class_node, key: normalized_key, fk: key)
173
+ else
174
+ any_belongs_to?(model_class_node, association: key)
175
+ end
176
+ end
177
+
178
+ def remove_presence_validation(corrector, node, options, presence)
179
+ if options.children.one?
180
+ corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
181
+ else
182
+ range = range_with_surrounding_comma(
183
+ range_with_surrounding_space(range: presence.source_range, side: :left),
184
+ :left
185
+ )
186
+ corrector.remove(range)
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end
@@ -5,8 +5,10 @@ module RuboCop
5
5
  module Rails
6
6
  # This cop checks if the value of the option `class_name`, in
7
7
  # the definition of a reflection is a string.
8
- # It is marked as unsafe because it cannot be determined whether
9
- # constant or method return value specified to `class_name` is a string.
8
+ #
9
+ # @safety
10
+ # This cop is unsafe because it cannot be determined whether
11
+ # constant or method return value specified to `class_name` is a string.
10
12
  #
11
13
  # @example
12
14
  # # bad
@@ -6,6 +6,9 @@ module RuboCop
6
6
  # This cop checks whether constant value isn't relative date.
7
7
  # Because the relative date will be evaluated only once.
8
8
  #
9
+ # @safety
10
+ # This cop's autocorrection is unsafe because its dependence on the constant is not corrected.
11
+ #
9
12
  # @example
10
13
  # # bad
11
14
  # class SomeClass
@@ -90,7 +93,7 @@ module RuboCop
90
93
  end
91
94
 
92
95
  def nested_relative_date(node, &callback)
93
- return if node.block_type?
96
+ return if node.nil? || node.block_type?
94
97
 
95
98
  node.each_child_node do |child|
96
99
  nested_relative_date(child, &callback)
@@ -179,7 +179,7 @@ module RuboCop
179
179
  MSG = '%<action>s is not reversible.'
180
180
 
181
181
  def_node_matcher :irreversible_schema_statement_call, <<~PATTERN
182
- (send nil? ${:execute :remove_belongs_to} ...)
182
+ (send nil? ${:change_column :execute :remove_belongs_to :remove_reference} ...)
183
183
  PATTERN
184
184
 
185
185
  def_node_matcher :drop_table_call, <<~PATTERN
@@ -317,16 +317,24 @@ module RuboCop
317
317
  return if receiver != node.receiver &&
318
318
  reversible_change_table_call?(node)
319
319
 
320
+ action = if method_name == :remove
321
+ target_rails_version >= 6.1 ? 't.remove (without type)' : 't.remove'
322
+ else
323
+ "change_table(with #{method_name})"
324
+ end
325
+
320
326
  add_offense(
321
327
  node,
322
- message: format(MSG, action: "change_table(with #{method_name})")
328
+ message: format(MSG, action: action)
323
329
  )
324
330
  end
325
331
 
326
332
  def reversible_change_table_call?(node)
327
333
  case node.method_name
328
- when :change, :remove
334
+ when :change
329
335
  false
336
+ when :remove
337
+ target_rails_version >= 6.1 && all_hash_key?(node.arguments.last, :type)
330
338
  when :change_default, :change_column_default, :change_table_comment,
331
339
  :change_column_comment
332
340
  all_hash_key?(node.arguments.last, :from, :to)
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # Use a single `#join` instead of chaining on `Rails.root` or `Rails.public_path`.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # Rails.root.join('db').join('schema.rb')
11
+ # Rails.root.join('db').join(migrate).join('migration.rb')
12
+ # Rails.public_path.join('path').join('file.pdf')
13
+ # Rails.public_path.join('path').join(to).join('file.pdf')
14
+ #
15
+ # # good
16
+ # Rails.root.join('db', 'schema.rb')
17
+ # Rails.root.join('db', migrate, 'migration.rb')
18
+ # Rails.public_path.join('path', 'file.pdf')
19
+ # Rails.public_path.join('path', to, 'file.pdf')
20
+ #
21
+ class RootJoinChain < Base
22
+ extend AutoCorrector
23
+ include RangeHelp
24
+
25
+ MSG = 'Use `%<root>s.join(...)` instead of chaining `#join` calls.'
26
+
27
+ RESTRICT_ON_SEND = %i[join].to_set.freeze
28
+
29
+ # @!method rails_root?(node)
30
+ def_node_matcher :rails_root?, <<~PATTERN
31
+ (send (const {nil? cbase} :Rails) {:root :public_path})
32
+ PATTERN
33
+
34
+ # @!method join?(node)
35
+ def_node_matcher :join?, <<~PATTERN
36
+ (send _ :join $...)
37
+ PATTERN
38
+
39
+ def on_send(node)
40
+ evidence(node) do |rails_node, args|
41
+ add_offense(node, message: format(MSG, root: rails_node.source)) do |corrector|
42
+ range = range_between(rails_node.loc.selector.end_pos, node.loc.expression.end_pos)
43
+ replacement = ".join(#{args.map(&:source).join(', ')})"
44
+
45
+ corrector.replace(range, replacement)
46
+ end
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def evidence(node)
53
+ # Are we at the *end* of the join chain?
54
+ return if join?(node.parent)
55
+ # Is there only one join?
56
+ return if rails_root?(node.receiver)
57
+
58
+ all_args = []
59
+
60
+ while (args = join?(node))
61
+ all_args = args + all_args
62
+ node = node.receiver
63
+ end
64
+
65
+ rails_root?(node) do
66
+ yield(node, all_args)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -6,9 +6,18 @@ module RuboCop
6
6
  # This cop checks to make sure safe navigation isn't used with `blank?` in
7
7
  # a conditional.
8
8
  #
9
- # While the safe navigation operator is generally a good idea, when
10
- # checking `foo&.blank?` in a conditional, `foo` being `nil` will actually
11
- # do the opposite of what the author intends.
9
+ # @safety
10
+ # While the safe navigation operator is generally a good idea, when
11
+ # checking `foo&.blank?` in a conditional, `foo` being `nil` will actually
12
+ # do the opposite of what the author intends.
13
+ #
14
+ # For example:
15
+ #
16
+ # [source,ruby]
17
+ # ----
18
+ # foo&.blank? #=> nil
19
+ # foo.blank? #=> true
20
+ # ----
12
21
  #
13
22
  # @example
14
23
  # # bad
@@ -25,6 +25,25 @@ module RuboCop
25
25
  # You can permit receivers that are giving false positives with
26
26
  # `AllowedReceivers: []`
27
27
  #
28
+ # @safety
29
+ # This cop's autocorrection is unsafe because a custom `update` method call would be changed to `update!`,
30
+ # but the method name in the definition would be unchanged.
31
+ #
32
+ # [source,ruby]
33
+ # ----
34
+ # # Original code
35
+ # def update_attributes
36
+ # end
37
+ #
38
+ # update_attributes
39
+ #
40
+ # # After running rubocop --safe-auto-correct
41
+ # def update_attributes
42
+ # end
43
+ #
44
+ # update
45
+ # ----
46
+ #
28
47
  # @example
29
48
  #
30
49
  # # bad
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop enforces the use of the `comment` option when adding a new table or column
7
+ # to the database during a migration.
8
+ #
9
+ # @example
10
+ # # bad (no comment for a new column or table)
11
+ # add_column :table, :column, :integer
12
+ #
13
+ # create_table :table do |t|
14
+ # t.type :column
15
+ # end
16
+ #
17
+ # # good
18
+ # add_column :table, :column, :integer, comment: 'Number of offenses'
19
+ #
20
+ # create_table :table, comment: 'Table of offenses data' do |t|
21
+ # t.type :column, comment: 'Number of offenses'
22
+ # end
23
+ #
24
+ class SchemaComment < Base
25
+ include ActiveRecordMigrationsHelper
26
+
27
+ COLUMN_MSG = 'New database column without `comment`.'
28
+ TABLE_MSG = 'New database table without `comment`.'
29
+ RESTRICT_ON_SEND = %i[add_column create_table].freeze
30
+ CREATE_TABLE_COLUMN_METHODS = Set[
31
+ *(
32
+ RAILS_ABSTRACT_SCHEMA_DEFINITIONS |
33
+ RAILS_ABSTRACT_SCHEMA_DEFINITIONS_HELPERS |
34
+ POSTGRES_SCHEMA_DEFINITIONS |
35
+ MYSQL_SCHEMA_DEFINITIONS
36
+ )
37
+ ].freeze
38
+
39
+ # @!method comment_present?(node)
40
+ def_node_matcher :comment_present?, <<~PATTERN
41
+ (hash <(pair {(sym :comment) (str "comment")} (_ [present?])) ...>)
42
+ PATTERN
43
+
44
+ # @!method add_column?(node)
45
+ def_node_matcher :add_column?, <<~PATTERN
46
+ (send nil? :add_column _table _column _type _?)
47
+ PATTERN
48
+
49
+ # @!method add_column_with_comment?(node)
50
+ def_node_matcher :add_column_with_comment?, <<~PATTERN
51
+ (send nil? :add_column _table _column _type #comment_present?)
52
+ PATTERN
53
+
54
+ # @!method create_table?(node)
55
+ def_node_matcher :create_table?, <<~PATTERN
56
+ (send nil? :create_table _table _?)
57
+ PATTERN
58
+
59
+ # @!method create_table?(node)
60
+ def_node_matcher :create_table_with_comment?, <<~PATTERN
61
+ (send nil? :create_table _table #comment_present? ...)
62
+ PATTERN
63
+
64
+ # @!method t_column?(node)
65
+ def_node_matcher :t_column?, <<~PATTERN
66
+ (send _var CREATE_TABLE_COLUMN_METHODS ...)
67
+ PATTERN
68
+
69
+ # @!method t_column_with_comment?(node)
70
+ def_node_matcher :t_column_with_comment?, <<~PATTERN
71
+ (send _var CREATE_TABLE_COLUMN_METHODS _column _type? #comment_present?)
72
+ PATTERN
73
+
74
+ def on_send(node)
75
+ if add_column_without_comment?(node)
76
+ add_offense(node, message: COLUMN_MSG)
77
+ elsif create_table?(node)
78
+ if create_table_without_comment?(node)
79
+ add_offense(node, message: TABLE_MSG)
80
+ elsif create_table_column_call_without_comment?(node)
81
+ add_offense(node.parent.body, message: COLUMN_MSG)
82
+ end
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def add_column_without_comment?(node)
89
+ add_column?(node) && !add_column_with_comment?(node)
90
+ end
91
+
92
+ def create_table_without_comment?(node)
93
+ create_table?(node) && !create_table_with_comment?(node)
94
+ end
95
+
96
+ def create_table_column_call_without_comment?(node)
97
+ create_table_with_block?(node.parent) &&
98
+ t_column?(node.parent.body) &&
99
+ !t_column_with_comment?(node.parent.body)
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -5,8 +5,10 @@ module RuboCop
5
5
  module Rails
6
6
  #
7
7
  # Checks SQL heredocs to use `.squish`.
8
- # Some SQL syntax (e.g. PostgreSQL comments and functions) requires newlines
9
- # to be preserved in order to work, thus auto-correction for this cop is not safe.
8
+ #
9
+ # @safety
10
+ # Some SQL syntax (e.g. PostgreSQL comments and functions) requires newlines
11
+ # to be preserved in order to work, thus auto-correction for this cop is not safe.
10
12
  #
11
13
  # @example
12
14
  # # bad
@@ -14,6 +14,9 @@ module RuboCop
14
14
  # When EnforcedStyle is 'flexible' then it's also allowed
15
15
  # to use `Time#in_time_zone`.
16
16
  #
17
+ # @safety
18
+ # This cop's autocorrection is unsafe because it may change handling time.
19
+ #
17
20
  # @example
18
21
  # # bad
19
22
  # Time.now