mutant 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
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