rubocop-rspec 2.18.1 → 2.20.0

Sign up to get free protection for your applications and to get access to all the features.
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