lib/rubocop/rspec/language.rb in rubocop-rspec-2.0.0.pre vs lib/rubocop/rspec/language.rb in rubocop-rspec-2.0.0
- old
+ new
@@ -1,153 +1,187 @@
# frozen_string_literal: true
module RuboCop
module RSpec
- # RSpec public API methods that are commonly used in cops
+ # Contains node matchers for common RSpec DSL.
+ #
+ # RSpec allows for configuring aliases for commonly used DSL elements, e.g.
+ # example groups and hooks. It is possible to configure RuboCop RSpec to
+ # be able to properly detect these elements in the `RSpec/Language` section
+ # of the RuboCop YAML configuration file.
+ #
+ # In addition to providing useful matchers, this class is responsible for
+ # using the configured aliases.
module Language
- # Set of method selectors
- class SelectorSet
- def initialize(selectors)
- @selectors = selectors.freeze
- freeze
- end
+ extend RuboCop::NodePattern::Macros
+ extend NodePattern
- def ==(other)
- selectors.eql?(other.selectors)
- end
+ class << self
+ attr_accessor :config
+ end
- def +(other)
- self.class.new(selectors + other.selectors)
- end
+ def_node_matcher :rspec?, '{(const {nil? cbase} :RSpec) nil?}'
- def include?(selector)
- selectors.include?(selector)
- end
+ def_node_matcher :example_group?, block_pattern('#ExampleGroups.all')
- def block_pattern
- "(block #{send_pattern} ...)"
- end
+ def_node_matcher :shared_group?, block_pattern('#SharedGroups.all')
- def block_pass_pattern
- "(send #rspec? #{node_pattern_union} _ block_pass)"
- end
+ def_node_matcher :spec_group?,
+ block_pattern('{#SharedGroups.all #ExampleGroups.all}')
- def block_or_block_pass_pattern
- "{#{block_pattern} #{block_pass_pattern}}"
- end
+ def_node_matcher :example_group_with_body?, <<-PATTERN
+ (block #{send_pattern('#ExampleGroups.all')} args !nil?)
+ PATTERN
- def send_pattern
- "(send #rspec? #{node_pattern_union} ...)"
- end
+ def_node_matcher :example?, block_pattern('#Examples.all')
- def send_or_block_or_block_pass_pattern
- "{#{send_pattern} #{block_pattern} #{block_pass_pattern}}"
- end
+ def_node_matcher :hook?, block_pattern('#Hooks.all')
- def node_pattern_union
- "{#{node_pattern}}"
- end
+ def_node_matcher :let?, <<-PATTERN
+ {
+ #{block_pattern('#Helpers.all')}
+ (send #rspec? #Helpers.all _ block_pass)
+ }
+ PATTERN
- def node_pattern
- selectors.map(&:inspect).join(' ')
- end
+ def_node_matcher :include?, <<-PATTERN
+ {
+ #{send_pattern('#Includes.all')}
+ #{block_pattern('#Includes.all')}
+ }
+ PATTERN
- def to_a
- selectors
- end
+ def_node_matcher :subject?, block_pattern('#Subjects.all')
- protected
+ module ExampleGroups # :nodoc:
+ class << self
+ def all(element)
+ regular(element) ||
+ skipped(element) ||
+ focused(element)
+ end
- attr_reader :selectors
- end
+ def regular(element)
+ Language.config['ExampleGroups']['Regular'].include?(element.to_s)
+ end
- module ExampleGroups
- GROUPS = SelectorSet.new(%i[describe context feature example_group])
- SKIPPED = SelectorSet.new(%i[xdescribe xcontext xfeature])
- FOCUSED = SelectorSet.new(%i[fdescribe fcontext ffeature])
+ def focused(element)
+ Language.config['ExampleGroups']['Focused'].include?(element.to_s)
+ end
- ALL = GROUPS + SKIPPED + FOCUSED
+ def skipped(element)
+ Language.config['ExampleGroups']['Skipped'].include?(element.to_s)
+ end
+ end
end
- module SharedGroups
- EXAMPLES = SelectorSet.new(%i[shared_examples shared_examples_for])
- CONTEXT = SelectorSet.new(%i[shared_context])
+ module Examples # :nodoc:
+ class << self
+ def all(element)
+ regular(element) ||
+ focused(element) ||
+ skipped(element) ||
+ pending(element)
+ end
- ALL = EXAMPLES + CONTEXT
+ def regular(element)
+ Language.config['Examples']['Regular'].include?(element.to_s)
+ end
+
+ def focused(element)
+ Language.config['Examples']['Focused'].include?(element.to_s)
+ end
+
+ def skipped(element)
+ Language.config['Examples']['Skipped'].include?(element.to_s)
+ end
+
+ def pending(element)
+ Language.config['Examples']['Pending'].include?(element.to_s)
+ end
+ end
end
- module Includes
- EXAMPLES = SelectorSet.new(
- %i[
- it_behaves_like
- it_should_behave_like
- include_examples
- ]
- )
- CONTEXT = SelectorSet.new(%i[include_context])
+ module Expectations # :nodoc:
+ def self.all(element)
+ Language.config['Expectations'].include?(element.to_s)
+ end
+ end
- ALL = EXAMPLES + CONTEXT
+ module Helpers # :nodoc:
+ def self.all(element)
+ Language.config['Helpers'].include?(element.to_s)
+ end
end
- module Examples
- EXAMPLES = SelectorSet.new(%i[it specify example scenario its])
- FOCUSED = SelectorSet.new(%i[fit fspecify fexample fscenario focus])
- SKIPPED = SelectorSet.new(%i[xit xspecify xexample xscenario skip])
- PENDING = SelectorSet.new(%i[pending])
+ module Hooks # :nodoc:
+ def self.all(element)
+ Language.config['Hooks'].include?(element.to_s)
+ end
+ end
- ALL = EXAMPLES + FOCUSED + SKIPPED + PENDING
+ module HookScopes # :nodoc:
+ def self.all(element)
+ Language.config['HookScopes'].include?(element.to_s)
+ end
end
- module Hooks
- ALL = SelectorSet.new(
- %i[
- prepend_before
- before
- append_before
- around
- prepend_after
- after
- append_after
- ]
- )
+ module Includes # :nodoc:
+ class << self
+ def all(element)
+ examples(element) ||
+ context(element)
+ end
- module Scopes
- ALL = SelectorSet.new(
- %i[
- each
- example
- context
- all
- suite
- ]
- )
+ def examples(element)
+ Language.config['Includes']['Examples'].include?(element.to_s)
+ end
+
+ def context(element)
+ Language.config['Includes']['Context'].include?(element.to_s)
+ end
end
end
- module Helpers
- ALL = SelectorSet.new(%i[let let!])
+ module Runners # :nodoc:
+ def self.all(element)
+ Language.config['Runners'].include?(element.to_s)
+ end
end
- module Subject
- ALL = SelectorSet.new(%i[subject subject!])
+ module SharedGroups # :nodoc:
+ class << self
+ def all(element)
+ examples(element) ||
+ context(element)
+ end
+
+ def examples(element)
+ Language.config['SharedGroups']['Examples'].include?(element.to_s)
+ end
+
+ def context(element)
+ Language.config['SharedGroups']['Context'].include?(element.to_s)
+ end
+ end
end
- module Expectations
- ALL = SelectorSet.new(%i[expect is_expected expect_any_instance_of])
+ module Subjects # :nodoc:
+ def self.all(element)
+ Language.config['Subjects'].include?(element.to_s)
+ end
end
- module Runners
- ALL = SelectorSet.new(%i[to to_not not_to])
+ # This is used in Dialect and DescribeClass cops to detect RSpec blocks.
+ module ALL # :nodoc:
+ def self.all(element)
+ [ExampleGroups, Examples, Expectations, Helpers, Hooks, Includes,
+ Runners, SharedGroups, Subjects]
+ .find { |concept| concept.all(element) }
+ end
end
- ALL =
- ExampleGroups::ALL +
- SharedGroups::ALL +
- Examples::ALL +
- Hooks::ALL +
- Helpers::ALL +
- Subject::ALL +
- Expectations::ALL +
- Runners::ALL
+ private_constant :ExampleGroups, :Examples, :Expectations, :Hooks,
+ :Includes, :Runners, :SharedGroups, :ALL
end
end
end