rubocop-rails 2.26.0 → 2.29.1
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.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +51 -1
- data/config/default.yml +30 -6
- data/lib/rubocop/cop/mixin/index_method.rb +12 -5
- data/lib/rubocop/cop/mixin/routes_helper.rb +20 -0
- data/lib/rubocop/cop/mixin/target_rails_version.rb +3 -5
- data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +5 -5
- data/lib/rubocop/cop/rails/action_order.rb +1 -5
- data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +1 -5
- data/lib/rubocop/cop/rails/add_column_index.rb +1 -0
- data/lib/rubocop/cop/rails/application_record.rb +4 -0
- data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -0
- data/lib/rubocop/cop/rails/compact_blank.rb +8 -4
- data/lib/rubocop/cop/rails/dangerous_column_names.rb +2 -0
- data/lib/rubocop/cop/rails/duplicate_association.rb +8 -4
- data/lib/rubocop/cop/rails/enum_syntax.rb +18 -14
- data/lib/rubocop/cop/rails/env_local.rb +26 -3
- data/lib/rubocop/cop/rails/file_path.rb +26 -3
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +7 -0
- data/lib/rubocop/cop/rails/index_by.rb +28 -12
- data/lib/rubocop/cop/rails/index_with.rb +28 -12
- data/lib/rubocop/cop/rails/match_route.rb +1 -9
- data/lib/rubocop/cop/rails/multiple_route_paths.rb +50 -0
- data/lib/rubocop/cop/rails/not_null_column.rb +6 -2
- data/lib/rubocop/cop/rails/pluck.rb +20 -0
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +1 -1
- data/lib/rubocop/cop/rails/present.rb +0 -2
- data/lib/rubocop/cop/rails/redundant_active_record_all_method.rb +1 -30
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +1 -1
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +1 -1
- data/lib/rubocop/cop/rails/reflection_class_name.rb +1 -1
- data/lib/rubocop/cop/rails/request_referer.rb +1 -1
- data/lib/rubocop/cop/rails/reversible_migration.rb +3 -1
- data/lib/rubocop/cop/rails/root_pathname_methods.rb +17 -8
- data/lib/rubocop/cop/rails/save_bang.rb +4 -3
- data/lib/rubocop/cop/rails/schema_comment.rb +1 -0
- data/lib/rubocop/cop/rails/select_map.rb +3 -2
- data/lib/rubocop/cop/rails/skips_model_validations.rb +4 -2
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +1 -1
- data/lib/rubocop/cop/rails/strong_parameters_expect.rb +104 -0
- data/lib/rubocop/cop/rails/three_state_boolean_column.rb +2 -1
- data/lib/rubocop/cop/rails/time_zone.rb +13 -6
- data/lib/rubocop/cop/rails/transaction_exit_statement.rb +5 -0
- data/lib/rubocop/cop/rails/where_equals.rb +6 -1
- data/lib/rubocop/cop/rails/where_not.rb +6 -1
- data/lib/rubocop/cop/rails/where_range.rb +7 -2
- data/lib/rubocop/cop/rails_cops.rb +3 -0
- data/lib/rubocop/rails/migration_file_skippable.rb +54 -0
- data/lib/rubocop/rails/version.rb +1 -1
- data/lib/rubocop/rails.rb +0 -1
- data/lib/rubocop-rails.rb +3 -0
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6fa236fdf79709d4d0baec3c3ed01bc254e807dbd5ec39229374187b1d3d30c
|
4
|
+
data.tar.gz: 99b29d27dd97c1adc12efb3d60a55370f6c4ad363bd6de51ca11ac33f3b1cd8a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 422221a038428edaf91477ef0ede6939023a686f3a62c14242efbfa1cb31be9d8f504eaf15ac103875696b5584b690cabcc86a4041b5c42cfd4480aa4ad27dbd
|
7
|
+
data.tar.gz: 8240dcae47150b3137a980e731d69133df5e54364b62014d296b51715b1e3f47077b828d4f256191c79d8a14121e0d5cce9b06857f54b632e398216290e31f29
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -63,9 +63,45 @@ RuboCop::RakeTask.new do |task|
|
|
63
63
|
end
|
64
64
|
```
|
65
65
|
|
66
|
+
## RuboCop Rails configuration
|
67
|
+
|
68
|
+
The following settings specific to RuboCop Rails can be configured in `.rubocop.yml`.
|
69
|
+
|
70
|
+
### `AllCops: TargetRailsVersion`
|
71
|
+
|
72
|
+
What version of Rails is the inspected code using? If a value is specified
|
73
|
+
for `TargetRailsVersion` then it is used. Acceptable values are specified
|
74
|
+
as a float (e.g., 7.2); the patch version of Rails should not be included.
|
75
|
+
|
76
|
+
```yaml
|
77
|
+
AllCops:
|
78
|
+
TargetRailsVersion: 7.2
|
79
|
+
```
|
80
|
+
|
81
|
+
If `TargetRailsVersion` is not set, RuboCop will parse the Gemfile.lock or
|
82
|
+
gems.locked file to find the version of Rails that has been bound to the
|
83
|
+
application. If neither of those files exist, RuboCop will use Rails 5.0
|
84
|
+
as the default.
|
85
|
+
|
86
|
+
### `AllCops: MigratedSchemaVersion`
|
87
|
+
|
88
|
+
By specifying the `MigratedSchemaVersion` option, migration files that have already been run can be ignored.
|
89
|
+
When `MigratedSchemaVersion: '20241225000000'` is set, migration files lower than or equal to '20241225000000' will be ignored.
|
90
|
+
For example, to ignore db/migrate/20241225000000_create_articles.rb and earlier migrations you would configure it the following way:
|
91
|
+
|
92
|
+
```yaml
|
93
|
+
AllCops:
|
94
|
+
MigratedSchemaVersion: '20241225000000'
|
95
|
+
```
|
96
|
+
|
97
|
+
This prevents inspecting schema settings for already applied migration files.
|
98
|
+
Changing already applied migrations should be avoided because it can lead to the schema getting out of sync
|
99
|
+
between your local copy and what it actually is in production, depending on when `bin/rails db:migrate` was executed.
|
100
|
+
If you want to modify your schema to comply with the cops, you should instead create new migrations.
|
101
|
+
|
66
102
|
## Rails configuration tip
|
67
103
|
|
68
|
-
|
104
|
+
In Rails 6.1+, add the following `config.generators.after_generate` setting to
|
69
105
|
your `config/environments/development.rb` to apply RuboCop autocorrection to code generated by `bin/rails g`.
|
70
106
|
|
71
107
|
```ruby
|
@@ -84,6 +120,20 @@ It uses `rubocop -A` to apply `Style/FrozenStringLiteralComment` and other unsaf
|
|
84
120
|
`rubocop -A` is unsafe autocorrection, but code generated by default is simple and less likely to
|
85
121
|
be incompatible with `rubocop -A`. If you have problems you can replace it with `rubocop -a` instead.
|
86
122
|
|
123
|
+
In Rails 7.2+, it is recommended to use `config.generators.apply_rubocop_autocorrect_after_generate!` instead of the above setting:
|
124
|
+
|
125
|
+
```diff
|
126
|
+
# config/environments/development.rb
|
127
|
+
Rails.application.configure do
|
128
|
+
(snip)
|
129
|
+
# Apply autocorrection by RuboCop to files generated by `bin/rails generate`.
|
130
|
+
- # config.generators.apply_rubocop_autocorrect_after_generate!
|
131
|
+
+ config.generators.apply_rubocop_autocorrect_after_generate!
|
132
|
+
end
|
133
|
+
```
|
134
|
+
|
135
|
+
You only need to uncomment.
|
136
|
+
|
87
137
|
## The Cops
|
88
138
|
|
89
139
|
All cops are located under
|
data/config/default.yml
CHANGED
@@ -17,14 +17,18 @@ AllCops:
|
|
17
17
|
# Enable checking Active Support extensions.
|
18
18
|
# See: https://docs.rubocop.org/rubocop/configuration.html#enable-checking-active-support-extensions
|
19
19
|
ActiveSupportExtensionsEnabled: true
|
20
|
-
# What version of Rails is the inspected code using?
|
21
|
-
# for TargetRailsVersion then it is used.
|
22
|
-
# as a float (
|
23
|
-
# If TargetRailsVersion is not set, RuboCop will parse the Gemfile.lock or
|
20
|
+
# What version of Rails is the inspected code using? If a value is specified
|
21
|
+
# for `TargetRailsVersion` then it is used. Acceptable values are specified
|
22
|
+
# as a float (e.g., 7.2); the patch version of Rails should not be included.
|
23
|
+
# If `TargetRailsVersion` is not set, RuboCop will parse the Gemfile.lock or
|
24
24
|
# gems.locked file to find the version of Rails that has been bound to the
|
25
|
-
# application.
|
25
|
+
# application. If neither of those files exist, RuboCop will use Rails 5.0
|
26
26
|
# as the default.
|
27
27
|
TargetRailsVersion: ~
|
28
|
+
# By specifying `MigratedSchemaVersion` option, migration files that have been migrated can be ignored.
|
29
|
+
# When `MigratedSchemaVersion: '20241231000000'` is set. Migration files lower than or equal to '20250101000000' will be ignored.
|
30
|
+
# For example, this is the timestamp in db/migrate/20250101000000_create_articles.rb.
|
31
|
+
MigratedSchemaVersion: ~
|
28
32
|
|
29
33
|
Lint/NumberConversion:
|
30
34
|
# Add Rails' duration methods to the ignore list for `Lint/NumberConversion`
|
@@ -212,7 +216,9 @@ Rails/ApplicationRecord:
|
|
212
216
|
Enabled: true
|
213
217
|
SafeAutoCorrect: false
|
214
218
|
VersionAdded: '0.49'
|
215
|
-
VersionChanged: '2.
|
219
|
+
VersionChanged: '2.26'
|
220
|
+
Exclude:
|
221
|
+
- db/**/*.rb
|
216
222
|
|
217
223
|
Rails/ArelStar:
|
218
224
|
Description: 'Enforces `Arel.star` instead of `"*"` for expanded columns.'
|
@@ -692,6 +698,15 @@ Rails/MigrationClassName:
|
|
692
698
|
Include:
|
693
699
|
- db/**/*.rb
|
694
700
|
|
701
|
+
Rails/MultipleRoutePaths:
|
702
|
+
Description: 'Checks for mapping a route with multiple paths, which is deprecated and will be removed in Rails 8.1.'
|
703
|
+
Enabled: pending
|
704
|
+
Severity: warning
|
705
|
+
VersionAdded: '2.29'
|
706
|
+
Include:
|
707
|
+
- config/routes.rb
|
708
|
+
- config/routes/**/*.rb
|
709
|
+
|
695
710
|
Rails/NegateInclude:
|
696
711
|
Description: 'Prefer `collection.exclude?(obj)` over `!collection.include?(obj)`.'
|
697
712
|
StyleGuide: 'https://rails.rubystyle.guide#exclude'
|
@@ -1066,6 +1081,15 @@ Rails/StripHeredoc:
|
|
1066
1081
|
Enabled: pending
|
1067
1082
|
VersionAdded: '2.15'
|
1068
1083
|
|
1084
|
+
Rails/StrongParametersExpect:
|
1085
|
+
Description: 'Enforces the use of `ActionController::Parameters#expect` as a method for strong parameter handling.'
|
1086
|
+
Reference: 'https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-expect'
|
1087
|
+
Enabled: pending
|
1088
|
+
Include:
|
1089
|
+
- app/controllers/**/*.rb
|
1090
|
+
SafeAutoCorrect: false
|
1091
|
+
VersionAdded: '2.29'
|
1092
|
+
|
1069
1093
|
Rails/TableNameAssignment:
|
1070
1094
|
Description: >-
|
1071
1095
|
Do not use `self.table_name =`. Use Inflections or `table_name_prefix` instead.
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
6
6
|
module IndexMethod # rubocop:disable Metrics/ModuleLength
|
7
7
|
RESTRICT_ON_SEND = %i[each_with_object to_h map collect []].freeze
|
8
8
|
|
9
|
-
def on_block(node)
|
9
|
+
def on_block(node)
|
10
10
|
on_bad_each_with_object(node) do |*match|
|
11
11
|
handle_possible_offense(node, match, 'each_with_object')
|
12
12
|
end
|
@@ -18,6 +18,8 @@ module RuboCop
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
alias on_numblock on_block
|
22
|
+
|
21
23
|
def on_send(node)
|
22
24
|
on_bad_map_to_h(node) do |*match|
|
23
25
|
handle_possible_offense(node, match, 'map { ... }.to_h')
|
@@ -122,9 +124,9 @@ module RuboCop
|
|
122
124
|
end
|
123
125
|
|
124
126
|
def self.from_map_to_h(node, match)
|
125
|
-
|
126
|
-
|
127
|
-
|
127
|
+
if node.block_literal?
|
128
|
+
strip_trailing_chars = 0
|
129
|
+
else
|
128
130
|
map_range = node.children.first.source_range
|
129
131
|
node_range = node.source_range
|
130
132
|
strip_trailing_chars = node_range.end_pos - map_range.end_pos
|
@@ -153,11 +155,16 @@ module RuboCop
|
|
153
155
|
end
|
154
156
|
|
155
157
|
def set_new_arg_name(transformed_argname, corrector)
|
158
|
+
return if block_node.numblock_type?
|
159
|
+
|
156
160
|
corrector.replace(block_node.arguments, "|#{transformed_argname}|")
|
157
161
|
end
|
158
162
|
|
159
163
|
def set_new_body_expression(transforming_body_expr, corrector)
|
160
|
-
|
164
|
+
body_source = transforming_body_expr.source
|
165
|
+
body_source = "{ #{body_source} }" if transforming_body_expr.hash_type? && !transforming_body_expr.braces?
|
166
|
+
|
167
|
+
corrector.replace(block_node.body, body_source)
|
161
168
|
end
|
162
169
|
end
|
163
170
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common functionality for cops working with routes.
|
6
|
+
module RoutesHelper
|
7
|
+
extend NodePattern::Macros
|
8
|
+
|
9
|
+
HTTP_METHODS = %i[get post put patch delete].freeze
|
10
|
+
|
11
|
+
def_node_matcher :routes_draw?, <<~PATTERN
|
12
|
+
(send (send _ :routes) :draw)
|
13
|
+
PATTERN
|
14
|
+
|
15
|
+
def within_routes?(node)
|
16
|
+
node.each_ancestor(:block).any? { |block| routes_draw?(block.send_node) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -7,6 +7,9 @@ module RuboCop
|
|
7
7
|
# Informs the base RuboCop gem that it the Rails version is checked via `requires_gem` API,
|
8
8
|
# without needing to call this `#support_target_rails_version` method.
|
9
9
|
USES_REQUIRES_GEM_API = true
|
10
|
+
# Look for `railties` instead of `rails`, to support apps that only use a subset of `rails`
|
11
|
+
# See https://github.com/rubocop/rubocop/pull/11289
|
12
|
+
TARGET_GEM_NAME = 'railties' # :nodoc:
|
10
13
|
|
11
14
|
def minimum_target_rails_version(version)
|
12
15
|
if respond_to?(:requires_gem)
|
@@ -33,11 +36,6 @@ module RuboCop
|
|
33
36
|
@minimum_target_rails_version <= version
|
34
37
|
end
|
35
38
|
end
|
36
|
-
|
37
|
-
# Look for `railties` instead of `rails`, to support apps that only use a subset of `rails`
|
38
|
-
# See https://github.com/rubocop/rubocop/pull/11289
|
39
|
-
TARGET_GEM_NAME = 'railties'
|
40
|
-
private_constant :TARGET_GEM_NAME
|
41
39
|
end
|
42
40
|
end
|
43
41
|
end
|
@@ -72,13 +72,13 @@ module RuboCop
|
|
72
72
|
if (node = context.each_ancestor(:if, :rescue).first)
|
73
73
|
return false if use_redirect_to?(context)
|
74
74
|
|
75
|
-
context = node
|
75
|
+
context = node
|
76
|
+
elsif context.right_siblings.empty?
|
77
|
+
return true
|
76
78
|
end
|
79
|
+
context = context.right_siblings
|
77
80
|
|
78
|
-
|
79
|
-
return true if siblings.empty?
|
80
|
-
|
81
|
-
siblings.compact.any? do |render_candidate|
|
81
|
+
context.compact.any? do |render_candidate|
|
82
82
|
render?(render_candidate)
|
83
83
|
end
|
84
84
|
end
|
@@ -92,11 +92,7 @@ module RuboCop
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def range_with_comments(node)
|
95
|
-
|
96
|
-
# Using `RuboCop::Ext::Comment#source_range` requires RuboCop > 1.46,
|
97
|
-
# which introduces https://github.com/rubocop/rubocop/pull/11630.
|
98
|
-
ranges = [node, *processed_source.ast_with_comments[node]].map { |comment| comment.loc.expression }
|
99
|
-
# rubocop:enable InternalAffairs/LocationExpression
|
95
|
+
ranges = [node, *processed_source.ast_with_comments[node]].map(&:source_range)
|
100
96
|
ranges.reduce do |result, range|
|
101
97
|
add_range(result, range)
|
102
98
|
end
|
@@ -123,11 +123,7 @@ module RuboCop
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def inline_comment?(comment)
|
126
|
-
|
127
|
-
# Using `RuboCop::Ext::Comment#source_range` requires RuboCop > 1.46,
|
128
|
-
# which introduces https://github.com/rubocop/rubocop/pull/11630.
|
129
|
-
!comment_line?(comment.loc.expression.source_line)
|
130
|
-
# rubocop:enable InternalAffairs/LocationExpression
|
126
|
+
!comment_line?(comment.source_range.source_line)
|
131
127
|
end
|
132
128
|
|
133
129
|
def start_line_position(node)
|
@@ -5,6 +5,10 @@ module RuboCop
|
|
5
5
|
module Rails
|
6
6
|
# Checks that models subclass `ApplicationRecord` with Rails 5.0.
|
7
7
|
#
|
8
|
+
# It is a common practice to define models inside migrations in order to retain forward
|
9
|
+
# compatibility by avoiding loading any application code. And so migration files are excluded
|
10
|
+
# by default for this cop.
|
11
|
+
#
|
8
12
|
# @safety
|
9
13
|
# This cop's autocorrection is unsafe because it may let the logic from `ApplicationRecord`
|
10
14
|
# sneak into an Active Record model that is not purposed to inherit logic common among other
|
@@ -25,6 +25,8 @@ module RuboCop
|
|
25
25
|
# collection.reject { |_k, v| v.blank? }
|
26
26
|
# collection.select(&:present?)
|
27
27
|
# collection.select { |_k, v| v.present? }
|
28
|
+
# collection.filter(&:present?)
|
29
|
+
# collection.filter { |_k, v| v.present? }
|
28
30
|
#
|
29
31
|
# # good
|
30
32
|
# collection.compact_blank
|
@@ -44,7 +46,8 @@ module RuboCop
|
|
44
46
|
extend TargetRailsVersion
|
45
47
|
|
46
48
|
MSG = 'Use `%<preferred_method>s` instead.'
|
47
|
-
RESTRICT_ON_SEND = %i[reject delete_if select keep_if].freeze
|
49
|
+
RESTRICT_ON_SEND = %i[reject delete_if select filter keep_if].freeze
|
50
|
+
DESTRUCTIVE_METHODS = %i[delete_if keep_if].freeze
|
48
51
|
|
49
52
|
minimum_target_rails_version 6.1
|
50
53
|
|
@@ -64,19 +67,20 @@ module RuboCop
|
|
64
67
|
|
65
68
|
def_node_matcher :select_with_block?, <<~PATTERN
|
66
69
|
(block
|
67
|
-
(send _ {:select :keep_if})
|
70
|
+
(send _ {:select :filter :keep_if})
|
68
71
|
$(args ...)
|
69
72
|
(send
|
70
73
|
$(lvar _) :present?))
|
71
74
|
PATTERN
|
72
75
|
|
73
76
|
def_node_matcher :select_with_block_pass?, <<~PATTERN
|
74
|
-
(send _ {:select :keep_if}
|
77
|
+
(send _ {:select :filter :keep_if}
|
75
78
|
(block-pass
|
76
79
|
(sym :present?)))
|
77
80
|
PATTERN
|
78
81
|
|
79
82
|
def on_send(node)
|
83
|
+
return if target_ruby_version < 2.6 && node.method?(:filter)
|
80
84
|
return unless bad_method?(node)
|
81
85
|
|
82
86
|
range = offense_range(node)
|
@@ -120,7 +124,7 @@ module RuboCop
|
|
120
124
|
end
|
121
125
|
|
122
126
|
def preferred_method(node)
|
123
|
-
|
127
|
+
DESTRUCTIVE_METHODS.include?(node.method_name) ? 'compact_blank!' : 'compact_blank'
|
124
128
|
end
|
125
129
|
end
|
126
130
|
end
|
@@ -63,11 +63,15 @@ module RuboCop
|
|
63
63
|
private
|
64
64
|
|
65
65
|
def register_offense(name, nodes, message_template)
|
66
|
-
nodes.
|
67
|
-
add_offense(node, message: format(message_template, name: name)) do |corrector|
|
68
|
-
next if same_line?(nodes.last, node)
|
66
|
+
last_node = nodes.last
|
69
67
|
|
70
|
-
|
68
|
+
nodes.each_with_index do |node, index|
|
69
|
+
add_offense(node, message: format(message_template, name: name)) do |corrector|
|
70
|
+
if index.zero?
|
71
|
+
corrector.replace(node, last_node.source)
|
72
|
+
else
|
73
|
+
corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
|
74
|
+
end
|
71
75
|
end
|
72
76
|
end
|
73
77
|
end
|
@@ -17,14 +17,19 @@ module RuboCop
|
|
17
17
|
#
|
18
18
|
class EnumSyntax < Base
|
19
19
|
extend AutoCorrector
|
20
|
+
extend TargetRubyVersion
|
20
21
|
extend TargetRailsVersion
|
21
22
|
|
23
|
+
minimum_target_ruby_version 3.0
|
22
24
|
minimum_target_rails_version 7.0
|
23
25
|
|
24
26
|
MSG = 'Enum defined with keyword arguments in `%<enum>s` enum declaration. Use positional arguments instead.'
|
25
27
|
MSG_OPTIONS = 'Enum defined with deprecated options in `%<enum>s` enum declaration. Remove the `_` prefix.'
|
26
28
|
RESTRICT_ON_SEND = %i[enum].freeze
|
27
|
-
|
29
|
+
|
30
|
+
# From https://github.com/rails/rails/blob/v7.2.1/activerecord/lib/active_record/enum.rb#L231
|
31
|
+
OPTION_NAMES = %w[prefix suffix scopes default instance_methods].freeze
|
32
|
+
UNDERSCORED_OPTION_NAMES = OPTION_NAMES.map { |option| "_#{option}" }.freeze
|
28
33
|
|
29
34
|
def_node_matcher :enum?, <<~PATTERN
|
30
35
|
(send nil? :enum (hash $...))
|
@@ -34,14 +39,6 @@ module RuboCop
|
|
34
39
|
(send nil? :enum $_ ${array hash} $_)
|
35
40
|
PATTERN
|
36
41
|
|
37
|
-
def_node_matcher :enum_values, <<~PATTERN
|
38
|
-
(pair $_ ${array hash})
|
39
|
-
PATTERN
|
40
|
-
|
41
|
-
def_node_matcher :enum_options, <<~PATTERN
|
42
|
-
(pair $_ $_)
|
43
|
-
PATTERN
|
44
|
-
|
45
42
|
def on_send(node)
|
46
43
|
check_and_correct_keyword_args(node)
|
47
44
|
check_enum_options(node)
|
@@ -52,10 +49,9 @@ module RuboCop
|
|
52
49
|
def check_and_correct_keyword_args(node)
|
53
50
|
enum?(node) do |pairs|
|
54
51
|
pairs.each do |pair|
|
55
|
-
|
56
|
-
next unless key
|
52
|
+
next if option_key?(pair)
|
57
53
|
|
58
|
-
correct_keyword_args(node, key,
|
54
|
+
correct_keyword_args(node, pair.key, pair.value, pairs[1..])
|
59
55
|
end
|
60
56
|
end
|
61
57
|
end
|
@@ -63,9 +59,11 @@ module RuboCop
|
|
63
59
|
def check_enum_options(node)
|
64
60
|
enum_with_options?(node) do |key, _, options|
|
65
61
|
options.children.each do |option|
|
66
|
-
|
62
|
+
next unless option_key?(option)
|
67
63
|
|
68
|
-
add_offense(
|
64
|
+
add_offense(option.key, message: format(MSG_OPTIONS, enum: enum_name_value(key))) do |corrector|
|
65
|
+
corrector.replace(option.key, option.key.source.delete_prefix('_'))
|
66
|
+
end
|
69
67
|
end
|
70
68
|
end
|
71
69
|
end
|
@@ -107,6 +105,12 @@ module RuboCop
|
|
107
105
|
end
|
108
106
|
end
|
109
107
|
|
108
|
+
def option_key?(pair)
|
109
|
+
return false unless pair.respond_to?(:key)
|
110
|
+
|
111
|
+
UNDERSCORED_OPTION_NAMES.include?(pair.key.source)
|
112
|
+
end
|
113
|
+
|
110
114
|
def correct_options(options)
|
111
115
|
corrected_options = options.map do |pair|
|
112
116
|
name = if pair.key.source[0] == '_'
|
@@ -19,20 +19,33 @@ module RuboCop
|
|
19
19
|
extend TargetRailsVersion
|
20
20
|
|
21
21
|
MSG = 'Use `Rails.env.local?` instead.'
|
22
|
+
MSG_NEGATED = 'Use `!Rails.env.local?` instead.'
|
22
23
|
LOCAL_ENVIRONMENTS = %i[development? test?].to_set.freeze
|
23
24
|
|
24
25
|
minimum_target_rails_version 7.1
|
25
26
|
|
26
|
-
# @!method
|
27
|
-
def_node_matcher :
|
27
|
+
# @!method rails_env_local_or?(node)
|
28
|
+
def_node_matcher :rails_env_local_or?, <<~PATTERN
|
28
29
|
(or
|
29
30
|
(send (send (const {cbase nil? } :Rails) :env) $%LOCAL_ENVIRONMENTS)
|
30
31
|
(send (send (const {cbase nil? } :Rails) :env) $%LOCAL_ENVIRONMENTS)
|
31
32
|
)
|
32
33
|
PATTERN
|
33
34
|
|
35
|
+
# @!method rails_env_local_and?(node)
|
36
|
+
def_node_matcher :rails_env_local_and?, <<~PATTERN
|
37
|
+
(and
|
38
|
+
(send
|
39
|
+
(send (send (const {cbase nil? } :Rails) :env) $%LOCAL_ENVIRONMENTS)
|
40
|
+
:!)
|
41
|
+
(send
|
42
|
+
(send (send (const {cbase nil? } :Rails) :env) $%LOCAL_ENVIRONMENTS)
|
43
|
+
:!)
|
44
|
+
)
|
45
|
+
PATTERN
|
46
|
+
|
34
47
|
def on_or(node)
|
35
|
-
|
48
|
+
rails_env_local_or?(node) do |*environments|
|
36
49
|
next unless environments.to_set == LOCAL_ENVIRONMENTS
|
37
50
|
|
38
51
|
add_offense(node) do |corrector|
|
@@ -40,6 +53,16 @@ module RuboCop
|
|
40
53
|
end
|
41
54
|
end
|
42
55
|
end
|
56
|
+
|
57
|
+
def on_and(node)
|
58
|
+
rails_env_local_and?(node) do |*environments|
|
59
|
+
next unless environments.to_set == LOCAL_ENVIRONMENTS
|
60
|
+
|
61
|
+
add_offense(node, message: MSG_NEGATED) do |corrector|
|
62
|
+
corrector.replace(node, '!Rails.env.local?')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
43
66
|
end
|
44
67
|
end
|
45
68
|
end
|
@@ -66,6 +66,8 @@ module RuboCop
|
|
66
66
|
|
67
67
|
def on_send(node)
|
68
68
|
check_for_file_join_with_rails_root(node)
|
69
|
+
return unless node.receiver
|
70
|
+
|
69
71
|
check_for_rails_root_join_with_slash_separated_path(node)
|
70
72
|
check_for_rails_root_join_with_string_arguments(node)
|
71
73
|
end
|
@@ -76,6 +78,7 @@ module RuboCop
|
|
76
78
|
rails_root_index = find_rails_root_index(node)
|
77
79
|
slash_node = node.children[rails_root_index + 1]
|
78
80
|
return unless slash_node&.str_type? && slash_node.source.start_with?(File::SEPARATOR)
|
81
|
+
return unless node.children[rails_root_index].children.first.send_type?
|
79
82
|
|
80
83
|
register_offense(node, require_to_s: false) do |corrector|
|
81
84
|
autocorrect_slash_after_rails_root_in_dstr(corrector, node, rails_root_index)
|
@@ -97,7 +100,7 @@ module RuboCop
|
|
97
100
|
return unless node.arguments.any? { |e| rails_root_nodes?(e) }
|
98
101
|
|
99
102
|
register_offense(node, require_to_s: true) do |corrector|
|
100
|
-
autocorrect_file_join(corrector, node)
|
103
|
+
autocorrect_file_join(corrector, node) unless node.first_argument.array_type?
|
101
104
|
end
|
102
105
|
end
|
103
106
|
|
@@ -170,7 +173,17 @@ module RuboCop
|
|
170
173
|
end
|
171
174
|
|
172
175
|
def autocorrect_file_join(corrector, node)
|
176
|
+
replace_receiver_with_rails_root(corrector, node)
|
177
|
+
remove_first_argument_with_comma(corrector, node)
|
178
|
+
process_arguments(corrector, node.arguments)
|
179
|
+
append_to_string_conversion(corrector, node)
|
180
|
+
end
|
181
|
+
|
182
|
+
def replace_receiver_with_rails_root(corrector, node)
|
173
183
|
corrector.replace(node.receiver, 'Rails.root')
|
184
|
+
end
|
185
|
+
|
186
|
+
def remove_first_argument_with_comma(corrector, node)
|
174
187
|
corrector.remove(
|
175
188
|
range_with_surrounding_space(
|
176
189
|
range_with_surrounding_comma(
|
@@ -180,9 +193,19 @@ module RuboCop
|
|
180
193
|
side: :right
|
181
194
|
)
|
182
195
|
)
|
183
|
-
|
184
|
-
|
196
|
+
end
|
197
|
+
|
198
|
+
def process_arguments(corrector, arguments)
|
199
|
+
arguments.each do |argument|
|
200
|
+
if argument.str_type?
|
201
|
+
corrector.replace(argument, argument.value.delete_prefix('/').inspect)
|
202
|
+
elsif argument.array_type?
|
203
|
+
corrector.replace(argument, "*#{argument.source}")
|
204
|
+
end
|
185
205
|
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def append_to_string_conversion(corrector, node)
|
186
209
|
corrector.insert_after(node, '.to_s')
|
187
210
|
end
|
188
211
|
|
@@ -40,6 +40,10 @@ module RuboCop
|
|
40
40
|
(hash (kwsplat _))
|
41
41
|
PATTERN
|
42
42
|
|
43
|
+
def_node_matcher :forwarded_kwrestarg?, <<~PATTERN
|
44
|
+
(hash (forwarded-kwrestarg))
|
45
|
+
PATTERN
|
46
|
+
|
43
47
|
def_node_matcher :include_rack_test_methods?, <<~PATTERN
|
44
48
|
(send nil? :include
|
45
49
|
(const
|
@@ -83,7 +87,9 @@ module RuboCop
|
|
83
87
|
end
|
84
88
|
end
|
85
89
|
|
90
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
86
91
|
def needs_conversion?(data)
|
92
|
+
return false if data.forwarded_args_type? || forwarded_kwrestarg?(data)
|
87
93
|
return true unless data.hash_type?
|
88
94
|
return false if kwsplat_hash?(data)
|
89
95
|
|
@@ -91,6 +97,7 @@ module RuboCop
|
|
91
97
|
special_keyword_arg?(pair.key) || (format_arg?(pair.key) && data.pairs.one?)
|
92
98
|
end
|
93
99
|
end
|
100
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
94
101
|
|
95
102
|
def special_keyword_arg?(node)
|
96
103
|
node.sym_type? && KEYWORD_ARGS.include?(node.value)
|