mutant 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +7 -0
  3. data/config/flay.yml +1 -1
  4. data/config/reek.yml +1 -0
  5. data/lib/mutant.rb +10 -3
  6. data/lib/mutant/actor.rb +2 -5
  7. data/lib/mutant/actor/env.rb +1 -3
  8. data/lib/mutant/actor/mailbox.rb +2 -4
  9. data/lib/mutant/actor/receiver.rb +0 -2
  10. data/lib/mutant/actor/sender.rb +0 -1
  11. data/lib/mutant/ast.rb +22 -28
  12. data/lib/mutant/ast/meta.rb +8 -88
  13. data/lib/mutant/ast/named_children.rb +1 -8
  14. data/lib/mutant/ast/sexp.rb +0 -2
  15. data/lib/mutant/cache.rb +1 -3
  16. data/lib/mutant/cli.rb +9 -19
  17. data/lib/mutant/color.rb +0 -3
  18. data/lib/mutant/config.rb +6 -2
  19. data/lib/mutant/context.rb +2 -4
  20. data/lib/mutant/context/scope.rb +10 -16
  21. data/lib/mutant/delegator.rb +0 -3
  22. data/lib/mutant/diff.rb +8 -17
  23. data/lib/mutant/env.rb +3 -5
  24. data/lib/mutant/env/bootstrap.rb +32 -39
  25. data/lib/mutant/expression.rb +14 -132
  26. data/lib/mutant/expression/method.rb +25 -42
  27. data/lib/mutant/expression/methods.rb +17 -29
  28. data/lib/mutant/expression/namespace.rb +33 -28
  29. data/lib/mutant/expression/parser.rb +71 -0
  30. data/lib/mutant/integration.rb +17 -16
  31. data/lib/mutant/isolation.rb +14 -14
  32. data/lib/mutant/loader.rb +2 -4
  33. data/lib/mutant/matcher.rb +1 -11
  34. data/lib/mutant/matcher/chain.rb +0 -1
  35. data/lib/mutant/matcher/compiler.rb +19 -52
  36. data/lib/mutant/matcher/config.rb +65 -5
  37. data/lib/mutant/matcher/filter.rb +11 -1
  38. data/lib/mutant/matcher/method.rb +11 -21
  39. data/lib/mutant/matcher/method/instance.rb +2 -16
  40. data/lib/mutant/matcher/method/singleton.rb +3 -20
  41. data/lib/mutant/matcher/methods.rb +11 -21
  42. data/lib/mutant/matcher/namespace.rb +0 -4
  43. data/lib/mutant/matcher/null.rb +0 -1
  44. data/lib/mutant/matcher/scope.rb +0 -12
  45. data/lib/mutant/meta.rb +0 -1
  46. data/lib/mutant/meta/example.rb +12 -26
  47. data/lib/mutant/meta/example/dsl.rb +1 -8
  48. data/lib/mutant/mutation.rb +6 -14
  49. data/lib/mutant/mutator.rb +2 -14
  50. data/lib/mutant/mutator/node.rb +6 -33
  51. data/lib/mutant/mutator/node/and_asgn.rb +0 -1
  52. data/lib/mutant/mutator/node/argument.rb +0 -5
  53. data/lib/mutant/mutator/node/arguments.rb +1 -7
  54. data/lib/mutant/mutator/node/begin.rb +0 -2
  55. data/lib/mutant/mutator/node/binary.rb +0 -3
  56. data/lib/mutant/mutator/node/block.rb +0 -2
  57. data/lib/mutant/mutator/node/break.rb +0 -1
  58. data/lib/mutant/mutator/node/case.rb +0 -3
  59. data/lib/mutant/mutator/node/conditional_loop.rb +0 -1
  60. data/lib/mutant/mutator/node/const.rb +0 -1
  61. data/lib/mutant/mutator/node/define.rb +0 -1
  62. data/lib/mutant/mutator/node/defined.rb +0 -1
  63. data/lib/mutant/mutator/node/dstr.rb +0 -1
  64. data/lib/mutant/mutator/node/dsym.rb +0 -1
  65. data/lib/mutant/mutator/node/generic.rb +0 -1
  66. data/lib/mutant/mutator/node/if.rb +0 -4
  67. data/lib/mutant/mutator/node/kwbegin.rb +0 -1
  68. data/lib/mutant/mutator/node/literal/array.rb +0 -2
  69. data/lib/mutant/mutator/node/literal/boolean.rb +0 -1
  70. data/lib/mutant/mutator/node/literal/fixnum.rb +2 -5
  71. data/lib/mutant/mutator/node/literal/float.rb +1 -4
  72. data/lib/mutant/mutator/node/literal/hash.rb +0 -3
  73. data/lib/mutant/mutator/node/literal/nil.rb +0 -1
  74. data/lib/mutant/mutator/node/literal/range.rb +1 -5
  75. data/lib/mutant/mutator/node/literal/regex.rb +1 -3
  76. data/lib/mutant/mutator/node/literal/string.rb +0 -1
  77. data/lib/mutant/mutator/node/literal/symbol.rb +0 -1
  78. data/lib/mutant/mutator/node/masgn.rb +0 -1
  79. data/lib/mutant/mutator/node/match_current_line.rb +0 -1
  80. data/lib/mutant/mutator/node/mlhs.rb +0 -1
  81. data/lib/mutant/mutator/node/named_value/access.rb +0 -1
  82. data/lib/mutant/mutator/node/named_value/constant_assignment.rb +0 -2
  83. data/lib/mutant/mutator/node/named_value/variable_assignment.rb +0 -2
  84. data/lib/mutant/mutator/node/next.rb +0 -1
  85. data/lib/mutant/mutator/node/noop.rb +0 -1
  86. data/lib/mutant/mutator/node/nthref.rb +0 -1
  87. data/lib/mutant/mutator/node/op_asgn.rb +0 -1
  88. data/lib/mutant/mutator/node/or_asgn.rb +1 -2
  89. data/lib/mutant/mutator/node/resbody.rb +0 -2
  90. data/lib/mutant/mutator/node/rescue.rb +1 -6
  91. data/lib/mutant/mutator/node/return.rb +0 -1
  92. data/lib/mutant/mutator/node/send.rb +16 -17
  93. data/lib/mutant/mutator/node/send/attribute_assignment.rb +0 -3
  94. data/lib/mutant/mutator/node/send/binary.rb +0 -1
  95. data/lib/mutant/mutator/node/send/index.rb +0 -3
  96. data/lib/mutant/mutator/node/splat.rb +0 -1
  97. data/lib/mutant/mutator/node/super.rb +0 -1
  98. data/lib/mutant/mutator/node/when.rb +2 -7
  99. data/lib/mutant/mutator/node/yield.rb +0 -1
  100. data/lib/mutant/mutator/node/zsuper.rb +0 -1
  101. data/lib/mutant/mutator/registry.rb +1 -4
  102. data/lib/mutant/mutator/util.rb +0 -2
  103. data/lib/mutant/mutator/util/array.rb +0 -3
  104. data/lib/mutant/mutator/util/symbol.rb +0 -1
  105. data/lib/mutant/parallel.rb +3 -9
  106. data/lib/mutant/parallel/master.rb +7 -17
  107. data/lib/mutant/parallel/source.rb +2 -7
  108. data/lib/mutant/parallel/worker.rb +1 -5
  109. data/lib/mutant/reporter.rb +0 -4
  110. data/lib/mutant/reporter/cli.rb +1 -8
  111. data/lib/mutant/reporter/cli/format.rb +7 -18
  112. data/lib/mutant/reporter/cli/printer.rb +2 -12
  113. data/lib/mutant/reporter/cli/printer/config.rb +1 -4
  114. data/lib/mutant/reporter/cli/printer/env_progress.rb +3 -7
  115. data/lib/mutant/reporter/cli/printer/env_result.rb +0 -1
  116. data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +0 -2
  117. data/lib/mutant/reporter/cli/printer/mutation_result.rb +3 -11
  118. data/lib/mutant/reporter/cli/printer/status.rb +1 -4
  119. data/lib/mutant/reporter/cli/printer/status_progressive.rb +1 -3
  120. data/lib/mutant/reporter/cli/printer/subject_progress.rb +0 -5
  121. data/lib/mutant/reporter/cli/printer/subject_result.rb +0 -1
  122. data/lib/mutant/reporter/cli/printer/test_result.rb +0 -1
  123. data/lib/mutant/reporter/cli/tput.rb +4 -1
  124. data/lib/mutant/reporter/trace.rb +2 -4
  125. data/lib/mutant/repository.rb +88 -0
  126. data/lib/mutant/require_highjack.rb +0 -1
  127. data/lib/mutant/result.rb +25 -48
  128. data/lib/mutant/runner.rb +7 -16
  129. data/lib/mutant/runner/sink.rb +3 -11
  130. data/lib/mutant/selector.rb +1 -2
  131. data/lib/mutant/selector/expression.rb +1 -2
  132. data/lib/mutant/subject.rb +10 -21
  133. data/lib/mutant/subject/method.rb +11 -12
  134. data/lib/mutant/subject/method/instance.rb +1 -5
  135. data/lib/mutant/subject/method/singleton.rb +1 -3
  136. data/lib/mutant/test.rb +1 -2
  137. data/lib/mutant/version.rb +2 -2
  138. data/lib/mutant/warning_filter.rb +2 -7
  139. data/lib/mutant/zombifier.rb +6 -10
  140. data/meta/send.rb +8 -0
  141. data/spec/spec_helper.rb +5 -1
  142. data/spec/support/corpus.rb +5 -9
  143. data/spec/support/rb_bug.rb +0 -1
  144. data/spec/support/rspec.rb +0 -1
  145. data/spec/support/ruby_vm.rb +0 -2
  146. data/spec/unit/mutant/ast/meta/send_spec.rb +42 -0
  147. data/spec/unit/mutant/ast/named_children_spec.rb +51 -0
  148. data/spec/unit/mutant/ast/sexp_spec.rb +36 -0
  149. data/spec/unit/mutant/ast_spec.rb +8 -0
  150. data/spec/unit/mutant/cli_spec.rb +34 -19
  151. data/spec/unit/mutant/context/scope_spec.rb +11 -0
  152. data/spec/unit/mutant/env/boostrap_spec.rb +5 -2
  153. data/spec/unit/mutant/env_spec.rb +14 -15
  154. data/spec/unit/mutant/expression/method_spec.rb +10 -14
  155. data/spec/unit/mutant/expression/methods_spec.rb +24 -11
  156. data/spec/unit/mutant/expression/namespace/flat_spec.rb +5 -6
  157. data/spec/unit/mutant/expression/namespace/recursive_spec.rb +16 -10
  158. data/spec/unit/mutant/expression/parser_spec.rb +67 -0
  159. data/spec/unit/mutant/expression_spec.rb +24 -57
  160. data/spec/unit/mutant/integration/rspec_spec.rb +7 -7
  161. data/spec/unit/mutant/integration_spec.rb +2 -2
  162. data/spec/unit/mutant/isolation_spec.rb +31 -29
  163. data/spec/unit/mutant/matcher/compiler/subject_prefix_spec.rb +2 -2
  164. data/spec/unit/mutant/matcher/compiler_spec.rb +27 -58
  165. data/spec/unit/mutant/matcher/config_spec.rb +45 -0
  166. data/spec/unit/mutant/matcher/filter_spec.rb +12 -5
  167. data/spec/unit/mutant/matcher/method/instance_spec.rb +0 -1
  168. data/spec/unit/mutant/matcher/method/singleton_spec.rb +0 -1
  169. data/spec/unit/mutant/matcher/namespace_spec.rb +4 -4
  170. data/spec/unit/mutant/parallel/worker_spec.rb +1 -1
  171. data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +4 -4
  172. data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +7 -7
  173. data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +2 -2
  174. data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +2 -2
  175. data/spec/unit/mutant/reporter/cli/printer/status_spec.rb +12 -12
  176. data/spec/unit/mutant/reporter/cli/printer/subject_progress_spec.rb +1 -1
  177. data/spec/unit/mutant/reporter/cli_spec.rb +9 -10
  178. data/spec/unit/mutant/repository/diff_spec.rb +80 -0
  179. data/spec/unit/mutant/repository/subject_filter_spec.rb +28 -0
  180. data/spec/unit/mutant/result/env_spec.rb +1 -1
  181. data/spec/unit/mutant/runner_spec.rb +0 -1
  182. data/spec/unit/mutant/selector/expression_spec.rb +14 -14
  183. data/spec/unit/mutant/subject/method/instance_spec.rb +2 -2
  184. data/spec/unit/mutant/subject/method/singleton_spec.rb +2 -2
  185. data/spec/unit/mutant/subject_spec.rb +5 -2
  186. metadata +20 -3
  187. data/spec/support/mutation_verifier.rb +0 -96
@@ -3,36 +3,45 @@ module Mutant
3
3
 
4
4
  # Abstract base class for methods expression
5
5
  class Methods < self
6
+ include Anima.new(:scope_name, :scope_symbol)
7
+ private(*anima.attribute_names)
6
8
 
7
9
  MATCHERS = IceNine.deep_freeze(
8
10
  '.' => Matcher::Methods::Singleton,
9
11
  '#' => Matcher::Methods::Instance
10
12
  )
13
+ private_constant(*constants(false))
11
14
 
12
- register(
13
- /\A(?<scope_name>#{SCOPE_PATTERN})(?<scope_symbol>[.#])\z/
14
- )
15
+ REGEXP = /\A#{SCOPE_NAME_PATTERN}#{SCOPE_SYMBOL_PATTERN}\z/.freeze
16
+
17
+ # Syntax of expression
18
+ #
19
+ # @return [String]
20
+ #
21
+ # @api private
22
+ def syntax
23
+ [scope_name, scope_symbol].join
24
+ end
25
+ memoize :syntax
15
26
 
16
- # Return method matcher
27
+ # Matcher on expression
17
28
  #
18
29
  # @param [Env] env
19
30
  #
20
31
  # @return [Matcher::Method]
21
32
  #
22
33
  # @api private
23
- #
24
34
  def matcher(env)
25
35
  MATCHERS.fetch(scope_symbol).new(env, scope)
26
36
  end
27
37
 
28
- # Return length of match
38
+ # Length of match with other expression
29
39
  #
30
40
  # @param [Expression] expression
31
41
  #
32
42
  # @return [Fixnum]
33
43
  #
34
44
  # @api private
35
- #
36
45
  def match_length(expression)
37
46
  if expression.syntax.start_with?(syntax)
38
47
  syntax.length
@@ -43,36 +52,15 @@ module Mutant
43
52
 
44
53
  private
45
54
 
46
- # Return scope name
47
- #
48
- # @return [String]
49
- #
50
- # @api private
51
- #
52
- def scope_name
53
- match[__method__]
54
- end
55
-
56
- # Return scope
55
+ # Scope object
57
56
  #
58
57
  # @return [Class, Method]
59
58
  #
60
59
  # @api private
61
- #
62
60
  def scope
63
61
  Object.const_get(scope_name)
64
62
  end
65
63
 
66
- # Return scope symbol
67
- #
68
- # @return [Symbol]
69
- #
70
- # @api private
71
- #
72
- def scope_symbol
73
- match[__method__]
74
- end
75
-
76
64
  end # Method
77
65
  end # Expression
78
66
  end # Mutant
@@ -2,24 +2,12 @@ module Mutant
2
2
  class Expression
3
3
  # Abstract base class for expressions matching namespaces
4
4
  class Namespace < self
5
- include AbstractType
6
-
7
- private
8
-
9
- # Return matched namespace
10
- #
11
- # @return [String]
12
- #
13
- # @api private
14
- #
15
- def namespace
16
- match[__method__]
17
- end
5
+ include AbstractType, Anima.new(:scope_name)
6
+ private(*anima.attribute_names)
18
7
 
19
8
  # Recursive namespace expression
20
9
  class Recursive < self
21
-
22
- register(/\A(?<namespace>#{SCOPE_PATTERN})?\*\z/)
10
+ REGEXP = /\A#{SCOPE_NAME_PATTERN}?\*\z/.freeze
23
11
 
24
12
  # Initialize object
25
13
  #
@@ -29,35 +17,43 @@ module Mutant
29
17
  def initialize(*)
30
18
  super
31
19
  @recursion_pattern = Regexp.union(
32
- /\A#{namespace}\z/,
33
- /\A#{namespace}::/,
34
- /\A#{namespace}[.#]/
20
+ /\A#{scope_name}\z/,
21
+ /\A#{scope_name}::/,
22
+ /\A#{scope_name}[.#]/
35
23
  )
36
24
  end
37
25
 
38
- # Return matcher
26
+ # Syntax for expression
27
+ #
28
+ # @return [String]
29
+ #
30
+ # @api private
31
+ def syntax
32
+ "#{scope_name}*"
33
+ end
34
+ memoize :syntax
35
+
36
+ # Matcher for expression
39
37
  #
40
38
  # @param [Env::Bootstrap] env
41
39
  #
42
40
  # @return [Matcher]
43
41
  #
44
42
  # @api private
45
- #
46
43
  def matcher(env)
47
44
  Matcher::Namespace.new(env, self)
48
45
  end
49
46
 
50
- # Return length of match
47
+ # Length of match with other expression
51
48
  #
52
49
  # @param [Expression] expression
53
50
  #
54
51
  # @return [Fixnum]
55
52
  #
56
53
  # @api private
57
- #
58
54
  def match_length(expression)
59
55
  if @recursion_pattern =~ expression.syntax
60
- namespace.length
56
+ scope_name.length
61
57
  else
62
58
  0
63
59
  end
@@ -68,22 +64,31 @@ module Mutant
68
64
  # Exact namespace expression
69
65
  class Exact < self
70
66
 
71
- register(/\A(?<namespace>#{SCOPE_PATTERN})\z/)
72
-
73
67
  MATCHER = Matcher::Scope
68
+ private_constant(*constants(false))
69
+
70
+ REGEXP = /\A#{SCOPE_NAME_PATTERN}\z/.freeze
74
71
 
75
- # Return matcher
72
+ # Matcher matcher on expression
76
73
  #
77
74
  # @param [Env::Bootstrap] env
78
75
  #
79
76
  # @return [Matcher]
80
77
  #
81
78
  # @api private
82
- #
83
79
  def matcher(env)
84
- Matcher::Scope.new(env, Object.const_get(namespace), self)
80
+ Matcher::Scope.new(env, Object.const_get(scope_name), self)
85
81
  end
86
82
 
83
+ # Syntax for expression
84
+ #
85
+ # @return [String]
86
+ #
87
+ # @api private
88
+ #
89
+ alias_method :syntax, :scope_name
90
+ public :syntax
91
+
87
92
  end # Exact
88
93
  end # Namespace
89
94
  end # Namespace
@@ -0,0 +1,71 @@
1
+ module Mutant
2
+ class Expression
3
+ class Parser
4
+ include Concord.new(:types)
5
+
6
+ class ParserError < RuntimeError
7
+ include AbstractType
8
+ end
9
+
10
+ # Error raised on invalid expressions
11
+ class InvalidExpressionError < ParserError; end
12
+
13
+ # Error raised on ambiguous expressions
14
+ class AmbiguousExpressionError < ParserError; end
15
+
16
+ # Parse input into expression or raise
17
+ #
18
+ # @param [String] syntax
19
+ #
20
+ # @return [Expression]
21
+ # if expression is valid
22
+ #
23
+ # @raise [ParserError]
24
+ # otherwise
25
+ #
26
+ # @api private
27
+ def call(input)
28
+ try_parse(input) or fail InvalidExpressionError, "Expression: #{input.inspect} is not valid"
29
+ end
30
+
31
+ # Try to parse input into expression
32
+ #
33
+ # @param [String] input
34
+ #
35
+ # @return [Expression]
36
+ # if expression is valid
37
+ #
38
+ # @return [nil]
39
+ # otherwise
40
+ #
41
+ # @api private
42
+ def try_parse(input)
43
+ expressions = expressions(input)
44
+ case expressions.length
45
+ when 0, 1
46
+ expressions.first
47
+ else
48
+ fail AmbiguousExpressionError, "Ambiguous expression: #{input.inspect}"
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ # Expressions parsed from input
55
+ #
56
+ # @param [String] input
57
+ #
58
+ # @return [Array<Expression>]
59
+ # if expressions can be parsed from input
60
+ #
61
+ # @api private
62
+ def expressions(input)
63
+ types.each_with_object([]) do |type, aggregate|
64
+ expression = type.try_parse(input)
65
+ aggregate << expression if expression
66
+ end
67
+ end
68
+
69
+ end # Parser
70
+ end # Expression
71
+ end # Mutant
@@ -2,7 +2,7 @@ module Mutant
2
2
 
3
3
  # Abstract base class mutant test framework integrations
4
4
  class Integration
5
- include AbstractType, Adamantium::Flat, Equalizer.new
5
+ include AbstractType, Adamantium::Flat, Concord.new(:config)
6
6
 
7
7
  REGISTRY = {}
8
8
 
@@ -13,7 +13,6 @@ module Mutant
13
13
  # @return [Integration]
14
14
  #
15
15
  # @api private
16
- #
17
16
  def self.setup(name)
18
17
  require "mutant/integration/#{name}"
19
18
  lookup(name)
@@ -27,9 +26,8 @@ module Mutant
27
26
  # if found
28
27
  #
29
28
  # @api private
30
- #
31
29
  def self.lookup(name)
32
- REGISTRY.fetch(name).new
30
+ REGISTRY.fetch(name)
33
31
  end
34
32
 
35
33
  # Register integration
@@ -39,11 +37,8 @@ module Mutant
39
37
  # @return [undefined]
40
38
  #
41
39
  # @api private
42
- #
43
40
  def self.register(name)
44
41
  REGISTRY[name] = self
45
-
46
- define_method(:name) { name }
47
42
  end
48
43
  private_class_method :register
49
44
 
@@ -52,52 +47,58 @@ module Mutant
52
47
  # @return [self]
53
48
  #
54
49
  # @api private
55
- #
56
50
  def setup
57
51
  self
58
52
  end
59
53
 
60
- # Return test result for tests
54
+ # Run a collection of tests
61
55
  #
62
56
  # @param [Enumerable<Test>] tests
63
57
  #
64
58
  # @return [Result::Test]
65
59
  #
66
60
  # @api private
67
- #
68
61
  abstract_method :call
69
62
 
70
- # Return all available tests by integration
63
+ # Available tests for integration
71
64
  #
72
65
  # @return [Enumerable<Test>]
73
66
  #
74
67
  # @api private
75
- #
76
68
  abstract_method :all_tests
77
69
 
70
+ private
71
+
72
+ # Expression parser
73
+ #
74
+ # @return [Expression::Parser]
75
+ #
76
+ # @api private
77
+ def expression_parser
78
+ config.expression_parser
79
+ end
80
+
78
81
  # Null integration that never kills a mutation
79
82
  class Null < self
80
83
 
81
84
  register('null')
82
85
 
83
- # Return all tests
86
+ # Available tests for integration
84
87
  #
85
88
  # @return [Enumerable<Test>]
86
89
  #
87
90
  # @api private
88
- #
89
91
  def all_tests
90
92
  EMPTY_ARRAY
91
93
  end
92
94
 
93
- # Return report for test
95
+ # Run a collection of tests
94
96
  #
95
97
  # @param [Enumerable<Mutant::Test>] tests
96
98
  #
97
99
  # @return [Result::Test]
98
100
  #
99
101
  # @api private
100
- #
101
102
  def call(tests)
102
103
  Result::Test.new(
103
104
  tests: tests,
@@ -13,7 +13,6 @@ module Mutant
13
13
  # if block terminates abnormal
14
14
  #
15
15
  # @api private
16
- #
17
16
  def self.call(&block)
18
17
  block.call
19
18
  rescue => exception
@@ -35,28 +34,29 @@ module Mutant
35
34
  # @raise [Error]
36
35
  # if block terminates abnormal
37
36
  #
38
- # @api private
39
- #
40
37
  # rubocop:disable MethodLength
41
38
  #
39
+ # @api private
42
40
  def self.call(&block)
43
- reader, writer = IO.pipe.map(&:binmode)
41
+ IO.pipe(binmode: true) do |reader, writer|
42
+ begin
43
+ pid = Process.fork do
44
+ File.open(File::NULL, 'w') do |file|
45
+ $stderr.reopen(file)
46
+ reader.close
47
+ writer.write(Marshal.dump(block.call))
48
+ writer.close
49
+ end
50
+ end
44
51
 
45
- pid = Process.fork do
46
- File.open('/dev/null', 'w') do |file|
47
- $stderr.reopen(file)
48
- reader.close
49
- writer.write(Marshal.dump(block.call))
50
52
  writer.close
53
+ Marshal.load(reader.read)
54
+ ensure
55
+ Process.waitpid(pid) if pid
51
56
  end
52
57
  end
53
-
54
- writer.close
55
- Marshal.load(reader.read)
56
58
  rescue => exception
57
59
  raise Error, exception
58
- ensure
59
- Process.waitpid(pid) if pid
60
60
  end
61
61
 
62
62
  end # Fork
@@ -10,12 +10,11 @@ module Mutant
10
10
  #
11
11
  # @return [undefined]
12
12
  #
13
- # @api private
14
- #
15
13
  # One off the very few valid uses of eval
16
14
  #
17
15
  # rubocop:disable Lint/Eval
18
16
  #
17
+ # @api private
19
18
  def call
20
19
  eval(
21
20
  source,
@@ -28,12 +27,11 @@ module Mutant
28
27
 
29
28
  private
30
29
 
31
- # Return source
30
+ # Source generated from AST
32
31
  #
33
32
  # @return [String]
34
33
  #
35
34
  # @api private
36
- #
37
35
  def source
38
36
  Unparser.unparse(root)
39
37
  end