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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2fc5d0adbf2ac9b5c3aa8ac43e1e375f82efa0906710ca38bd41c145c3a2bb41
4
- data.tar.gz: fd8b73bcc7ea73410c6634a3dbd5fcb3b38f3af26570482b22a2d05b2f42f6b3
3
+ metadata.gz: ed778fc5bb1459cd5c3c35812b5274177e48515b434b2581c897f40ae6d47448
4
+ data.tar.gz: 179393f59351517e7d510cdf5a1a4c0762d2b2f64186f0f8470017125ae42d77
5
5
  SHA512:
6
- metadata.gz: 9024936b3ef659bae3242f40c793e72249edde9d6838f65edf570039077aad0abebe18ad8e2be52dad270ef4322bce2b841ffc33d42323a151b55b97d86cdc5a
7
- data.tar.gz: 19450fde029f352c3bba68362bb8a0db0c2ec01ceb319702565083768d281613b9bd123b34345f1096350a6bd3eab7efdb89079cd0f63526406f8d6b0b404b9c
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.0)
4
+ sevencop (0.13.0)
5
5
  rubocop
6
6
 
7
7
  GEM
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.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`.
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sevencop
4
- VERSION = '0.12.0'
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.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-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