rubocop-rspec 1.44.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -1
  3. data/README.md +5 -1
  4. data/config/default.yml +171 -81
  5. data/lib/rubocop-rspec.rb +8 -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/any_instance.rb +6 -10
  9. data/lib/rubocop/cop/rspec/around_block.rb +1 -1
  10. data/lib/rubocop/cop/rspec/base.rb +6 -55
  11. data/lib/rubocop/cop/rspec/be.rb +2 -2
  12. data/lib/rubocop/cop/rspec/be_eql.rb +1 -0
  13. data/lib/rubocop/cop/rspec/before_after_all.rb +5 -3
  14. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +4 -2
  15. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +3 -2
  16. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +2 -0
  17. data/lib/rubocop/cop/rspec/describe_class.rb +2 -2
  18. data/lib/rubocop/cop/rspec/describe_method.rb +2 -2
  19. data/lib/rubocop/cop/rspec/describe_symbol.rb +1 -0
  20. data/lib/rubocop/cop/rspec/described_class.rb +1 -2
  21. data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -2
  22. data/lib/rubocop/cop/rspec/dialect.rb +1 -1
  23. data/lib/rubocop/cop/rspec/empty_example_group.rb +6 -45
  24. data/lib/rubocop/cop/rspec/empty_hook.rb +1 -1
  25. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +1 -1
  26. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +1 -1
  27. data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +1 -1
  28. data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +1 -1
  29. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +2 -2
  30. data/lib/rubocop/cop/rspec/expect_actual.rb +2 -1
  31. data/lib/rubocop/cop/rspec/expect_change.rb +1 -0
  32. data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
  33. data/lib/rubocop/cop/rspec/expect_output.rb +1 -1
  34. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +1 -0
  35. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +1 -0
  36. data/lib/rubocop/cop/rspec/file_path.rb +24 -17
  37. data/lib/rubocop/cop/rspec/focus.rb +43 -8
  38. data/lib/rubocop/cop/rspec/hook_argument.rb +2 -4
  39. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +2 -2
  40. data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +1 -0
  41. data/lib/rubocop/cop/rspec/implicit_expect.rb +1 -1
  42. data/lib/rubocop/cop/rspec/implicit_subject.rb +1 -0
  43. data/lib/rubocop/cop/rspec/instance_spy.rb +1 -1
  44. data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
  45. data/lib/rubocop/cop/rspec/it_behaves_like.rb +2 -1
  46. data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
  47. data/lib/rubocop/cop/rspec/let_before_examples.rb +2 -2
  48. data/lib/rubocop/cop/rspec/let_setup.rb +7 -4
  49. data/lib/rubocop/cop/rspec/message_chain.rb +4 -10
  50. data/lib/rubocop/cop/rspec/message_expectation.rb +1 -0
  51. data/lib/rubocop/cop/rspec/message_spies.rb +3 -3
  52. data/lib/rubocop/cop/rspec/mixin/comments_help.rb +38 -0
  53. data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +51 -0
  54. data/lib/rubocop/cop/rspec/mixin/final_end_location.rb +19 -0
  55. data/lib/rubocop/cop/rspec/mixin/top_level_group.rb +54 -0
  56. data/lib/rubocop/cop/rspec/mixin/variable.rb +20 -0
  57. data/lib/rubocop/cop/rspec/multiple_describes.rb +2 -3
  58. data/lib/rubocop/cop/rspec/multiple_expectations.rb +1 -1
  59. data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +3 -1
  60. data/lib/rubocop/cop/rspec/named_subject.rb +8 -12
  61. data/lib/rubocop/cop/rspec/nested_groups.rb +1 -1
  62. data/lib/rubocop/cop/rspec/not_to_not.rb +1 -0
  63. data/lib/rubocop/cop/rspec/overwriting_setup.rb +2 -1
  64. data/lib/rubocop/cop/rspec/pending.rb +13 -5
  65. data/lib/rubocop/cop/rspec/predicate_matcher.rb +3 -3
  66. data/lib/rubocop/cop/rspec/rails/http_status.rb +1 -0
  67. data/lib/rubocop/cop/rspec/receive_counts.rb +2 -0
  68. data/lib/rubocop/cop/rspec/receive_never.rb +1 -0
  69. data/lib/rubocop/cop/rspec/repeated_include_example.rb +3 -2
  70. data/lib/rubocop/cop/rspec/return_from_stub.rb +1 -0
  71. data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
  72. data/lib/rubocop/cop/rspec/shared_context.rb +18 -11
  73. data/lib/rubocop/cop/rspec/shared_examples.rb +3 -1
  74. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +2 -1
  75. data/lib/rubocop/cop/rspec/stubbed_mock.rb +1 -1
  76. data/lib/rubocop/cop/rspec/subject_stub.rb +16 -6
  77. data/lib/rubocop/cop/rspec/unspecified_exception.rb +1 -0
  78. data/lib/rubocop/cop/rspec/variable_definition.rb +1 -1
  79. data/lib/rubocop/cop/rspec/variable_name.rb +1 -1
  80. data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -0
  81. data/lib/rubocop/cop/rspec/void_expect.rb +1 -0
  82. data/lib/rubocop/cop/rspec_cops.rb +0 -1
  83. data/lib/rubocop/rspec/align_let_brace.rb +1 -1
  84. data/lib/rubocop/rspec/concept.rb +2 -2
  85. data/lib/rubocop/rspec/config_formatter.rb +5 -3
  86. data/lib/rubocop/rspec/corrector/move_node.rb +7 -10
  87. data/lib/rubocop/rspec/example_group.rb +15 -5
  88. data/lib/rubocop/rspec/hook.rb +1 -1
  89. data/lib/rubocop/rspec/inject.rb +4 -2
  90. data/lib/rubocop/rspec/language.rb +143 -109
  91. data/lib/rubocop/rspec/language/node_pattern.rb +7 -24
  92. data/lib/rubocop/rspec/node.rb +1 -1
  93. data/lib/rubocop/rspec/version.rb +1 -1
  94. metadata +12 -15
  95. data/lib/rubocop/cop/rspec/cop.rb +0 -10
  96. data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +0 -41
  97. data/lib/rubocop/rspec.rb +0 -12
  98. data/lib/rubocop/rspec/empty_line_separation.rb +0 -48
  99. data/lib/rubocop/rspec/final_end_location.rb +0 -17
  100. data/lib/rubocop/rspec/top_level_describe.rb +0 -52
  101. data/lib/rubocop/rspec/top_level_group.rb +0 -57
  102. data/lib/rubocop/rspec/variable.rb +0 -16
@@ -53,20 +53,27 @@ module RuboCop
53
53
  class SharedContext < Base
54
54
  extend AutoCorrector
55
55
 
56
- MSG_EXAMPLES = "Use `shared_examples` when you don't "\
57
- 'define context.'
56
+ MSG_EXAMPLES = "Use `shared_examples` when you don't define context."
57
+ MSG_CONTEXT = "Use `shared_context` when you don't define examples."
58
58
 
59
- MSG_CONTEXT = "Use `shared_context` when you don't "\
60
- 'define examples.'
59
+ def_node_search :examples?,
60
+ send_pattern('{#Includes.examples #Examples.all}')
61
61
 
62
- examples = (Examples::ALL + Includes::EXAMPLES)
63
- def_node_search :examples?, examples.send_pattern
62
+ def_node_search :context?, <<-PATTERN
63
+ (
64
+ send #rspec? {
65
+ #Subjects.all
66
+ #Helpers.all
67
+ #Includes.context
68
+ #Hooks.all
69
+ } ...
70
+ )
71
+ PATTERN
64
72
 
65
- context = (Hooks::ALL + Helpers::ALL + Includes::CONTEXT + Subject::ALL)
66
- def_node_search :context?, context.send_pattern
67
-
68
- def_node_matcher :shared_context, SharedGroups::CONTEXT.block_pattern
69
- def_node_matcher :shared_example, SharedGroups::EXAMPLES.block_pattern
73
+ def_node_matcher :shared_context,
74
+ block_pattern('#SharedGroups.context')
75
+ def_node_matcher :shared_example,
76
+ block_pattern('#SharedGroups.examples')
70
77
 
71
78
  def on_block(node)
72
79
  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
@@ -19,8 +19,9 @@ module RuboCop
19
19
  class SingleArgumentMessageChain < Base
20
20
  extend AutoCorrector
21
21
 
22
- MSG = 'Use `%<recommended>s` instead of calling '\
22
+ MSG = 'Use `%<recommended>s` instead of calling ' \
23
23
  '`%<called>s` with a single argument.'
24
+ RESTRICT_ON_SEND = %i[receive_message_chain stub_chain].freeze
24
25
 
25
26
  def_node_matcher :message_chain, <<-PATTERN
26
27
  (send _ {:receive_message_chain :stub_chain} $_)
@@ -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
 
@@ -13,16 +13,26 @@ module RuboCop
13
13
  #
14
14
  # @example
15
15
  # # bad
16
- # describe Foo do
17
- # subject(:bar) { baz }
16
+ # describe Article do
17
+ # subject(:article) { Article.new }
18
18
  #
19
- # before do
20
- # allow(bar).to receive(:qux?).and_return(true)
19
+ # it 'indicates that the author is unknown' do
20
+ # allow(article).to receive(:author).and_return(nil)
21
+ # expect(article.description).to include('by an unknown author')
22
+ # end
23
+ # end
24
+ #
25
+ # # good
26
+ # describe Article do
27
+ # subject(:article) { Article.new(author: nil) }
28
+ #
29
+ # it 'indicates that the author is unknown' do
30
+ # expect(article.description).to include('by an unknown author')
21
31
  # end
22
32
  # end
23
33
  #
24
34
  class SubjectStub < Base
25
- include RuboCop::RSpec::TopLevelGroup
35
+ include TopLevelGroup
26
36
 
27
37
  MSG = 'Do not stub methods of the object under test.'
28
38
 
@@ -66,7 +76,7 @@ module RuboCop
66
76
  (send nil? { :expect :allow } (send nil? {% :subject}))
67
77
  (send nil? :is_expected)
68
78
  }
69
- #{Runners::ALL.node_pattern_union}
79
+ #Runners.all
70
80
  #message_expectation_matcher?
71
81
  )
72
82
  PATTERN
@@ -32,6 +32,7 @@ module RuboCop
32
32
  # expect { do_something }.not_to raise_error
33
33
  class UnspecifiedException < Base
34
34
  MSG = 'Specify the exception being captured'
35
+ RESTRICT_ON_SEND = %i[to].freeze
35
36
 
36
37
  def_node_matcher :empty_raise_error_or_exception, <<-PATTERN
37
38
  (send
@@ -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
 
@@ -24,6 +24,7 @@ module RuboCop
24
24
  # end
25
25
  class VerifiedDoubles < Base
26
26
  MSG = 'Prefer using verifying doubles over normal doubles.'
27
+ RESTRICT_ON_SEND = %i[double spy].freeze
27
28
 
28
29
  def_node_matcher :unverified_double, <<-PATTERN
29
30
  {(send nil? {:double :spy} $...)}
@@ -14,6 +14,7 @@ module RuboCop
14
14
  class VoidExpect < Base
15
15
  MSG = 'Do not use `expect()` without `.to` or `.not_to`. ' \
16
16
  'Chain the methods or remove it.'
17
+ RESTRICT_ON_SEND = %i[expect].freeze
17
18
 
18
19
  def_node_matcher :expect?, <<-PATTERN
19
20
  (send nil? :expect ...)
@@ -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,9 @@ 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)
19
+ .gsub(EXTENSION_ROOT_DEPARTMENT, "\n\\1")
20
+ .gsub(/^(\s+)- /, '\1 - ')
19
21
  end
20
22
 
21
23
  private
@@ -29,7 +31,7 @@ module RuboCop
29
31
  end
30
32
 
31
33
  def cops
32
- (descriptions.keys | config.keys).grep(NAMESPACES)
34
+ (descriptions.keys | config.keys).grep(EXTENSION_ROOT_DEPARTMENT)
33
35
  end
34
36
 
35
37
  attr_reader :config, :descriptions
@@ -6,7 +6,8 @@ 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::CommentsHelp
10
+ include RuboCop::Cop::RSpec::FinalEndLocation
10
11
 
11
12
  attr_reader :original, :corrector, :processed_source
12
13
 
@@ -17,20 +18,16 @@ module RuboCop
17
18
  end
18
19
 
19
20
  def move_before(other)
20
- position = other.loc.expression
21
- indent = ' ' * other.loc.column
22
- newline_indent = "\n#{indent}"
21
+ position = start_line_position(other)
23
22
 
24
- corrector.insert_before(position, source(original) + newline_indent)
23
+ corrector.insert_before(position, "#{source(original)}\n")
25
24
  corrector.remove(node_range_with_surrounding_space(original))
26
25
  end
27
26
 
28
27
  def move_after(other)
29
- position = final_end_location(other)
30
- indent = ' ' * other.loc.column
31
- newline_indent = "\n#{indent}"
28
+ position = end_line_position(other)
32
29
 
33
- corrector.insert_after(position, newline_indent + source(original))
30
+ corrector.insert_after(position, "\n#{source(original)}")
34
31
  corrector.remove(node_range_with_surrounding_space(original))
35
32
  end
36
33
 
@@ -41,7 +38,7 @@ module RuboCop
41
38
  end
42
39
 
43
40
  def node_range(node)
44
- node.loc.expression.with(end_pos: final_end_location(node).end_pos)
41
+ source_range_with_comment(node)
45
42
  end
46
43
 
47
44
  def node_range_with_surrounding_space(node)
@@ -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