sevencop 0.12.0 → 0.13.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: 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