sevencop 0.12.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: adcb3382c32455ca63651bf5593974e773cf00dfd0b3d14955541c6ce219c6c7
4
- data.tar.gz: d6f50b292bb6f56c0f6ec36fc4271c931af4c1c46cef9b8c14a2505cf984f8ed
3
+ metadata.gz: ed778fc5bb1459cd5c3c35812b5274177e48515b434b2581c897f40ae6d47448
4
+ data.tar.gz: 179393f59351517e7d510cdf5a1a4c0762d2b2f64186f0f8470017125ae42d77
5
5
  SHA512:
6
- metadata.gz: 552d6582fc4aa3baa550afd6d27477c822e4f098b470c0c038a36380c6ab74f9962a27e8f04be05cc60586be43376de1ec20a0a5b56587d71b24d3fa36e8e4cb
7
- data.tar.gz: 05df622c8de515879b816077ba5fc40cd47858c1666390beac8d2ac29e86c1983921d5d8964b8b7de64106e789f3217032b6338a9988442207dbe5aeb62a8031
6
+ metadata.gz: cc12be9dc75e7507094a9349560ce08f8e9d5e61755837d2747fd101763b51885383b4d4f3416571303ea9e8e593ed0dc99cc6581206c248a82a41c5ce53a874
7
+ data.tar.gz: 96286dac7849f571eac18cfde45e76b81044f0381246943082f003abab28109b9f1b19c9127e013a260d1deb7654b6e67a03133714caa9d86b02dc6830645660
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sevencop (0.12.1)
4
+ sevencop (0.13.0)
5
5
  rubocop
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -88,25 +88,6 @@ belongs_to :group, options
88
88
 
89
89
  This is useful for migration of `config.active_record.belongs_to_required_by_default`.
90
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
91
  ### Sevencop/HashLiteralOrder
111
92
 
112
93
  Sort Hash literal entries by key.
@@ -145,6 +126,24 @@ RSpec.describe User
145
126
  RSpec.describe User, type: :request
146
127
  ```
147
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
+
148
147
  ### Sevencop/MethodDefinitionMultilineArguments
149
148
 
150
149
  Inserts new lines between method definition parameters.
@@ -183,24 +182,6 @@ reorder('field(id, ?)', a)
183
182
  reorder(Arel.sql('field(id, ?)'), a)
184
183
  ```
185
184
 
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
185
  ### Sevencop/UniquenessValidatorExplicitCaseSensitivity
205
186
 
206
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.0'
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`.
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sevencop
4
- VERSION = '0.12.1'
4
+ VERSION = '0.13.0'
5
5
  end
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.12.1
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-23 00:00:00.000000000 Z
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