# frozen_string_literal: true
# Library namespace
#
# @api private
# rubocop:disable Metrics/ModuleLength
module Mutant
# Boot timing infrastructure
get_timestamp = lambda do
Process.clock_gettime(Process::CLOCK_MONOTONIC)
end
library_timestamp = get_timestamp.call
boot_events = []
record = lambda do |name, &block|
start = get_timestamp.call
block.call.tap do
boot_events << [name, start, get_timestamp.call]
end
end
record.call(:require_dependencies) do
%w[
diff/lcs
diff/lcs/hunk
digest/sha1
etc
irb
json
open3
optparse
parser
parser/current
pathname
regexp_parser
securerandom
set
singleton
sorbet-runtime
stringio
unparser
yaml
].each { |name| require(name) }
end
# This setting is done to make errors within the parallel
# reporter / execution visible in the main thread.
Thread.abort_on_exception = true
AbstractType = Unparser::AbstractType
Adamantium = Unparser::Adamantium
Anima = Unparser::Anima
Concord = Unparser::Concord
Either = Unparser::Either
Equalizer = Unparser::Equalizer
EMPTY_STRING = ''
EMPTY_ARRAY = [].freeze
EMPTY_HASH = {}.freeze
SCOPE_OPERATOR = '::'
env_key = /[a-zA-Z_\d]+/
ENV_VARIABLE_KEY_VALUE_REGEXP = /\A(?<key>#{env_key}+)=(?<value>.*)\z/
ENV_VARIABLE_KEY_REGEXP = /\A#{env_key}\z/
# rubocop:disable Metrics/BlockLength
record.call(:require_mutant_lib) do
require 'mutant/procto'
require 'mutant/transform'
require 'mutant/variable'
require 'mutant/bootstrap'
require 'mutant/version'
require 'mutant/env'
require 'mutant/util'
require 'mutant/registry'
require 'mutant/ast'
require 'mutant/ast/sexp'
require 'mutant/ast/types'
require 'mutant/ast/nodes'
require 'mutant/ast/named_children'
require 'mutant/ast/node_predicates'
require 'mutant/ast/find_metaclass_containing'
require 'mutant/ast/meta'
require 'mutant/ast/meta/send'
require 'mutant/ast/meta/const'
require 'mutant/ast/meta/symbol'
require 'mutant/ast/meta/optarg'
require 'mutant/ast/meta/resbody'
require 'mutant/ast/pattern'
require 'mutant/ast/pattern/lexer'
require 'mutant/ast/pattern/parser'
require 'mutant/ast/pattern/source'
require 'mutant/ast/pattern/token'
require 'mutant/ast/structure'
require 'mutant/parser'
require 'mutant/isolation'
require 'mutant/isolation/exception'
require 'mutant/isolation/fork'
require 'mutant/isolation/none'
require 'mutant/parallel'
require 'mutant/parallel/connection'
require 'mutant/parallel/pipe'
require 'mutant/parallel/driver'
require 'mutant/parallel/source'
require 'mutant/parallel/worker'
require 'mutant/require_highjack'
require 'mutant/mutation'
require 'mutant/mutation/operators'
require 'mutant/usage'
require 'mutant/mutation/config'
require 'mutant/mutator'
require 'mutant/mutator/util'
require 'mutant/mutator/util/array'
require 'mutant/mutator/util/symbol'
require 'mutant/mutator/node'
require 'mutant/mutator/node/generic'
require 'mutant/mutator/node/literal'
require 'mutant/mutator/node/literal/boolean'
require 'mutant/mutator/node/literal/range'
require 'mutant/mutator/node/literal/symbol'
require 'mutant/mutator/node/literal/string'
require 'mutant/mutator/node/literal/integer'
require 'mutant/mutator/node/literal/float'
require 'mutant/mutator/node/literal/array'
require 'mutant/mutator/node/literal/hash'
require 'mutant/mutator/node/literal/regex'
require 'mutant/mutator/node/literal/nil'
require 'mutant/mutator/node/argument'
require 'mutant/mutator/node/arguments'
require 'mutant/mutator/node/begin'
require 'mutant/mutator/node/binary'
require 'mutant/mutator/node/const'
require 'mutant/mutator/node/dynamic_literal'
require 'mutant/mutator/node/kwbegin'
require 'mutant/mutator/node/named_value/access'
require 'mutant/mutator/node/named_value/constant_assignment'
require 'mutant/mutator/node/named_value/variable_assignment'
require 'mutant/mutator/node/next'
require 'mutant/mutator/node/break'
require 'mutant/mutator/node/noop'
require 'mutant/mutator/node/or_asgn'
require 'mutant/mutator/node/and_asgn'
require 'mutant/mutator/node/defined'
require 'mutant/mutator/node/op_asgn'
require 'mutant/mutator/node/conditional_loop'
require 'mutant/mutator/node/yield'
require 'mutant/mutator/node/super'
require 'mutant/mutator/node/zsuper'
require 'mutant/mutator/node/send'
require 'mutant/mutator/node/send/binary'
require 'mutant/mutator/node/send/conditional'
require 'mutant/mutator/node/send/attribute_assignment'
require 'mutant/mutator/node/when'
require 'mutant/mutator/node/class'
require 'mutant/mutator/node/sclass'
require 'mutant/mutator/node/define'
require 'mutant/mutator/node/mlhs'
require 'mutant/mutator/node/nthref'
require 'mutant/mutator/node/masgn'
require 'mutant/mutator/node/module'
require 'mutant/mutator/node/return'
require 'mutant/mutator/node/block'
require 'mutant/mutator/node/block_pass'
require 'mutant/mutator/node/if'
require 'mutant/mutator/node/case'
require 'mutant/mutator/node/splat'
require 'mutant/mutator/node/regopt'
require 'mutant/mutator/node/resbody'
require 'mutant/mutator/node/rescue'
require 'mutant/mutator/node/match_current_line'
require 'mutant/mutator/node/index'
require 'mutant/mutator/node/procarg_zero'
require 'mutant/mutator/node/kwargs'
require 'mutant/mutator/node/numblock'
require 'mutant/mutator/node/const_pattern'
require 'mutant/mutator/regexp'
require 'mutant/loader'
require 'mutant/context'
require 'mutant/scope'
require 'mutant/subject'
require 'mutant/subject/config'
require 'mutant/subject/method'
require 'mutant/subject/method/instance'
require 'mutant/subject/method/singleton'
require 'mutant/subject/method/metaclass'
require 'mutant/matcher'
require 'mutant/matcher/chain'
require 'mutant/matcher/config'
require 'mutant/matcher/descendants'
require 'mutant/matcher/filter'
require 'mutant/matcher/method'
require 'mutant/matcher/method/instance'
require 'mutant/matcher/method/metaclass'
require 'mutant/matcher/method/singleton'
require 'mutant/matcher/methods'
require 'mutant/matcher/namespace'
require 'mutant/matcher/null'
require 'mutant/matcher/scope'
require 'mutant/matcher/static'
require 'mutant/expression'
require 'mutant/expression/descendants'
require 'mutant/expression/method'
require 'mutant/expression/methods'
require 'mutant/expression/namespace'
require 'mutant/expression/parser'
require 'mutant/expression/source'
require 'mutant/test'
require 'mutant/test/runner'
require 'mutant/test/runner/sink'
require 'mutant/timer'
require 'mutant/integration'
require 'mutant/integration/null'
require 'mutant/selector'
require 'mutant/selector/expression'
require 'mutant/selector/null'
require 'mutant/world'
require 'mutant/hooks'
require 'mutant/config'
require 'mutant/config/coverage_criteria'
require 'mutant/cli'
require 'mutant/cli/command'
require 'mutant/cli/command/environment'
require 'mutant/cli/command/environment/irb'
require 'mutant/cli/command/environment/run'
require 'mutant/cli/command/environment/show'
require 'mutant/cli/command/environment/subject'
require 'mutant/cli/command/environment/test'
require 'mutant/cli/command/util'
require 'mutant/cli/command/root'
require 'mutant/mutation/runner'
require 'mutant/mutation/runner/sink'
require 'mutant/result'
require 'mutant/reporter'
require 'mutant/reporter/null'
require 'mutant/reporter/sequence'
require 'mutant/reporter/cli'
require 'mutant/reporter/cli/printer'
require 'mutant/reporter/cli/printer/config'
require 'mutant/reporter/cli/printer/coverage_result'
require 'mutant/reporter/cli/printer/env'
require 'mutant/reporter/cli/printer/env_progress'
require 'mutant/reporter/cli/printer/env_result'
require 'mutant/reporter/cli/printer/isolation_result'
require 'mutant/reporter/cli/printer/mutation'
require 'mutant/reporter/cli/printer/mutation_result'
require 'mutant/reporter/cli/printer/status_progressive'
require 'mutant/reporter/cli/printer/subject_result'
require 'mutant/reporter/cli/printer/test'
require 'mutant/reporter/cli/format'
require 'mutant/repository'
require 'mutant/repository/diff'
require 'mutant/repository/diff/ranges'
require 'mutant/zombifier'
require 'mutant/range'
require 'mutant/segment'
require 'mutant/segment/recorder'
end
# rubocop:enable Metrics/BlockLength
gen_id = SecureRandom.method(:uuid)
# Transform boot events into segments
if instance_variable_defined?(:@executable_timestamp)
recording_start = @executable_timestamp
executable_segment =
Segment.new(
id: gen_id.call,
name: :executable,
parent_id: nil,
timestamp_end: nil,
timestamp_start: @executable_timestamp
)
remove_instance_variable(:@executable_timestamp)
else
recording_start = library_timestamp
end
library_segment = Segment.new(
id: gen_id.call,
name: :library,
parent_id: executable_segment&.id,
timestamp_end: nil,
timestamp_start: library_timestamp
)
boot_segments = boot_events.map do |name, timestamp_start, timestamp_end|
Segment.new(
id: gen_id.call,
name:,
parent_id: library_segment.id,
timestamp_end:,
timestamp_start:
)
end
timer = Timer.new(process: Process)
recorder = Segment::Recorder.new(
gen_id:,
root_id: (executable_segment || library_segment).id,
parent_id: library_segment.id,
recording_start:,
segments: [*executable_segment, library_segment, *boot_segments],
timer:
)
WORLD = World.new(
condition_variable: ConditionVariable,
environment_variables: ENV,
gem: Gem,
gem_method: method(:gem),
io: IO,
json: JSON,
kernel: Kernel,
load_path: $LOAD_PATH,
marshal: Marshal,
mutex: Mutex,
object_space: ObjectSpace,
open3: Open3,
pathname: Pathname,
process: Process,
random: Random,
recorder:,
stderr: $stderr,
stdout: $stdout,
tempfile: Tempfile,
thread: Thread,
time: Time,
timer:
)
# Reopen class to initialize constant to avoid dep circle
class Config
DEFAULT = new(
coverage_criteria: Config::CoverageCriteria::DEFAULT,
expression_parser: Expression::Parser.new(
types: [
Expression::Descendants,
Expression::Method,
Expression::Methods,
Expression::Namespace::Exact,
Expression::Namespace::Recursive,
Expression::Source
].freeze
),
environment_variables: EMPTY_HASH,
fail_fast: false,
hooks: EMPTY_ARRAY,
includes: EMPTY_ARRAY,
integration: Integration::Config::DEFAULT,
isolation: Mutant::Isolation::Fork.new(world: WORLD),
jobs: nil,
matcher: Matcher::Config::DEFAULT,
mutation: Mutation::Config::EMPTY,
reporter: Reporter::CLI.build(WORLD.stdout),
requires: EMPTY_ARRAY,
usage: Usage::Unknown.new
)
end # Config
# Traverse values against action
#
# Specialized to Either. Its *always* traverse.
def self.traverse(action, values)
Either::Right.new(
values.map do |value|
action.call(value).from_right do |error|
return Either::Left.new(error)
end
end
)
end
end # Mutant
# rubocop:enable Metrics/ModuleLength