free_mutant/lib/mutant/matcher/compiler.rb
Markus Schirp 41d9700473 Refactor runer infrastructure
* Nuke around 800 lock
* Honor LSP with not anymore squeezing something non LSP compatible in
  the same inheritance tree.
* Separate running from result tree.
* Clean up kill logic and early exits on already dead mutations.
* Fix #runnin? smell for reporters.
* Decouple config object from VM state. Makes it serializable to enable
  config loading.
* Fix sequence of global VM events to match PRIOR rspec infects VM with
  gazillions of classes / modules. Thix fixes a startup speed
  degeneration.
* Various fixes to enhance determinism.
* Replace some unneded manual double dispatch with single manual dispatch for
  reporter / runners.
2014-07-05 23:04:38 +00:00

107 lines
2.5 KiB
Ruby

module Mutant
class Matcher
# Compiler for complex matchers
class Compiler
include Concord.new(:env, :config), AST::Sexp, Procto.call(:result)
# Return generated matcher
#
# @return [Mutant::Matcher]
#
# @api private
#
def result
matchers = config.match_expressions.map(&method(:matcher))
if matchers.empty?
return Matcher::Null.new
end
matcher = Matcher::Chain.build(matchers)
if predicate
Matcher::Filter.new(matcher, predicate)
else
matcher
end
end
private
# Return subject selector
#
# @return [#call]
# if selector is present
#
# @return [nil]
# otherwise
#
# @api private
#
def subject_selector
selectors = config.subject_selects.map do |attribute, value|
Morpher.compile(s(:eql, s(:attribute, attribute), s(:static, value)))
end
Morpher::Evaluator::Predicate::Boolean::Or.new(selectors) if selectors.any?
end
# Return predicate
#
# @return [#call]
# if filter is needed
#
# @return [nil]
# othrwise
#
# @api private
#
def predicate
if subject_selector && subject_rejector
Morpher::Evaluator::Predicate::Boolean::And.new([
subject_selector,
Morpher::Evaluator::Predicate::Negation.new(subject_rejector)
])
elsif subject_selector
subject_selector
elsif subject_rejector
Morpher::Evaluator::Predicate::Negation.new(subject_rejector)
else
nil
end
end
# Return subject rejector
#
# @return [#call]
# if there is a subject rejector
#
# @return [nil]
# otherwise
#
# @api private
#
def subject_rejector
rejectors = config.subject_ignores.map(&method(:matcher)).flat_map(&:to_a).map do |subject|
Morpher.compile(s(:eql, s(:attribute, :identification), s(:static, subject.identification)))
end
Morpher::Evaluator::Predicate::Boolean::Or.new(rejectors) if rejectors.any?
end
# Return a matcher from expression
#
# @param [Mutant::Expression] expression
#
# @return [Matcher]
#
# @api private
#
def matcher(expression)
expression.matcher(env)
end
end # Compiler
end # Matcher
end # Mutant