sevencop 0.12.1 → 0.14.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/.rubocop.yml +7 -0
- data/Gemfile.lock +1 -1
- data/README.md +11 -189
- data/config/default.yml +14 -22
- data/lib/rubocop/cop/sevencop/autoload_ordered.rb +2 -2
- data/lib/rubocop/cop/sevencop/{hash_literal_order.rb → hash_element_ordered.rb} +19 -19
- data/lib/rubocop/cop/sevencop/{method_definition_multiline_arguments.rb → method_definition_arguments_multiline.rb} +8 -8
- data/lib/rubocop/cop/sevencop/method_definition_keyword_arguments_ordered.rb +58 -0
- data/lib/rubocop/cop/sevencop/method_definition_ordered.rb +111 -0
- data/lib/rubocop/cop/sevencop/uniqueness_validator_explicit_case_sensitivity.rb +5 -5
- data/lib/sevencop/version.rb +1 -1
- data/lib/sevencop.rb +4 -5
- metadata +6 -7
- data/lib/rubocop/cop/sevencop/factory_bot_create_list.rb +0 -95
- data/lib/rubocop/cop/sevencop/redundant_existence_check.rb +0 -188
- data/lib/rubocop/cop/sevencop/to_s_with_argument.rb +0 -42
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5b95d5ba5dafb534e8e3a9e5c49bd9724db92840e1ca00543251c48a6b0f74f5
|
|
4
|
+
data.tar.gz: c6f7822017c94416417238387b5e16b76b00e401a8819a27c0d6df40ac1373c2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 131bb0495d50ebd37c0c03aa81b22d79d3488d8428697cd3af4263342f884b1857363920c40fa6794ba99e1de3e118bf94cf205cee96cc0aad77525f040072ee
|
|
7
|
+
data.tar.gz: f49be306dde9d6fda9db8d79a653c7814a4b43059265ceaf42fb4bbad2eee61fe112cb0ad56cdb152f626c26da9b54302f89f51f98652aa5ef37574ffcb06d45
|
data/.rubocop.yml
CHANGED
|
@@ -3,6 +3,7 @@ require:
|
|
|
3
3
|
- rubocop-performance
|
|
4
4
|
- rubocop-rake
|
|
5
5
|
- rubocop-rspec
|
|
6
|
+
- sevencop
|
|
6
7
|
|
|
7
8
|
AllCops:
|
|
8
9
|
NewCops: enable
|
|
@@ -25,5 +26,11 @@ RSpec/ExampleLength:
|
|
|
25
26
|
RSpec/MultipleExpectations:
|
|
26
27
|
Enabled: false
|
|
27
28
|
|
|
29
|
+
Sevencop/MethodDefinitionOrdered:
|
|
30
|
+
Enabled: true
|
|
31
|
+
|
|
28
32
|
Style/Documentation:
|
|
29
33
|
Enabled: false
|
|
34
|
+
|
|
35
|
+
Style/MultilineBlockChain:
|
|
36
|
+
Enabled: false
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# sevencop
|
|
2
2
|
|
|
3
3
|
[](https://github.com/r7kamura/sevencop/actions/workflows/test.yml)
|
|
4
|
-
[](https://rubygems.org/gems/sevencop)
|
|
5
4
|
|
|
6
5
|
Custom cops for [RuboCop](https://github.com/rubocop/rubocop).
|
|
7
6
|
|
|
@@ -45,193 +44,16 @@ Sevencop/BelongsToOptional:
|
|
|
45
44
|
|
|
46
45
|
## Cops
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
See YARD comments in each cop class for details:
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
- [Sevencop/BelongsToOptional](lib/rubocop/cop/sevencop/belongs_to_optional.rb)
|
|
50
|
+
- [Sevencop/HashElementOrdered](lib/rubocop/cop/sevencop/hash_element_ordered.rb)
|
|
51
|
+
- [Sevencop/InferredSpecType](lib/rubocop/cop/sevencop/inferred_spec_type.rb)
|
|
52
|
+
- [Sevencop/MethodDefinitionArgumentsMultiline](lib/rubocop/cop/sevencop/method_definition_arguments_multiline.rb)
|
|
53
|
+
- [Sevencop/MethodDefinitionKeywordArgumentsOrdered](lib/rubocop/cop/sevencop/method_definition_keyword_arguments_ordered.rb)
|
|
54
|
+
- [Sevencop/MethodDefinitionOrdered](lib/rubocop/cop/sevencop/method_definition_ordered.rb)
|
|
55
|
+
- [Sevencop/OrderField](lib/rubocop/cop/sevencop/order_field.rb)
|
|
56
|
+
- [Sevencop/UniquenessValidatorExplicitCaseSensitivity](lib/rubocop/cop/sevencop/uniqueness_validator_explicit_case_sensitivity.rb)
|
|
57
|
+
- [Sevencop/WhereNot](lib/rubocop/cop/sevencop/where_not.rb)
|
|
51
58
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
```ruby
|
|
55
|
-
# bad
|
|
56
|
-
autoload :B, 'b'
|
|
57
|
-
autoload :A, 'a'
|
|
58
|
-
|
|
59
|
-
# good
|
|
60
|
-
autoload :A, 'a'
|
|
61
|
-
autoload :B, 'b'
|
|
62
|
-
|
|
63
|
-
# good
|
|
64
|
-
autoload :B, 'b'
|
|
65
|
-
autoload :D, 'd'
|
|
66
|
-
|
|
67
|
-
autoload :A, 'a'
|
|
68
|
-
autoload :C, 'a'
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### Sevencop/BelongsToOptional
|
|
72
|
-
|
|
73
|
-
Force `belongs_to` with `optional: true` option.
|
|
74
|
-
|
|
75
|
-
```ruby
|
|
76
|
-
# bad
|
|
77
|
-
belongs_to :group
|
|
78
|
-
|
|
79
|
-
# good
|
|
80
|
-
belongs_to :group, optional: true
|
|
81
|
-
|
|
82
|
-
# good
|
|
83
|
-
belongs_to :group, optional: false
|
|
84
|
-
|
|
85
|
-
# good
|
|
86
|
-
belongs_to :group, options
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
This is useful for migration of `config.active_record.belongs_to_required_by_default`.
|
|
90
|
-
|
|
91
|
-
### Sevencop/FactoryBotCreateList
|
|
92
|
-
|
|
93
|
-
Finds possible substitutions for `FactoryBot.create_list`.
|
|
94
|
-
|
|
95
|
-
```ruby
|
|
96
|
-
# bad
|
|
97
|
-
Array.new(2) do
|
|
98
|
-
create(:user)
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# good
|
|
102
|
-
create_list(:user, 2)
|
|
103
|
-
|
|
104
|
-
# good
|
|
105
|
-
Array.new(2) do |i|
|
|
106
|
-
create(:user, order: i)
|
|
107
|
-
end
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### Sevencop/HashLiteralOrder
|
|
111
|
-
|
|
112
|
-
Sort Hash literal entries by key.
|
|
113
|
-
|
|
114
|
-
```ruby
|
|
115
|
-
# bad
|
|
116
|
-
{
|
|
117
|
-
b: 1,
|
|
118
|
-
a: 1,
|
|
119
|
-
c: 1
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
# good
|
|
123
|
-
{
|
|
124
|
-
a: 1,
|
|
125
|
-
b: 1,
|
|
126
|
-
c: 1
|
|
127
|
-
}
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
### Sevencop/InferredSpecType
|
|
131
|
-
|
|
132
|
-
Identifies redundant spec type.
|
|
133
|
-
|
|
134
|
-
```ruby
|
|
135
|
-
# bad
|
|
136
|
-
# spec/models/user_spec.rb
|
|
137
|
-
RSpec.describe User, type: :model
|
|
138
|
-
|
|
139
|
-
# good
|
|
140
|
-
# spec/models/user_spec.rb
|
|
141
|
-
RSpec.describe User
|
|
142
|
-
|
|
143
|
-
# good
|
|
144
|
-
# spec/models/user_spec.rb
|
|
145
|
-
RSpec.describe User, type: :request
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Sevencop/MethodDefinitionMultilineArguments
|
|
149
|
-
|
|
150
|
-
Inserts new lines between method definition parameters.
|
|
151
|
-
|
|
152
|
-
```ruby
|
|
153
|
-
# bad
|
|
154
|
-
def foo(a, b)
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
# good
|
|
158
|
-
def foo(
|
|
159
|
-
a,
|
|
160
|
-
b
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
# good
|
|
164
|
-
def foo(a)
|
|
165
|
-
end
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
### Sevencop/OrderField
|
|
169
|
-
|
|
170
|
-
Identifies a String including "field" is passed to `order` or `reorder`.
|
|
171
|
-
|
|
172
|
-
```ruby
|
|
173
|
-
# bad
|
|
174
|
-
articles.order('field(id, ?)', a)
|
|
175
|
-
|
|
176
|
-
# good
|
|
177
|
-
articles.order(Arel.sql('field(id, ?)'), a)
|
|
178
|
-
|
|
179
|
-
# bad
|
|
180
|
-
reorder('field(id, ?)', a)
|
|
181
|
-
|
|
182
|
-
# good
|
|
183
|
-
reorder(Arel.sql('field(id, ?)'), a)
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### Sevencop/RedundantExistenceCheck
|
|
187
|
-
|
|
188
|
-
Identifies redundant existent check before file operation.
|
|
189
|
-
|
|
190
|
-
```ruby
|
|
191
|
-
# bad
|
|
192
|
-
FileUtils.mkdir(a) unless FileTest.exist?(a)
|
|
193
|
-
|
|
194
|
-
# good
|
|
195
|
-
FileUtils.mkdir_p(a)
|
|
196
|
-
|
|
197
|
-
# bad
|
|
198
|
-
FileUtils.rm(a) if FileTest.exist?(a)
|
|
199
|
-
|
|
200
|
-
# good
|
|
201
|
-
FileUtils.rm_f(a)
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
### Sevencop/UniquenessValidatorExplicitCaseSensitivity
|
|
205
|
-
|
|
206
|
-
Identifies use of UniquenessValidator without :case_sensitive option.
|
|
207
|
-
|
|
208
|
-
```ruby
|
|
209
|
-
# bad
|
|
210
|
-
validates :name, uniqueness: true
|
|
211
|
-
|
|
212
|
-
# good
|
|
213
|
-
validates :name, uniqueness: { case_sensitive: true }
|
|
214
|
-
|
|
215
|
-
# good
|
|
216
|
-
validates :name, uniqueness: { case_sensitive: false }
|
|
217
|
-
|
|
218
|
-
# bad
|
|
219
|
-
validates :name, uniqueness: { allow_nil: true, scope: :user_id }
|
|
220
|
-
|
|
221
|
-
# good
|
|
222
|
-
validates :name, uniqueness: { allow_nil: true, scope: :user_id, case_sensitive: true }
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
Useful to keep the same behavior between Rails 6.0 and 6.1 where case insensitive collation is used in MySQL.
|
|
226
|
-
|
|
227
|
-
### Sevencop/WhereNot
|
|
228
|
-
|
|
229
|
-
Identifies passing multi-elements Hash literal to `where.not`.
|
|
230
|
-
|
|
231
|
-
```ruby
|
|
232
|
-
# bad
|
|
233
|
-
where.not(key1: value1, key2: value2)
|
|
234
|
-
|
|
235
|
-
# good
|
|
236
|
-
where.not(key1: value1).where.not(key2: value2)
|
|
237
|
-
```
|
|
59
|
+
Note that all cops are `Enabled: false` by default.
|
data/config/default.yml
CHANGED
|
@@ -2,7 +2,7 @@ Sevencop/AutoloadOrdered:
|
|
|
2
2
|
Description: |
|
|
3
3
|
Sort `autoload` in alphabetical order.
|
|
4
4
|
Enabled: false
|
|
5
|
-
VersionAdded: '0.12
|
|
5
|
+
VersionAdded: '0.12'
|
|
6
6
|
|
|
7
7
|
Sevencop/BelongsToOptional:
|
|
8
8
|
Description: |
|
|
@@ -11,15 +11,9 @@ Sevencop/BelongsToOptional:
|
|
|
11
11
|
Safe: false
|
|
12
12
|
VersionAdded: '0.5'
|
|
13
13
|
|
|
14
|
-
Sevencop/
|
|
14
|
+
Sevencop/HashElementOrdered:
|
|
15
15
|
Description: |
|
|
16
|
-
|
|
17
|
-
Enabled: false
|
|
18
|
-
VersionAdded: '0.10'
|
|
19
|
-
|
|
20
|
-
Sevencop/HashLiteralOrder:
|
|
21
|
-
Description: |
|
|
22
|
-
Sort Hash literal entries by key.
|
|
16
|
+
Sort Hash elements by key.
|
|
23
17
|
Enabled: false
|
|
24
18
|
VersionAdded: '0.6'
|
|
25
19
|
|
|
@@ -29,32 +23,30 @@ Sevencop/InferredSpecType:
|
|
|
29
23
|
Enabled: false
|
|
30
24
|
VersionAdded: '0.9'
|
|
31
25
|
|
|
32
|
-
Sevencop/
|
|
26
|
+
Sevencop/MethodDefinitionArgumentsMultiline:
|
|
33
27
|
Description: |
|
|
34
|
-
Inserts new lines between method definition
|
|
28
|
+
Inserts new lines between method definition arguments.
|
|
35
29
|
Enabled: false
|
|
36
30
|
VersionAdded: '0.11'
|
|
37
31
|
|
|
38
|
-
Sevencop/
|
|
32
|
+
Sevencop/MethodDefinitionOrdered:
|
|
39
33
|
Description: |
|
|
40
|
-
|
|
34
|
+
Sort method definitions in alphabetical order.
|
|
41
35
|
Enabled: false
|
|
42
|
-
|
|
43
|
-
VersionAdded: '0.4'
|
|
36
|
+
VersionAdded: '0.14'
|
|
44
37
|
|
|
45
|
-
Sevencop/
|
|
38
|
+
Sevencop/MethodDefinitionKeywordArgumentsOrdered:
|
|
46
39
|
Description: |
|
|
47
|
-
|
|
40
|
+
Sort method definition keyword arguments in alphabetical order.
|
|
48
41
|
Enabled: false
|
|
49
|
-
|
|
50
|
-
VersionAdded: '0.1'
|
|
42
|
+
VersionAdded: '0.13'
|
|
51
43
|
|
|
52
|
-
Sevencop/
|
|
44
|
+
Sevencop/OrderField:
|
|
53
45
|
Description: |
|
|
54
|
-
|
|
46
|
+
Wrap safe SQL String by `Arel.sql`.
|
|
55
47
|
Enabled: false
|
|
56
48
|
Safe: false
|
|
57
|
-
VersionAdded: '0.
|
|
49
|
+
VersionAdded: '0.4'
|
|
58
50
|
|
|
59
51
|
Sevencop/UniquenessValidatorExplicitCaseSensitivity:
|
|
60
52
|
Description: |
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Sevencop
|
|
6
|
-
# Sort `autoload` in alphabetical order
|
|
6
|
+
# Sort `autoload` in alphabetical order.
|
|
7
7
|
#
|
|
8
8
|
# @example
|
|
9
9
|
# # bad
|
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
|
25
25
|
|
|
26
26
|
include RangeHelp
|
|
27
27
|
|
|
28
|
-
MSG = 'Sort `autoload` in alphabetical order
|
|
28
|
+
MSG = 'Sort `autoload` in alphabetical order.'
|
|
29
29
|
|
|
30
30
|
RESTRICT_ON_SEND = %i[
|
|
31
31
|
autoload
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Sevencop
|
|
6
|
-
# Sort Hash
|
|
6
|
+
# Sort Hash elements by key.
|
|
7
7
|
#
|
|
8
8
|
# @example
|
|
9
9
|
#
|
|
@@ -21,10 +21,10 @@ module RuboCop
|
|
|
21
21
|
# c: 1
|
|
22
22
|
# }
|
|
23
23
|
#
|
|
24
|
-
class
|
|
24
|
+
class HashElementOrdered < Base
|
|
25
25
|
extend AutoCorrector
|
|
26
26
|
|
|
27
|
-
MSG = 'Sort Hash
|
|
27
|
+
MSG = 'Sort Hash elements by key.'
|
|
28
28
|
|
|
29
29
|
# @!method hash_literal?(node)
|
|
30
30
|
def_node_matcher :hash_literal?, <<~PATTERN
|
|
@@ -64,6 +64,16 @@ module RuboCop
|
|
|
64
64
|
parts.join
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
+
# @param [RuboCop::AST::HashNode] node
|
|
68
|
+
# @return [Integer]
|
|
69
|
+
def offset_for(node)
|
|
70
|
+
if node.braces?
|
|
71
|
+
1
|
|
72
|
+
else
|
|
73
|
+
0
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
67
77
|
# @param [Array<RuboCop::AST::PairNode>] pairs
|
|
68
78
|
# @return [Array<RuboCop::AST::PairNode>]
|
|
69
79
|
def sort(pairs)
|
|
@@ -95,32 +105,22 @@ module RuboCop
|
|
|
95
105
|
# @param [RuboCop::AST::HashNode] node
|
|
96
106
|
# @return [String]
|
|
97
107
|
# { a: 1, b: 1 }
|
|
98
|
-
#
|
|
99
|
-
def
|
|
108
|
+
# ^^^^
|
|
109
|
+
def whitespace_leading(node)
|
|
100
110
|
processed_source.raw_source[
|
|
101
|
-
node.
|
|
111
|
+
node.location.expression.begin.end_pos + offset_for(node)...node.pairs[0].location.expression.begin_pos
|
|
102
112
|
]
|
|
103
113
|
end
|
|
104
114
|
|
|
105
115
|
# @param [RuboCop::AST::HashNode] node
|
|
106
116
|
# @return [String]
|
|
107
117
|
# { a: 1, b: 1 }
|
|
108
|
-
#
|
|
109
|
-
def
|
|
118
|
+
# ^^
|
|
119
|
+
def whitespace_trailing(node)
|
|
110
120
|
processed_source.raw_source[
|
|
111
|
-
node.location.expression.
|
|
121
|
+
node.pairs[-1].location.expression.end_pos...node.location.expression.end.begin_pos - offset_for(node)
|
|
112
122
|
]
|
|
113
123
|
end
|
|
114
|
-
|
|
115
|
-
# @param [RuboCop::AST::HashNode] node
|
|
116
|
-
# @return [Integer]
|
|
117
|
-
def offset_for(node)
|
|
118
|
-
if node.braces?
|
|
119
|
-
1
|
|
120
|
-
else
|
|
121
|
-
0
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
124
|
end
|
|
125
125
|
end
|
|
126
126
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Sevencop
|
|
6
|
-
# Inserts new lines between method definition
|
|
6
|
+
# Inserts new lines between method definition arguments.
|
|
7
7
|
#
|
|
8
8
|
# @example
|
|
9
9
|
# # bad
|
|
@@ -19,10 +19,10 @@ module RuboCop
|
|
|
19
19
|
# # good
|
|
20
20
|
# def foo(a)
|
|
21
21
|
# end
|
|
22
|
-
class
|
|
22
|
+
class MethodDefinitionArgumentsMultiline < Base
|
|
23
23
|
extend AutoCorrector
|
|
24
24
|
|
|
25
|
-
MSG = 'Insert new lines between method definition
|
|
25
|
+
MSG = 'Insert new lines between method definition arguments.'
|
|
26
26
|
|
|
27
27
|
# @param node [RuboCop::AST::ArgsNode]
|
|
28
28
|
def on_args(node)
|
|
@@ -54,6 +54,11 @@ module RuboCop
|
|
|
54
54
|
)
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
# @return [Boolean]
|
|
58
|
+
def method_args?(node)
|
|
59
|
+
!node.parent.nil? && node.parent.def_type?
|
|
60
|
+
end
|
|
61
|
+
|
|
57
62
|
# @param node [RuboCop::AST::ArgsNode]
|
|
58
63
|
# @return [Boolean]
|
|
59
64
|
def multilined?(node)
|
|
@@ -61,11 +66,6 @@ module RuboCop
|
|
|
61
66
|
child.location.expression.line
|
|
62
67
|
end.uniq.length == node.children.length
|
|
63
68
|
end
|
|
64
|
-
|
|
65
|
-
# @return [Boolean]
|
|
66
|
-
def method_args?(node)
|
|
67
|
-
!node.parent.nil? && node.parent.def_type?
|
|
68
|
-
end
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
71
|
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Sevencop
|
|
6
|
+
# Sort method definition keyword arguments in alphabetical order.
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# # bad
|
|
10
|
+
# def foo(b:, a:); end
|
|
11
|
+
#
|
|
12
|
+
# # good
|
|
13
|
+
# def foo(a:, b:); end
|
|
14
|
+
#
|
|
15
|
+
# # bad
|
|
16
|
+
# def foo(c:, d:, b: 1, a: 2); end
|
|
17
|
+
#
|
|
18
|
+
# # good
|
|
19
|
+
# def foo(c:, d:, a: 2, b: 1); end
|
|
20
|
+
class MethodDefinitionKeywordArgumentsOrdered < Base
|
|
21
|
+
extend AutoCorrector
|
|
22
|
+
|
|
23
|
+
MSG = 'Sort method definition keyword arguments in alphabetical order.'
|
|
24
|
+
|
|
25
|
+
# @param node [RuboCop::AST::ArgNode]
|
|
26
|
+
def on_kwarg(node)
|
|
27
|
+
previous_older_kwarg = find_previous_older_sibling(node)
|
|
28
|
+
return unless previous_older_kwarg
|
|
29
|
+
|
|
30
|
+
add_offense(node) do |corrector|
|
|
31
|
+
corrector.insert_before(
|
|
32
|
+
previous_older_kwarg,
|
|
33
|
+
"#{node.source}, "
|
|
34
|
+
)
|
|
35
|
+
corrector.remove(
|
|
36
|
+
node.location.expression.with(
|
|
37
|
+
begin_pos: node.left_sibling.location.expression.end_pos
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
alias on_kwoptarg on_kwarg
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
# @param node [RuboCop::AST::ArgNode]
|
|
47
|
+
# @return [RuboCop::AST::ArgNode]
|
|
48
|
+
def find_previous_older_sibling(node)
|
|
49
|
+
node.left_siblings.find do |sibling|
|
|
50
|
+
next if sibling.type != node.type
|
|
51
|
+
|
|
52
|
+
sibling.name > node.name
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Sevencop
|
|
6
|
+
# Sort method definition in alphabetical order.
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# # bad
|
|
10
|
+
# def b; end
|
|
11
|
+
# def a; end
|
|
12
|
+
#
|
|
13
|
+
# # good
|
|
14
|
+
# def a; end
|
|
15
|
+
# def b; end
|
|
16
|
+
#
|
|
17
|
+
# # good
|
|
18
|
+
# def b; end
|
|
19
|
+
# def c; end
|
|
20
|
+
# private
|
|
21
|
+
# def a; end
|
|
22
|
+
# def d; end
|
|
23
|
+
#
|
|
24
|
+
# # good
|
|
25
|
+
# def initialize; end
|
|
26
|
+
# def a; end
|
|
27
|
+
class MethodDefinitionOrdered < Base
|
|
28
|
+
extend AutoCorrector
|
|
29
|
+
|
|
30
|
+
include RangeHelp
|
|
31
|
+
include VisibilityHelp
|
|
32
|
+
|
|
33
|
+
MSG = 'Sort method definition in alphabetical order.'
|
|
34
|
+
|
|
35
|
+
# @param node [RuboCop::AST::DefNode]
|
|
36
|
+
def on_def(node)
|
|
37
|
+
previous_older_sibling = find_previous_older_sibling(node)
|
|
38
|
+
return unless previous_older_sibling
|
|
39
|
+
|
|
40
|
+
add_offense(node) do |corrector|
|
|
41
|
+
swap(
|
|
42
|
+
range_by_whole_lines(
|
|
43
|
+
range_with_comments(previous_older_sibling),
|
|
44
|
+
include_final_newline: true
|
|
45
|
+
),
|
|
46
|
+
range_by_whole_lines(
|
|
47
|
+
range_with_comments(node),
|
|
48
|
+
include_final_newline: true
|
|
49
|
+
),
|
|
50
|
+
corrector: corrector
|
|
51
|
+
)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
alias on_defs on_def
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
# @param node [RuboCop::AST::DefNode]
|
|
59
|
+
# @return [RuboCop::AST::DefNode]
|
|
60
|
+
def find_previous_older_sibling(node)
|
|
61
|
+
previous_siblings_in_same_section_of(node).find do |sibling|
|
|
62
|
+
next if sibling.type != node.type
|
|
63
|
+
|
|
64
|
+
(sort_key_of(sibling) <=> sort_key_of(node)) == 1
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @param node [RuboCop::AST::Node]
|
|
69
|
+
# @return [Array<RuboCop::AST::Node>]
|
|
70
|
+
def previous_siblings_in_same_section_of(node)
|
|
71
|
+
return node.left_siblings if node.defs_type?
|
|
72
|
+
|
|
73
|
+
node.left_siblings.reverse.take_while do |sibling|
|
|
74
|
+
!visibility_block?(sibling)
|
|
75
|
+
end.reverse
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# @param node [RuboCop::AST::Node]
|
|
79
|
+
# @return [Paresr::Source::Range]
|
|
80
|
+
def range_with_comments(node)
|
|
81
|
+
comment = processed_source.ast_with_comments[node].first
|
|
82
|
+
if comment
|
|
83
|
+
node.location.expression.with(begin_pos: comment.location.expression.begin_pos)
|
|
84
|
+
else
|
|
85
|
+
node.location.expression
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# @param node [RuboCop::AST::DefNode]
|
|
90
|
+
# @return [#<=>]
|
|
91
|
+
def sort_key_of(node)
|
|
92
|
+
[
|
|
93
|
+
node.method?(:initialize) ? 0 : 1,
|
|
94
|
+
node.method_name
|
|
95
|
+
]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# @param range1 [Paresr::Source::Range]
|
|
99
|
+
# @param range2 [Paresr::Source::Range]
|
|
100
|
+
# @param corrector [RuboCop::AST::Corrector]
|
|
101
|
+
def swap(range1, range2, corrector:)
|
|
102
|
+
corrector.insert_before(
|
|
103
|
+
range1,
|
|
104
|
+
"#{range2.source}\n"
|
|
105
|
+
)
|
|
106
|
+
corrector.remove(range2)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -65,6 +65,11 @@ module RuboCop
|
|
|
65
65
|
)
|
|
66
66
|
PATTERN
|
|
67
67
|
|
|
68
|
+
# @param [RuboCop::AST::SendNode] node
|
|
69
|
+
def find_uniqueness_value(node)
|
|
70
|
+
node.arguments[1].pairs.find { |pair| pair.key.value == :uniqueness }.value
|
|
71
|
+
end
|
|
72
|
+
|
|
68
73
|
# @param [RuboCop::AST::SendNode] node
|
|
69
74
|
def on_send(node)
|
|
70
75
|
return unless validates_uniqueness?(node) && !validates_uniqueness_with_case_sensitivity?(node)
|
|
@@ -84,11 +89,6 @@ module RuboCop
|
|
|
84
89
|
end
|
|
85
90
|
end
|
|
86
91
|
end
|
|
87
|
-
|
|
88
|
-
# @param [RuboCop::AST::SendNode] node
|
|
89
|
-
def find_uniqueness_value(node)
|
|
90
|
-
node.arguments[1].pairs.find { |pair| pair.key.value == :uniqueness }.value
|
|
91
|
-
end
|
|
92
92
|
end
|
|
93
93
|
end
|
|
94
94
|
end
|
data/lib/sevencop/version.rb
CHANGED
data/lib/sevencop.rb
CHANGED
|
@@ -5,12 +5,11 @@ require_relative 'sevencop/version'
|
|
|
5
5
|
|
|
6
6
|
require_relative 'rubocop/cop/sevencop/autoload_ordered'
|
|
7
7
|
require_relative 'rubocop/cop/sevencop/belongs_to_optional'
|
|
8
|
-
require_relative 'rubocop/cop/sevencop/
|
|
9
|
-
require_relative 'rubocop/cop/sevencop/hash_literal_order'
|
|
8
|
+
require_relative 'rubocop/cop/sevencop/hash_element_ordered'
|
|
10
9
|
require_relative 'rubocop/cop/sevencop/inferred_spec_type'
|
|
11
|
-
require_relative 'rubocop/cop/sevencop/
|
|
10
|
+
require_relative 'rubocop/cop/sevencop/method_definition_arguments_multiline'
|
|
11
|
+
require_relative 'rubocop/cop/sevencop/method_definition_keyword_arguments_ordered'
|
|
12
|
+
require_relative 'rubocop/cop/sevencop/method_definition_ordered'
|
|
12
13
|
require_relative 'rubocop/cop/sevencop/order_field'
|
|
13
|
-
require_relative 'rubocop/cop/sevencop/redundant_existence_check'
|
|
14
|
-
require_relative 'rubocop/cop/sevencop/to_s_with_argument'
|
|
15
14
|
require_relative 'rubocop/cop/sevencop/uniqueness_validator_explicit_case_sensitivity'
|
|
16
15
|
require_relative 'rubocop/cop/sevencop/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.14.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-09-
|
|
11
|
+
date: 2022-09-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rubocop
|
|
@@ -43,13 +43,12 @@ files:
|
|
|
43
43
|
- config/default.yml
|
|
44
44
|
- lib/rubocop/cop/sevencop/autoload_ordered.rb
|
|
45
45
|
- lib/rubocop/cop/sevencop/belongs_to_optional.rb
|
|
46
|
-
- lib/rubocop/cop/sevencop/
|
|
47
|
-
- lib/rubocop/cop/sevencop/hash_literal_order.rb
|
|
46
|
+
- lib/rubocop/cop/sevencop/hash_element_ordered.rb
|
|
48
47
|
- lib/rubocop/cop/sevencop/inferred_spec_type.rb
|
|
49
|
-
- lib/rubocop/cop/sevencop/
|
|
48
|
+
- lib/rubocop/cop/sevencop/method_definition_arguments_multiline.rb
|
|
49
|
+
- lib/rubocop/cop/sevencop/method_definition_keyword_arguments_ordered.rb
|
|
50
|
+
- lib/rubocop/cop/sevencop/method_definition_ordered.rb
|
|
50
51
|
- lib/rubocop/cop/sevencop/order_field.rb
|
|
51
|
-
- lib/rubocop/cop/sevencop/redundant_existence_check.rb
|
|
52
|
-
- lib/rubocop/cop/sevencop/to_s_with_argument.rb
|
|
53
52
|
- lib/rubocop/cop/sevencop/uniqueness_validator_explicit_case_sensitivity.rb
|
|
54
53
|
- lib/rubocop/cop/sevencop/where_not.rb
|
|
55
54
|
- lib/sevencop.rb
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module RuboCop
|
|
4
|
-
module Cop
|
|
5
|
-
module Sevencop
|
|
6
|
-
# Finds possible substitutions for `FactoryBot.create_list`.
|
|
7
|
-
#
|
|
8
|
-
# @example
|
|
9
|
-
#
|
|
10
|
-
# # bad
|
|
11
|
-
# Array.new(2) do
|
|
12
|
-
# create(:user)
|
|
13
|
-
# end
|
|
14
|
-
#
|
|
15
|
-
# # good
|
|
16
|
-
# create_list(:user, 2)
|
|
17
|
-
#
|
|
18
|
-
# # good
|
|
19
|
-
# Array.new(2) do |i|
|
|
20
|
-
# create(:user, order: i)
|
|
21
|
-
# end
|
|
22
|
-
#
|
|
23
|
-
# @note
|
|
24
|
-
# This cop does not support `Integer#times` intentionally because it
|
|
25
|
-
# should be treated by `Performance/TimesMap` cop.
|
|
26
|
-
#
|
|
27
|
-
class FactoryBotCreateList < Base
|
|
28
|
-
extend AutoCorrector
|
|
29
|
-
|
|
30
|
-
MSG = 'Use `create_list` instead.'
|
|
31
|
-
|
|
32
|
-
# @param node [RuboCop::AST::BlockNode]
|
|
33
|
-
# @return [void]
|
|
34
|
-
def on_block(node)
|
|
35
|
-
count_node, factory_name_node, extra_argument_nodes = extract(node)
|
|
36
|
-
return unless count_node
|
|
37
|
-
|
|
38
|
-
add_offense(node) do |corrector|
|
|
39
|
-
corrector.replace(
|
|
40
|
-
node,
|
|
41
|
-
format(
|
|
42
|
-
'create_list(%<arguments>s)',
|
|
43
|
-
arguments: [
|
|
44
|
-
factory_name_node,
|
|
45
|
-
count_node,
|
|
46
|
-
*extra_argument_nodes
|
|
47
|
-
].map(&:source).join(', ')
|
|
48
|
-
)
|
|
49
|
-
)
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
alias on_numblock on_block
|
|
53
|
-
|
|
54
|
-
private
|
|
55
|
-
|
|
56
|
-
# @!method extract(node)
|
|
57
|
-
# @param node [RuboCop::AST::BlockNode]
|
|
58
|
-
# @return [Array(Integer, RuboCop::AST::SendNode)]
|
|
59
|
-
def_node_matcher :extract, <<~PATTERN
|
|
60
|
-
(block
|
|
61
|
-
(send
|
|
62
|
-
(const {nil? | cbase} :Array)
|
|
63
|
-
:new
|
|
64
|
-
$(int _)
|
|
65
|
-
)
|
|
66
|
-
(args)
|
|
67
|
-
(send
|
|
68
|
-
nil?
|
|
69
|
-
:create
|
|
70
|
-
$(sym _) $(...)?
|
|
71
|
-
)
|
|
72
|
-
)
|
|
73
|
-
PATTERN
|
|
74
|
-
|
|
75
|
-
# @param corrector [RuboCop::Cop::Corrector]
|
|
76
|
-
# @param node [RuboCop::AST::BlockNode]
|
|
77
|
-
# @return [void]
|
|
78
|
-
def autocorrect(corrector, node)
|
|
79
|
-
count_node, factory_name_node, extra_argument_nodes = extract(node)
|
|
80
|
-
corrector.replace(
|
|
81
|
-
node,
|
|
82
|
-
format(
|
|
83
|
-
'create_list(%<arguments>s)',
|
|
84
|
-
arguments: [
|
|
85
|
-
factory_name_node,
|
|
86
|
-
count_node,
|
|
87
|
-
*extra_argument_nodes
|
|
88
|
-
].map(&:source).join(', ')
|
|
89
|
-
)
|
|
90
|
-
)
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
end
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module RuboCop
|
|
4
|
-
module Cop
|
|
5
|
-
module Sevencop
|
|
6
|
-
# Identifies redundant existent check before file operation.
|
|
7
|
-
#
|
|
8
|
-
# @safety
|
|
9
|
-
# This cop is unsafe because it can register a false positive where the check is truly needed.
|
|
10
|
-
#
|
|
11
|
-
# @example
|
|
12
|
-
#
|
|
13
|
-
# # bad
|
|
14
|
-
# FileUtils.mkdir(a) unless FileTest.exist?(a)
|
|
15
|
-
#
|
|
16
|
-
# # good
|
|
17
|
-
# FileUtils.mkdir_p(a)
|
|
18
|
-
#
|
|
19
|
-
# # bad
|
|
20
|
-
# FileUtils.rm(a) if File.exist?(a)
|
|
21
|
-
#
|
|
22
|
-
# # good
|
|
23
|
-
# FileUtils.rm_f(a)
|
|
24
|
-
#
|
|
25
|
-
class RedundantExistenceCheck < Base
|
|
26
|
-
extend AutoCorrector
|
|
27
|
-
|
|
28
|
-
CLASS_NAMES_FOR_EXIST = ::Set[
|
|
29
|
-
:File,
|
|
30
|
-
:FileTest,
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
CLASS_NAMES_FOR_OPERATION = ::Set[
|
|
34
|
-
:File,
|
|
35
|
-
:FileUtils,
|
|
36
|
-
]
|
|
37
|
-
|
|
38
|
-
METHOD_NAMES_FOR_MAKE = ::Set[
|
|
39
|
-
:makedirs,
|
|
40
|
-
:mkdir,
|
|
41
|
-
:mkdir_p,
|
|
42
|
-
:mkpath,
|
|
43
|
-
:touch,
|
|
44
|
-
]
|
|
45
|
-
|
|
46
|
-
METHOD_NAMES_FOR_REMOVE = ::Set[
|
|
47
|
-
:delete,
|
|
48
|
-
:remove,
|
|
49
|
-
:remove_dir,
|
|
50
|
-
:remove_entry,
|
|
51
|
-
:remove_entry_secure,
|
|
52
|
-
:remove_file,
|
|
53
|
-
:rm,
|
|
54
|
-
:rm_f,
|
|
55
|
-
:rm_r,
|
|
56
|
-
:rm_rf,
|
|
57
|
-
:rmdir,
|
|
58
|
-
:rmtree,
|
|
59
|
-
:safe_unlink,
|
|
60
|
-
:unlink,
|
|
61
|
-
]
|
|
62
|
-
|
|
63
|
-
METHOD_NAMES_FOR_EXIST = ::Set[
|
|
64
|
-
:exist?,
|
|
65
|
-
:exists?,
|
|
66
|
-
]
|
|
67
|
-
|
|
68
|
-
METHOD_NAMES_FOR_FORCE_OPERATION = ::Set[
|
|
69
|
-
:makedirs,
|
|
70
|
-
:mkdir_p,
|
|
71
|
-
:mkpath,
|
|
72
|
-
:rm_f,
|
|
73
|
-
:rm_rf,
|
|
74
|
-
:rm_tree,
|
|
75
|
-
:safe_unlink,
|
|
76
|
-
:touch,
|
|
77
|
-
]
|
|
78
|
-
|
|
79
|
-
METHOD_MAPPING_FOR_FORCE_REPLACEMENT = {
|
|
80
|
-
'FileUtils.mkdir' => 'FileUtils.mkdir_p',
|
|
81
|
-
'File.delete' => 'FileUtils.rm_f',
|
|
82
|
-
'File.unlink' => 'FileUtils.rm_f'
|
|
83
|
-
}.freeze
|
|
84
|
-
|
|
85
|
-
MSG = 'Avoid redundant existent check before file operation.'
|
|
86
|
-
|
|
87
|
-
# @!method make_unless_exist?(node)
|
|
88
|
-
def_node_matcher :make_unless_exist?, <<~PATTERN
|
|
89
|
-
(if
|
|
90
|
-
(send (const nil? CLASS_NAMES_FOR_EXIST) METHOD_NAMES_FOR_EXIST _)
|
|
91
|
-
nil?
|
|
92
|
-
(send (const nil? CLASS_NAMES_FOR_OPERATION) METHOD_NAMES_FOR_MAKE ...)
|
|
93
|
-
)
|
|
94
|
-
PATTERN
|
|
95
|
-
|
|
96
|
-
# @!method remove_if_exist?(node)
|
|
97
|
-
def_node_matcher :remove_if_exist?, <<~PATTERN
|
|
98
|
-
(if
|
|
99
|
-
(send (const nil? CLASS_NAMES_FOR_EXIST) METHOD_NAMES_FOR_EXIST _)
|
|
100
|
-
(send (const nil? CLASS_NAMES_FOR_OPERATION) METHOD_NAMES_FOR_REMOVE ...)
|
|
101
|
-
nil?
|
|
102
|
-
)
|
|
103
|
-
PATTERN
|
|
104
|
-
|
|
105
|
-
def on_if(node)
|
|
106
|
-
return unless redundant_on_if(node) || redundant_on_unless(node)
|
|
107
|
-
|
|
108
|
-
add_offense(node) do |corrector|
|
|
109
|
-
corrector.replace(
|
|
110
|
-
node.location.expression,
|
|
111
|
-
enforce(node)
|
|
112
|
-
)
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
private
|
|
117
|
-
|
|
118
|
-
def enforce(node)
|
|
119
|
-
if force_operation?(node)
|
|
120
|
-
node.if_branch.source
|
|
121
|
-
elsif force_replaceable_method?(node)
|
|
122
|
-
enforce_by_replacement(node)
|
|
123
|
-
else
|
|
124
|
-
enforce_by_force_option(node)
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def enforce_by_force_option(node)
|
|
129
|
-
arguments = node.if_branch.arguments.map(&:source)
|
|
130
|
-
arguments << 'force: true' unless force_operation?(node)
|
|
131
|
-
format(
|
|
132
|
-
'%<receiver>s.%<method_name>s(%<arguments>s)',
|
|
133
|
-
arguments: arguments.join(', '),
|
|
134
|
-
method_name: node.if_branch.method_name,
|
|
135
|
-
receiver: node.if_branch.receiver.source
|
|
136
|
-
)
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def enforce_by_replacement(node)
|
|
140
|
-
format(
|
|
141
|
-
'%<signature>s(%<arguments>s)',
|
|
142
|
-
arguments: node.if_branch.arguments.map(&:source).join(', '),
|
|
143
|
-
signature: METHOD_MAPPING_FOR_FORCE_REPLACEMENT[operation_method_signature(node)]
|
|
144
|
-
)
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def force_operation?(node)
|
|
148
|
-
force_operation_method_name?(node) || force_operation_argument?(node)
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
def force_operation_argument?(node)
|
|
152
|
-
node.if_branch.last_argument.hash_type? &&
|
|
153
|
-
node.if_branch.last_argument.pairs.any? do |pair|
|
|
154
|
-
pair.key.value == :force && pair.value.true_type?
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
def force_operation_method_name?(node)
|
|
159
|
-
METHOD_NAMES_FOR_FORCE_OPERATION.include?(node.if_branch.method_name)
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def redundant_on_if(node)
|
|
163
|
-
remove_if_exist?(node) && same_argument?(node)
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
def redundant_on_unless(node)
|
|
167
|
-
make_unless_exist?(node) && same_argument?(node)
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
def force_replaceable_method?(node)
|
|
171
|
-
METHOD_MAPPING_FOR_FORCE_REPLACEMENT.key?(operation_method_signature(node))
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
def operation_method_signature(node)
|
|
175
|
-
format(
|
|
176
|
-
'%<receiver>s.%<method_name>s',
|
|
177
|
-
method_name: node.if_branch.method_name,
|
|
178
|
-
receiver: node.if_branch.receiver.source
|
|
179
|
-
)
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
def same_argument?(node)
|
|
183
|
-
node.condition.first_argument == node.if_branch.first_argument
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
end
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module RuboCop
|
|
4
|
-
module Cop
|
|
5
|
-
module Sevencop
|
|
6
|
-
# Identifies passing any argument to `#to_s`.
|
|
7
|
-
#
|
|
8
|
-
# @example
|
|
9
|
-
#
|
|
10
|
-
# # bad
|
|
11
|
-
# to_s(:delimited)
|
|
12
|
-
#
|
|
13
|
-
# # good
|
|
14
|
-
# to_formatted_s(:delimited)
|
|
15
|
-
#
|
|
16
|
-
class ToSWithArgument < Base
|
|
17
|
-
extend AutoCorrector
|
|
18
|
-
|
|
19
|
-
MSG = 'Use `to_formatted_s(...)` instead of `to_s(...)`.'
|
|
20
|
-
|
|
21
|
-
RESTRICT_ON_SEND = %i[to_s].freeze
|
|
22
|
-
|
|
23
|
-
# @!method to_s_with_any_argument?(node)
|
|
24
|
-
def_node_matcher :to_s_with_any_argument?, <<~PATTERN
|
|
25
|
-
(call _ :to_s _+)
|
|
26
|
-
PATTERN
|
|
27
|
-
|
|
28
|
-
def on_send(node)
|
|
29
|
-
return unless to_s_with_any_argument?(node)
|
|
30
|
-
|
|
31
|
-
add_offense(node) do |rewriter|
|
|
32
|
-
rewriter.replace(
|
|
33
|
-
node.loc.selector,
|
|
34
|
-
'to_formatted_s'
|
|
35
|
-
)
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
alias on_csend on_send
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|