rubocop-rails 2.35.4 → 2.36.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.
- checksums.yaml +4 -4
- data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +1 -1
- data/lib/rubocop/cop/rails/env.rb +15 -2
- data/lib/rubocop/cop/rails/reversible_migration.rb +8 -0
- data/lib/rubocop/cop/rails/safe_navigation.rb +33 -5
- data/lib/rubocop/cop/rails/save_bang.rb +10 -1
- data/lib/rubocop/rails/migration_file_skippable.rb +0 -4
- data/lib/rubocop/rails/version.rb +1 -1
- data/lib/rubocop-rails.rb +10 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5fcf30164d8e9727b16702ab937a902890c342d02c1865e4588295a355380f7a
|
|
4
|
+
data.tar.gz: 8c88a959e8b7b07e6751c6a385302deabc39f8bf328278b979d62c46becaccc7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bc070f9148d8b3b8d87c06cf95ae2b604eb81758548cfab082a38300760ac714ac0d1741e19c8c7d604563868be6b03b4c1b1bdc87af6d7999a4386aa37701d4
|
|
7
|
+
data.tar.gz: 14e8a2fa9886a93625e49678688e7b00e2075bfcfa00a04adc23c3de5d3b8e9fd3c5be88b19e532d4cd30b1dc746320b273f0a2c7f7b984625e1a6874f16d649
|
|
@@ -5,22 +5,34 @@ module RuboCop
|
|
|
5
5
|
module Rails
|
|
6
6
|
# Checks for usage of `Rails.env` which can be replaced with Feature Flags
|
|
7
7
|
#
|
|
8
|
+
# The cop does not flag `Rails.env.local?`, the built-in alias for
|
|
9
|
+
# "development or test" introduced in Rails 7.1. Unlike per-environment
|
|
10
|
+
# predicates such as `development?` or `production?`, `local?` expresses
|
|
11
|
+
# the intent of guarding code that must only ever run in development or
|
|
12
|
+
# test (sanity checks, devtools, seed data) rather than gating an
|
|
13
|
+
# environment rollout, so a Feature Flag is not a suitable replacement.
|
|
14
|
+
#
|
|
8
15
|
# @example
|
|
9
16
|
#
|
|
10
17
|
# # bad
|
|
11
|
-
# Rails.env.production? || Rails.env.
|
|
18
|
+
# Rails.env.production? || Rails.env.development?
|
|
12
19
|
#
|
|
13
20
|
# # good
|
|
14
21
|
# if FeatureFlag.enabled?(:new_feature)
|
|
15
22
|
# # new feature code
|
|
16
23
|
# end
|
|
17
24
|
#
|
|
25
|
+
# # good
|
|
26
|
+
# raise 'This should never run in production' unless Rails.env.local?
|
|
27
|
+
#
|
|
18
28
|
class Env < Base
|
|
19
29
|
MSG = 'Use Feature Flags or config instead of `Rails.env`.'
|
|
20
30
|
RESTRICT_ON_SEND = %i[env].freeze
|
|
21
31
|
# This allow list is derived from:
|
|
22
32
|
# (Rails.env.methods - Object.instance_methods).select { |m| m.to_s.end_with?('?') }
|
|
23
|
-
# and then removing the environment specific methods like development?, test?, production
|
|
33
|
+
# and then removing the environment specific methods like development?, test?, and production?.
|
|
34
|
+
# `local?` is kept on the allow list because it intentionally expresses
|
|
35
|
+
# "development or test" rather than a single environment rollout.
|
|
24
36
|
ALLOWED_LIST = Set.new(
|
|
25
37
|
%i[
|
|
26
38
|
unicode_normalized?
|
|
@@ -38,6 +50,7 @@ module RuboCop
|
|
|
38
50
|
valid_encoding?
|
|
39
51
|
ascii_only?
|
|
40
52
|
between?
|
|
53
|
+
local?
|
|
41
54
|
]
|
|
42
55
|
).freeze
|
|
43
56
|
|
|
@@ -294,6 +294,8 @@ module RuboCop
|
|
|
294
294
|
false
|
|
295
295
|
when :remove
|
|
296
296
|
target_rails_version >= 6.1 && all_hash_key?(node.last_argument, :type)
|
|
297
|
+
when :remove_index
|
|
298
|
+
reversible_remove_index?(node)
|
|
297
299
|
when :change_default, :change_column_default, :change_table_comment,
|
|
298
300
|
:change_column_comment
|
|
299
301
|
all_hash_key?(node.last_argument, :from, :to)
|
|
@@ -302,6 +304,12 @@ module RuboCop
|
|
|
302
304
|
end
|
|
303
305
|
end
|
|
304
306
|
|
|
307
|
+
def reversible_remove_index?(node)
|
|
308
|
+
return true if node.arguments.any? { |arg| !arg.hash_type? }
|
|
309
|
+
|
|
310
|
+
all_hash_key?(node.last_argument, :column)
|
|
311
|
+
end
|
|
312
|
+
|
|
305
313
|
def within_change_method?(node)
|
|
306
314
|
node.each_ancestor(:def).any? do |ancestor|
|
|
307
315
|
ancestor.method?(:change)
|
|
@@ -12,8 +12,10 @@ module RuboCop
|
|
|
12
12
|
# foo.try!(:bar)
|
|
13
13
|
# foo.try!(:bar, baz)
|
|
14
14
|
# foo.try!(:bar) { |e| e.baz }
|
|
15
|
+
# foo.try!(&:bar)
|
|
15
16
|
#
|
|
16
17
|
# foo.try!(:[], 0)
|
|
18
|
+
# foo.try!(:==, baz)
|
|
17
19
|
#
|
|
18
20
|
# # good
|
|
19
21
|
# foo.try(:bar)
|
|
@@ -23,20 +25,28 @@ module RuboCop
|
|
|
23
25
|
# foo&.bar
|
|
24
26
|
# foo&.bar(baz)
|
|
25
27
|
# foo&.bar { |e| e.baz }
|
|
28
|
+
# foo&.[](0)
|
|
29
|
+
# foo&.==(baz)
|
|
26
30
|
#
|
|
27
31
|
# @example ConvertTry: true
|
|
28
32
|
# # bad
|
|
29
33
|
# foo.try!(:bar)
|
|
30
34
|
# foo.try!(:bar, baz)
|
|
31
35
|
# foo.try!(:bar) { |e| e.baz }
|
|
36
|
+
# foo.try!(&:bar)
|
|
32
37
|
# foo.try(:bar)
|
|
33
38
|
# foo.try(:bar, baz)
|
|
34
39
|
# foo.try(:bar) { |e| e.baz }
|
|
40
|
+
# foo.try(&:bar)
|
|
41
|
+
# foo.try(:[], 0)
|
|
42
|
+
# foo.try(:==, baz)
|
|
35
43
|
#
|
|
36
44
|
# # good
|
|
37
45
|
# foo&.bar
|
|
38
46
|
# foo&.bar(baz)
|
|
39
47
|
# foo&.bar { |e| e.baz }
|
|
48
|
+
# foo&.[](0)
|
|
49
|
+
# foo&.==(baz)
|
|
40
50
|
class SafeNavigation < Base
|
|
41
51
|
include RangeHelp
|
|
42
52
|
extend AutoCorrector
|
|
@@ -51,6 +61,11 @@ module RuboCop
|
|
|
51
61
|
(send _ ${:try :try!} $_ ...)
|
|
52
62
|
PATTERN
|
|
53
63
|
|
|
64
|
+
# Extracts the method name from a symbol-to-proc block argument, e.g. `:foo` from `try(&:foo)`.
|
|
65
|
+
def_node_matcher :symbol_proc_method, <<~PATTERN
|
|
66
|
+
(block_pass (sym $_))
|
|
67
|
+
PATTERN
|
|
68
|
+
|
|
54
69
|
def self.autocorrect_incompatible_with
|
|
55
70
|
[Style::RedundantSelf]
|
|
56
71
|
end
|
|
@@ -58,11 +73,16 @@ module RuboCop
|
|
|
58
73
|
def on_send(node)
|
|
59
74
|
try_call(node) do |try_method, dispatch|
|
|
60
75
|
return if try_method == :try && !cop_config['ConvertTry']
|
|
61
|
-
return unless dispatch.sym_type?
|
|
76
|
+
return unless dispatch.sym_type? || symbol_proc_method(dispatch)
|
|
77
|
+
# When a `try` is nested in another `try`'s argument, correcting both at once
|
|
78
|
+
# produces overlapping replacements. Correct the outer one first and defer the
|
|
79
|
+
# inner one to a subsequent pass.
|
|
80
|
+
return if part_of_ignored_node?(node)
|
|
62
81
|
|
|
63
82
|
add_offense(node, message: format(MSG, try: try_method)) do |corrector|
|
|
64
83
|
autocorrect(corrector, node)
|
|
65
84
|
end
|
|
85
|
+
ignore_node(node)
|
|
66
86
|
end
|
|
67
87
|
end
|
|
68
88
|
|
|
@@ -70,7 +90,6 @@ module RuboCop
|
|
|
70
90
|
|
|
71
91
|
def autocorrect(corrector, node)
|
|
72
92
|
method_node, *params = *node.arguments
|
|
73
|
-
method = method_node.source[1..]
|
|
74
93
|
|
|
75
94
|
range = if node.receiver
|
|
76
95
|
range_between(node.loc.dot.begin_pos, node.source_range.end_pos)
|
|
@@ -79,13 +98,16 @@ module RuboCop
|
|
|
79
98
|
node
|
|
80
99
|
end
|
|
81
100
|
|
|
82
|
-
corrector.replace(range, replacement(
|
|
101
|
+
corrector.replace(range, replacement(method_node, params))
|
|
83
102
|
end
|
|
84
103
|
|
|
85
|
-
def replacement(
|
|
104
|
+
def replacement(method_node, params)
|
|
105
|
+
return "&.#{symbol_proc_method(method_node)}" if method_node.block_pass_type?
|
|
106
|
+
|
|
107
|
+
method = method_node.source[1..]
|
|
86
108
|
new_params = params.map(&:source).join(', ')
|
|
87
109
|
|
|
88
|
-
if
|
|
110
|
+
if setter_method?(method)
|
|
89
111
|
"&.#{method[0...-1]} = #{new_params}"
|
|
90
112
|
elsif params.empty?
|
|
91
113
|
"&.#{method}"
|
|
@@ -93,6 +115,12 @@ module RuboCop
|
|
|
93
115
|
"&.#{method}(#{new_params})"
|
|
94
116
|
end
|
|
95
117
|
end
|
|
118
|
+
|
|
119
|
+
# Operator methods such as `==` and `[]=` also end with `=`, but they are not setters
|
|
120
|
+
# and must keep the explicit call form (e.g. `&.==(bar)`, `&.[]=(key, value)`).
|
|
121
|
+
def setter_method?(method)
|
|
122
|
+
method.match?(/\A\w+=\z/)
|
|
123
|
+
end
|
|
96
124
|
end
|
|
97
125
|
end
|
|
98
126
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# rubocop:disable Metrics/ClassLength
|
|
3
4
|
module RuboCop
|
|
4
5
|
module Cop
|
|
5
6
|
module Rails
|
|
@@ -303,13 +304,20 @@ module RuboCop
|
|
|
303
304
|
def implicit_return?(node)
|
|
304
305
|
return false unless cop_config['AllowImplicitReturn']
|
|
305
306
|
|
|
306
|
-
node = assignable_node(node)
|
|
307
|
+
node = last_expression_in_begin(assignable_node(node))
|
|
307
308
|
method, sibling_index = find_method_with_sibling_index(node.parent)
|
|
308
309
|
return false unless method&.type?(:def, :any_block)
|
|
309
310
|
|
|
310
311
|
method.children.size == node.sibling_index + sibling_index
|
|
311
312
|
end
|
|
312
313
|
|
|
314
|
+
# A multiline method or block body is wrapped in a `begin` node, so climb
|
|
315
|
+
# to it when the node is the last expression, to detect the implicit return.
|
|
316
|
+
def last_expression_in_begin(node)
|
|
317
|
+
node = node.parent while node.parent&.begin_type? && node.right_sibling.nil?
|
|
318
|
+
node
|
|
319
|
+
end
|
|
320
|
+
|
|
313
321
|
def find_method_with_sibling_index(node, sibling_index = 1)
|
|
314
322
|
return node, sibling_index unless node&.or_type?
|
|
315
323
|
|
|
@@ -348,3 +356,4 @@ module RuboCop
|
|
|
348
356
|
end
|
|
349
357
|
end
|
|
350
358
|
end
|
|
359
|
+
# rubocop:enable Metrics/ClassLength
|
data/lib/rubocop-rails.rb
CHANGED
|
@@ -12,7 +12,8 @@ require_relative 'rubocop/rails/plugin'
|
|
|
12
12
|
require_relative 'rubocop/cop/rails_cops'
|
|
13
13
|
|
|
14
14
|
require_relative 'rubocop/rails/migration_file_skippable'
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
RuboCop::Cop::Base.prepend(RuboCop::Rails::MigrationFileSkippable)
|
|
16
17
|
|
|
17
18
|
RuboCop::Cop::Style::HashExcept.minimum_target_ruby_version(2.0)
|
|
18
19
|
|
|
@@ -39,3 +40,11 @@ RuboCop::Cop::Style::RedundantSelf.singleton_class.prepend(
|
|
|
39
40
|
end
|
|
40
41
|
end
|
|
41
42
|
)
|
|
43
|
+
|
|
44
|
+
RuboCop::Cop::Style::TrailingCommaInArguments.singleton_class.prepend(
|
|
45
|
+
Module.new do
|
|
46
|
+
def autocorrect_incompatible_with
|
|
47
|
+
super.push(RuboCop::Cop::Rails::LinkToBlank)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubocop-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.36.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bozhidar Batsov
|
|
@@ -269,7 +269,7 @@ metadata:
|
|
|
269
269
|
homepage_uri: https://docs.rubocop.org/rubocop-rails/
|
|
270
270
|
changelog_uri: https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md
|
|
271
271
|
source_code_uri: https://github.com/rubocop/rubocop-rails/
|
|
272
|
-
documentation_uri: https://docs.rubocop.org/rubocop-rails/2.
|
|
272
|
+
documentation_uri: https://docs.rubocop.org/rubocop-rails/2.36/
|
|
273
273
|
bug_tracker_uri: https://github.com/rubocop/rubocop-rails/issues
|
|
274
274
|
rubygems_mfa_required: 'true'
|
|
275
275
|
default_lint_roller_plugin: RuboCop::Rails::Plugin
|
|
@@ -287,7 +287,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
287
287
|
- !ruby/object:Gem::Version
|
|
288
288
|
version: '0'
|
|
289
289
|
requirements: []
|
|
290
|
-
rubygems_version: 4.0.
|
|
290
|
+
rubygems_version: 4.0.10
|
|
291
291
|
specification_version: 4
|
|
292
292
|
summary: Automatic Rails code style checking tool.
|
|
293
293
|
test_files: []
|