rubocop-rspec 2.18.1 → 2.20.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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -2
  3. data/README.md +1 -1
  4. data/config/default.yml +46 -1
  5. data/lib/rubocop/cop/rspec/be_empty.rb +44 -0
  6. data/lib/rubocop/cop/rspec/be_nil.rb +2 -2
  7. data/lib/rubocop/cop/rspec/change_by_zero.rb +3 -3
  8. data/lib/rubocop/cop/rspec/contain_exactly.rb +56 -0
  9. data/lib/rubocop/cop/rspec/context_wording.rb +13 -5
  10. data/lib/rubocop/cop/rspec/describe_method.rb +16 -8
  11. data/lib/rubocop/cop/rspec/described_class.rb +2 -1
  12. data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +7 -5
  13. data/lib/rubocop/cop/rspec/dialect.rb +1 -1
  14. data/lib/rubocop/cop/rspec/duplicated_metadata.rb +1 -1
  15. data/lib/rubocop/cop/rspec/empty_example_group.rb +7 -7
  16. data/lib/rubocop/cop/rspec/empty_hook.rb +2 -2
  17. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +1 -1
  18. data/lib/rubocop/cop/rspec/example_wording.rb +1 -1
  19. data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +1 -1
  20. data/lib/rubocop/cop/rspec/expect_actual.rb +2 -2
  21. data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
  22. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +1 -1
  23. data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +3 -3
  24. data/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb +2 -2
  25. data/lib/rubocop/cop/rspec/file_path.rb +1 -1
  26. data/lib/rubocop/cop/rspec/focus.rb +4 -5
  27. data/lib/rubocop/cop/rspec/hook_argument.rb +12 -9
  28. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +5 -3
  29. data/lib/rubocop/cop/rspec/indexed_let.rb +76 -0
  30. data/lib/rubocop/cop/rspec/let_before_examples.rb +4 -4
  31. data/lib/rubocop/cop/rspec/let_setup.rb +6 -8
  32. data/lib/rubocop/cop/rspec/match_array.rb +59 -0
  33. data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +1 -2
  34. data/lib/rubocop/cop/rspec/mixin/location_help.rb +37 -0
  35. data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +20 -4
  36. data/lib/rubocop/cop/rspec/multiple_expectations.rb +2 -1
  37. data/lib/rubocop/cop/rspec/named_subject.rb +6 -4
  38. data/lib/rubocop/cop/rspec/no_expectation_example.rb +2 -5
  39. data/lib/rubocop/cop/rspec/overwriting_setup.rb +3 -1
  40. data/lib/rubocop/cop/rspec/pending.rb +12 -12
  41. data/lib/rubocop/cop/rspec/pending_without_reason.rb +74 -36
  42. data/lib/rubocop/cop/rspec/predicate_matcher.rb +9 -35
  43. data/lib/rubocop/cop/rspec/rails/have_http_status.rb +8 -5
  44. data/lib/rubocop/cop/rspec/rails/http_status.rb +89 -33
  45. data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +4 -4
  46. data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +5 -5
  47. data/lib/rubocop/cop/rspec/rails/travel_around.rb +92 -0
  48. data/lib/rubocop/cop/rspec/receive_counts.rb +1 -1
  49. data/lib/rubocop/cop/rspec/redundant_around.rb +65 -0
  50. data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +3 -6
  51. data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +3 -6
  52. data/lib/rubocop/cop/rspec/repeated_include_example.rb +3 -4
  53. data/lib/rubocop/cop/rspec/scattered_setup.rb +23 -6
  54. data/lib/rubocop/cop/rspec/shared_context.rb +12 -13
  55. data/lib/rubocop/cop/rspec/shared_examples.rb +6 -4
  56. data/lib/rubocop/cop/rspec/skip_block_inside_example.rb +46 -0
  57. data/lib/rubocop/cop/rspec/sort_metadata.rb +2 -2
  58. data/lib/rubocop/cop/rspec/variable_definition.rb +3 -0
  59. data/lib/rubocop/cop/rspec/variable_name.rb +4 -1
  60. data/lib/rubocop/cop/rspec/verified_double_reference.rb +3 -3
  61. data/lib/rubocop/cop/rspec_cops.rb +7 -0
  62. data/lib/rubocop/rspec/example_group.rb +6 -8
  63. data/lib/rubocop/rspec/language/node_pattern.rb +26 -0
  64. data/lib/rubocop/rspec/language.rb +25 -16
  65. data/lib/rubocop/rspec/version.rb +1 -1
  66. data/lib/rubocop-rspec.rb +1 -0
  67. metadata +11 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b2ef643f2d262910bba4db8e0e6a722b96d0cb6424d04d4261326155176f321
4
- data.tar.gz: 29ae9b634075bd3dc11d44969fb00a7542aad3302f3a1aa360a2637e3875a3bc
3
+ metadata.gz: 1ebfcc955ecfa8b3437defde668d955020f03a2dbba2c9337f0b75a8fb9a3c26
4
+ data.tar.gz: 7a547b1e24c278de072b2c912be27e1dc5fb1450b6fa65d563278d0f054d6d1d
5
5
  SHA512:
6
- metadata.gz: b14f91843dcbc6cd8abfca82a8f21244991aacb79d09a92e975c1eb6d36e554adc44bd1d8b14d2d014fed60b6383f1e102f5142c4a771532be1b60db47c01df1
7
- data.tar.gz: 0626b43df05da5b5f386d18be195d2aaa14347a7f70cd99d2d1731e9f9107536c8a0076897b78d9f2f4e69cdeb2a79bc0caaab488a6bee822ea08add9b083fe9
6
+ metadata.gz: f8942cdf262718de32bfbc765e3f2aac9eae49e364d7a2d866300b77e0bd39fd24b168d513577a1a95a82ce10a0f325a66c6b2914da71dd3951011c2399b0b3e
7
+ data.tar.gz: 89c8fce01b42c53c50460b9411cd44f96b99663ce3a2e7735e6cb0f260c1cc3a86ba0daba553b4ebeba25625dde25f41d8b2129929cf92514e06e0f0f8191ec5
data/CHANGELOG.md CHANGED
@@ -2,6 +2,38 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 2.20.0 (2023-04-18)
6
+
7
+ - Add new `RSpec/IndexedLet` cop. ([@dmitrytsepelev])
8
+ - Add new `RSpec/BeEmpty` cop. ([@ydah], [@bquorning])
9
+ - Add autocorrect support for `RSpec/ScatteredSetup`. ([@ydah])
10
+ - Add support `be_status` style for `RSpec/Rails/HttpStatus`. ([@ydah])
11
+ - Add support for shared example groups to `RSpec/EmptyLineAfterExampleGroup`. ([@pirj])
12
+ - Add support for `RSpec/HaveHttpStatus` when using `response.code`. ([@ydah])
13
+ - Fix order of expected and actual in correction for `RSpec/Rails/MinitestAssertions` ([@mvz])
14
+ - Fix a false positive for `RSpec/DescribedClassModuleWrapping` when RSpec.describe numblock is nested within a module. ([@ydah])
15
+ - Fix a false positive for `RSpec/FactoryBot/ConsistentParenthesesStyle` inside `&&`, `||` and `:?` when `omit_parentheses` is on ([@dmitrytsepelev])
16
+ - Fix a false positive for `RSpec/PendingWithoutReason` when pending/skip has a reason inside an example group. ([@ydah])
17
+ - Fix a false negative for `RSpec/RedundantAround` when redundant numblock `around`. ([@ydah])
18
+ - Change `RSpec/ContainExactly` to ignore calls with no arguments, and change `RSpec/MatchArray` to ignore calls with an empty array literal argument. ([@ydah], [@bquorning])
19
+ - Make `RSpec/MatchArray` and `RSpec/ContainExactly` pending. ([@ydah])
20
+
21
+ ## 2.19.0 (2023-03-06)
22
+
23
+ - Fix a false positive for `RSpec/ContextWording` when context is interpolated string literal or execute string. ([@ydah])
24
+ - Fix a false positive for `RSpec/DescribeMethod` when multi-line describe without `#` and `.` at the beginning. ([@ydah], [@pirj])
25
+ - Fix a false positive for `RSpec/VariableName` when inside non-spec code. ([@ydah])
26
+ - Fix a false positive for `RSpec/VariableDefinition` when inside non-spec code. ([@ydah])
27
+ - Add new `RSpec/PendingBlockInsideExample` cop. ([@ydah])
28
+ - Add `RSpec/RedundantAround` cop. ([@r7kamura])
29
+ - Add `RSpec/Rails/TravelAround` cop. ([@r7kamura])
30
+ - Add `RSpec/ContainExactly` and `RSpec/MatchArray` cops. ([@faucct])
31
+ - Fix a false positive for `RSpec/PendingWithoutReason` when not inside example and pending/skip with block. ([@ydah], [@pirj])
32
+ - Fix a false positive for `RSpec/PendingWithoutReason` when `skip` is passed a block inside example. ([@ydah], [@pirj])
33
+ - Rename `RSpec/PendingBlockInsideExample` cop to `RSpec/SkipBlockInsideExample`. ([@pirj])
34
+ - Deprecate `send_pattern`/`block_pattern`/`numblock_pattern` helpers in favour of using node pattern explicitly. ([@pirj], [@ydah])
35
+ - Fix an incorrect autocorrect for `RSpec/VerifiedDoubleReference` when namespaced class. ([@ydah])
36
+
5
37
  ## 2.18.1 (2023-01-19)
6
38
 
7
39
  - Add `rubocop-capybara` version constraint to prevent sudden cop enabling when it hits 3.0. ([@pirj])
@@ -313,7 +345,7 @@
313
345
  ## 1.37.0 (2019-11-25)
314
346
 
315
347
  - Implement `RSpec/DescribedClassModuleWrapping` to disallow RSpec statements within a module. ([@kellysutton])
316
- - Fix documentation rake task to support Rubocop 0.75. ([@nickcampbell18])
348
+ - Fix documentation rake task to support RuboCop 0.75. ([@nickcampbell18])
317
349
  - Fix `RSpec/SubjectStub` to detect implicit subjects stubbed. ([@QQism])
318
350
  - Fix `RSpec/Pending` not flagging `skip` with string values. ([@pirj])
319
351
  - Add `AllowedExplicitMatchers` config option for `RSpec/PredicateMatcher`. ([@mkrawc])
@@ -644,7 +676,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
644
676
  - Skip `DescribeClass` cop for view specs. ([@andyw8])
645
677
  - Skip `FilePath` cop for Rails routing specs. ([@andyw8])
646
678
  - Add cop to check for focused specs. ([@renanborgescampos], [@jaredmoody])
647
- - Clean-up `RSpec::NotToNot` to use same configuration semantics as other Rubocop cops, add autocorrect support for `RSpec::NotToNot`. ([@baberthal])
679
+ - Clean-up `RSpec::NotToNot` to use same configuration semantics as other RuboCop cops, add autocorrect support for `RSpec::NotToNot`. ([@baberthal])
648
680
  - Update to rubocop 0.40.0. ([@nijikon])
649
681
 
650
682
  ## 1.4.1 (2016-04-03)
@@ -742,6 +774,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
742
774
  [@dduugg]: https://github.com/dduugg
743
775
  [@deivid-rodriguez]: https://github.com/deivid-rodriguez
744
776
  [@dgollahon]: https://github.com/dgollahon
777
+ [@dmitrytsepelev]: https://github.com/dmitrytsepelev
745
778
  [@drowze]: https://github.com/Drowze
746
779
  [@dswij]: https://github.com/dswij
747
780
  [@dvandersluis]: https://github.com/dvandersluis
@@ -751,6 +784,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
751
784
  [@elebow]: https://github.com/elebow
752
785
  [@elisefitz15]: https://github.com/EliseFitz15
753
786
  [@elliterate]: https://github.com/elliterate
787
+ [@faucct]: https://github.com/faucct
754
788
  [@foton]: https://github.com/foton
755
789
  [@francois-ferrandis]: https://github.com/francois-ferrandis
756
790
  [@g-rath]: https://github.com/G-Rath
@@ -783,6 +817,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
783
817
  [@mlarraz]: https://github.com/mlarraz
784
818
  [@mockdeep]: https://github.com/mockdeep
785
819
  [@mothonmars]: https://github.com/MothOnMars
820
+ [@mvz]: https://github.com/mvz
786
821
  [@nc-holodakg]: https://github.com/nc-holodakg
787
822
  [@nevir]: https://github.com/nevir
788
823
  [@ngouy]: https://github.com/ngouy
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Gem Version](https://badge.fury.io/rb/rubocop-rspec.svg)](https://rubygems.org/gems/rubocop-rspec)
5
5
  ![CI](https://github.com/rubocop/rubocop-rspec/workflows/CI/badge.svg)
6
6
 
7
- RSpec-specific analysis for your projects, as an extension to
7
+ [RSpec](https://rspec.info/)-specific analysis for your projects, as an extension to
8
8
  [RuboCop](https://github.com/rubocop/rubocop).
9
9
 
10
10
  ## Installation
data/config/default.yml CHANGED
@@ -144,6 +144,12 @@ RSpec/Be:
144
144
  StyleGuide: https://rspec.rubystyle.guide/#be-matcher
145
145
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Be
146
146
 
147
+ RSpec/BeEmpty:
148
+ Description: Prefer using `be_empty` when checking for an empty array.
149
+ Enabled: pending
150
+ VersionAdded: '2.20'
151
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEmpty
152
+
147
153
  RSpec/BeEq:
148
154
  Description: Check for expectations where `be(...)` can replace `eq(...)`.
149
155
  Enabled: pending
@@ -201,6 +207,12 @@ RSpec/ClassCheck:
201
207
  - be_kind_of
202
208
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ClassCheck
203
209
 
210
+ RSpec/ContainExactly:
211
+ Description: Checks where `contain_exactly` is used.
212
+ Enabled: pending
213
+ VersionAdded: '2.19'
214
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContainExactly
215
+
204
216
  RSpec/ContextMethod:
205
217
  Description: "`context` should not be used for specifying methods."
206
218
  Enabled: true
@@ -497,6 +509,13 @@ RSpec/ImplicitSubject:
497
509
  VersionChanged: '2.13'
498
510
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitSubject
499
511
 
512
+ RSpec/IndexedLet:
513
+ Description: Do not set up test data using indexes (e.g., `item_1`, `item_2`).
514
+ Enabled: pending
515
+ VersionAdded: '2.20'
516
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IndexedLet
517
+ Max: 1
518
+
500
519
  RSpec/InstanceSpy:
501
520
  Description: Checks for `instance_double` used with `have_received`.
502
521
  Enabled: true
@@ -556,6 +575,12 @@ RSpec/LetSetup:
556
575
  VersionAdded: '1.7'
557
576
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LetSetup
558
577
 
578
+ RSpec/MatchArray:
579
+ Description: Checks where `match_array` is used.
580
+ Enabled: pending
581
+ VersionAdded: '2.19'
582
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MatchArray
583
+
559
584
  RSpec/MessageChain:
560
585
  Description: Check that chains of messages are not being stubbed.
561
586
  Enabled: true
@@ -706,6 +731,12 @@ RSpec/ReceiveNever:
706
731
  VersionAdded: '1.28'
707
732
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveNever
708
733
 
734
+ RSpec/RedundantAround:
735
+ Description: Remove redundant `around` hook.
736
+ Enabled: pending
737
+ VersionAdded: '2.19'
738
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RedundantAround
739
+
709
740
  RSpec/RepeatedDescription:
710
741
  Description: Check for repeated description strings in example groups.
711
742
  Enabled: true
@@ -779,6 +810,12 @@ RSpec/SingleArgumentMessageChain:
779
810
  VersionChanged: '1.10'
780
811
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SingleArgumentMessageChain
781
812
 
813
+ RSpec/SkipBlockInsideExample:
814
+ Description: Checks for passing a block to `skip` within examples.
815
+ Enabled: pending
816
+ VersionAdded: '2.19'
817
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SkipBlockInsideExample
818
+
782
819
  RSpec/SortMetadata:
783
820
  Description: Sort RSpec metadata alphabetically.
784
821
  Enabled: pending
@@ -1024,8 +1061,9 @@ RSpec/Rails/HttpStatus:
1024
1061
  SupportedStyles:
1025
1062
  - numeric
1026
1063
  - symbolic
1064
+ - be_status
1027
1065
  VersionAdded: '1.23'
1028
- VersionChanged: '2.0'
1066
+ VersionChanged: '2.20'
1029
1067
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HttpStatus
1030
1068
 
1031
1069
  RSpec/Rails/InferredSpecType:
@@ -1056,3 +1094,10 @@ RSpec/Rails/MinitestAssertions:
1056
1094
  Enabled: pending
1057
1095
  VersionAdded: '2.17'
1058
1096
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/MinitestAssertions
1097
+
1098
+ RSpec/Rails/TravelAround:
1099
+ Description: Prefer to travel in `before` rather than `around`.
1100
+ Enabled: pending
1101
+ Safe: false
1102
+ VersionAdded: '2.19'
1103
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/TravelAround
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Prefer using `be_empty` when checking for an empty array.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # expect(array).to contain_exactly
11
+ # expect(array).to match_array([])
12
+ #
13
+ # # good
14
+ # expect(array).to be_empty
15
+ #
16
+ class BeEmpty < Base
17
+ extend AutoCorrector
18
+
19
+ MSG = 'Use `be_empty` matchers for checking an empty array.'
20
+ RESTRICT_ON_SEND = %i[contain_exactly match_array].freeze
21
+
22
+ # @!method expect_array_matcher?(node)
23
+ def_node_matcher :expect_array_matcher?, <<~PATTERN
24
+ (send
25
+ (send nil? :expect _)
26
+ #Runners.all
27
+ ${
28
+ (send nil? :match_array (array))
29
+ (send nil? :contain_exactly)
30
+ }
31
+ )
32
+ PATTERN
33
+
34
+ def on_send(node)
35
+ expect_array_matcher?(node.parent) do |expect|
36
+ add_offense(expect) do |corrector|
37
+ corrector.replace(expect, 'be_empty')
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -57,7 +57,7 @@ module RuboCop
57
57
  return unless be_nil_matcher?(node)
58
58
 
59
59
  add_offense(node, message: BE_MSG) do |corrector|
60
- corrector.replace(node.loc.expression, 'be(nil)')
60
+ corrector.replace(node, 'be(nil)')
61
61
  end
62
62
  end
63
63
 
@@ -65,7 +65,7 @@ module RuboCop
65
65
  return unless nil_value_expectation?(node)
66
66
 
67
67
  add_offense(node, message: BE_NIL_MSG) do |corrector|
68
- corrector.replace(node.loc.expression, 'be_nil')
68
+ corrector.replace(node, 'be_nil')
69
69
  end
70
70
  end
71
71
  end
@@ -99,7 +99,7 @@ module RuboCop
99
99
  private
100
100
 
101
101
  def check_offense(node)
102
- expression = node.loc.expression
102
+ expression = node.source_range
103
103
  if compound_expectations?(node)
104
104
  add_offense(expression, message: message_compound) do |corrector|
105
105
  autocorrect_compound(corrector, node)
@@ -117,7 +117,7 @@ module RuboCop
117
117
 
118
118
  def autocorrect(corrector, node)
119
119
  corrector.replace(node.parent.loc.selector, 'not_to')
120
- range = node.loc.dot.with(end_pos: node.loc.expression.end_pos)
120
+ range = node.loc.dot.with(end_pos: node.source_range.end_pos)
121
121
  corrector.remove(range)
122
122
  end
123
123
 
@@ -126,7 +126,7 @@ module RuboCop
126
126
 
127
127
  change_nodes(node) do |change_node|
128
128
  corrector.replace(change_node.loc.selector, negated_matcher)
129
- range = node.loc.dot.with(end_pos: node.loc.expression.end_pos)
129
+ range = node.loc.dot.with(end_pos: node.source_range.end_pos)
130
130
  corrector.remove(range)
131
131
  end
132
132
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks where `contain_exactly` is used.
7
+ #
8
+ # This cop checks for the following:
9
+ # - Prefer `match_array` when matching array values.
10
+ # - Prefer `be_empty` when using `contain_exactly` with no arguments.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # it { is_expected.to contain_exactly(*array1, *array2) }
15
+ #
16
+ # # good
17
+ # it { is_expected.to match_array(array1 + array2) }
18
+ #
19
+ # # good
20
+ # it { is_expected.to contain_exactly(content, *array) }
21
+ #
22
+ class ContainExactly < Base
23
+ extend AutoCorrector
24
+
25
+ MSG = 'Prefer `match_array` when matching array values.'
26
+ RESTRICT_ON_SEND = %i[contain_exactly].freeze
27
+
28
+ def on_send(node)
29
+ return if node.arguments.empty?
30
+
31
+ check_populated_collection(node)
32
+ end
33
+
34
+ private
35
+
36
+ def check_populated_collection(node)
37
+ return unless node.each_child_node.all?(&:splat_type?)
38
+
39
+ add_offense(node) do |corrector|
40
+ autocorrect_for_populated_array(node, corrector)
41
+ end
42
+ end
43
+
44
+ def autocorrect_for_populated_array(node, corrector)
45
+ arrays = node.arguments.map do |splat_node|
46
+ splat_node.children.first
47
+ end
48
+ corrector.replace(
49
+ node,
50
+ "match_array(#{arrays.map(&:source).join(' + ')})"
51
+ )
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -62,12 +62,12 @@ module RuboCop
62
62
 
63
63
  # @!method context_wording(node)
64
64
  def_node_matcher :context_wording, <<-PATTERN
65
- (block (send #rspec? { :context :shared_context } $(str $_) ...) ...)
65
+ (block (send #rspec? { :context :shared_context } $({str dstr xstr} ...) ...) ...)
66
66
  PATTERN
67
67
 
68
68
  def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
69
- context_wording(node) do |context, description|
70
- if bad_pattern?(description)
69
+ context_wording(node) do |context|
70
+ if bad_pattern?(context)
71
71
  message = format(MSG, patterns: expect_patterns)
72
72
  add_offense(context, message: message)
73
73
  end
@@ -84,10 +84,18 @@ module RuboCop
84
84
  @prefix_regexes ||= prefixes.map { |pre| /^#{Regexp.escape(pre)}\b/ }
85
85
  end
86
86
 
87
- def bad_pattern?(description)
87
+ def bad_pattern?(node)
88
88
  return false if allowed_patterns.empty?
89
89
 
90
- !matches_allowed_pattern?(description)
90
+ !matches_allowed_pattern?(description(node))
91
+ end
92
+
93
+ def description(context)
94
+ if context.xstr_type?
95
+ context.value.value
96
+ else
97
+ context.value
98
+ end
91
99
  end
92
100
 
93
101
  def expect_patterns
@@ -23,20 +23,28 @@ module RuboCop
23
23
  MSG = 'The second argument to describe should be the method ' \
24
24
  "being tested. '#instance' or '.class'."
25
25
 
26
- # @!method second_argument(node)
27
- def_node_matcher :second_argument, <<~PATTERN
26
+ # @!method second_string_literal_argument(node)
27
+ def_node_matcher :second_string_literal_argument, <<~PATTERN
28
28
  (block
29
- (send #rspec? :describe _first_argument $(str _) ...) ...
30
- )
29
+ (send #rspec? :describe _first_argument ${str dstr} ...)
30
+ ...)
31
+ PATTERN
32
+
33
+ # @!method method_name?(node)
34
+ def_node_matcher :method_name?, <<~PATTERN
35
+ {(str #method_name_prefix?) (dstr (str #method_name_prefix?) ...)}
31
36
  PATTERN
32
37
 
33
38
  def on_top_level_group(node)
34
- second_argument = second_argument(node)
39
+ second_string_literal_argument(node) do |argument|
40
+ add_offense(argument) unless method_name?(argument)
41
+ end
42
+ end
35
43
 
36
- return unless second_argument
37
- return if second_argument.str_content.start_with?('#', '.')
44
+ private
38
45
 
39
- add_offense(second_argument)
46
+ def method_name_prefix?(description)
47
+ description.start_with?('.', '#')
40
48
  end
41
49
  end
42
50
  end
@@ -68,7 +68,8 @@ module RuboCop
68
68
  PATTERN
69
69
 
70
70
  # @!method rspec_block?(node)
71
- def_node_matcher :rspec_block?, block_pattern('#ALL.all')
71
+ def_node_matcher :rspec_block?,
72
+ '({block numblock} (send #rspec? #ALL.all ...) ...)'
72
73
 
73
74
  # @!method scope_changing_syntax?(node)
74
75
  def_node_matcher :scope_changing_syntax?, '{def class module}'
@@ -22,13 +22,15 @@ module RuboCop
22
22
  class DescribedClassModuleWrapping < Base
23
23
  MSG = 'Avoid opening modules and defining specs within them.'
24
24
 
25
- # @!method find_rspec_blocks(node)
26
- def_node_search :find_rspec_blocks, block_pattern('#ExampleGroups.all')
25
+ # @!method include_rspec_blocks?(node)
26
+ def_node_search :include_rspec_blocks?, <<~PATTERN
27
+ ({block numblock} (send #explicit_rspec? #ExampleGroups.all ...) ...)
28
+ PATTERN
27
29
 
28
30
  def on_module(node)
29
- find_rspec_blocks(node) do
30
- add_offense(node)
31
- end
31
+ return unless include_rspec_blocks?(node)
32
+
33
+ add_offense(node)
32
34
  end
33
35
  end
34
36
  end
@@ -49,7 +49,7 @@ module RuboCop
49
49
  MSG = 'Prefer `%<prefer>s` over `%<current>s`.'
50
50
 
51
51
  # @!method rspec_method?(node)
52
- def_node_matcher :rspec_method?, send_pattern('#ALL.all')
52
+ def_node_matcher :rspec_method?, '(send #rspec? #ALL.all ...)'
53
53
 
54
54
  def on_send(node)
55
55
  return unless rspec_method?(node)
@@ -39,7 +39,7 @@ module RuboCop
39
39
  corrector.remove(
40
40
  range_with_surrounding_comma(
41
41
  range_with_surrounding_space(
42
- node.location.expression,
42
+ node.source_range,
43
43
  side: :left
44
44
  ),
45
45
  :left
@@ -53,7 +53,7 @@ module RuboCop
53
53
  # @param node [RuboCop::AST::Node]
54
54
  # @yield [RuboCop::AST::Node] example group body
55
55
  def_node_matcher :example_group_body, <<~PATTERN
56
- (block #{send_pattern('#ExampleGroups.all')} args $_)
56
+ (block (send #rspec? #ExampleGroups.all ...) args $_)
57
57
  PATTERN
58
58
 
59
59
  # @!method example_or_group_or_include?(node)
@@ -72,10 +72,10 @@ module RuboCop
72
72
  # @return [Array<RuboCop::AST::Node>] matching nodes
73
73
  def_node_matcher :example_or_group_or_include?, <<~PATTERN
74
74
  {
75
- #{block_pattern(
76
- '{#Examples.all #ExampleGroups.all #Includes.all}'
77
- )}
78
- #{send_pattern('{#Examples.all #Includes.all}')}
75
+ (block
76
+ (send #rspec? {#Examples.all #ExampleGroups.all #Includes.all} ...)
77
+ ...)
78
+ (send nil? {#Examples.all #Includes.all} ...)
79
79
  }
80
80
  PATTERN
81
81
 
@@ -95,7 +95,7 @@ module RuboCop
95
95
  # @param node [RuboCop::AST::Node]
96
96
  # @return [Array<RuboCop::AST::Node>] matching nodes
97
97
  def_node_matcher :examples_inside_block?, <<~PATTERN
98
- (block !#{send_pattern('#Hooks.all')} _ #examples?)
98
+ (block !(send nil? #Hooks.all ...) _ #examples?)
99
99
  PATTERN
100
100
 
101
101
  # @!method examples_directly_or_in_block?(node)
@@ -174,7 +174,7 @@ module RuboCop
174
174
 
175
175
  def removed_range(node)
176
176
  range_by_whole_lines(
177
- node.location.expression,
177
+ node.source_range,
178
178
  include_final_newline: true
179
179
  )
180
180
  end
@@ -31,14 +31,14 @@ module RuboCop
31
31
 
32
32
  # @!method empty_hook?(node)
33
33
  def_node_matcher :empty_hook?, <<~PATTERN
34
- (block $#{send_pattern('#Hooks.all')} _ nil?)
34
+ (block $(send nil? #Hooks.all ...) _ nil?)
35
35
  PATTERN
36
36
 
37
37
  def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
38
38
  empty_hook?(node) do |hook|
39
39
  add_offense(hook) do |corrector|
40
40
  corrector.remove(
41
- range_with_surrounding_space(node.loc.expression, side: :left)
41
+ range_with_surrounding_space(node.source_range, side: :left)
42
42
  )
43
43
  end
44
44
  end
@@ -30,7 +30,7 @@ module RuboCop
30
30
  MSG = 'Add an empty line after `%<example_group>s`.'
31
31
 
32
32
  def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
33
- return unless example_group?(node)
33
+ return unless spec_group?(node)
34
34
 
35
35
  missing_separating_line_offense(node) do |method|
36
36
  format(MSG, example_group: method)
@@ -88,7 +88,7 @@ module RuboCop
88
88
  end
89
89
 
90
90
  def docstring(node)
91
- expr = node.loc.expression
91
+ expr = node.source_range
92
92
 
93
93
  Parser::Source::Range.new(
94
94
  expr.source_buffer,
@@ -74,7 +74,7 @@ module RuboCop
74
74
  end
75
75
 
76
76
  def docstring(node)
77
- expr = node.loc.expression
77
+ expr = node.source_range
78
78
 
79
79
  Parser::Source::Range.new(
80
80
  expr.source_buffer,
@@ -93,8 +93,8 @@ module RuboCop
93
93
  end
94
94
 
95
95
  def swap(corrector, actual, expected)
96
- corrector.replace(actual.source_range, expected.source)
97
- corrector.replace(expected.source_range, actual.source)
96
+ corrector.replace(actual, expected.source)
97
+ corrector.replace(expected, actual.source)
98
98
  end
99
99
  end
100
100
  end
@@ -25,7 +25,7 @@ module RuboCop
25
25
  MSG = 'Do not use `%<expect>s` in `%<hook>s` hook'
26
26
 
27
27
  # @!method expectation(node)
28
- def_node_search :expectation, send_pattern('#Expectations.all')
28
+ def_node_search :expectation, '(send nil? #Expectations.all ...)'
29
29
 
30
30
  def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
31
31
  return unless hook?(node)
@@ -96,7 +96,7 @@ module RuboCop
96
96
  left_braces, right_braces = braces(node)
97
97
 
98
98
  argument = node.first_argument
99
- expression = argument.location.expression
99
+ expression = argument.source_range
100
100
  corrector.insert_before(expression, left_braces)
101
101
  corrector.insert_after(expression, right_braces)
102
102
  end
@@ -100,10 +100,10 @@ module RuboCop
100
100
  end
101
101
  end
102
102
 
103
+ AMBIGUOUS_TYPES = %i[send pair array and or if].freeze
104
+
103
105
  def ambiguous_without_parentheses?(node)
104
- node.parent&.send_type? ||
105
- node.parent&.pair_type? ||
106
- node.parent&.array_type?
106
+ node.parent && AMBIGUOUS_TYPES.include?(node.parent.type)
107
107
  end
108
108
 
109
109
  def remove_parentheses(corrector, node)
@@ -71,14 +71,14 @@ module RuboCop
71
71
 
72
72
  def crime_scene(node)
73
73
  range_between(
74
- node.loc.expression.begin_pos,
74
+ node.source_range.begin_pos,
75
75
  node.loc.selector.end_pos
76
76
  )
77
77
  end
78
78
 
79
79
  def offense(node)
80
80
  range_between(
81
- node.loc.expression.begin_pos,
81
+ node.source_range.begin_pos,
82
82
  node.loc.selector.begin_pos
83
83
  )
84
84
  end
@@ -165,7 +165,7 @@ module RuboCop
165
165
  end
166
166
 
167
167
  def expanded_file_path
168
- File.expand_path(processed_source.buffer.name)
168
+ File.expand_path(processed_source.file_path)
169
169
  end
170
170
  end
171
171
  end