sevencop 0.9.1 → 0.10.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: 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