rubocop-rspec 2.0.0.pre → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -2
  3. data/README.md +4 -0
  4. data/config/default.yml +100 -18
  5. data/lib/rubocop-rspec.rb +7 -8
  6. data/lib/rubocop/cop/rspec/align_left_let_brace.rb +7 -3
  7. data/lib/rubocop/cop/rspec/align_right_let_brace.rb +7 -3
  8. data/lib/rubocop/cop/rspec/base.rb +6 -55
  9. data/lib/rubocop/cop/rspec/be.rb +1 -1
  10. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +2 -2
  11. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +3 -2
  12. data/lib/rubocop/cop/rspec/describe_class.rb +1 -1
  13. data/lib/rubocop/cop/rspec/describe_method.rb +1 -1
  14. data/lib/rubocop/cop/rspec/described_class.rb +1 -2
  15. data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -2
  16. data/lib/rubocop/cop/rspec/dialect.rb +1 -1
  17. data/lib/rubocop/cop/rspec/empty_example_group.rb +6 -45
  18. data/lib/rubocop/cop/rspec/empty_hook.rb +1 -1
  19. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +1 -1
  20. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +1 -1
  21. data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +1 -1
  22. data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +1 -1
  23. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +2 -2
  24. data/lib/rubocop/cop/rspec/expect_actual.rb +1 -1
  25. data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
  26. data/lib/rubocop/cop/rspec/file_path.rb +1 -1
  27. data/lib/rubocop/cop/rspec/focus.rb +13 -7
  28. data/lib/rubocop/cop/rspec/hook_argument.rb +2 -4
  29. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +2 -2
  30. data/lib/rubocop/cop/rspec/implicit_expect.rb +1 -1
  31. data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
  32. data/lib/rubocop/cop/rspec/let_before_examples.rb +2 -2
  33. data/lib/rubocop/cop/rspec/let_setup.rb +7 -4
  34. data/lib/rubocop/cop/rspec/message_spies.rb +1 -1
  35. data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +51 -0
  36. data/lib/rubocop/cop/rspec/mixin/final_end_location.rb +19 -0
  37. data/lib/rubocop/cop/rspec/mixin/top_level_group.rb +54 -0
  38. data/lib/rubocop/cop/rspec/mixin/variable.rb +20 -0
  39. data/lib/rubocop/cop/rspec/multiple_describes.rb +1 -1
  40. data/lib/rubocop/cop/rspec/multiple_expectations.rb +1 -1
  41. data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +3 -1
  42. data/lib/rubocop/cop/rspec/named_subject.rb +8 -12
  43. data/lib/rubocop/cop/rspec/nested_groups.rb +1 -1
  44. data/lib/rubocop/cop/rspec/overwriting_setup.rb +2 -1
  45. data/lib/rubocop/cop/rspec/pending.rb +13 -5
  46. data/lib/rubocop/cop/rspec/predicate_matcher.rb +3 -3
  47. data/lib/rubocop/cop/rspec/repeated_include_example.rb +3 -2
  48. data/lib/rubocop/cop/rspec/shared_context.rb +16 -6
  49. data/lib/rubocop/cop/rspec/shared_examples.rb +3 -1
  50. data/lib/rubocop/cop/rspec/stubbed_mock.rb +1 -1
  51. data/lib/rubocop/cop/rspec/subject_stub.rb +2 -2
  52. data/lib/rubocop/cop/rspec/variable_definition.rb +1 -1
  53. data/lib/rubocop/cop/rspec/variable_name.rb +1 -1
  54. data/lib/rubocop/cop/rspec_cops.rb +0 -1
  55. data/lib/rubocop/rspec/align_let_brace.rb +1 -1
  56. data/lib/rubocop/rspec/concept.rb +2 -2
  57. data/lib/rubocop/rspec/config_formatter.rb +3 -3
  58. data/lib/rubocop/rspec/corrector/move_node.rb +1 -1
  59. data/lib/rubocop/rspec/example_group.rb +15 -5
  60. data/lib/rubocop/rspec/hook.rb +1 -1
  61. data/lib/rubocop/rspec/inject.rb +4 -2
  62. data/lib/rubocop/rspec/language.rb +143 -109
  63. data/lib/rubocop/rspec/language/node_pattern.rb +7 -24
  64. data/lib/rubocop/rspec/version.rb +1 -1
  65. metadata +22 -12
  66. data/lib/rubocop/cop/rspec/cop.rb +0 -10
  67. data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +0 -41
  68. data/lib/rubocop/rspec.rb +0 -12
  69. data/lib/rubocop/rspec/empty_line_separation.rb +0 -48
  70. data/lib/rubocop/rspec/final_end_location.rb +0 -17
  71. data/lib/rubocop/rspec/top_level_describe.rb +0 -52
  72. data/lib/rubocop/rspec/top_level_group.rb +0 -57
  73. data/lib/rubocop/rspec/variable.rb +0 -16
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Helps check offenses with variable definitions
7
+ module Variable
8
+ extend RuboCop::NodePattern::Macros
9
+
10
+ Subjects = RuboCop::RSpec::Language::Subjects
11
+ Helpers = RuboCop::RSpec::Language::Helpers
12
+
13
+ def_node_matcher :variable_definition?, <<~PATTERN
14
+ (send nil? {#Subjects.all #Helpers.all}
15
+ $({sym str dsym dstr} ...) ...)
16
+ PATTERN
17
+ end
18
+ end
19
+ end
20
+ end
@@ -23,7 +23,7 @@ module RuboCop
23
23
  # end
24
24
  # end
25
25
  class MultipleDescribes < Base
26
- include RuboCop::RSpec::TopLevelGroup
26
+ include TopLevelGroup
27
27
 
28
28
  MSG = 'Do not use multiple top-level example groups - '\
29
29
  'try to nest them.'
@@ -60,7 +60,7 @@ module RuboCop
60
60
  } ...)
61
61
  PATTERN
62
62
 
63
- def_node_matcher :expect?, Expectations::ALL.send_pattern
63
+ def_node_matcher :expect?, send_pattern('#Expectations.all')
64
64
  def_node_matcher :aggregate_failures_block?, <<-PATTERN
65
65
  (block (send nil? :aggregate_failures ...) ...)
66
66
  PATTERN
@@ -85,7 +85,7 @@ module RuboCop
85
85
  #
86
86
  class MultipleMemoizedHelpers < Base
87
87
  include ConfigurableMax
88
- include RuboCop::RSpec::Variable
88
+ include Variable
89
89
 
90
90
  MSG = 'Example group has too many memoized helpers [%<count>d/%<max>d]'
91
91
 
@@ -101,6 +101,7 @@ module RuboCop
101
101
  end
102
102
 
103
103
  def on_new_investigation
104
+ super
104
105
  @example_group_memoized_helpers = {}
105
106
  end
106
107
 
@@ -128,6 +129,7 @@ module RuboCop
128
129
 
129
130
  def variable_nodes(node)
130
131
  example_group = RuboCop::RSpec::ExampleGroup.new(node)
132
+
131
133
  if allow_subject?
132
134
  example_group.lets
133
135
  else
@@ -42,24 +42,20 @@ module RuboCop
42
42
  # it { is_expected.to be_valid }
43
43
  # end
44
44
  class NamedSubject < Base
45
- MSG = 'Name your test subject if you need '\
46
- 'to reference it explicitly.'
45
+ MSG = 'Name your test subject if you need to reference it explicitly.'
47
46
 
48
- def_node_matcher :rspec_block?, <<-PATTERN
49
- {
50
- #{Examples::ALL.block_pattern}
51
- #{Hooks::ALL.block_pattern}
52
- }
53
- PATTERN
47
+ def_node_matcher :example_or_hook_block?,
48
+ block_pattern('{#Examples.all #Hooks.all}')
54
49
 
55
- def_node_matcher :shared_example?, <<-PATTERN
56
- #{SharedGroups::EXAMPLES.block_pattern}
57
- PATTERN
50
+ def_node_matcher :shared_example?,
51
+ block_pattern('#SharedGroups.examples')
58
52
 
59
53
  def_node_search :subject_usage, '$(send nil? :subject)'
60
54
 
61
55
  def on_block(node)
62
- return if !rspec_block?(node) || ignored_shared_example?(node)
56
+ if !example_or_hook_block?(node) || ignored_shared_example?(node)
57
+ return
58
+ end
63
59
 
64
60
  subject_usage(node) do |subject_node|
65
61
  add_offense(subject_node.loc.selector)
@@ -87,7 +87,7 @@ module RuboCop
87
87
  #
88
88
  class NestedGroups < Base
89
89
  include ConfigurableMax
90
- include RuboCop::RSpec::TopLevelGroup
90
+ include TopLevelGroup
91
91
 
92
92
  MSG = 'Maximum example group nesting exceeded [%<total>d/%<max>d].'
93
93
 
@@ -24,7 +24,8 @@ module RuboCop
24
24
  class OverwritingSetup < Base
25
25
  MSG = '`%<name>s` is already defined.'
26
26
 
27
- def_node_matcher :setup?, (Helpers::ALL + Subject::ALL).block_pattern
27
+ def_node_matcher :setup?, block_pattern('{#Helpers.all #Subjects.all}')
28
+
28
29
  def_node_matcher :first_argument_name, '(send _ _ ({str sym} $_))'
29
30
 
30
31
  def on_block(node)
@@ -34,10 +34,10 @@ module RuboCop
34
34
  class Pending < Base
35
35
  MSG = 'Pending spec found.'
36
36
 
37
- PENDING = Examples::PENDING + Examples::SKIPPED + ExampleGroups::SKIPPED
38
- SKIPPABLE = ExampleGroups::GROUPS + Examples::EXAMPLES
39
-
40
- def_node_matcher :skippable?, SKIPPABLE.send_pattern
37
+ def_node_matcher :skippable?,
38
+ send_pattern(<<~PATTERN)
39
+ {#ExampleGroups.regular #Examples.regular}
40
+ PATTERN
41
41
 
42
42
  def_node_matcher :skipped_in_metadata?, <<-PATTERN
43
43
  {
@@ -47,7 +47,15 @@ module RuboCop
47
47
  PATTERN
48
48
 
49
49
  def_node_matcher :skip_or_pending?, '{(sym :skip) (sym :pending)}'
50
- def_node_matcher :pending_block?, PENDING.send_pattern
50
+
51
+ def_node_matcher :pending_block?,
52
+ send_pattern(<<~PATTERN)
53
+ {
54
+ #ExampleGroups.skipped
55
+ #Examples.skipped
56
+ #Examples.pending
57
+ }
58
+ PATTERN
51
59
 
52
60
  def on_send(node)
53
61
  return unless pending_block?(node) || skipped?(node)
@@ -30,7 +30,7 @@ module RuboCop
30
30
  (send nil? :expect {
31
31
  (block $(send !nil? #predicate? ...) ...)
32
32
  $(send !nil? #predicate? ...)})
33
- $#{Runners::ALL.node_pattern_union}
33
+ $#Runners.all
34
34
  $#boolean_matcher?)
35
35
  PATTERN
36
36
 
@@ -155,7 +155,7 @@ module RuboCop
155
155
  def_node_matcher :predicate_matcher?, <<-PATTERN
156
156
  (send
157
157
  (send nil? :expect $!nil?)
158
- #{Runners::ALL.node_pattern_union}
158
+ #Runners.all
159
159
  {$(send nil? #predicate_matcher_name? ...)
160
160
  (block $(send nil? #predicate_matcher_name? ...) ...)})
161
161
  PATTERN
@@ -164,7 +164,7 @@ module RuboCop
164
164
  (block
165
165
  (send
166
166
  (send nil? :expect $!nil?)
167
- #{Runners::ALL.node_pattern_union}
167
+ #Runners.all
168
168
  $(send nil? #predicate_matcher_name?))
169
169
  ...)
170
170
  PATTERN
@@ -54,10 +54,11 @@ module RuboCop
54
54
  (begin <#include_examples? #include_examples? ...>)
55
55
  PATTERN
56
56
 
57
- def_node_matcher :include_examples?, Includes::EXAMPLES.send_pattern
57
+ def_node_matcher :include_examples?,
58
+ send_pattern('#Includes.examples')
58
59
 
59
60
  def_node_matcher :shared_examples_name, <<-PATTERN
60
- (send _ #{Includes::EXAMPLES.node_pattern_union} $_ ...)
61
+ (send _ #Includes.examples $_ ...)
61
62
  PATTERN
62
63
 
63
64
  def on_begin(node)
@@ -59,14 +59,24 @@ module RuboCop
59
59
  MSG_CONTEXT = "Use `shared_context` when you don't "\
60
60
  'define examples.'
61
61
 
62
- examples = (Examples::ALL + Includes::EXAMPLES)
63
- def_node_search :examples?, examples.send_pattern
62
+ def_node_search :examples?,
63
+ send_pattern('{#Includes.examples #Examples.all}')
64
64
 
65
- context = (Hooks::ALL + Helpers::ALL + Includes::CONTEXT + Subject::ALL)
66
- def_node_search :context?, context.send_pattern
65
+ def_node_search :context?, <<-PATTERN
66
+ (
67
+ send #rspec? {
68
+ #Subjects.all
69
+ #Helpers.all
70
+ #Includes.context
71
+ #Hooks.all
72
+ } ...
73
+ )
74
+ PATTERN
67
75
 
68
- def_node_matcher :shared_context, SharedGroups::CONTEXT.block_pattern
69
- def_node_matcher :shared_example, SharedGroups::EXAMPLES.block_pattern
76
+ def_node_matcher :shared_context,
77
+ block_pattern('#SharedGroups.context')
78
+ def_node_matcher :shared_example,
79
+ block_pattern('#SharedGroups.examples')
70
80
 
71
81
  def on_block(node)
72
82
  context_with_only_examples(node) do
@@ -24,7 +24,9 @@ module RuboCop
24
24
  extend AutoCorrector
25
25
 
26
26
  def_node_matcher :shared_examples,
27
- (SharedGroups::ALL + Includes::ALL).send_pattern
27
+ send_pattern(
28
+ '{#SharedGroups.all #Includes.all}'
29
+ )
28
30
 
29
31
  def on_send(node)
30
32
  shared_examples(node) do
@@ -60,7 +60,7 @@ module RuboCop
60
60
  # @yield [RuboCop::AST::Node] expectation, method name, matcher
61
61
  def_node_matcher :expectation, <<~PATTERN
62
62
  (send
63
- $(send nil? $#{Expectations::ALL.node_pattern_union} ...)
63
+ $(send nil? $#Expectations.all ...)
64
64
  :to $_)
65
65
  PATTERN
66
66
 
@@ -22,7 +22,7 @@ module RuboCop
22
22
  # end
23
23
  #
24
24
  class SubjectStub < Base
25
- include RuboCop::RSpec::TopLevelGroup
25
+ include TopLevelGroup
26
26
 
27
27
  MSG = 'Do not stub methods of the object under test.'
28
28
 
@@ -66,7 +66,7 @@ module RuboCop
66
66
  (send nil? { :expect :allow } (send nil? {% :subject}))
67
67
  (send nil? :is_expected)
68
68
  }
69
- #{Runners::ALL.node_pattern_union}
69
+ #Runners.all
70
70
  #message_expectation_matcher?
71
71
  )
72
72
  PATTERN
@@ -24,7 +24,7 @@ module RuboCop
24
24
  # let('user_name') { 'Adam' }
25
25
  class VariableDefinition < Base
26
26
  include ConfigurableEnforcedStyle
27
- include RuboCop::RSpec::Variable
27
+ include Variable
28
28
 
29
29
  MSG = 'Use %<style>s for variable names.'
30
30
 
@@ -42,7 +42,7 @@ module RuboCop
42
42
  class VariableName < Base
43
43
  include ConfigurableNaming
44
44
  include IgnoredPattern
45
- include RuboCop::RSpec::Variable
45
+ include Variable
46
46
 
47
47
  MSG = 'Use %<style>s for variable names.'
48
48
 
@@ -52,7 +52,6 @@ require_relative 'rspec/implicit_expect'
52
52
  require_relative 'rspec/implicit_subject'
53
53
  require_relative 'rspec/instance_spy'
54
54
  require_relative 'rspec/instance_variable'
55
- require_relative 'rspec/invalid_predicate_matcher'
56
55
  require_relative 'rspec/it_behaves_like'
57
56
  require_relative 'rspec/iterated_expectation'
58
57
  require_relative 'rspec/leading_subject'
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module RSpec
5
5
  # Shared behavior for aligning braces for single line lets
6
6
  class AlignLetBrace
7
- include RuboCop::RSpec::Language::NodePattern
7
+ include RuboCop::RSpec::Language
8
8
 
9
9
  def initialize(root, token)
10
10
  @root = root
@@ -4,9 +4,9 @@ module RuboCop
4
4
  module RSpec
5
5
  # Wrapper for RSpec DSL methods
6
6
  class Concept
7
+ extend RuboCop::NodePattern::Macros
8
+ extend Language::NodePattern
7
9
  include Language
8
- include Language::NodePattern
9
- extend NodePattern::Macros
10
10
 
11
11
  def initialize(node)
12
12
  @node = node
@@ -6,7 +6,7 @@ module RuboCop
6
6
  module RSpec
7
7
  # Builds a YAML config file from two config hashes
8
8
  class ConfigFormatter
9
- NAMESPACES = /^(RSpec|Capybara|FactoryBot|Rails)/.freeze
9
+ EXTENSION_ROOT_DEPARTMENT = %r{^(RSpec/)}.freeze
10
10
  STYLE_GUIDE_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/'
11
11
 
12
12
  def initialize(config, descriptions)
@@ -15,7 +15,7 @@ module RuboCop
15
15
  end
16
16
 
17
17
  def dump
18
- YAML.dump(unified_config).gsub(NAMESPACES, "\n\\1")
18
+ YAML.dump(unified_config).gsub(EXTENSION_ROOT_DEPARTMENT, "\n\\1")
19
19
  end
20
20
 
21
21
  private
@@ -29,7 +29,7 @@ module RuboCop
29
29
  end
30
30
 
31
31
  def cops
32
- (descriptions.keys | config.keys).grep(NAMESPACES)
32
+ (descriptions.keys | config.keys).grep(EXTENSION_ROOT_DEPARTMENT)
33
33
  end
34
34
 
35
35
  attr_reader :config, :descriptions
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # Helper methods to move a node
7
7
  class MoveNode
8
8
  include RuboCop::Cop::RangeHelp
9
- include RuboCop::RSpec::FinalEndLocation
9
+ include RuboCop::Cop::RSpec::FinalEndLocation
10
10
 
11
11
  attr_reader :original, :corrector, :processed_source
12
12
 
@@ -10,9 +10,14 @@ module RuboCop
10
10
  #
11
11
  # Selectors which indicate that we should stop searching
12
12
  #
13
- def_node_matcher :scope_change?, (
14
- ExampleGroups::ALL + SharedGroups::ALL + Includes::ALL
15
- ).block_pattern
13
+ def_node_matcher :scope_change?,
14
+ block_pattern(<<~PATTERN)
15
+ {
16
+ #SharedGroups.all
17
+ #ExampleGroups.all
18
+ #Includes.all
19
+ }
20
+ PATTERN
16
21
 
17
22
  def lets
18
23
  find_all_in_scope(node, :let?)
@@ -23,11 +28,15 @@ module RuboCop
23
28
  end
24
29
 
25
30
  def examples
26
- find_all_in_scope(node, :example?).map(&Example.public_method(:new))
31
+ find_all_in_scope(node, :example?).map do |node|
32
+ Example.new(node)
33
+ end
27
34
  end
28
35
 
29
36
  def hooks
30
- find_all_in_scope(node, :hook?).map(&Hook.public_method(:new))
37
+ find_all_in_scope(node, :hook?).map do |node|
38
+ Hook.new(node)
39
+ end
31
40
  end
32
41
 
33
42
  private
@@ -37,6 +46,7 @@ module RuboCop
37
46
  # Searches node and halts when a scope change is detected
38
47
  #
39
48
  # @param node [RuboCop::AST::Node] node to recursively search
49
+ # @param predicate [Symbol] method to call with node as argument
40
50
  #
41
51
  # @return [Array<RuboCop::AST::Node>] discovered nodes
42
52
  def find_all_in_scope(node, predicate)
@@ -44,7 +44,7 @@ module RuboCop
44
44
  private
45
45
 
46
46
  def valid_scope?(node)
47
- node&.sym_type? && Hooks::Scopes::ALL.include?(node.value)
47
+ node&.sym_type? && Language::HookScopes.all(node.value)
48
48
  end
49
49
 
50
50
  def transform_metadata(meta)
@@ -6,9 +6,11 @@ module RuboCop
6
6
  # bit of our configuration.
7
7
  module Inject
8
8
  def self.defaults!
9
- path = CONFIG_DEFAULT.to_s
9
+ project_root = Pathname.new(__dir__).parent.parent.parent.expand_path
10
+ config_default = project_root.join('config', 'default.yml')
11
+ path = config_default.to_s
10
12
  hash = ConfigLoader.send(:load_yaml_configuration, path)
11
- config = Config.new(hash, path)
13
+ config = RuboCop::Config.new(hash, path)
12
14
  puts "configuration from #{path}" if ConfigLoader.debug?
13
15
  config = ConfigLoader.merge_with_default(config, path)
14
16
  ConfigLoader.instance_variable_set(:@default_configuration, config)
@@ -2,152 +2,186 @@
2
2
 
3
3
  module RuboCop
4
4
  module RSpec
5
- # RSpec public API methods that are commonly used in cops
5
+ # Contains node matchers for common RSpec DSL.
6
+ #
7
+ # RSpec allows for configuring aliases for commonly used DSL elements, e.g.
8
+ # example groups and hooks. It is possible to configure RuboCop RSpec to
9
+ # be able to properly detect these elements in the `RSpec/Language` section
10
+ # of the RuboCop YAML configuration file.
11
+ #
12
+ # In addition to providing useful matchers, this class is responsible for
13
+ # using the configured aliases.
6
14
  module Language
7
- # Set of method selectors
8
- class SelectorSet
9
- def initialize(selectors)
10
- @selectors = selectors.freeze
11
- freeze
12
- end
15
+ extend RuboCop::NodePattern::Macros
16
+ extend NodePattern
13
17
 
14
- def ==(other)
15
- selectors.eql?(other.selectors)
16
- end
18
+ class << self
19
+ attr_accessor :config
20
+ end
17
21
 
18
- def +(other)
19
- self.class.new(selectors + other.selectors)
20
- end
22
+ def_node_matcher :rspec?, '{(const {nil? cbase} :RSpec) nil?}'
21
23
 
22
- def include?(selector)
23
- selectors.include?(selector)
24
- end
24
+ def_node_matcher :example_group?, block_pattern('#ExampleGroups.all')
25
25
 
26
- def block_pattern
27
- "(block #{send_pattern} ...)"
28
- end
26
+ def_node_matcher :shared_group?, block_pattern('#SharedGroups.all')
29
27
 
30
- def block_pass_pattern
31
- "(send #rspec? #{node_pattern_union} _ block_pass)"
32
- end
28
+ def_node_matcher :spec_group?,
29
+ block_pattern('{#SharedGroups.all #ExampleGroups.all}')
33
30
 
34
- def block_or_block_pass_pattern
35
- "{#{block_pattern} #{block_pass_pattern}}"
36
- end
31
+ def_node_matcher :example_group_with_body?, <<-PATTERN
32
+ (block #{send_pattern('#ExampleGroups.all')} args !nil?)
33
+ PATTERN
37
34
 
38
- def send_pattern
39
- "(send #rspec? #{node_pattern_union} ...)"
40
- end
35
+ def_node_matcher :example?, block_pattern('#Examples.all')
41
36
 
42
- def send_or_block_or_block_pass_pattern
43
- "{#{send_pattern} #{block_pattern} #{block_pass_pattern}}"
44
- end
37
+ def_node_matcher :hook?, block_pattern('#Hooks.all')
45
38
 
46
- def node_pattern_union
47
- "{#{node_pattern}}"
48
- end
39
+ def_node_matcher :let?, <<-PATTERN
40
+ {
41
+ #{block_pattern('#Helpers.all')}
42
+ (send #rspec? #Helpers.all _ block_pass)
43
+ }
44
+ PATTERN
49
45
 
50
- def node_pattern
51
- selectors.map(&:inspect).join(' ')
52
- end
46
+ def_node_matcher :include?, <<-PATTERN
47
+ {
48
+ #{send_pattern('#Includes.all')}
49
+ #{block_pattern('#Includes.all')}
50
+ }
51
+ PATTERN
53
52
 
54
- def to_a
55
- selectors
56
- end
53
+ def_node_matcher :subject?, block_pattern('#Subjects.all')
57
54
 
58
- protected
55
+ module ExampleGroups # :nodoc:
56
+ class << self
57
+ def all(element)
58
+ regular(element) ||
59
+ skipped(element) ||
60
+ focused(element)
61
+ end
59
62
 
60
- attr_reader :selectors
61
- end
63
+ def regular(element)
64
+ Language.config['ExampleGroups']['Regular'].include?(element.to_s)
65
+ end
62
66
 
63
- module ExampleGroups
64
- GROUPS = SelectorSet.new(%i[describe context feature example_group])
65
- SKIPPED = SelectorSet.new(%i[xdescribe xcontext xfeature])
66
- FOCUSED = SelectorSet.new(%i[fdescribe fcontext ffeature])
67
+ def focused(element)
68
+ Language.config['ExampleGroups']['Focused'].include?(element.to_s)
69
+ end
67
70
 
68
- ALL = GROUPS + SKIPPED + FOCUSED
71
+ def skipped(element)
72
+ Language.config['ExampleGroups']['Skipped'].include?(element.to_s)
73
+ end
74
+ end
69
75
  end
70
76
 
71
- module SharedGroups
72
- EXAMPLES = SelectorSet.new(%i[shared_examples shared_examples_for])
73
- CONTEXT = SelectorSet.new(%i[shared_context])
77
+ module Examples # :nodoc:
78
+ class << self
79
+ def all(element)
80
+ regular(element) ||
81
+ focused(element) ||
82
+ skipped(element) ||
83
+ pending(element)
84
+ end
85
+
86
+ def regular(element)
87
+ Language.config['Examples']['Regular'].include?(element.to_s)
88
+ end
89
+
90
+ def focused(element)
91
+ Language.config['Examples']['Focused'].include?(element.to_s)
92
+ end
93
+
94
+ def skipped(element)
95
+ Language.config['Examples']['Skipped'].include?(element.to_s)
96
+ end
97
+
98
+ def pending(element)
99
+ Language.config['Examples']['Pending'].include?(element.to_s)
100
+ end
101
+ end
102
+ end
74
103
 
75
- ALL = EXAMPLES + CONTEXT
104
+ module Expectations # :nodoc:
105
+ def self.all(element)
106
+ Language.config['Expectations'].include?(element.to_s)
107
+ end
76
108
  end
77
109
 
78
- module Includes
79
- EXAMPLES = SelectorSet.new(
80
- %i[
81
- it_behaves_like
82
- it_should_behave_like
83
- include_examples
84
- ]
85
- )
86
- CONTEXT = SelectorSet.new(%i[include_context])
87
-
88
- ALL = EXAMPLES + CONTEXT
110
+ module Helpers # :nodoc:
111
+ def self.all(element)
112
+ Language.config['Helpers'].include?(element.to_s)
113
+ end
89
114
  end
90
115
 
91
- module Examples
92
- EXAMPLES = SelectorSet.new(%i[it specify example scenario its])
93
- FOCUSED = SelectorSet.new(%i[fit fspecify fexample fscenario focus])
94
- SKIPPED = SelectorSet.new(%i[xit xspecify xexample xscenario skip])
95
- PENDING = SelectorSet.new(%i[pending])
116
+ module Hooks # :nodoc:
117
+ def self.all(element)
118
+ Language.config['Hooks'].include?(element.to_s)
119
+ end
120
+ end
96
121
 
97
- ALL = EXAMPLES + FOCUSED + SKIPPED + PENDING
122
+ module HookScopes # :nodoc:
123
+ def self.all(element)
124
+ Language.config['HookScopes'].include?(element.to_s)
125
+ end
98
126
  end
99
127
 
100
- module Hooks
101
- ALL = SelectorSet.new(
102
- %i[
103
- prepend_before
104
- before
105
- append_before
106
- around
107
- prepend_after
108
- after
109
- append_after
110
- ]
111
- )
112
-
113
- module Scopes
114
- ALL = SelectorSet.new(
115
- %i[
116
- each
117
- example
118
- context
119
- all
120
- suite
121
- ]
122
- )
128
+ module Includes # :nodoc:
129
+ class << self
130
+ def all(element)
131
+ examples(element) ||
132
+ context(element)
133
+ end
134
+
135
+ def examples(element)
136
+ Language.config['Includes']['Examples'].include?(element.to_s)
137
+ end
138
+
139
+ def context(element)
140
+ Language.config['Includes']['Context'].include?(element.to_s)
141
+ end
123
142
  end
124
143
  end
125
144
 
126
- module Helpers
127
- ALL = SelectorSet.new(%i[let let!])
145
+ module Runners # :nodoc:
146
+ def self.all(element)
147
+ Language.config['Runners'].include?(element.to_s)
148
+ end
128
149
  end
129
150
 
130
- module Subject
131
- ALL = SelectorSet.new(%i[subject subject!])
151
+ module SharedGroups # :nodoc:
152
+ class << self
153
+ def all(element)
154
+ examples(element) ||
155
+ context(element)
156
+ end
157
+
158
+ def examples(element)
159
+ Language.config['SharedGroups']['Examples'].include?(element.to_s)
160
+ end
161
+
162
+ def context(element)
163
+ Language.config['SharedGroups']['Context'].include?(element.to_s)
164
+ end
165
+ end
132
166
  end
133
167
 
134
- module Expectations
135
- ALL = SelectorSet.new(%i[expect is_expected expect_any_instance_of])
168
+ module Subjects # :nodoc:
169
+ def self.all(element)
170
+ Language.config['Subjects'].include?(element.to_s)
171
+ end
136
172
  end
137
173
 
138
- module Runners
139
- ALL = SelectorSet.new(%i[to to_not not_to])
174
+ # This is used in Dialect and DescribeClass cops to detect RSpec blocks.
175
+ module ALL # :nodoc:
176
+ def self.all(element)
177
+ [ExampleGroups, Examples, Expectations, Helpers, Hooks, Includes,
178
+ Runners, SharedGroups, Subjects]
179
+ .find { |concept| concept.all(element) }
180
+ end
140
181
  end
141
182
 
142
- ALL =
143
- ExampleGroups::ALL +
144
- SharedGroups::ALL +
145
- Examples::ALL +
146
- Hooks::ALL +
147
- Helpers::ALL +
148
- Subject::ALL +
149
- Expectations::ALL +
150
- Runners::ALL
183
+ private_constant :ExampleGroups, :Examples, :Expectations, :Hooks,
184
+ :Includes, :Runners, :SharedGroups, :ALL
151
185
  end
152
186
  end
153
187
  end