sevencop 0.31.0 → 0.32.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/Gemfile.lock +1 -1
- data/README.md +1 -0
- data/config/default.yml +8 -2
- data/lib/rubocop/cop/sevencop/constant_base.rb +25 -12
- data/lib/rubocop/cop/sevencop/factory_bot_association_option.rb +2 -2
- data/lib/rubocop/cop/sevencop/rails_order_field_in_order_of.rb +316 -0
- data/lib/sevencop/version.rb +1 -1
- data/lib/sevencop.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b73ab476e9b75a7c542283153fb21a6e34bc065305f174ad7fc360d8d4fe83ab
|
4
|
+
data.tar.gz: 36704b1877d0042042c91112699c201566a60bfc84e9bea4eb00824f910d6516
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6d0f76043cf888387a230e1de66233a0ba68be0b647883bd8dac259f7cd7c97b504a3ce24577a14fd15fc590f146e17ff605223e2616e6c13992ec4e9a855d0
|
7
|
+
data.tar.gz: ac8f462e97a095a80c612318d9eb69373c0b3c9ce11a3fc49c8143ba92d40adcdfc2279b6ad0edb0eaf07a6c12ac500a8090b12969feee0529ec91c981a1a72f
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -40,6 +40,7 @@ Note that all cops are `Enabled: false` by default.
|
|
40
40
|
- [Sevencop/RailsBelongsToOptional](lib/rubocop/cop/sevencop/rails_belongs_to_optional.rb)
|
41
41
|
- [Sevencop/RailsDateAndTimeCalculation](lib/rubocop/cop/sevencop/rails_date_and_time_calculation.rb)
|
42
42
|
- [Sevencop/RailsOrderField](lib/rubocop/cop/sevencop/rails_order_field.rb)
|
43
|
+
- [Sevencop/RailsOrderFieldInOrderOf](lib/rubocop/cop/sevencop/rails_order_field_in_order_of.rb)
|
43
44
|
- [Sevencop/RailsSpecificActionName](lib/rubocop/cop/sevencop/rails_specific_action_name.rb)
|
44
45
|
- [Sevencop/RailsUniquenessValidatorExplicitCaseSensitivity](lib/rubocop/cop/sevencop/rails_uniqueness_validator_explicit_case_sensitivity.rb)
|
45
46
|
- [Sevencop/RailsWhereNot](lib/rubocop/cop/sevencop/rails_where_not.rb)
|
data/config/default.yml
CHANGED
@@ -7,13 +7,13 @@ Sevencop/AutoloadOrdered:
|
|
7
7
|
|
8
8
|
Sevencop/ConstantBase:
|
9
9
|
Description: |
|
10
|
-
|
10
|
+
Avoid unnecessary `::` prefix on constant.
|
11
11
|
Enabled: false
|
12
12
|
VersionAdded: '0.31'
|
13
13
|
|
14
14
|
Sevencop/FactoryBotAssociationOption:
|
15
15
|
Description: |
|
16
|
-
|
16
|
+
Avoid redundant options on FactoryBot associations.
|
17
17
|
Enabled: false
|
18
18
|
VersionAdded: '0.21'
|
19
19
|
|
@@ -95,6 +95,12 @@ Sevencop/RailsOrderField:
|
|
95
95
|
Safe: false
|
96
96
|
VersionAdded: '0.4'
|
97
97
|
|
98
|
+
Sevencop/RailsOrderFieldInOrderOf:
|
99
|
+
Description: |
|
100
|
+
Prefer `in_order_of` to MySQL `FIELD` function.
|
101
|
+
Enabled: false
|
102
|
+
VersionAdded: '0.32'
|
103
|
+
|
98
104
|
Sevencop/RailsSpecificActionName:
|
99
105
|
Description: |
|
100
106
|
Use only specific action names.
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Sevencop
|
6
|
-
#
|
6
|
+
# Avoid unnecessary `::` prefix on constant.
|
7
7
|
#
|
8
8
|
# @example
|
9
9
|
# # bad
|
@@ -23,18 +23,18 @@ module RuboCop
|
|
23
23
|
# end
|
24
24
|
#
|
25
25
|
# # good
|
26
|
-
# class
|
26
|
+
# class A
|
27
27
|
# ::Const
|
28
28
|
# end
|
29
29
|
#
|
30
30
|
# # good
|
31
|
-
# class
|
31
|
+
# class A
|
32
32
|
# ::Const
|
33
33
|
# end
|
34
34
|
class ConstantBase < Base
|
35
35
|
extend AutoCorrector
|
36
36
|
|
37
|
-
MSG = '
|
37
|
+
MSG = 'Avoid unnecessary `::` prefix on constant.'
|
38
38
|
|
39
39
|
# @param node [RuboCop::AST::CbaseNode]
|
40
40
|
# @return [void]
|
@@ -48,17 +48,30 @@ module RuboCop
|
|
48
48
|
|
49
49
|
private
|
50
50
|
|
51
|
-
# @!method named_class_or_module?(node)
|
52
|
-
# @param node [RuboCop::AST::Node]
|
53
|
-
# @return [Boolean]
|
54
|
-
def_node_matcher :named_class_or_module?, <<~PATTERN
|
55
|
-
({class module} const ...)
|
56
|
-
PATTERN
|
57
|
-
|
58
51
|
# @param node [RuboCop::AST::CbaseNode]
|
59
52
|
# @return [Boolean]
|
60
53
|
def bad?(node)
|
61
|
-
node
|
54
|
+
module_nesting_ancestors_of(node).none?
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param node [RuboCop::AST::Node]
|
58
|
+
# @return [Enumerable<RuboCop::AST::Node>]
|
59
|
+
def module_nesting_ancestors_of(node)
|
60
|
+
node.each_ancestor(:class, :module).reject do |ancestor|
|
61
|
+
ancestor.class_type? && used_in_super_class_part?(node, class_node: ancestor)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# @param class_node [RuboCop::AST::Node]
|
66
|
+
# @param node [RuboCop::AST::CbaseNode]
|
67
|
+
# @return [Boolean]
|
68
|
+
def used_in_super_class_part?(
|
69
|
+
node,
|
70
|
+
class_node:
|
71
|
+
)
|
72
|
+
class_node.parent_class&.each_descendant(:cbase)&.any? do |descendant|
|
73
|
+
descendant.eql?(node)
|
74
|
+
end
|
62
75
|
end
|
63
76
|
end
|
64
77
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Sevencop
|
6
|
-
#
|
6
|
+
# Avoid redundant options on FactoryBot associations.
|
7
7
|
#
|
8
8
|
# @example
|
9
9
|
# # bad
|
@@ -16,7 +16,7 @@ module RuboCop
|
|
16
16
|
|
17
17
|
include RangeHelp
|
18
18
|
|
19
|
-
MSG = '
|
19
|
+
MSG = 'Avoid redundant options on FactoryBot associations.'
|
20
20
|
|
21
21
|
RESTRICT_ON_SEND = %i[association].freeze
|
22
22
|
|
@@ -0,0 +1,316 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Sevencop
|
6
|
+
# Prefer `in_order_of` to MySQL `FIELD` function.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# order('FIELD(id, 1, 2, 3)')
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# in_order_of(:id, [1, 2, 3])
|
14
|
+
#
|
15
|
+
# # bad
|
16
|
+
# order(Arel.sql('FIELD(id, 1, 2, 3)'))
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# in_order_of(:id, [1, 2, 3])
|
20
|
+
#
|
21
|
+
# # bad
|
22
|
+
# order('FIELD(id, 1, 2, 3) DESC')
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# in_order_of(:id, [1, 2, 3]).reverse_order
|
26
|
+
#
|
27
|
+
# # bad
|
28
|
+
# order("FIELD(id, #{ids.join(', ')})")
|
29
|
+
#
|
30
|
+
# # good
|
31
|
+
# in_order_of(:id, ids)
|
32
|
+
class RailsOrderFieldInOrderOf < Base
|
33
|
+
extend AutoCorrector
|
34
|
+
|
35
|
+
REGEXP_FIELD_DSTR_HEAD = /
|
36
|
+
\A
|
37
|
+
\s*
|
38
|
+
field\(
|
39
|
+
\s*
|
40
|
+
(?<column_name>\w+)
|
41
|
+
,\s*
|
42
|
+
\z
|
43
|
+
/ix.freeze
|
44
|
+
|
45
|
+
REGEXP_FIELD_DSTR_TAIL = /
|
46
|
+
\A
|
47
|
+
\s*
|
48
|
+
\)
|
49
|
+
\s*
|
50
|
+
(?:
|
51
|
+
\s+
|
52
|
+
(?<order>asc|desc)
|
53
|
+
)?
|
54
|
+
\z
|
55
|
+
/ix.freeze
|
56
|
+
|
57
|
+
REGEXP_FIELD_STR = /
|
58
|
+
\A
|
59
|
+
\s*
|
60
|
+
field\(
|
61
|
+
\s*
|
62
|
+
(?<column_name>\w+)
|
63
|
+
,\s*
|
64
|
+
(?<values>.+)
|
65
|
+
\s*
|
66
|
+
\)
|
67
|
+
(?:
|
68
|
+
\s+
|
69
|
+
(?<order>asc|desc)
|
70
|
+
)?
|
71
|
+
\s*
|
72
|
+
\z
|
73
|
+
/ix.freeze
|
74
|
+
|
75
|
+
MSG = 'Prefer `in_order_of` to MySQL `FIELD` function.'
|
76
|
+
|
77
|
+
RESTRICT_ON_SEND = %i[
|
78
|
+
order
|
79
|
+
reorder
|
80
|
+
].freeze
|
81
|
+
|
82
|
+
# @param node [RuboCop::AST::SendNode]
|
83
|
+
# @return [void]
|
84
|
+
def on_send(node)
|
85
|
+
return unless bad?(node)
|
86
|
+
|
87
|
+
add_offense(node) do |corrector|
|
88
|
+
autocorrect(corrector, node)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
# @!method match_arel_sql_field?(node)
|
95
|
+
# @param node [RuboCop::AST::Node, nil]
|
96
|
+
# @return [Boolean]
|
97
|
+
def_node_matcher :match_arel_sql_field?, <<~PATTERN
|
98
|
+
(send
|
99
|
+
(const {nil? cbase} :Arel)
|
100
|
+
:sql
|
101
|
+
#match_field?
|
102
|
+
)
|
103
|
+
PATTERN
|
104
|
+
|
105
|
+
# @!method match_field?(node)
|
106
|
+
# @param node [RuboCop::AST::Node, nil]
|
107
|
+
# @return [Boolean]
|
108
|
+
def_node_matcher :match_field?, <<~PATTERN
|
109
|
+
{
|
110
|
+
#match_field_dstr?
|
111
|
+
#match_field_str?
|
112
|
+
}
|
113
|
+
PATTERN
|
114
|
+
|
115
|
+
# @!method match_field_dstr_body?(node)
|
116
|
+
# @param node [RuboCop::AST::Node, nil]
|
117
|
+
# @return [Boolean]
|
118
|
+
def_node_matcher :match_field_dstr_body?, <<~PATTERN
|
119
|
+
(begin
|
120
|
+
(send
|
121
|
+
_
|
122
|
+
:join
|
123
|
+
(str #match_field_dstr_body_separator?)
|
124
|
+
)
|
125
|
+
)
|
126
|
+
PATTERN
|
127
|
+
|
128
|
+
# @!method match_order_with_field?(node)
|
129
|
+
# @param node [RuboCop::AST::Node, nil]
|
130
|
+
# @return [Boolean]
|
131
|
+
def_node_matcher :match_order_with_field?, <<~PATTERN
|
132
|
+
(send
|
133
|
+
_
|
134
|
+
_
|
135
|
+
{
|
136
|
+
#match_arel_sql_field?
|
137
|
+
#match_field?
|
138
|
+
}
|
139
|
+
...
|
140
|
+
)
|
141
|
+
PATTERN
|
142
|
+
alias bad? match_order_with_field?
|
143
|
+
|
144
|
+
# @param corrector [RuboCop::Cop::Corrector]
|
145
|
+
# @param node [RuboCop::AST::SendNode]
|
146
|
+
def autocorrect(
|
147
|
+
corrector,
|
148
|
+
node
|
149
|
+
)
|
150
|
+
corrector.replace(
|
151
|
+
node.location.expression.with(
|
152
|
+
begin_pos: node.location.selector.begin_pos
|
153
|
+
),
|
154
|
+
format_in_order_of(node)
|
155
|
+
)
|
156
|
+
end
|
157
|
+
|
158
|
+
# @param node [RuboCop::AST::SendNode]
|
159
|
+
# @return [String, nil]
|
160
|
+
def extract_column_name(node)
|
161
|
+
if node.each_descendant(:dstr).any?
|
162
|
+
extract_column_name_from_dstr(node)
|
163
|
+
else
|
164
|
+
extract_column_name_from_str(node)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# @param node [RuboCop::AST::SendNode]
|
169
|
+
# @return [String]
|
170
|
+
def extract_column_name_from_dstr(node)
|
171
|
+
node.each_descendant(:str).first.value[REGEXP_FIELD_DSTR_HEAD, :column_name]
|
172
|
+
end
|
173
|
+
|
174
|
+
# @param node [RuboCop::AST::SendNode]
|
175
|
+
# @return [String]
|
176
|
+
def extract_column_name_from_str(node)
|
177
|
+
node.each_descendant(:str).first.value[REGEXP_FIELD_STR, :column_name]
|
178
|
+
end
|
179
|
+
|
180
|
+
# @param node [RuboCop::AST::SendNode]
|
181
|
+
# @return [String, nil]
|
182
|
+
def extract_order_from_dstr(node)
|
183
|
+
node.each_descendant(:str).to_a.last.value[REGEXP_FIELD_DSTR_TAIL, :order]
|
184
|
+
end
|
185
|
+
|
186
|
+
# @param node [RuboCop::AST::SendNode]
|
187
|
+
# @return [String, nil]
|
188
|
+
def extract_order_from_str(node)
|
189
|
+
node.each_descendant(:str).first.value[REGEXP_FIELD_STR, :order]
|
190
|
+
end
|
191
|
+
|
192
|
+
# @param node [RuboCop::AST::SendNode]
|
193
|
+
# @return [String, nil]
|
194
|
+
def extract_rest_order(node)
|
195
|
+
rest_order_arguments = node.arguments[1..]
|
196
|
+
return if rest_order_arguments.empty?
|
197
|
+
|
198
|
+
format(
|
199
|
+
'.order(%<rest_order_arguments>s)',
|
200
|
+
rest_order_arguments: rest_order_arguments.map(&:source).join(', ')
|
201
|
+
)
|
202
|
+
end
|
203
|
+
|
204
|
+
# @param node [RuboCop::AST::SendNode]
|
205
|
+
# @return [String, nil]
|
206
|
+
def extract_reverse_order_from_dstr(node)
|
207
|
+
'.reverse_order' if match_desc_on_dstr?(node)
|
208
|
+
end
|
209
|
+
|
210
|
+
# @param node [RuboCop::AST::SendNode]
|
211
|
+
# @return [String, nil]
|
212
|
+
def extract_reverse_order_from_str(node)
|
213
|
+
'.reverse_order' if match_desc_on_str?(node)
|
214
|
+
end
|
215
|
+
|
216
|
+
# @param node [RuboCop::AST::SendNode]
|
217
|
+
# @return [String]
|
218
|
+
def extract_values_from_dstr(node)
|
219
|
+
node.each_descendant.find do |descendant|
|
220
|
+
match_field_dstr_body?(descendant)
|
221
|
+
end.children.first.receiver.source
|
222
|
+
end
|
223
|
+
|
224
|
+
# @param node [RuboCop::AST::SendNode]
|
225
|
+
# @return [String]
|
226
|
+
def extract_values_from_str(node)
|
227
|
+
format(
|
228
|
+
'[%<values>s]',
|
229
|
+
values: node.each_descendant(:str).first.value[REGEXP_FIELD_STR, :values].split(',').map(&:strip).join(', ')
|
230
|
+
)
|
231
|
+
end
|
232
|
+
|
233
|
+
# @param node [RuboCop::AST::SendNode]
|
234
|
+
# @return [String]
|
235
|
+
def format_in_order_of(node)
|
236
|
+
if node.each_descendant(:dstr).any?
|
237
|
+
format_in_order_of_on_dstr(node)
|
238
|
+
else
|
239
|
+
format_in_order_of_on_str(node)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
# @param node [RuboCop::AST::SendNode]
|
244
|
+
# @return [String]
|
245
|
+
def format_in_order_of_on_dstr(node)
|
246
|
+
format(
|
247
|
+
'in_order_of(:%<column_name>s, %<values>s)%<reverse_order>s%<rest_order>s',
|
248
|
+
column_name: extract_column_name_from_dstr(node),
|
249
|
+
rest_order: extract_rest_order(node),
|
250
|
+
reverse_order: extract_reverse_order_from_dstr(node),
|
251
|
+
values: extract_values_from_dstr(node)
|
252
|
+
)
|
253
|
+
end
|
254
|
+
|
255
|
+
# @param node [RuboCop::AST::SendNode]
|
256
|
+
# @return [String]
|
257
|
+
def format_in_order_of_on_str(node)
|
258
|
+
format(
|
259
|
+
'in_order_of(:%<column_name>s, %<values>s)%<reverse_order>s%<rest_order>s',
|
260
|
+
column_name: extract_column_name_from_str(node),
|
261
|
+
rest_order: extract_rest_order(node),
|
262
|
+
reverse_order: extract_reverse_order_from_str(node),
|
263
|
+
values: extract_values_from_str(node)
|
264
|
+
)
|
265
|
+
end
|
266
|
+
|
267
|
+
# @param node [RuboCop::AST::SendNode]
|
268
|
+
# @return [Boolean]
|
269
|
+
def match_desc_on_dstr?(node)
|
270
|
+
extract_order_from_dstr(node).to_s.casecmp('desc').zero?
|
271
|
+
end
|
272
|
+
|
273
|
+
# @param node [RuboCop::AST::SendNode]
|
274
|
+
# @return [Boolean]
|
275
|
+
def match_desc_on_str?(node)
|
276
|
+
extract_order_from_str(node).to_s.casecmp('desc').zero?
|
277
|
+
end
|
278
|
+
|
279
|
+
# @param node [RuboCop::AST::Node]
|
280
|
+
# @return [Boolean]
|
281
|
+
def match_field_dstr?(node)
|
282
|
+
node.dstr_type? &&
|
283
|
+
node.children.size == 3 &&
|
284
|
+
match_field_dstr_head?(node.children[0]) &&
|
285
|
+
match_field_dstr_body?(node.children[1]) &&
|
286
|
+
match_field_dstr_tail?(node.children[2])
|
287
|
+
end
|
288
|
+
|
289
|
+
# @param separator [String]
|
290
|
+
# @return [Boolean]
|
291
|
+
def match_field_dstr_body_separator?(separator)
|
292
|
+
separator.strip == ','
|
293
|
+
end
|
294
|
+
|
295
|
+
# @param node [RuboCop::AST::Node]
|
296
|
+
# @return [Boolean]
|
297
|
+
def match_field_dstr_head?(node)
|
298
|
+
node&.str_type? &&
|
299
|
+
node.value.match?(REGEXP_FIELD_DSTR_HEAD)
|
300
|
+
end
|
301
|
+
|
302
|
+
def match_field_dstr_tail?(node)
|
303
|
+
node&.str_type? &&
|
304
|
+
node.value.match?(REGEXP_FIELD_DSTR_TAIL)
|
305
|
+
end
|
306
|
+
|
307
|
+
# @param node [RuboCop::AST::Node]
|
308
|
+
# @return [Boolean]
|
309
|
+
def match_field_str?(node)
|
310
|
+
node.str_type? &&
|
311
|
+
node.value.match?(REGEXP_FIELD_STR)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
data/lib/sevencop/version.rb
CHANGED
data/lib/sevencop.rb
CHANGED
@@ -16,6 +16,7 @@ require_relative 'rubocop/cop/sevencop/method_definition_ordered'
|
|
16
16
|
require_relative 'rubocop/cop/sevencop/rails_belongs_to_optional'
|
17
17
|
require_relative 'rubocop/cop/sevencop/rails_date_and_time_calculation'
|
18
18
|
require_relative 'rubocop/cop/sevencop/rails_order_field'
|
19
|
+
require_relative 'rubocop/cop/sevencop/rails_order_field_in_order_of'
|
19
20
|
require_relative 'rubocop/cop/sevencop/rails_specific_action_name'
|
20
21
|
require_relative 'rubocop/cop/sevencop/rails_uniqueness_validator_explicit_case_sensitivity'
|
21
22
|
require_relative 'rubocop/cop/sevencop/rails_where_not'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sevencop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.32.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryo Nakamura
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-11-
|
11
|
+
date: 2022-11-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -68,6 +68,7 @@ files:
|
|
68
68
|
- lib/rubocop/cop/sevencop/rails_belongs_to_optional.rb
|
69
69
|
- lib/rubocop/cop/sevencop/rails_date_and_time_calculation.rb
|
70
70
|
- lib/rubocop/cop/sevencop/rails_order_field.rb
|
71
|
+
- lib/rubocop/cop/sevencop/rails_order_field_in_order_of.rb
|
71
72
|
- lib/rubocop/cop/sevencop/rails_specific_action_name.rb
|
72
73
|
- lib/rubocop/cop/sevencop/rails_uniqueness_validator_explicit_case_sensitivity.rb
|
73
74
|
- lib/rubocop/cop/sevencop/rails_where_not.rb
|