sevencop 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b59b9e87fae854412dd7555c8e0afb4d6c8c5e2a4a629ceb0b5840d94bfbd25c
4
- data.tar.gz: d2a7a9cf5eb6b2722e44bb1f29f84ff3557e8be03fab8ecfd7441fb5723b64ec
3
+ metadata.gz: 6671a53ba1051be4f4ea86dc41b3c4d4adfef282c8ca1078ea4271161e0e54ac
4
+ data.tar.gz: aea5e2be6ae30fe9ca7ba5237e3444cebe5e71ab7352b03f2929fef8c71fccd9
5
5
  SHA512:
6
- metadata.gz: a8be2a642fcda52bb7b779032bb1714366ef300a44fc2b0d435333c0239d16b7aff7802e8a43206a65e105e328c6d42c400fbf132d2baa40eecadbf54e16b177
7
- data.tar.gz: 8581bf84c297111f877db7d3e51eeddea2c1000af8ebaae49dbac164f229d9e73f7ef878a4cfe8520d8a40d1ec01954b04eaafe4370a3e7359e78f8573a45715
6
+ metadata.gz: 1ad6a03a60543e5171f8d41a0d8b257d7fe7b0141c1f2922556b89e8b1e068e3e68ea5db5ef1a941acdb4b2674898d25077e98c5f1c6e0abebb0d73b3aa7ffc2
7
+ data.tar.gz: af5b8df28c323361fe79082e26dc6d3910b1bc1d7bf8f1bb9d6d9321ba2a525615bc5fc65cbc24e47a5fccab2cd2a1271315c461cf32495b55a9494363c2b934
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.2.0 - 2022-06-07
6
+
7
+ ### Changed
8
+
9
+ - Correct to enforced operation at `Sevencop/RedundantExistenceCheck`.
10
+
5
11
  ## 0.1.0 - 2022-06-07
6
12
 
7
13
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sevencop (0.1.0)
4
+ sevencop (0.2.0)
5
5
  rubocop (>= 1.27)
6
6
 
7
7
  GEM
@@ -6,8 +6,7 @@ module RuboCop
6
6
  # Identifies redundant existent check before file operation.
7
7
  #
8
8
  # @safety
9
- # This cop is unsafe because it can register a false positive
10
- # where the check is truly needed.
9
+ # This cop is unsafe because it can register a false positive where the check is truly needed.
11
10
  #
12
11
  # @example
13
12
  #
@@ -15,13 +14,13 @@ module RuboCop
15
14
  # FileUtils.mkdir(a) unless FileTest.exist?(a)
16
15
  #
17
16
  # # good
18
- # FileUtils.mkdir(a)
17
+ # FileUtils.mkdir_p(a)
19
18
  #
20
19
  # # bad
21
- # FileUtils.rm(a) if FileTest.exist?(a)
20
+ # FileUtils.rm(a) if File.exist?(a)
22
21
  #
23
22
  # # good
24
- # FileUtils.rm(a)
23
+ # FileUtils.rm_f(a)
25
24
  #
26
25
  class RedundantExistenceCheck < Base
27
26
  extend AutoCorrector
@@ -31,6 +30,11 @@ module RuboCop
31
30
  :FileTest,
32
31
  ]
33
32
 
33
+ CLASS_NAMES_FOR_OPERATION = ::Set[
34
+ :File,
35
+ :FileUtils,
36
+ ]
37
+
34
38
  METHOD_NAMES_FOR_MAKE = ::Set[
35
39
  :makedirs,
36
40
  :mkdir,
@@ -40,6 +44,7 @@ module RuboCop
40
44
  ]
41
45
 
42
46
  METHOD_NAMES_FOR_REMOVE = ::Set[
47
+ :delete,
43
48
  :remove,
44
49
  :remove_dir,
45
50
  :remove_entry,
@@ -52,6 +57,7 @@ module RuboCop
52
57
  :rmdir,
53
58
  :rmtree,
54
59
  :safe_unlink,
60
+ :unlink,
55
61
  ]
56
62
 
57
63
  METHOD_NAMES_FOR_EXIST = ::Set[
@@ -59,72 +65,120 @@ module RuboCop
59
65
  :exists?,
60
66
  ]
61
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
+
62
85
  MSG = 'Avoid redundant existent check before file operation.'
63
86
 
64
87
  def_node_matcher :make_unless_exist?, <<~PATTERN
65
88
  (if
66
89
  (send (const nil? CLASS_NAMES_FOR_EXIST) METHOD_NAMES_FOR_EXIST _)
67
90
  nil?
68
- (send (const nil? :FileUtils) METHOD_NAMES_FOR_MAKE ...)
91
+ (send (const nil? CLASS_NAMES_FOR_OPERATION) METHOD_NAMES_FOR_MAKE ...)
69
92
  )
70
93
  PATTERN
71
94
 
72
95
  def_node_matcher :remove_if_exist?, <<~PATTERN
73
96
  (if
74
97
  (send (const nil? CLASS_NAMES_FOR_EXIST) METHOD_NAMES_FOR_EXIST _)
75
- (send (const nil? :FileUtils) METHOD_NAMES_FOR_REMOVE ...)
98
+ (send (const nil? CLASS_NAMES_FOR_OPERATION) METHOD_NAMES_FOR_REMOVE ...)
76
99
  nil?
77
100
  )
78
101
  PATTERN
79
102
 
80
103
  def on_if(node)
81
- if redundant_on_if(node)
82
- add_offense(node) do |rewriter|
83
- remove_if(
84
- node: node,
85
- rewriter: rewriter
86
- )
87
- end
88
- elsif redundant_on_unless(node)
89
- add_offense(node) do |rewriter|
90
- remove_unless(
91
- node: node,
92
- rewriter: rewriter
93
- )
94
- end
104
+ return unless redundant_on_if(node) || redundant_on_unless(node)
105
+
106
+ add_offense(node) do |corrector|
107
+ corrector.replace(
108
+ node.location.expression,
109
+ enforce(node)
110
+ )
95
111
  end
96
112
  end
97
113
 
98
114
  private
99
115
 
100
- def redundant_on_if(node)
101
- remove_if_exist?(node) && same_argument_on_if(node)
116
+ def enforce(node)
117
+ if force_operation?(node)
118
+ node.if_branch.source
119
+ elsif force_replaceable_method?(node)
120
+ enforce_by_replacement(node)
121
+ else
122
+ enforce_by_force_option(node)
123
+ end
102
124
  end
103
125
 
104
- def redundant_on_unless(node)
105
- make_unless_exist?(node) && same_argument_on_unless(node)
126
+ def enforce_by_force_option(node)
127
+ arguments = node.if_branch.arguments.map(&:source)
128
+ arguments << 'force: true' unless force_operation?(node)
129
+ format(
130
+ '%<receiver>s.%<method_name>s(%<arguments>s)',
131
+ arguments: arguments.join(', '),
132
+ method_name: node.if_branch.method_name,
133
+ receiver: node.if_branch.receiver.source
134
+ )
106
135
  end
107
136
 
108
- def remove_if(node:, rewriter:)
109
- rewriter.replace(
110
- node.location.expression,
111
- node.children[1].source
137
+ def enforce_by_replacement(node)
138
+ format(
139
+ '%<signature>s(%<arguments>s)',
140
+ arguments: node.if_branch.arguments.map(&:source).join(', '),
141
+ signature: METHOD_MAPPING_FOR_FORCE_REPLACEMENT[operation_method_signature(node)]
112
142
  )
113
143
  end
114
144
 
115
- def remove_unless(node:, rewriter:)
116
- rewriter.replace(
117
- node.location.expression,
118
- node.children[2].source
119
- )
145
+ def force_operation?(node)
146
+ force_operation_method_name?(node) || force_operation_argument?(node)
120
147
  end
121
148
 
122
- def same_argument_on_if(node)
123
- node.children[0].children[2] == node.children[1].children[2]
149
+ def force_operation_argument?(node)
150
+ node.if_branch.last_argument.hash_type? &&
151
+ node.if_branch.last_argument.pairs.any? do |pair|
152
+ pair.key.value == :force && pair.value.true_type?
153
+ end
154
+ end
155
+
156
+ def force_operation_method_name?(node)
157
+ METHOD_NAMES_FOR_FORCE_OPERATION.include?(node.if_branch.method_name)
158
+ end
159
+
160
+ def redundant_on_if(node)
161
+ remove_if_exist?(node) && same_argument?(node)
162
+ end
163
+
164
+ def redundant_on_unless(node)
165
+ make_unless_exist?(node) && same_argument?(node)
166
+ end
167
+
168
+ def force_replaceable_method?(node)
169
+ METHOD_MAPPING_FOR_FORCE_REPLACEMENT.key?(operation_method_signature(node))
170
+ end
171
+
172
+ def operation_method_signature(node)
173
+ format(
174
+ '%<receiver>s.%<method_name>s',
175
+ method_name: node.if_branch.method_name,
176
+ receiver: node.if_branch.receiver.source
177
+ )
124
178
  end
125
179
 
126
- def same_argument_on_unless(node)
127
- node.children[0].children[2] == node.children[2].children[2]
180
+ def same_argument?(node)
181
+ node.condition.first_argument == node.if_branch.first_argument
128
182
  end
129
183
  end
130
184
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sevencop
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
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.1.0
4
+ version: 0.2.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-06-06 00:00:00.000000000 Z
11
+ date: 2022-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop