rubocop-rails 2.17.0 → 2.17.4
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/config/default.yml +4 -4
- data/lib/rubocop/cop/mixin/active_record_helper.rb +2 -2
- data/lib/rubocop/cop/mixin/index_method.rb +1 -1
- data/lib/rubocop/cop/mixin/migrations_helper.rb +1 -1
- data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +15 -10
- data/lib/rubocop/cop/rails/action_controller_test_case.rb +1 -1
- data/lib/rubocop/cop/rails/action_order.rb +39 -3
- data/lib/rubocop/cop/rails/application_controller.rb +1 -1
- data/lib/rubocop/cop/rails/application_job.rb +1 -1
- data/lib/rubocop/cop/rails/application_mailer.rb +1 -1
- data/lib/rubocop/cop/rails/application_record.rb +1 -1
- data/lib/rubocop/cop/rails/content_tag.rb +1 -1
- data/lib/rubocop/cop/rails/dot_separated_keys.rb +1 -1
- data/lib/rubocop/cop/rails/duration_arithmetic.rb +2 -2
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +16 -6
- data/lib/rubocop/cop/rails/file_path.rb +3 -3
- data/lib/rubocop/cop/rails/freeze_time.rb +7 -5
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +1 -1
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +1 -1
- data/lib/rubocop/cop/rails/http_status.rb +1 -6
- data/lib/rubocop/cop/rails/i18n_lazy_lookup.rb +2 -0
- data/lib/rubocop/cop/rails/i18n_locale_texts.rb +2 -2
- data/lib/rubocop/cop/rails/index_by.rb +1 -1
- data/lib/rubocop/cop/rails/index_with.rb +1 -1
- data/lib/rubocop/cop/rails/mailer_name.rb +3 -3
- data/lib/rubocop/cop/rails/migration_class_name.rb +1 -1
- data/lib/rubocop/cop/rails/output.rb +1 -1
- data/lib/rubocop/cop/rails/pluck.rb +29 -10
- data/lib/rubocop/cop/rails/require_dependency.rb +1 -1
- data/lib/rubocop/cop/rails/root_pathname_methods.rb +38 -14
- data/lib/rubocop/cop/rails/short_i18n.rb +1 -1
- data/lib/rubocop/cop/rails/skips_model_validations.rb +1 -1
- data/lib/rubocop/cop/rails/time_zone.rb +15 -2
- data/lib/rubocop/cop/rails/time_zone_assignment.rb +1 -1
- data/lib/rubocop/cop/rails/to_s_with_argument.rb +38 -1
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +10 -1
- data/lib/rubocop/cop/rails/where_missing.rb +9 -2
- data/lib/rubocop/cop/rails/where_not_with_multiple_conditions.rb +1 -1
- data/lib/rubocop/rails/version.rb +1 -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: 8a9beeaefa16cbe4afb5d598878444a835536ccda5d9b46c3e44e111513f1d8e
|
4
|
+
data.tar.gz: 669a9681ce5ab1fca038229a831f7e5acae6bbdcc3a58ecfc88d65fd54ef7190
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72ca38ec9a9136bfa5bd635db9290314a4d1a4c8e3942f15aa62a823885ff1a1783f884598dce6f52765db75daccf8e4054d3faecdf973da6f2c53b10dc2c153
|
7
|
+
data.tar.gz: 536c7d8f5dfec22444d2d0fc4b297eac18f7b87cc6c871ce250bec58a2a6d380e814749534e5aedc47c0a66c7ae80ac8c61ffec330093c575cd1cc8dd76e4de9
|
data/config/default.yml
CHANGED
@@ -73,7 +73,7 @@ Rails/ActionControllerFlashBeforeRender:
|
|
73
73
|
StyleGuide: 'https://rails.rubystyle.guide/#flash-before-render'
|
74
74
|
Reference: 'https://api.rubyonrails.org/classes/ActionController/FlashBeforeRender.html'
|
75
75
|
Enabled: 'pending'
|
76
|
-
|
76
|
+
SafeAutoCorrect: false
|
77
77
|
VersionAdded: '2.16'
|
78
78
|
|
79
79
|
Rails/ActionControllerTestCase:
|
@@ -81,7 +81,7 @@ Rails/ActionControllerTestCase:
|
|
81
81
|
StyleGuide: 'https://rails.rubystyle.guide/#integration-testing'
|
82
82
|
Reference: 'https://api.rubyonrails.org/classes/ActionController/TestCase.html'
|
83
83
|
Enabled: 'pending'
|
84
|
-
|
84
|
+
SafeAutoCorrect: false
|
85
85
|
VersionAdded: '2.14'
|
86
86
|
Include:
|
87
87
|
- '**/test/**/*.rb'
|
@@ -540,7 +540,7 @@ Rails/I18nLazyLookup:
|
|
540
540
|
Enabled: pending
|
541
541
|
VersionAdded: '2.14'
|
542
542
|
Include:
|
543
|
-
- 'controllers
|
543
|
+
- 'app/controllers/**/*.rb'
|
544
544
|
|
545
545
|
Rails/I18nLocaleAssignment:
|
546
546
|
Description: 'Prefer the usage of `I18n.with_locale` instead of manually updating `I18n.locale` value.'
|
@@ -873,7 +873,7 @@ Rails/RootJoinChain:
|
|
873
873
|
Rails/RootPathnameMethods:
|
874
874
|
Description: 'Use `Rails.root` IO methods instead of passing it to `File`.'
|
875
875
|
Enabled: pending
|
876
|
-
|
876
|
+
SafeAutoCorrect: false
|
877
877
|
VersionAdded: '2.16'
|
878
878
|
|
879
879
|
Rails/RootPublicPath:
|
@@ -10,8 +10,8 @@ module RuboCop
|
|
10
10
|
|
11
11
|
def_node_matcher :active_record?, <<~PATTERN
|
12
12
|
{
|
13
|
-
(const nil? :ApplicationRecord)
|
14
|
-
(const (const nil? :ActiveRecord) :Base)
|
13
|
+
(const {nil? cbase} :ApplicationRecord)
|
14
|
+
(const (const {nil? cbase} :ActiveRecord) :Base)
|
15
15
|
}
|
16
16
|
PATTERN
|
17
17
|
|
@@ -134,7 +134,7 @@ module RuboCop
|
|
134
134
|
end
|
135
135
|
|
136
136
|
def self.from_hash_brackets_map(node, match)
|
137
|
-
new(match, node.children.last,
|
137
|
+
new(match, node.children.last, "#{node.receiver.source}[".length, ']'.length)
|
138
138
|
end
|
139
139
|
|
140
140
|
def strip_prefix_and_suffix(node, corrector)
|
@@ -37,14 +37,14 @@ module RuboCop
|
|
37
37
|
^(send (send nil? :flash) :[]= ...)
|
38
38
|
PATTERN
|
39
39
|
|
40
|
-
def_node_search :
|
41
|
-
(send nil? :
|
40
|
+
def_node_search :render?, <<~PATTERN
|
41
|
+
(send nil? :render ...)
|
42
42
|
PATTERN
|
43
43
|
|
44
44
|
def_node_search :action_controller?, <<~PATTERN
|
45
45
|
{
|
46
|
-
(const nil? :ApplicationController)
|
47
|
-
(const (const nil? :ActionController) :Base)
|
46
|
+
(const {nil? cbase} :ApplicationController)
|
47
|
+
(const (const {nil? cbase} :ActionController) :Base)
|
48
48
|
}
|
49
49
|
PATTERN
|
50
50
|
|
@@ -53,7 +53,7 @@ module RuboCop
|
|
53
53
|
def on_send(flash_node)
|
54
54
|
return unless flash_assignment?(flash_node)
|
55
55
|
|
56
|
-
return
|
56
|
+
return unless followed_by_render?(flash_node)
|
57
57
|
|
58
58
|
return unless instance_method_or_block?(flash_node)
|
59
59
|
|
@@ -66,13 +66,18 @@ module RuboCop
|
|
66
66
|
|
67
67
|
private
|
68
68
|
|
69
|
-
def
|
69
|
+
def followed_by_render?(flash_node)
|
70
70
|
flash_assigment_node = find_ancestor(flash_node, type: :send)
|
71
|
-
context = flash_assigment_node
|
71
|
+
context = flash_assigment_node
|
72
|
+
if (node = context.each_ancestor(:if, :rescue).first)
|
73
|
+
context = node
|
74
|
+
elsif context.right_siblings.empty?
|
75
|
+
return true
|
76
|
+
end
|
77
|
+
context = context.right_siblings
|
72
78
|
|
73
|
-
|
74
|
-
|
75
|
-
index > flash_index && redirect_to?(node)
|
79
|
+
context.compact.any? do |render_candidate|
|
80
|
+
render?(render_candidate)
|
76
81
|
end
|
77
82
|
end
|
78
83
|
|
@@ -6,7 +6,8 @@ module RuboCop
|
|
6
6
|
# Enforces consistent ordering of the standard Rails RESTful controller actions.
|
7
7
|
#
|
8
8
|
# The cop is configurable and can enforce any ordering of the standard actions.
|
9
|
-
# All other methods are ignored.
|
9
|
+
# All other methods are ignored. So, the actions specified in `ExpectedOrder` should be
|
10
|
+
# defined before actions not specified.
|
10
11
|
#
|
11
12
|
# [source,yaml]
|
12
13
|
# ----
|
@@ -35,6 +36,7 @@ module RuboCop
|
|
35
36
|
extend AutoCorrector
|
36
37
|
include VisibilityHelp
|
37
38
|
include DefNode
|
39
|
+
include RangeHelp
|
38
40
|
|
39
41
|
MSG = 'Action `%<current>s` should appear before `%<previous>s`.'
|
40
42
|
|
@@ -71,9 +73,43 @@ module RuboCop
|
|
71
73
|
current: current.method_name
|
72
74
|
)
|
73
75
|
add_offense(current, message: message) do |corrector|
|
74
|
-
|
75
|
-
|
76
|
+
current = correction_target(current)
|
77
|
+
previous = correction_target(previous)
|
78
|
+
|
79
|
+
swap_range(corrector, current, previous)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def correction_target(def_node)
|
84
|
+
range_with_comments_and_lines(def_node.each_ancestor(:if).first || def_node)
|
85
|
+
end
|
86
|
+
|
87
|
+
def add_range(range1, range2)
|
88
|
+
range1.with(
|
89
|
+
begin_pos: [range1.begin_pos, range2.begin_pos].min,
|
90
|
+
end_pos: [range1.end_pos, range2.end_pos].max
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
def range_with_comments(node)
|
95
|
+
ranges = [
|
96
|
+
node,
|
97
|
+
*processed_source.ast_with_comments[node]
|
98
|
+
].map do |element|
|
99
|
+
element.location.expression
|
76
100
|
end
|
101
|
+
ranges.reduce do |result, range|
|
102
|
+
add_range(result, range)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def range_with_comments_and_lines(node)
|
107
|
+
range_by_whole_lines(range_with_comments(node), include_final_newline: true)
|
108
|
+
end
|
109
|
+
|
110
|
+
def swap_range(corrector, range1, range2)
|
111
|
+
corrector.insert_before(range2, range1.source)
|
112
|
+
corrector.remove(range1)
|
77
113
|
end
|
78
114
|
end
|
79
115
|
end
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
25
25
|
|
26
26
|
MSG = 'Controllers should subclass `ApplicationController`.'
|
27
27
|
SUPERCLASS = 'ApplicationController'
|
28
|
-
BASE_PATTERN = '(const (const nil? :ActionController) :Base)'
|
28
|
+
BASE_PATTERN = '(const (const {nil? cbase} :ActionController) :Base)'
|
29
29
|
|
30
30
|
# rubocop:disable Layout/ClassStructure
|
31
31
|
include RuboCop::Cop::EnforceSuperclass
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
28
28
|
|
29
29
|
MSG = 'Jobs should subclass `ApplicationJob`.'
|
30
30
|
SUPERCLASS = 'ApplicationJob'
|
31
|
-
BASE_PATTERN = '(const (const nil? :ActiveJob) :Base)'
|
31
|
+
BASE_PATTERN = '(const (const {nil? cbase} :ActiveJob) :Base)'
|
32
32
|
|
33
33
|
# rubocop:disable Layout/ClassStructure
|
34
34
|
include RuboCop::Cop::EnforceSuperclass
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
28
28
|
|
29
29
|
MSG = 'Mailers should subclass `ApplicationMailer`.'
|
30
30
|
SUPERCLASS = 'ApplicationMailer'
|
31
|
-
BASE_PATTERN = '(const (const nil? :ActionMailer) :Base)'
|
31
|
+
BASE_PATTERN = '(const (const {nil? cbase} :ActionMailer) :Base)'
|
32
32
|
|
33
33
|
# rubocop:disable Layout/ClassStructure
|
34
34
|
include RuboCop::Cop::EnforceSuperclass
|
@@ -29,7 +29,7 @@ module RuboCop
|
|
29
29
|
|
30
30
|
MSG = 'Models should subclass `ApplicationRecord`.'
|
31
31
|
SUPERCLASS = 'ApplicationRecord'
|
32
|
-
BASE_PATTERN = '(const (const nil? :ActiveRecord) :Base)'
|
32
|
+
BASE_PATTERN = '(const (const {nil? cbase} :ActiveRecord) :Base)'
|
33
33
|
|
34
34
|
# rubocop:disable Layout/ClassStructure
|
35
35
|
include RuboCop::Cop::EnforceSuperclass
|
@@ -81,7 +81,7 @@ module RuboCop
|
|
81
81
|
def allowed_name?(argument)
|
82
82
|
return false unless argument.str_type? || argument.sym_type?
|
83
83
|
|
84
|
-
!/^[a-zA-Z
|
84
|
+
!/^[a-zA-Z-][a-zA-Z\-0-9]*$/.match?(argument.value)
|
85
85
|
end
|
86
86
|
|
87
87
|
def correction_range(node)
|
@@ -24,7 +24,7 @@ module RuboCop
|
|
24
24
|
TRANSLATE_METHODS = %i[translate t].freeze
|
25
25
|
|
26
26
|
def_node_matcher :translate_with_scope?, <<~PATTERN
|
27
|
-
(send {nil? (const nil? :I18n)} {:translate :t} ${sym_type? str_type?}
|
27
|
+
(send {nil? (const {nil? cbase} :I18n)} {:translate :t} ${sym_type? str_type?}
|
28
28
|
(hash <$(pair (sym :scope) ${array_type? sym_type?}) ...>)
|
29
29
|
)
|
30
30
|
PATTERN
|
@@ -70,8 +70,8 @@ module RuboCop
|
|
70
70
|
# @return [Boolean] true if matches
|
71
71
|
def_node_matcher :time_current?, <<~PATTERN
|
72
72
|
{
|
73
|
-
(send (const
|
74
|
-
(send (send (const
|
73
|
+
(send (const {nil? cbase} :Time) :current)
|
74
|
+
(send (send (const {nil? cbase} :Time) :zone) :now)
|
75
75
|
}
|
76
76
|
PATTERN
|
77
77
|
|
@@ -53,7 +53,7 @@ module RuboCop
|
|
53
53
|
method_name = node.method_name
|
54
54
|
static_name = static_method_name(method_name)
|
55
55
|
return unless static_name
|
56
|
-
return
|
56
|
+
return unless dynamic_find_by_arguments?(node)
|
57
57
|
|
58
58
|
message = format(MSG, static_name: static_name, method: method_name)
|
59
59
|
add_offense(node, message: message) do |corrector|
|
@@ -65,12 +65,8 @@ module RuboCop
|
|
65
65
|
private
|
66
66
|
|
67
67
|
def autocorrect(corrector, node)
|
68
|
-
keywords = column_keywords(node.method_name)
|
69
|
-
|
70
|
-
return if keywords.size != node.arguments.size
|
71
|
-
|
72
68
|
autocorrect_method_name(corrector, node)
|
73
|
-
autocorrect_argument_keywords(corrector, node,
|
69
|
+
autocorrect_argument_keywords(corrector, node, column_keywords(node.method_name))
|
74
70
|
end
|
75
71
|
|
76
72
|
def allowed_invocation?(node)
|
@@ -120,6 +116,20 @@ module RuboCop
|
|
120
116
|
|
121
117
|
match[2] ? 'find_by!' : 'find_by'
|
122
118
|
end
|
119
|
+
|
120
|
+
def dynamic_find_by_arguments?(node)
|
121
|
+
dynamic_find_by_arguments_count?(node) && dynamic_find_by_arguments_type?(node)
|
122
|
+
end
|
123
|
+
|
124
|
+
def dynamic_find_by_arguments_count?(node)
|
125
|
+
column_keywords(node.method_name).size == node.arguments.size
|
126
|
+
end
|
127
|
+
|
128
|
+
def dynamic_find_by_arguments_type?(node)
|
129
|
+
node.arguments.none? do |argument|
|
130
|
+
IGNORED_ARGUMENT_TYPES.include?(argument.type)
|
131
|
+
end
|
132
|
+
end
|
123
133
|
end
|
124
134
|
end
|
125
135
|
end
|
@@ -34,15 +34,15 @@ module RuboCop
|
|
34
34
|
RESTRICT_ON_SEND = %i[join].freeze
|
35
35
|
|
36
36
|
def_node_matcher :file_join_nodes?, <<~PATTERN
|
37
|
-
(send (const nil? :File) :join ...)
|
37
|
+
(send (const {nil? cbase} :File) :join ...)
|
38
38
|
PATTERN
|
39
39
|
|
40
40
|
def_node_search :rails_root_nodes?, <<~PATTERN
|
41
|
-
(send (const nil? :Rails) :root)
|
41
|
+
(send (const {nil? cbase} :Rails) :root)
|
42
42
|
PATTERN
|
43
43
|
|
44
44
|
def_node_matcher :rails_root_join_nodes?, <<~PATTERN
|
45
|
-
(send
|
45
|
+
(send #rails_root_nodes? :join ...)
|
46
46
|
PATTERN
|
47
47
|
|
48
48
|
def on_dstr(node)
|
@@ -29,17 +29,17 @@ module RuboCop
|
|
29
29
|
|
30
30
|
MSG = 'Use `freeze_time` instead of `travel_to`.'
|
31
31
|
NOW_METHODS = %i[now new current].freeze
|
32
|
-
|
32
|
+
CONVERT_METHODS = %i[to_time in_time_zone].freeze
|
33
33
|
RESTRICT_ON_SEND = %i[travel_to].freeze
|
34
34
|
|
35
35
|
# @!method time_now?(node)
|
36
36
|
def_node_matcher :time_now?, <<~PATTERN
|
37
|
-
(const nil? {:Time :DateTime})
|
37
|
+
(const {nil? cbase} {:Time :DateTime})
|
38
38
|
PATTERN
|
39
39
|
|
40
40
|
# @!method zoned_time_now?(node)
|
41
41
|
def_node_matcher :zoned_time_now?, <<~PATTERN
|
42
|
-
(send (const nil? :Time) :zone)
|
42
|
+
(send (const {nil? cbase} :Time) :zone)
|
43
43
|
PATTERN
|
44
44
|
|
45
45
|
def on_send(node)
|
@@ -63,9 +63,11 @@ module RuboCop
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def current_time_with_convert?(node, method_name)
|
66
|
-
return false unless
|
66
|
+
return false unless CONVERT_METHODS.include?(method_name)
|
67
|
+
|
68
|
+
child_node, child_method_name, time_argument = *node.children
|
69
|
+
return if time_argument
|
67
70
|
|
68
|
-
child_node, child_method_name = *node.children
|
69
71
|
current_time?(child_node, child_method_name)
|
70
72
|
end
|
71
73
|
end
|
@@ -37,7 +37,7 @@ module RuboCop
|
|
37
37
|
RESTRICT_ON_SEND = %i[has_many has_one].freeze
|
38
38
|
|
39
39
|
def_node_search :active_resource_class?, <<~PATTERN
|
40
|
-
(const (const nil? :ActiveResource) :Base)
|
40
|
+
(const (const {nil? cbase} :ActiveResource) :Base)
|
41
41
|
PATTERN
|
42
42
|
|
43
43
|
def_node_matcher :association_without_options?, <<~PATTERN
|
@@ -12,7 +12,6 @@ module RuboCop
|
|
12
12
|
# render plain: 'foo/bar', status: 304
|
13
13
|
# redirect_to root_url, status: 301
|
14
14
|
# head 200
|
15
|
-
# get '/foobar', to: redirect('/foobar/baz', status: 301)
|
16
15
|
#
|
17
16
|
# # good
|
18
17
|
# render :foo, status: :ok
|
@@ -20,7 +19,6 @@ module RuboCop
|
|
20
19
|
# render plain: 'foo/bar', status: :not_modified
|
21
20
|
# redirect_to root_url, status: :moved_permanently
|
22
21
|
# head :ok
|
23
|
-
# get '/foobar', to: redirect('/foobar/baz', status: :moved_permanently)
|
24
22
|
#
|
25
23
|
# @example EnforcedStyle: numeric
|
26
24
|
# # bad
|
@@ -29,7 +27,6 @@ module RuboCop
|
|
29
27
|
# render plain: 'foo/bar', status: :not_modified
|
30
28
|
# redirect_to root_url, status: :moved_permanently
|
31
29
|
# head :ok
|
32
|
-
# get '/foobar', to: redirect('/foobar/baz', status: :moved_permanently)
|
33
30
|
#
|
34
31
|
# # good
|
35
32
|
# render :foo, status: 200
|
@@ -37,20 +34,18 @@ module RuboCop
|
|
37
34
|
# render plain: 'foo/bar', status: 304
|
38
35
|
# redirect_to root_url, status: 301
|
39
36
|
# head 200
|
40
|
-
# get '/foobar', to: redirect('/foobar/baz', status: 301)
|
41
37
|
#
|
42
38
|
class HttpStatus < Base
|
43
39
|
include ConfigurableEnforcedStyle
|
44
40
|
extend AutoCorrector
|
45
41
|
|
46
|
-
RESTRICT_ON_SEND = %i[render redirect_to head
|
42
|
+
RESTRICT_ON_SEND = %i[render redirect_to head].freeze
|
47
43
|
|
48
44
|
def_node_matcher :http_status, <<~PATTERN
|
49
45
|
{
|
50
46
|
(send nil? {:render :redirect_to} _ $hash)
|
51
47
|
(send nil? {:render :redirect_to} $hash)
|
52
48
|
(send nil? :head ${int sym} ...)
|
53
|
-
(send nil? :redirect _ $hash)
|
54
49
|
}
|
55
50
|
PATTERN
|
56
51
|
|
@@ -69,7 +69,7 @@ module RuboCop
|
|
69
69
|
class I18nLocaleTexts < Base
|
70
70
|
MSG = 'Move locale texts to the locale files in the `config/locales` directory.'
|
71
71
|
|
72
|
-
RESTRICT_ON_SEND = %i[validates redirect_to []= mail].freeze
|
72
|
+
RESTRICT_ON_SEND = %i[validates redirect_to redirect_back []= mail].freeze
|
73
73
|
|
74
74
|
def_node_search :validation_message, <<~PATTERN
|
75
75
|
(pair (sym :message) $str)
|
@@ -94,7 +94,7 @@ module RuboCop
|
|
94
94
|
add_offense(text_node)
|
95
95
|
end
|
96
96
|
return
|
97
|
-
when :redirect_to
|
97
|
+
when :redirect_to, :redirect_back
|
98
98
|
text_node = redirect_to_flash(node).to_a.last
|
99
99
|
when :[]=
|
100
100
|
text_node = flash_assignment?(node)
|
@@ -34,8 +34,8 @@ module RuboCop
|
|
34
34
|
|
35
35
|
def_node_matcher :mailer_base_class?, <<~PATTERN
|
36
36
|
{
|
37
|
-
(const (const nil? :ActionMailer) :Base)
|
38
|
-
(const nil? :ApplicationMailer)
|
37
|
+
(const (const {nil? cbase} :ActionMailer) :Base)
|
38
|
+
(const {nil? cbase} :ApplicationMailer)
|
39
39
|
}
|
40
40
|
PATTERN
|
41
41
|
|
@@ -44,7 +44,7 @@ module RuboCop
|
|
44
44
|
PATTERN
|
45
45
|
|
46
46
|
def_node_matcher :class_new_definition?, <<~PATTERN
|
47
|
-
(send (const nil? :Class) :new #mailer_base_class?)
|
47
|
+
(send (const {nil? cbase} :Class) :new #mailer_base_class?)
|
48
48
|
PATTERN
|
49
49
|
|
50
50
|
def on_class(node)
|
@@ -29,7 +29,7 @@ module RuboCop
|
|
29
29
|
|
30
30
|
basename = basename_without_timestamp_and_suffix(processed_source.file_path)
|
31
31
|
|
32
|
-
class_identifier = node.identifier
|
32
|
+
class_identifier = node.identifier.location.name
|
33
33
|
camelized_basename = camelize(basename)
|
34
34
|
return if class_identifier.source.casecmp(camelized_basename).zero?
|
35
35
|
|
@@ -26,34 +26,53 @@ module RuboCop
|
|
26
26
|
minimum_target_rails_version 5.0
|
27
27
|
|
28
28
|
def_node_matcher :pluck_candidate?, <<~PATTERN
|
29
|
-
({block numblock} (send _ {:map :collect}) $_argument (send
|
29
|
+
({block numblock} (send _ {:map :collect}) $_argument (send lvar :[] $_key))
|
30
30
|
PATTERN
|
31
31
|
|
32
32
|
def on_block(node)
|
33
|
-
pluck_candidate?(node) do |argument,
|
33
|
+
pluck_candidate?(node) do |argument, key|
|
34
|
+
next unless use_one_block_argument?(argument)
|
35
|
+
|
34
36
|
match = if node.block_type?
|
35
|
-
argument.children.first.source
|
37
|
+
block_argument = argument.children.first.source
|
38
|
+
use_block_argument_in_key?(block_argument, key)
|
36
39
|
else # numblock
|
37
|
-
argument == 1 &&
|
40
|
+
argument == 1 && use_block_argument_in_key?('_1', key)
|
38
41
|
end
|
39
42
|
next unless match
|
40
43
|
|
41
|
-
|
42
|
-
message = message(replacement, node)
|
43
|
-
|
44
|
-
add_offense(offense_range(node), message: message) do |corrector|
|
45
|
-
corrector.replace(offense_range(node), replacement)
|
46
|
-
end
|
44
|
+
register_offense(node, key)
|
47
45
|
end
|
48
46
|
end
|
49
47
|
alias on_numblock on_block
|
50
48
|
|
51
49
|
private
|
52
50
|
|
51
|
+
def use_one_block_argument?(argument)
|
52
|
+
return true if argument == 1 # Checks for numbered argument `_1`.
|
53
|
+
|
54
|
+
argument.respond_to?(:one?) && argument.one?
|
55
|
+
end
|
56
|
+
|
57
|
+
def use_block_argument_in_key?(block_argument, key)
|
58
|
+
return false if block_argument == key.source
|
59
|
+
|
60
|
+
key.each_descendant(:lvar).none? { |lvar| block_argument == lvar.source }
|
61
|
+
end
|
62
|
+
|
53
63
|
def offense_range(node)
|
54
64
|
node.send_node.loc.selector.join(node.loc.end)
|
55
65
|
end
|
56
66
|
|
67
|
+
def register_offense(node, key)
|
68
|
+
replacement = "pluck(#{key.source})"
|
69
|
+
message = message(replacement, node)
|
70
|
+
|
71
|
+
add_offense(offense_range(node), message: message) do |corrector|
|
72
|
+
corrector.replace(offense_range(node), replacement)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
57
76
|
def message(replacement, node)
|
58
77
|
current = offense_range(node).source
|
59
78
|
|
@@ -26,7 +26,7 @@ module RuboCop
|
|
26
26
|
RESTRICT_ON_SEND = %i[require_dependency].freeze
|
27
27
|
|
28
28
|
def_node_matcher :require_dependency_call?, <<~PATTERN
|
29
|
-
(send {nil? (const
|
29
|
+
(send {nil? (const {nil? cbase} :Kernel)} :require_dependency _)
|
30
30
|
PATTERN
|
31
31
|
|
32
32
|
def on_send(node)
|
@@ -163,12 +163,11 @@ module RuboCop
|
|
163
163
|
def on_send(node)
|
164
164
|
evidence(node) do |method, path, args, rails_root|
|
165
165
|
add_offense(node, message: format(MSG, method: method, rails_root: rails_root.source)) do |corrector|
|
166
|
-
if dir_glob?(node)
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
end
|
166
|
+
replacement = if dir_glob?(node)
|
167
|
+
build_path_glob_replacement(path, method)
|
168
|
+
else
|
169
|
+
build_path_replacement(path, method, args)
|
170
|
+
end
|
172
171
|
|
173
172
|
corrector.replace(node, replacement)
|
174
173
|
end
|
@@ -184,18 +183,26 @@ module RuboCop
|
|
184
183
|
yield(method, path, args, rails_root)
|
185
184
|
end
|
186
185
|
|
187
|
-
def
|
186
|
+
def build_path_glob_replacement(path, method)
|
188
187
|
receiver = range_between(path.loc.expression.begin_pos, path.children.first.loc.selector.end_pos).source
|
189
188
|
|
190
|
-
argument =
|
191
|
-
path.first_argument.source
|
192
|
-
else
|
193
|
-
join_arguments(path.arguments)
|
194
|
-
end
|
189
|
+
argument = path.arguments.one? ? path.first_argument.source : join_arguments(path.arguments)
|
195
190
|
|
196
191
|
"#{receiver}.#{method}(#{argument})"
|
197
192
|
end
|
198
193
|
|
194
|
+
def build_path_replacement(path, method, args)
|
195
|
+
path_replacement = path.source
|
196
|
+
if path.arguments? && !path.parenthesized_call?
|
197
|
+
path_replacement[' '] = '('
|
198
|
+
path_replacement << ')'
|
199
|
+
end
|
200
|
+
|
201
|
+
replacement = "#{path_replacement}.#{method}"
|
202
|
+
replacement += "(#{args.map(&:source).join(', ')})" unless args.empty?
|
203
|
+
replacement
|
204
|
+
end
|
205
|
+
|
199
206
|
def include_interpolation?(arguments)
|
200
207
|
arguments.any? do |argument|
|
201
208
|
argument.children.any? { |child| child.respond_to?(:begin_type?) && child.begin_type? }
|
@@ -203,11 +210,28 @@ module RuboCop
|
|
203
210
|
end
|
204
211
|
|
205
212
|
def join_arguments(arguments)
|
206
|
-
|
207
|
-
|
213
|
+
use_interpolation = false
|
214
|
+
|
215
|
+
joined_arguments = arguments.map do |arg|
|
216
|
+
if arg.respond_to?(:value)
|
217
|
+
arg.value
|
218
|
+
else
|
219
|
+
use_interpolation = true
|
220
|
+
"\#{#{arg.source}}"
|
221
|
+
end
|
222
|
+
end.join('/')
|
223
|
+
quote = enforce_double_quotes? || include_interpolation?(arguments) || use_interpolation ? '"' : "'"
|
208
224
|
|
209
225
|
"#{quote}#{joined_arguments}#{quote}"
|
210
226
|
end
|
227
|
+
|
228
|
+
def enforce_double_quotes?
|
229
|
+
string_literals_config['EnforcedStyle'] == 'double_quotes'
|
230
|
+
end
|
231
|
+
|
232
|
+
def string_literals_config
|
233
|
+
config.for_cop('Style/StringLiterals')
|
234
|
+
end
|
211
235
|
end
|
212
236
|
end
|
213
237
|
end
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
49
49
|
RESTRICT_ON_SEND = PREFERRED_METHODS.keys.freeze
|
50
50
|
|
51
51
|
def_node_matcher :long_i18n?, <<~PATTERN
|
52
|
-
(send {nil? (const nil? :I18n)} ${:translate :localize} ...)
|
52
|
+
(send {nil? (const {nil? cbase} :I18n)} ${:translate :localize} ...)
|
53
53
|
PATTERN
|
54
54
|
|
55
55
|
def on_send(node)
|
@@ -228,12 +228,25 @@ module RuboCop
|
|
228
228
|
acceptable
|
229
229
|
end
|
230
230
|
|
231
|
-
# Time.new can be called with a time zone offset
|
231
|
+
# Time.new, Time.at, and Time.now can be called with a time zone offset
|
232
232
|
# When it is, that should be considered safe
|
233
233
|
# Example:
|
234
234
|
# Time.new(1988, 3, 15, 3, 0, 0, "-05:00")
|
235
235
|
def offset_provided?(node)
|
236
|
-
node.
|
236
|
+
case node.method_name
|
237
|
+
when :new
|
238
|
+
node.arguments.size == 7 || offset_option_provided?(node)
|
239
|
+
when :at, :now
|
240
|
+
offset_option_provided?(node)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def offset_option_provided?(node)
|
245
|
+
options = node.last_argument
|
246
|
+
options&.hash_type? &&
|
247
|
+
options.each_pair.any? do |pair|
|
248
|
+
pair.key.sym_type? && pair.key.value == :in && !pair.value.nil_type?
|
249
|
+
end
|
237
250
|
end
|
238
251
|
end
|
239
252
|
end
|
@@ -21,6 +21,37 @@ module RuboCop
|
|
21
21
|
extend AutoCorrector
|
22
22
|
extend TargetRailsVersion
|
23
23
|
|
24
|
+
# These types are defined by the following files in ActiveSupport:
|
25
|
+
# lib/active_support/core_ext/array/conversions.rb
|
26
|
+
# lib/active_support/core_ext/date/conversions.rb
|
27
|
+
# lib/active_support/core_ext/date_time/conversions.rb
|
28
|
+
# lib/active_support/core_ext/numeric/conversions.rb
|
29
|
+
# lib/active_support/core_ext/range/conversions.rb
|
30
|
+
# lib/active_support/core_ext/time/conversions.rb
|
31
|
+
# lib/active_support/time_with_zone.rb
|
32
|
+
EXTENDED_FORMAT_TYPES = Set.new(
|
33
|
+
%i[
|
34
|
+
currency
|
35
|
+
db
|
36
|
+
delimited
|
37
|
+
human
|
38
|
+
human_size
|
39
|
+
inspect
|
40
|
+
iso8601
|
41
|
+
long
|
42
|
+
long_ordinal
|
43
|
+
nsec
|
44
|
+
number
|
45
|
+
percentage
|
46
|
+
phone
|
47
|
+
rfc822
|
48
|
+
rounded
|
49
|
+
short
|
50
|
+
time
|
51
|
+
usec
|
52
|
+
]
|
53
|
+
)
|
54
|
+
|
24
55
|
MSG = 'Use `to_formatted_s` instead.'
|
25
56
|
|
26
57
|
RESTRICT_ON_SEND = %i[to_s].freeze
|
@@ -28,13 +59,19 @@ module RuboCop
|
|
28
59
|
minimum_target_rails_version 7.0
|
29
60
|
|
30
61
|
def on_send(node)
|
31
|
-
return
|
62
|
+
return unless rails_extended_to_s?(node)
|
32
63
|
|
33
64
|
add_offense(node.loc.selector) do |corrector|
|
34
65
|
corrector.replace(node.loc.selector, 'to_formatted_s')
|
35
66
|
end
|
36
67
|
end
|
37
68
|
alias on_csend on_send
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def rails_extended_to_s?(node)
|
73
|
+
node.first_argument&.sym_type? && EXTENDED_FORMAT_TYPES.include?(node.first_argument.value)
|
74
|
+
end
|
38
75
|
end
|
39
76
|
end
|
40
77
|
end
|
@@ -139,11 +139,20 @@ module RuboCop
|
|
139
139
|
pairs = node.arguments.last
|
140
140
|
return unless pairs.hash_type?
|
141
141
|
|
142
|
+
return true if condition_hash_part?(pairs, keys: %i[if unless])
|
143
|
+
|
144
|
+
uniqueness_node = uniqueness_part(node)
|
145
|
+
return unless uniqueness_node&.hash_type?
|
146
|
+
|
147
|
+
condition_hash_part?(uniqueness_node, keys: %i[if unless conditions])
|
148
|
+
end
|
149
|
+
|
150
|
+
def condition_hash_part?(pairs, keys:)
|
142
151
|
pairs.each_pair.any? do |pair|
|
143
152
|
key = pair.key
|
144
153
|
next unless key.sym_type?
|
145
154
|
|
146
|
-
|
155
|
+
keys.include?(key.value)
|
147
156
|
end
|
148
157
|
end
|
149
158
|
|
@@ -38,7 +38,9 @@ module RuboCop
|
|
38
38
|
def on_send(node)
|
39
39
|
return unless node.first_argument.sym_type?
|
40
40
|
|
41
|
-
|
41
|
+
root_receiver = root_receiver(node)
|
42
|
+
where_node_and_argument(root_receiver) do |where_node, where_argument|
|
43
|
+
next unless root_receiver == root_receiver(where_node)
|
42
44
|
next unless same_relationship?(where_argument, node.first_argument)
|
43
45
|
|
44
46
|
range = range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
|
@@ -50,7 +52,12 @@ module RuboCop
|
|
50
52
|
private
|
51
53
|
|
52
54
|
def root_receiver(node)
|
53
|
-
|
55
|
+
parent = node.parent
|
56
|
+
if !parent&.send_type? || parent.method?(:or) || parent.method?(:and)
|
57
|
+
node
|
58
|
+
else
|
59
|
+
root_receiver(parent)
|
60
|
+
end
|
54
61
|
end
|
55
62
|
|
56
63
|
def same_relationship?(where, left_joins)
|
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.17.
|
4
|
+
version: 2.17.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-12-25 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -235,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
235
235
|
- !ruby/object:Gem::Version
|
236
236
|
version: '0'
|
237
237
|
requirements: []
|
238
|
-
rubygems_version: 3.
|
238
|
+
rubygems_version: 3.3.26
|
239
239
|
signing_key:
|
240
240
|
specification_version: 4
|
241
241
|
summary: Automatic Rails code style checking tool.
|