sevencop 0.9.1 → 0.10.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: 405e633edd8f28955ac15fa662affb4ff70e0296d45dbdc43c75426fa51c7280
4
- data.tar.gz: c943dd42168df6e02e9630ed7eb80050da6d81ed1ea8ac333d19e933b9966a8e
3
+ metadata.gz: ee9785d463d0e83d3f55dc1554e250e826a9cbd5aa6aacb510f11a4bdfb1947a
4
+ data.tar.gz: 9ca8456b525226ba8a599c4ef87f08ea208000268fa73ccf9f1501531682d294
5
5
  SHA512:
6
- metadata.gz: 8ff7ec748e6078d83c4e5215ade19f42eadffeb46a1fdcdb653712d8a8f8834bfabebbb9d21253a864384fec30c06e19bd7e120fd58c2d334ca362fbf0b985ba
7
- data.tar.gz: a60a3173ab3b6010563f80860ad6b591e39ba8260b2fe05ba6f0b5230d2e69d9d2441e29d4d2fb2fd5f53e5d32fe27107357a75b9d2e9db3955e63104e1dc6ca
6
+ metadata.gz: edc7f9620eaa81224e47c8e8785df67bc29c51a0c6969f30bd24a3d6869a64be26686ccce7c3b43c89bc89f06b9283b67030587c86eb0b7ef5598d42ee1dc90b
7
+ data.tar.gz: 9a3bf2ecc2eed54ae8dd6207d0f0cd93c13f577bbcab69cdc9992e42f87687e416d9612136f1483952cfb51bdf22890727b14d6d66653e9294732dcb1da8d389
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sevencop (0.9.1)
4
+ sevencop (0.10.0)
5
5
  rubocop
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -67,6 +67,25 @@ belongs_to :group, options
67
67
 
68
68
  This is useful for migration of `config.active_record.belongs_to_required_by_default`.
69
69
 
70
+ ### Sevencop/FactoryBotCreateList
71
+
72
+ Finds possible substitutions for `FactoryBot.create_list`.
73
+
74
+ ```ruby
75
+ # bad
76
+ Array.new(2) do
77
+ create(:user)
78
+ end
79
+
80
+ # good
81
+ create_list(:user, 2)
82
+
83
+ # good
84
+ Array.new(2) do |i|
85
+ create(:user, order: i)
86
+ end
87
+ ```
88
+
70
89
  ### Sevencop/HashLiteralOrder
71
90
 
72
91
  Sort Hash literal entries by key.
data/config/default.yml CHANGED
@@ -5,12 +5,24 @@ Sevencop/BelongsToOptional:
5
5
  Safe: false
6
6
  VersionAdded: '0.5'
7
7
 
8
+ Sevencop/FactoryBotCreateList:
9
+ Description: |
10
+ Finds possible substitutions for `FactoryBot.create_list`.
11
+ Enabled: false
12
+ VersionAdded: '0.10'
13
+
8
14
  Sevencop/HashLiteralOrder:
9
15
  Description: |
10
16
  Sort Hash literal entries by key.
11
17
  Enabled: false
12
18
  VersionAdded: '0.6'
13
19
 
20
+ Sevencop/InferredSpecType:
21
+ Description: |
22
+ Identifies redundant spec type.
23
+ Enabled: false
24
+ VersionAdded: '0.9'
25
+
14
26
  Sevencop/OrderField:
15
27
  Description: |
16
28
  Wrap safe SQL String by `Arel.sql`.
@@ -0,0 +1,94 @@
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
+
53
+ private
54
+
55
+ # @!method extract(node)
56
+ # @param node [RuboCop::AST::BlockNode]
57
+ # @return [Array(Integer, RuboCop::AST::SendNode)]
58
+ def_node_matcher :extract, <<~PATTERN
59
+ (block
60
+ (send
61
+ (const {nil? | cbase} :Array)
62
+ :new
63
+ $(int _)
64
+ )
65
+ (args)
66
+ (send
67
+ nil?
68
+ :create
69
+ $(sym _) $(...)?
70
+ )
71
+ )
72
+ PATTERN
73
+
74
+ # @param corrector [RuboCop::Cop::Corrector]
75
+ # @param node [RuboCop::AST::BlockNode]
76
+ # @return [void]
77
+ def autocorrect(corrector, node)
78
+ count_node, factory_name_node, extra_argument_nodes = extract(node)
79
+ corrector.replace(
80
+ node,
81
+ format(
82
+ 'create_list(%<arguments>s)',
83
+ arguments: [
84
+ factory_name_node,
85
+ count_node,
86
+ *extra_argument_nodes
87
+ ].map(&:source).join(', ')
88
+ )
89
+ )
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -55,13 +55,13 @@ module RuboCop
55
55
  # @param [RuboCop::AST::HashNode] node
56
56
  # @return [String]
57
57
  def autocorrect(node)
58
- [
59
- '{',
58
+ parts = [
60
59
  whitespace_leading(node),
61
60
  sort(node.pairs).map(&:source).join(",#{whitespace_between(node)}"),
62
- whitespace_trailing(node),
63
- '}'
64
- ].join
61
+ whitespace_trailing(node)
62
+ ]
63
+ parts = ['{', *parts, '}'] if node.braces?
64
+ parts.join
65
65
  end
66
66
 
67
67
  # @param [Array<RuboCop::AST::PairNode>] pairs
@@ -84,7 +84,9 @@ module RuboCop
84
84
  # ^^^
85
85
  def whitespace_between(node)
86
86
  if node.pairs.length >= 2
87
- node.source[node.pairs[0].location.expression.end_pos + 1...node.pairs[1].location.expression.begin_pos]
87
+ processed_source.raw_source[
88
+ node.pairs[0].location.expression.end_pos + 1...node.pairs[1].location.expression.begin_pos
89
+ ]
88
90
  else
89
91
  ' '
90
92
  end
@@ -95,7 +97,9 @@ module RuboCop
95
97
  # { a: 1, b: 1 }
96
98
  # ^^
97
99
  def whitespace_trailing(node)
98
- node.source[node.pairs[-1].location.expression.end_pos...node.location.end.begin_pos]
100
+ processed_source.raw_source[
101
+ node.pairs[-1].location.expression.end_pos...node.location.expression.end.begin_pos - offset_for(node)
102
+ ]
99
103
  end
100
104
 
101
105
  # @param [RuboCop::AST::HashNode] node
@@ -103,7 +107,19 @@ module RuboCop
103
107
  # { a: 1, b: 1 }
104
108
  # ^^^^
105
109
  def whitespace_leading(node)
106
- node.source[node.location.begin.end_pos...node.pairs[0].location.expression.begin_pos]
110
+ processed_source.raw_source[
111
+ node.location.expression.begin.end_pos + offset_for(node)...node.pairs[0].location.expression.begin_pos
112
+ ]
113
+ end
114
+
115
+ # @param [RuboCop::AST::HashNode] node
116
+ # @return [Integer]
117
+ def offset_for(node)
118
+ if node.braces?
119
+ 1
120
+ else
121
+ 0
122
+ end
107
123
  end
108
124
  end
109
125
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+
5
+ module Sevencop
6
+ # Merge default RuboCop config with plugin config.
7
+ class ConfigLoader
8
+ PLUGIN_CONFIG_PATH = ::File.expand_path(
9
+ '../../config/default.yml',
10
+ __dir__
11
+ )
12
+
13
+ class << self
14
+ # @return [RuboCop::Config]
15
+ def call
16
+ new.call
17
+ end
18
+ end
19
+
20
+ # @return [RuboCop::Config]
21
+ def call
22
+ ::RuboCop::ConfigLoader.merge_with_default(
23
+ plugin_config,
24
+ PLUGIN_CONFIG_PATH
25
+ )
26
+ end
27
+
28
+ private
29
+
30
+ # @return [RuboCop::Config]
31
+ def plugin_config
32
+ config = ::RuboCop::Config.new(
33
+ plugin_config_hash,
34
+ PLUGIN_CONFIG_PATH
35
+ )
36
+ config.make_excludes_absolute
37
+ config
38
+ end
39
+
40
+ # @return [Hash]
41
+ def plugin_config_hash
42
+ ::RuboCop::ConfigLoader.send(
43
+ :load_yaml_configuration,
44
+ PLUGIN_CONFIG_PATH
45
+ )
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+
5
+ require_relative 'config_loader'
6
+
7
+ RuboCop::ConfigLoader.instance_variable_set(
8
+ :@default_configuration,
9
+ Sevencop::ConfigLoader.call
10
+ )
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sevencop
4
- VERSION = '0.9.1'
4
+ VERSION = '0.10.0'
5
5
  end
data/lib/sevencop.rb CHANGED
@@ -1,12 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pathname'
4
- require 'yaml'
5
-
6
- require_relative 'sevencop/inject'
3
+ require_relative 'sevencop/rubocop_extension'
7
4
  require_relative 'sevencop/version'
8
5
 
9
6
  require_relative 'rubocop/cop/sevencop/belongs_to_optional'
7
+ require_relative 'rubocop/cop/sevencop/factory_bot_create_list'
10
8
  require_relative 'rubocop/cop/sevencop/hash_literal_order'
11
9
  require_relative 'rubocop/cop/sevencop/inferred_spec_type'
12
10
  require_relative 'rubocop/cop/sevencop/order_field'
@@ -14,15 +12,3 @@ require_relative 'rubocop/cop/sevencop/redundant_existence_check'
14
12
  require_relative 'rubocop/cop/sevencop/to_s_with_argument'
15
13
  require_relative 'rubocop/cop/sevencop/uniqueness_validator_explicit_case_sensitivity'
16
14
  require_relative 'rubocop/cop/sevencop/where_not'
17
-
18
- module Sevencop
19
- PROJECT_ROOT = ::Pathname.new(__dir__).parent.expand_path.freeze
20
-
21
- CONFIG_DEFAULT = PROJECT_ROOT.join('config', 'default.yml').freeze
22
-
23
- CONFIG = ::YAML.safe_load(CONFIG_DEFAULT.read).freeze
24
-
25
- private_constant(:CONFIG_DEFAULT, :PROJECT_ROOT)
26
- end
27
-
28
- Sevencop::Inject.defaults!
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.9.1
4
+ version: 0.10.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-08-19 00:00:00.000000000 Z
11
+ date: 2022-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -42,6 +42,7 @@ files:
42
42
  - Rakefile
43
43
  - config/default.yml
44
44
  - lib/rubocop/cop/sevencop/belongs_to_optional.rb
45
+ - lib/rubocop/cop/sevencop/factory_bot_create_list.rb
45
46
  - lib/rubocop/cop/sevencop/hash_literal_order.rb
46
47
  - lib/rubocop/cop/sevencop/inferred_spec_type.rb
47
48
  - lib/rubocop/cop/sevencop/order_field.rb
@@ -50,7 +51,8 @@ files:
50
51
  - lib/rubocop/cop/sevencop/uniqueness_validator_explicit_case_sensitivity.rb
51
52
  - lib/rubocop/cop/sevencop/where_not.rb
52
53
  - lib/sevencop.rb
53
- - lib/sevencop/inject.rb
54
+ - lib/sevencop/config_loader.rb
55
+ - lib/sevencop/rubocop_extension.rb
54
56
  - lib/sevencop/version.rb
55
57
  - sevencop.gemspec
56
58
  homepage: https://github.com/r7kamura/sevencop
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rubocop'
4
-
5
- # The original code is from https://github.com/rubocop/rubocop-rspec/blob/main/lib/rubocop/rspec/inject.rb
6
- # See https://github.com/rubocop/rubocop-rspec/blob/main/MIT-LICENSE.md
7
- module Sevencop
8
- module Inject
9
- def self.defaults!
10
- path = CONFIG_DEFAULT.to_s
11
- hash = ::RuboCop::ConfigLoader.send(:load_yaml_configuration, path)
12
- config = ::RuboCop::Config.new(hash, path).tap(&:make_excludes_absolute)
13
- puts "configuration from #{path}" if ::RuboCop::ConfigLoader.debug?
14
- config = ::RuboCop::ConfigLoader.merge_with_default(config, path)
15
- ::RuboCop::ConfigLoader.instance_variable_set(:@default_configuration, config)
16
- end
17
- end
18
- end