sevencop 0.12.0 → 0.13.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 +26 -38
- data/config/default.yml +7 -14
- data/lib/rubocop/cop/sevencop/autoload_ordered.rb +19 -2
- data/lib/rubocop/cop/sevencop/method_definition_keyword_arguments_ordered.rb +58 -0
- data/lib/sevencop/version.rb +1 -1
- data/lib/sevencop.rb +1 -2
- metadata +3 -4
- data/lib/rubocop/cop/sevencop/factory_bot_create_list.rb +0 -95
- data/lib/rubocop/cop/sevencop/redundant_existence_check.rb +0 -188
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ed778fc5bb1459cd5c3c35812b5274177e48515b434b2581c897f40ae6d47448
|
|
4
|
+
data.tar.gz: 179393f59351517e7d510cdf5a1a4c0762d2b2f64186f0f8470017125ae42d77
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cc12be9dc75e7507094a9349560ce08f8e9d5e61755837d2747fd101763b51885383b4d4f3416571303ea9e8e593ed0dc99cc6581206c248a82a41c5ce53a874
|
|
7
|
+
data.tar.gz: 96286dac7849f571eac18cfde45e76b81044f0381246943082f003abab28109b9f1b19c9127e013a260d1deb7654b6e67a03133714caa9d86b02dc6830645660
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -49,7 +49,7 @@ All cops are `Enabled: false` by default.
|
|
|
49
49
|
|
|
50
50
|
### Sevencop/AutoloadOrdered
|
|
51
51
|
|
|
52
|
-
Sort `autoload` in alphabetical order.
|
|
52
|
+
Sort `autoload` in alphabetical order within their section.
|
|
53
53
|
|
|
54
54
|
```ruby
|
|
55
55
|
# bad
|
|
@@ -59,6 +59,13 @@ autoload :A, 'a'
|
|
|
59
59
|
# good
|
|
60
60
|
autoload :A, 'a'
|
|
61
61
|
autoload :B, 'b'
|
|
62
|
+
|
|
63
|
+
# good
|
|
64
|
+
autoload :B, 'b'
|
|
65
|
+
autoload :D, 'd'
|
|
66
|
+
|
|
67
|
+
autoload :A, 'a'
|
|
68
|
+
autoload :C, 'a'
|
|
62
69
|
```
|
|
63
70
|
|
|
64
71
|
### Sevencop/BelongsToOptional
|
|
@@ -81,25 +88,6 @@ belongs_to :group, options
|
|
|
81
88
|
|
|
82
89
|
This is useful for migration of `config.active_record.belongs_to_required_by_default`.
|
|
83
90
|
|
|
84
|
-
### Sevencop/FactoryBotCreateList
|
|
85
|
-
|
|
86
|
-
Finds possible substitutions for `FactoryBot.create_list`.
|
|
87
|
-
|
|
88
|
-
```ruby
|
|
89
|
-
# bad
|
|
90
|
-
Array.new(2) do
|
|
91
|
-
create(:user)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
# good
|
|
95
|
-
create_list(:user, 2)
|
|
96
|
-
|
|
97
|
-
# good
|
|
98
|
-
Array.new(2) do |i|
|
|
99
|
-
create(:user, order: i)
|
|
100
|
-
end
|
|
101
|
-
```
|
|
102
|
-
|
|
103
91
|
### Sevencop/HashLiteralOrder
|
|
104
92
|
|
|
105
93
|
Sort Hash literal entries by key.
|
|
@@ -138,6 +126,24 @@ RSpec.describe User
|
|
|
138
126
|
RSpec.describe User, type: :request
|
|
139
127
|
```
|
|
140
128
|
|
|
129
|
+
### Sevencop/MethodDefinitionKeywordArgumentsOrdered
|
|
130
|
+
|
|
131
|
+
Sort method definition keyword arguments in alphabetical order.
|
|
132
|
+
|
|
133
|
+
```ruby
|
|
134
|
+
# bad
|
|
135
|
+
def foo(b:, a:); end
|
|
136
|
+
|
|
137
|
+
# good
|
|
138
|
+
def foo(a:, b:); end
|
|
139
|
+
|
|
140
|
+
# bad
|
|
141
|
+
def foo(c:, d:, b: 1, a: 2); end
|
|
142
|
+
|
|
143
|
+
# good
|
|
144
|
+
def foo(c:, d:, a: 2, b: 1); end
|
|
145
|
+
```
|
|
146
|
+
|
|
141
147
|
### Sevencop/MethodDefinitionMultilineArguments
|
|
142
148
|
|
|
143
149
|
Inserts new lines between method definition parameters.
|
|
@@ -176,24 +182,6 @@ reorder('field(id, ?)', a)
|
|
|
176
182
|
reorder(Arel.sql('field(id, ?)'), a)
|
|
177
183
|
```
|
|
178
184
|
|
|
179
|
-
### Sevencop/RedundantExistenceCheck
|
|
180
|
-
|
|
181
|
-
Identifies redundant existent check before file operation.
|
|
182
|
-
|
|
183
|
-
```ruby
|
|
184
|
-
# bad
|
|
185
|
-
FileUtils.mkdir(a) unless FileTest.exist?(a)
|
|
186
|
-
|
|
187
|
-
# good
|
|
188
|
-
FileUtils.mkdir_p(a)
|
|
189
|
-
|
|
190
|
-
# bad
|
|
191
|
-
FileUtils.rm(a) if FileTest.exist?(a)
|
|
192
|
-
|
|
193
|
-
# good
|
|
194
|
-
FileUtils.rm_f(a)
|
|
195
|
-
```
|
|
196
|
-
|
|
197
185
|
### Sevencop/UniquenessValidatorExplicitCaseSensitivity
|
|
198
186
|
|
|
199
187
|
Identifies use of UniquenessValidator without :case_sensitive option.
|
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,12 +11,6 @@ Sevencop/BelongsToOptional:
|
|
|
11
11
|
Safe: false
|
|
12
12
|
VersionAdded: '0.5'
|
|
13
13
|
|
|
14
|
-
Sevencop/FactoryBotCreateList:
|
|
15
|
-
Description: |
|
|
16
|
-
Finds possible substitutions for `FactoryBot.create_list`.
|
|
17
|
-
Enabled: false
|
|
18
|
-
VersionAdded: '0.10'
|
|
19
|
-
|
|
20
14
|
Sevencop/HashLiteralOrder:
|
|
21
15
|
Description: |
|
|
22
16
|
Sort Hash literal entries by key.
|
|
@@ -29,6 +23,12 @@ Sevencop/InferredSpecType:
|
|
|
29
23
|
Enabled: false
|
|
30
24
|
VersionAdded: '0.9'
|
|
31
25
|
|
|
26
|
+
Sevencop/MethodDefinitionKeywordArgumentsOrdered:
|
|
27
|
+
Description: |
|
|
28
|
+
Sort method definition keyword arguments in alphabetical order.
|
|
29
|
+
Enabled: false
|
|
30
|
+
VersionAdded: '0.13'
|
|
31
|
+
|
|
32
32
|
Sevencop/MethodDefinitionMultilineArguments:
|
|
33
33
|
Description: |
|
|
34
34
|
Inserts new lines between method definition parameters.
|
|
@@ -42,13 +42,6 @@ Sevencop/OrderField:
|
|
|
42
42
|
Safe: false
|
|
43
43
|
VersionAdded: '0.4'
|
|
44
44
|
|
|
45
|
-
Sevencop/RedundantExistenceCheck:
|
|
46
|
-
Description: |
|
|
47
|
-
Avoid redundant existent check before file operation.
|
|
48
|
-
Enabled: false
|
|
49
|
-
Safe: false
|
|
50
|
-
VersionAdded: '0.1'
|
|
51
|
-
|
|
52
45
|
Sevencop/ToSWithArgument:
|
|
53
46
|
Description: |
|
|
54
47
|
Identifies passing any argument to `#to_s`.
|
|
@@ -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 within their section.
|
|
7
7
|
#
|
|
8
8
|
# @example
|
|
9
9
|
# # bad
|
|
@@ -13,12 +13,19 @@ module RuboCop
|
|
|
13
13
|
# # good
|
|
14
14
|
# autoload :A, 'a'
|
|
15
15
|
# autoload :B, 'b'
|
|
16
|
+
#
|
|
17
|
+
# # good
|
|
18
|
+
# autoload :A, 'a'
|
|
19
|
+
# autoload :D, 'd'
|
|
20
|
+
#
|
|
21
|
+
# autoload :B, 'b'
|
|
22
|
+
# autoload :C, 'c'
|
|
16
23
|
class AutoloadOrdered < Base
|
|
17
24
|
extend AutoCorrector
|
|
18
25
|
|
|
19
26
|
include RangeHelp
|
|
20
27
|
|
|
21
|
-
MSG = 'Sort `autoload` in alphabetical order.'
|
|
28
|
+
MSG = 'Sort `autoload` in alphabetical order within their section.'
|
|
22
29
|
|
|
23
30
|
RESTRICT_ON_SEND = %i[
|
|
24
31
|
autoload
|
|
@@ -52,11 +59,21 @@ module RuboCop
|
|
|
52
59
|
node.left_siblings.find do |sibling|
|
|
53
60
|
next unless sibling.send_type?
|
|
54
61
|
next unless sibling.method?(:autoload)
|
|
62
|
+
next unless in_same_section?(sibling, node)
|
|
55
63
|
|
|
56
64
|
node.first_argument.source < sibling.first_argument.source
|
|
57
65
|
end
|
|
58
66
|
end
|
|
59
67
|
|
|
68
|
+
# @param node1 [RuboCop::AST::SendNode]
|
|
69
|
+
# @param node2 [RuboCop::AST::SendNode]
|
|
70
|
+
# @return [Boolean]
|
|
71
|
+
def in_same_section?(node1, node2)
|
|
72
|
+
!node1.location.expression.with(
|
|
73
|
+
end_pos: node2.location.expression.end_pos
|
|
74
|
+
).source.include?("\n\n")
|
|
75
|
+
end
|
|
76
|
+
|
|
60
77
|
# @param range1 [Paresr::Source::Range]
|
|
61
78
|
# @param range2 [Paresr::Source::Range]
|
|
62
79
|
# @param corrector [RuboCop::AST::Corrector]
|
|
@@ -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
|
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/factory_bot_create_list'
|
|
9
8
|
require_relative 'rubocop/cop/sevencop/hash_literal_order'
|
|
10
9
|
require_relative 'rubocop/cop/sevencop/inferred_spec_type'
|
|
10
|
+
require_relative 'rubocop/cop/sevencop/method_definition_keyword_arguments_ordered'
|
|
11
11
|
require_relative 'rubocop/cop/sevencop/method_definition_multiline_arguments'
|
|
12
12
|
require_relative 'rubocop/cop/sevencop/order_field'
|
|
13
|
-
require_relative 'rubocop/cop/sevencop/redundant_existence_check'
|
|
14
13
|
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.13.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-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rubocop
|
|
@@ -43,12 +43,11 @@ 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/factory_bot_create_list.rb
|
|
47
46
|
- lib/rubocop/cop/sevencop/hash_literal_order.rb
|
|
48
47
|
- lib/rubocop/cop/sevencop/inferred_spec_type.rb
|
|
48
|
+
- lib/rubocop/cop/sevencop/method_definition_keyword_arguments_ordered.rb
|
|
49
49
|
- lib/rubocop/cop/sevencop/method_definition_multiline_arguments.rb
|
|
50
50
|
- lib/rubocop/cop/sevencop/order_field.rb
|
|
51
|
-
- lib/rubocop/cop/sevencop/redundant_existence_check.rb
|
|
52
51
|
- 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
|
|
@@ -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
|