rubocop-rspec 2.21.0 → 2.23.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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/README.md +1 -1
  4. data/config/default.yml +37 -16
  5. data/config/obsoletion.yml +6 -0
  6. data/lib/rubocop/cop/rspec/empty_example_group.rb +3 -0
  7. data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +11 -4
  8. data/lib/rubocop/cop/rspec/expect_actual.rb +2 -2
  9. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +25 -118
  10. data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +40 -107
  11. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +30 -250
  12. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +19 -46
  13. data/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb +23 -64
  14. data/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb +45 -79
  15. data/lib/rubocop/cop/rspec/focus.rb +13 -0
  16. data/lib/rubocop/cop/rspec/indexed_let.rb +32 -1
  17. data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
  18. data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
  19. data/lib/rubocop/cop/rspec/let_before_examples.rb +4 -0
  20. data/lib/rubocop/cop/rspec/named_subject.rb +1 -1
  21. data/lib/rubocop/cop/rspec/pending.rb +12 -2
  22. data/lib/rubocop/cop/rspec/predicate_matcher.rb +3 -3
  23. data/lib/rubocop/cop/rspec/rails/negation_be_valid.rb +92 -0
  24. data/lib/rubocop/cop/rspec/receive_messages.rb +155 -0
  25. data/lib/rubocop/cop/rspec/verified_double_reference.rb +1 -1
  26. data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
  27. data/lib/rubocop/cop/rspec_cops.rb +2 -0
  28. data/lib/rubocop/rspec/config_formatter.rb +6 -0
  29. data/lib/rubocop/rspec/version.rb +1 -1
  30. data/lib/rubocop-rspec.rb +1 -3
  31. metadata +18 -4
  32. data/lib/rubocop/rspec/factory_bot/language.rb +0 -37
  33. data/lib/rubocop/rspec/factory_bot.rb +0 -64
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5a388b40471f85e4da35358c9c9c0ab8bdce272c171b989553a174ea5f2fa04f
4
- data.tar.gz: 251c7b2c7f83daeb4f3e3f4e10f1b0f37763088ac792982e27052da26c1645ea
3
+ metadata.gz: e0eebbfb772c1598b0ee4cfe88c74d8b81171e197dbd4d5dc6020df95005440e
4
+ data.tar.gz: 2936be502e0062b94a0346bd98696194fd33fe6f7693f8c92bc38a952ee31b26
5
5
  SHA512:
6
- metadata.gz: 6311a48d125da92639f8bebbeebdd9b16e7968bf2b522d29310c913490977a465aa77112e39497880373be23732a2fb3cfa205b92475e2edd069c1009ae91aac
7
- data.tar.gz: fd3d495d5ec63969e2d926c5c151cf888de321b74486644983c6aa72b3c18b071daafe19b0996a0fa476334d00bf05768c09ae4ce03d39bbdf436898b64809c0
6
+ metadata.gz: 14e3e53093b7e104ab212217fdc8226a909fba9bdd84fa44c22963cf8e62d17ce858a2180b8b5b3727b5dd2a74a9b4c6e2139d8d61cbc6595b2c46f9022214af
7
+ data.tar.gz: 9408c50d35ae50e1825fef43f2c6a6def0d87e44bfbbd968bb19996b1a867f215df36ab62d451af892e6855c4330c0d4fb9d09b8400ff5f35b4ecef1cfb86adb
data/CHANGELOG.md CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 2.23.0 (2023-07-30)
6
+
7
+ - Add new `RSpec/Rails/NegationBeValid` cop. ([@ydah])
8
+ - Fix a false negative for `RSpec/ExcessiveDocstringSpacing` when finds description with em space. ([@ydah])
9
+ - Fix a false positive for `RSpec/EmptyExampleGroup` when example group with examples defined in `if` branch inside iterator. ([@ydah])
10
+ - Update the message output of `RSpec/ExpectActual` to include the word 'value'. ([@corydiamand])
11
+ - Fix a false negative for `RSpec/Pending` when `it` without body. ([@ydah])
12
+ - Add new `RSpec/ReceiveMessages` cop. ([@ydah])
13
+ - Change default.yml path to use `**/spec/*` instead of `spec/*`. ([@ydah])
14
+ - Add `AllowedIdentifiers` and `AllowedPatterns` configuration option to `RSpec/IndexedLet`. ([@ydah])
15
+ - Fix `RSpec/NamedSubject` when block has no body. ([@splattael])
16
+ - Fix `RSpec/LetBeforeExamples` autocorrect incompatible with `RSpec/ScatteredLet` autocorrect. ([@ydah])
17
+ - Update `RSpec/Focus` to support `shared_context` and `shared_examples` ([@tmaier])
18
+
19
+ ## 2.22.0 (2023-05-06)
20
+
21
+ - Extract factory_bot cops to a separate repository, [`rubocop-factory_bot`](https://github.com/rubocop/rubocop-factory_bot). The `rubocop-factory_bot` repository is a dependency of `rubocop-rspec` and the factory_bot cops are aliased (`RSpec/FactoryBot/Foo` == `FactoryBot/Foo`) until v3.0 is released, so the change will be invisible to users until then. ([@ydah])
22
+
5
23
  ## 2.21.0 (2023-05-05)
6
24
 
7
25
  - Fix a false positive in `RSpec/IndexedLet` with suffixes after index-like numbers. ([@pirj])
@@ -777,6 +795,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
777
795
  [@cfabianski]: https://github.com/cfabianski
778
796
  [@clupprich]: https://github.com/clupprich
779
797
  [@composerinteralia]: https://github.com/composerinteralia
798
+ [@corydiamand]: https://github.com/corydiamand
780
799
  [@darhazer]: https://github.com/Darhazer
781
800
  [@daveworth]: https://github.com/daveworth
782
801
  [@dduugg]: https://github.com/dduugg
@@ -855,6 +874,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
855
874
  [@seanpdoyle]: https://github.com/seanpdoyle
856
875
  [@sl4vr]: https://github.com/sl4vr
857
876
  [@smcgivern]: https://github.com/smcgivern
877
+ [@splattael]: https://github.com/splattael
858
878
  [@stephannv]: https://github.com/stephannv
859
879
  [@t3h2mas]: https://github.com/t3h2mas
860
880
  [@tdeo]: https://github.com/tdeo
@@ -862,6 +882,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
862
882
  [@telmofcosta]: https://github.com/telmofcosta
863
883
  [@tietew]: https://github.com/Tietew
864
884
  [@timrogers]: https://github.com/timrogers
885
+ [@tmaier]: https://github.com/tmaier
865
886
  [@topalovic]: https://github.com/topalovic
866
887
  [@twalpole]: https://github.com/twalpole
867
888
  [@vzvu3k6k]: https://github.com/vzvu3k6k
data/README.md CHANGED
@@ -17,7 +17,7 @@ gem install rubocop-rspec
17
17
 
18
18
  or if you use bundler put this in your `Gemfile`
19
19
 
20
- ```
20
+ ```ruby
21
21
  gem 'rubocop-rspec', require: false
22
22
  ```
23
23
 
data/config/default.yml CHANGED
@@ -181,10 +181,11 @@ RSpec/BeforeAfterAll:
181
181
  Description: Check that before/after(:all) isn't being used.
182
182
  Enabled: true
183
183
  Exclude:
184
- - spec/spec_helper.rb
185
- - spec/rails_helper.rb
186
- - spec/support/**/*.rb
184
+ - "**/spec/spec_helper.rb"
185
+ - "**/spec/rails_helper.rb"
186
+ - "**/spec/support/**/*.rb"
187
187
  VersionAdded: '1.12'
188
+ VersionChanged: '2.23'
188
189
  StyleGuide: https://rspec.rubystyle.guide/#avoid-hooks-with-context-scope
189
190
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll
190
191
 
@@ -404,8 +405,9 @@ RSpec/ExpectActual:
404
405
  Description: Checks for `expect(...)` calls containing literal values.
405
406
  Enabled: true
406
407
  Exclude:
407
- - spec/routing/**/*
408
+ - "**/spec/routing/**/*"
408
409
  VersionAdded: '1.7'
410
+ VersionChanged: '2.23'
409
411
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectActual
410
412
 
411
413
  RSpec/ExpectChange:
@@ -513,8 +515,11 @@ RSpec/IndexedLet:
513
515
  Description: Do not set up test data using indexes (e.g., `item_1`, `item_2`).
514
516
  Enabled: pending
515
517
  VersionAdded: '2.20'
518
+ VersionChanged: '2.23'
516
519
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IndexedLet
517
520
  Max: 1
521
+ AllowedIdentifiers: []
522
+ AllowedPatterns: []
518
523
 
519
524
  RSpec/InstanceSpy:
520
525
  Description: Checks for `instance_double` used with `have_received`.
@@ -725,6 +730,12 @@ RSpec/ReceiveCounts:
725
730
  VersionAdded: '1.26'
726
731
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveCounts
727
732
 
733
+ RSpec/ReceiveMessages:
734
+ Description: Checks for multiple messages stubbed on the same object.
735
+ Enabled: pending
736
+ VersionAdded: '2.23'
737
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveMessages
738
+
728
739
  RSpec/ReceiveNever:
729
740
  Description: Prefer `not_to receive(...)` over `receive(...).never`.
730
741
  Enabled: true
@@ -974,11 +985,11 @@ RSpec/FactoryBot/AttributeDefinedStatically:
974
985
  Description: Always declare attribute values as blocks.
975
986
  Enabled: true
976
987
  Include:
977
- - spec/factories.rb
978
- - spec/factories/**/*.rb
979
- - features/support/factories/**/*.rb
988
+ - "**/spec/factories.rb"
989
+ - "**/spec/factories/**/*.rb"
990
+ - "**/features/support/factories/**/*.rb"
980
991
  VersionAdded: '1.28'
981
- VersionChanged: '2.0'
992
+ VersionChanged: '2.23'
982
993
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/AttributeDefinedStatically
983
994
 
984
995
  RSpec/FactoryBot/ConsistentParenthesesStyle:
@@ -997,26 +1008,26 @@ RSpec/FactoryBot/CreateList:
997
1008
  Include:
998
1009
  - "**/*_spec.rb"
999
1010
  - "**/spec/**/*"
1000
- - spec/factories.rb
1001
- - spec/factories/**/*.rb
1002
- - features/support/factories/**/*.rb
1011
+ - "**/spec/factories.rb"
1012
+ - "**/spec/factories/**/*.rb"
1013
+ - "**/features/support/factories/**/*.rb"
1003
1014
  EnforcedStyle: create_list
1004
1015
  SupportedStyles:
1005
1016
  - create_list
1006
1017
  - n_times
1007
1018
  VersionAdded: '1.25'
1008
- VersionChanged: '2.0'
1019
+ VersionChanged: '2.23'
1009
1020
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/CreateList
1010
1021
 
1011
1022
  RSpec/FactoryBot/FactoryClassName:
1012
1023
  Description: Use string value when setting the class attribute explicitly.
1013
1024
  Enabled: true
1014
1025
  Include:
1015
- - spec/factories.rb
1016
- - spec/factories/**/*.rb
1017
- - features/support/factories/**/*.rb
1026
+ - "**/spec/factories.rb"
1027
+ - "**/spec/factories/**/*.rb"
1028
+ - "**/features/support/factories/**/*.rb"
1018
1029
  VersionAdded: '1.37'
1019
- VersionChanged: '2.0'
1030
+ VersionChanged: '2.23'
1020
1031
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryClassName
1021
1032
 
1022
1033
  RSpec/FactoryBot/FactoryNameStyle:
@@ -1095,6 +1106,16 @@ RSpec/Rails/MinitestAssertions:
1095
1106
  VersionAdded: '2.17'
1096
1107
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/MinitestAssertions
1097
1108
 
1109
+ RSpec/Rails/NegationBeValid:
1110
+ Description: Enforces use of `be_invalid` or `not_to` for negated be_valid.
1111
+ EnforcedStyle: not_to
1112
+ SupportedStyles:
1113
+ - not_to
1114
+ - be_invalid
1115
+ Enabled: pending
1116
+ VersionAdded: '2.23'
1117
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/NegationBeValid
1118
+
1098
1119
  RSpec/Rails/TravelAround:
1099
1120
  Description: Prefer to travel in `before` rather than `around`.
1100
1121
  Enabled: pending
@@ -21,3 +21,9 @@ renamed:
21
21
  RSpec/Capybara/SpecificFinders: Capybara/SpecificFinders
22
22
  RSpec/Capybara/SpecificMatcher: Capybara/SpecificMatcher
23
23
  RSpec/Capybara/VisibilityMatcher: Capybara/VisibilityMatcher
24
+ RSpec/FactoryBot/AttributeDefinedStatically: FactoryBot/AttributeDefinedStatically
25
+ RSpec/FactoryBot/ConsistentParenthesesStyle: FactoryBot/ConsistentParenthesesStyle
26
+ RSpec/FactoryBot/CreateList: FactoryBot/CreateList
27
+ RSpec/FactoryBot/FactoryClassName: FactoryBot/FactoryClassName
28
+ RSpec/FactoryBot/FactoryNameStyle: FactoryBot/FactoryNameStyle
29
+ RSpec/FactoryBot/SyntaxMethods: FactoryBot/SyntaxMethods
@@ -131,6 +131,7 @@ module RuboCop
131
131
  {
132
132
  #examples_directly_or_in_block?
133
133
  (begin <#examples_directly_or_in_block? ...>)
134
+ (begin <#examples_in_branches? ...>)
134
135
  }
135
136
  PATTERN
136
137
 
@@ -169,6 +170,8 @@ module RuboCop
169
170
  end
170
171
 
171
172
  def examples_in_branches?(condition_node)
173
+ return if !condition_node.if_type? && !condition_node.case_type?
174
+
172
175
  condition_node.branches.any? { |branch| examples?(branch) }
173
176
  end
174
177
 
@@ -52,14 +52,21 @@ module RuboCop
52
52
 
53
53
  # @param text [String]
54
54
  def excessive_whitespace?(text)
55
- return true if text.start_with?(' ') || text.end_with?(' ')
56
-
57
- text.match?(/[^\n ] +[^ ]/)
55
+ text.match?(/
56
+ # Leading space
57
+ \A[[:blank:]]
58
+ |
59
+ # Trailing space
60
+ [[:blank:]]\z
61
+ |
62
+ # Two or more consecutive spaces, except if they are leading spaces
63
+ [^[[:space:]]][[:blank:]]{2,}[^[[:blank:]]]
64
+ /x)
58
65
  end
59
66
 
60
67
  # @param text [String]
61
68
  def strip_excessive_whitespace(text)
62
- text.strip.gsub(/ +/, ' ')
69
+ text.strip.gsub(/[[:blank:]]{2,}/, ' ')
63
70
  end
64
71
 
65
72
  # @param node [RuboCop::AST::Node]
@@ -24,7 +24,7 @@ module RuboCop
24
24
  class ExpectActual < Base
25
25
  extend AutoCorrector
26
26
 
27
- MSG = 'Provide the actual you are testing to `expect(...)`.'
27
+ MSG = 'Provide the actual value you are testing to `expect(...)`.'
28
28
 
29
29
  RESTRICT_ON_SEND = Runners.all
30
30
 
@@ -77,7 +77,7 @@ module RuboCop
77
77
 
78
78
  private
79
79
 
80
- # This is not implement using a NodePattern because it seems
80
+ # This is not implemented using a NodePattern because it seems
81
81
  # to not be able to match against an explicit (nil) sexp
82
82
  def literal?(node)
83
83
  node && (simple_literal?(node) || complex_literal?(node))
@@ -4,124 +4,31 @@ module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
6
  module FactoryBot
7
- # Always declare attribute values as blocks.
8
- #
9
- # @example
10
- # # bad
11
- # kind [:active, :rejected].sample
12
- #
13
- # # good
14
- # kind { [:active, :rejected].sample }
15
- #
16
- # # bad
17
- # closed_at 1.day.from_now
18
- #
19
- # # good
20
- # closed_at { 1.day.from_now }
21
- #
22
- # # bad
23
- # count 1
24
- #
25
- # # good
26
- # count { 1 }
27
- #
28
- class AttributeDefinedStatically < ::RuboCop::Cop::Base
29
- extend AutoCorrector
30
-
31
- MSG = 'Use a block to declare attribute values.'
32
-
33
- # @!method value_matcher(node)
34
- def_node_matcher :value_matcher, <<-PATTERN
35
- (send _ !#reserved_method? $...)
36
- PATTERN
37
-
38
- # @!method factory_attributes(node)
39
- def_node_matcher :factory_attributes, <<-PATTERN
40
- (block (send _ #attribute_defining_method? ...) _ { (begin $...) $(send ...) } )
41
- PATTERN
42
-
43
- def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
44
- attributes = factory_attributes(node) || []
45
- attributes = [attributes] unless attributes.is_a?(Array) # rubocop:disable Style/ArrayCoercion, Lint/RedundantCopDisableDirective
46
-
47
- attributes.each do |attribute|
48
- next unless offensive_receiver?(attribute.receiver, node)
49
- next if proc?(attribute) || association?(attribute.first_argument)
50
-
51
- add_offense(attribute) do |corrector|
52
- autocorrect(corrector, attribute)
53
- end
54
- end
55
- end
56
-
57
- private
58
-
59
- def autocorrect(corrector, node)
60
- if node.parenthesized?
61
- autocorrect_replacing_parens(corrector, node)
62
- else
63
- autocorrect_without_parens(corrector, node)
64
- end
65
- end
66
-
67
- def offensive_receiver?(receiver, node)
68
- receiver.nil? ||
69
- receiver.self_type? ||
70
- receiver_matches_first_block_argument?(receiver, node)
71
- end
72
-
73
- def receiver_matches_first_block_argument?(receiver, node)
74
- first_block_argument = node.arguments.first
75
-
76
- !first_block_argument.nil? &&
77
- receiver.lvar_type? &&
78
- receiver.node_parts == first_block_argument.node_parts
79
- end
80
-
81
- def proc?(attribute)
82
- value_matcher(attribute).to_a.all?(&:block_pass_type?)
83
- end
84
-
85
- # @!method association?(node)
86
- def_node_matcher :association?, '(hash <(pair (sym :factory) _) ...>)'
87
-
88
- def autocorrect_replacing_parens(corrector, node)
89
- left_braces, right_braces = braces(node)
90
-
91
- corrector.replace(node.location.begin, " #{left_braces}")
92
- corrector.replace(node.location.end, right_braces)
93
- end
94
-
95
- def autocorrect_without_parens(corrector, node)
96
- left_braces, right_braces = braces(node)
97
-
98
- argument = node.first_argument
99
- expression = argument.source_range
100
- corrector.insert_before(expression, left_braces)
101
- corrector.insert_after(expression, right_braces)
102
- end
103
-
104
- def braces(node)
105
- if value_hash_without_braces?(node.first_argument)
106
- ['{ { ', ' } }']
107
- else
108
- ['{ ', ' }']
109
- end
110
- end
111
-
112
- def value_hash_without_braces?(node)
113
- node.hash_type? && !node.braces?
114
- end
115
-
116
- def reserved_method?(method_name)
117
- RuboCop::RSpec::FactoryBot.reserved_methods.include?(method_name)
118
- end
119
-
120
- def attribute_defining_method?(method_name)
121
- RuboCop::RSpec::FactoryBot.attribute_defining_methods
122
- .include?(method_name)
123
- end
124
- end
7
+ # @!parse
8
+ # # Always declare attribute values as blocks.
9
+ # #
10
+ # # @example
11
+ # # # bad
12
+ # # kind [:active, :rejected].sample
13
+ # #
14
+ # # # good
15
+ # # kind { [:active, :rejected].sample }
16
+ # #
17
+ # # # bad
18
+ # # closed_at 1.day.from_now
19
+ # #
20
+ # # # good
21
+ # # closed_at { 1.day.from_now }
22
+ # #
23
+ # # # bad
24
+ # # count 1
25
+ # #
26
+ # # # good
27
+ # # count { 1 }
28
+ # #
29
+ # class AttributeDefinedStatically < ::RuboCop::Cop::Base; end
30
+ AttributeDefinedStatically =
31
+ ::RuboCop::Cop::FactoryBot::AttributeDefinedStatically
125
32
  end
126
33
  end
127
34
  end
@@ -4,113 +4,46 @@ module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
6
  module FactoryBot
7
- # Use a consistent style for parentheses in factory bot calls.
8
- #
9
- # @example
10
- #
11
- # # bad
12
- # create :user
13
- # build(:user)
14
- # create(:login)
15
- # create :login
16
- #
17
- # @example `EnforcedStyle: require_parentheses` (default)
18
- #
19
- # # good
20
- # create(:user)
21
- # create(:user)
22
- # create(:login)
23
- # build(:login)
24
- #
25
- # @example `EnforcedStyle: omit_parentheses`
26
- #
27
- # # good
28
- # create :user
29
- # build :user
30
- # create :login
31
- # create :login
32
- #
33
- # # also good
34
- # # when method name and first argument are not on same line
35
- # create(
36
- # :user
37
- # )
38
- # build(
39
- # :user,
40
- # name: 'foo'
41
- # )
42
- #
43
- class ConsistentParenthesesStyle < ::RuboCop::Cop::Base
44
- extend AutoCorrector
45
- include ConfigurableEnforcedStyle
46
- include RuboCop::RSpec::FactoryBot::Language
47
- include RuboCop::Cop::Util
48
-
49
- def self.autocorrect_incompatible_with
50
- [Style::MethodCallWithArgsParentheses]
51
- end
52
-
53
- MSG_REQUIRE_PARENS = 'Prefer method call with parentheses'
54
- MSG_OMIT_PARENS = 'Prefer method call without parentheses'
55
-
56
- FACTORY_CALLS = RuboCop::RSpec::FactoryBot::Language::METHODS
57
-
58
- RESTRICT_ON_SEND = FACTORY_CALLS
59
-
60
- # @!method factory_call(node)
61
- def_node_matcher :factory_call, <<-PATTERN
62
- (send
63
- {#factory_bot? nil?} %FACTORY_CALLS
64
- {sym str send lvar} _*
65
- )
66
- PATTERN
67
-
68
- def on_send(node)
69
- return if ambiguous_without_parentheses?(node)
70
-
71
- factory_call(node) do
72
- return if node.method?(:generate) && node.arguments.count > 1
73
-
74
- if node.parenthesized?
75
- process_with_parentheses(node)
76
- else
77
- process_without_parentheses(node)
78
- end
79
- end
80
- end
81
-
82
- private
83
-
84
- def process_with_parentheses(node)
85
- return unless style == :omit_parentheses
86
- return unless same_line?(node, node.first_argument)
87
-
88
- add_offense(node.loc.selector,
89
- message: MSG_OMIT_PARENS) do |corrector|
90
- remove_parentheses(corrector, node)
91
- end
92
- end
93
-
94
- def process_without_parentheses(node)
95
- return unless style == :require_parentheses
96
-
97
- add_offense(node.loc.selector,
98
- message: MSG_REQUIRE_PARENS) do |corrector|
99
- add_parentheses(node, corrector)
100
- end
101
- end
102
-
103
- AMBIGUOUS_TYPES = %i[send pair array and or if].freeze
104
-
105
- def ambiguous_without_parentheses?(node)
106
- node.parent && AMBIGUOUS_TYPES.include?(node.parent.type)
107
- end
108
-
109
- def remove_parentheses(corrector, node)
110
- corrector.replace(node.location.begin, ' ')
111
- corrector.remove(node.location.end)
112
- end
113
- end
7
+ # @!parse
8
+ # # Use a consistent style for parentheses in factory bot calls.
9
+ # #
10
+ # # @example
11
+ # #
12
+ # # # bad
13
+ # # create :user
14
+ # # build(:user)
15
+ # # create(:login)
16
+ # # create :login
17
+ # #
18
+ # # @example `EnforcedStyle: require_parentheses` (default)
19
+ # #
20
+ # # # good
21
+ # # create(:user)
22
+ # # create(:user)
23
+ # # create(:login)
24
+ # # build(:login)
25
+ # #
26
+ # # @example `EnforcedStyle: omit_parentheses`
27
+ # #
28
+ # # # good
29
+ # # create :user
30
+ # # build :user
31
+ # # create :login
32
+ # # create :login
33
+ # #
34
+ # # # also good
35
+ # # # when method name and first argument are not on same line
36
+ # # create(
37
+ # # :user
38
+ # # )
39
+ # # build(
40
+ # # :user,
41
+ # # name: 'foo'
42
+ # # )
43
+ # #
44
+ # class ConsistentParenthesesStyle < ::RuboCop::Cop::Base; end
45
+ ConsistentParenthesesStyle =
46
+ ::RuboCop::Cop::FactoryBot::ConsistentParenthesesStyle
114
47
  end
115
48
  end
116
49
  end