mutant 0.9.6 → 0.9.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +121 -0
  3. data/.rubocop.yml +203 -0
  4. data/Changelog.md +26 -0
  5. data/Gemfile +0 -7
  6. data/Gemfile.lock +27 -87
  7. data/Gemfile.shared +7 -0
  8. data/README.md +88 -27
  9. data/config/reek.yml +1 -0
  10. data/lib/mutant.rb +4 -2
  11. data/lib/mutant/ast.rb +0 -9
  12. data/lib/mutant/ast/find_metaclass_containing.rb +48 -0
  13. data/lib/mutant/ast/meta/send.rb +0 -6
  14. data/lib/mutant/bootstrap.rb +0 -36
  15. data/lib/mutant/cli.rb +5 -49
  16. data/lib/mutant/config.rb +0 -8
  17. data/lib/mutant/context.rb +0 -3
  18. data/lib/mutant/env.rb +0 -6
  19. data/lib/mutant/expression/method.rb +6 -6
  20. data/lib/mutant/expression/methods.rb +6 -6
  21. data/lib/mutant/expression/parser.rb +0 -6
  22. data/lib/mutant/integration.rb +0 -18
  23. data/lib/mutant/isolation/fork.rb +0 -22
  24. data/lib/mutant/license.rb +11 -0
  25. data/lib/mutant/matcher.rb +0 -14
  26. data/lib/mutant/matcher/config.rb +0 -11
  27. data/lib/mutant/matcher/method.rb +0 -31
  28. data/lib/mutant/matcher/method/instance.rb +0 -8
  29. data/lib/mutant/matcher/method/metaclass.rb +86 -0
  30. data/lib/mutant/matcher/method/singleton.rb +0 -25
  31. data/lib/mutant/matcher/methods.rb +17 -28
  32. data/lib/mutant/matcher/namespace.rb +0 -10
  33. data/lib/mutant/matcher/scope.rb +2 -4
  34. data/lib/mutant/meta/example/dsl.rb +0 -21
  35. data/lib/mutant/meta/example/verification.rb +0 -20
  36. data/lib/mutant/mutation.rb +0 -3
  37. data/lib/mutant/mutator.rb +1 -29
  38. data/lib/mutant/mutator/node.rb +1 -66
  39. data/lib/mutant/mutator/node/and_asgn.rb +0 -3
  40. data/lib/mutant/mutator/node/argument.rb +0 -15
  41. data/lib/mutant/mutator/node/arguments.rb +0 -20
  42. data/lib/mutant/mutator/node/begin.rb +0 -3
  43. data/lib/mutant/mutator/node/binary.rb +0 -23
  44. data/lib/mutant/mutator/node/block.rb +0 -15
  45. data/lib/mutant/mutator/node/break.rb +0 -3
  46. data/lib/mutant/mutator/node/case.rb +0 -9
  47. data/lib/mutant/mutator/node/class.rb +0 -3
  48. data/lib/mutant/mutator/node/conditional_loop.rb +0 -3
  49. data/lib/mutant/mutator/node/const.rb +0 -3
  50. data/lib/mutant/mutator/node/define.rb +0 -11
  51. data/lib/mutant/mutator/node/defined.rb +0 -3
  52. data/lib/mutant/mutator/node/dstr.rb +0 -3
  53. data/lib/mutant/mutator/node/dsym.rb +0 -3
  54. data/lib/mutant/mutator/node/generic.rb +0 -67
  55. data/lib/mutant/mutator/node/if.rb +0 -12
  56. data/lib/mutant/mutator/node/index.rb +0 -27
  57. data/lib/mutant/mutator/node/kwbegin.rb +0 -3
  58. data/lib/mutant/mutator/node/literal.rb +0 -3
  59. data/lib/mutant/mutator/node/literal/array.rb +0 -6
  60. data/lib/mutant/mutator/node/literal/boolean.rb +0 -4
  61. data/lib/mutant/mutator/node/literal/float.rb +0 -9
  62. data/lib/mutant/mutator/node/literal/hash.rb +0 -9
  63. data/lib/mutant/mutator/node/literal/integer.rb +0 -9
  64. data/lib/mutant/mutator/node/literal/nil.rb +0 -3
  65. data/lib/mutant/mutator/node/literal/range.rb +4 -7
  66. data/lib/mutant/mutator/node/literal/regex.rb +0 -6
  67. data/lib/mutant/mutator/node/literal/string.rb +0 -3
  68. data/lib/mutant/mutator/node/literal/symbol.rb +0 -3
  69. data/lib/mutant/mutator/node/masgn.rb +0 -3
  70. data/lib/mutant/mutator/node/match_current_line.rb +0 -3
  71. data/lib/mutant/mutator/node/mlhs.rb +0 -3
  72. data/lib/mutant/mutator/node/named_value/access.rb +2 -14
  73. data/lib/mutant/mutator/node/named_value/constant_assignment.rb +0 -9
  74. data/lib/mutant/mutator/node/named_value/variable_assignment.rb +0 -6
  75. data/lib/mutant/mutator/node/next.rb +0 -3
  76. data/lib/mutant/mutator/node/noop.rb +0 -3
  77. data/lib/mutant/mutator/node/nthref.rb +0 -3
  78. data/lib/mutant/mutator/node/op_asgn.rb +0 -3
  79. data/lib/mutant/mutator/node/or_asgn.rb +0 -3
  80. data/lib/mutant/mutator/node/procarg_zero.rb +0 -3
  81. data/lib/mutant/mutator/node/regopt.rb +0 -6
  82. data/lib/mutant/mutator/node/resbody.rb +0 -6
  83. data/lib/mutant/mutator/node/rescue.rb +2 -19
  84. data/lib/mutant/mutator/node/return.rb +0 -3
  85. data/lib/mutant/mutator/node/sclass.rb +20 -0
  86. data/lib/mutant/mutator/node/send.rb +2 -61
  87. data/lib/mutant/mutator/node/send/attribute_assignment.rb +0 -9
  88. data/lib/mutant/mutator/node/send/binary.rb +0 -11
  89. data/lib/mutant/mutator/node/send/conditional.rb +0 -3
  90. data/lib/mutant/mutator/node/splat.rb +0 -3
  91. data/lib/mutant/mutator/node/super.rb +0 -3
  92. data/lib/mutant/mutator/node/when.rb +0 -19
  93. data/lib/mutant/mutator/node/yield.rb +0 -3
  94. data/lib/mutant/mutator/node/zsuper.rb +0 -3
  95. data/lib/mutant/mutator/util/array.rb +0 -6
  96. data/lib/mutant/mutator/util/symbol.rb +0 -3
  97. data/lib/mutant/parallel.rb +0 -13
  98. data/lib/mutant/parallel/driver.rb +0 -10
  99. data/lib/mutant/parallel/worker.rb +0 -22
  100. data/lib/mutant/registry.rb +2 -7
  101. data/lib/mutant/reporter/cli.rb +0 -5
  102. data/lib/mutant/reporter/cli/format.rb +0 -9
  103. data/lib/mutant/reporter/cli/printer.rb +2 -42
  104. data/lib/mutant/reporter/cli/printer/env_progress.rb +0 -15
  105. data/lib/mutant/reporter/cli/printer/isolation_result.rb +0 -18
  106. data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +0 -5
  107. data/lib/mutant/reporter/cli/printer/mutation_result.rb +1 -22
  108. data/lib/mutant/reporter/cli/printer/status_progressive.rb +0 -8
  109. data/lib/mutant/reporter/cli/printer/subject_progress.rb +0 -9
  110. data/lib/mutant/repository/diff.rb +1 -13
  111. data/lib/mutant/repository/diff/ranges.rb +0 -11
  112. data/lib/mutant/result.rb +0 -3
  113. data/lib/mutant/runner.rb +0 -18
  114. data/lib/mutant/runner/sink.rb +0 -5
  115. data/lib/mutant/subject.rb +0 -8
  116. data/lib/mutant/subject/method.rb +0 -3
  117. data/lib/mutant/subject/method/instance.rb +40 -6
  118. data/lib/mutant/subject/method/metaclass.rb +30 -0
  119. data/lib/mutant/transform.rb +0 -92
  120. data/lib/mutant/version.rb +1 -1
  121. data/lib/mutant/warnings.rb +0 -6
  122. data/lib/mutant/zombifier.rb +2 -34
  123. data/meta/and.rb +0 -2
  124. data/meta/array.rb +0 -3
  125. data/meta/begin.rb +0 -3
  126. data/meta/block.rb +0 -3
  127. data/meta/break.rb +0 -1
  128. data/meta/case.rb +0 -6
  129. data/meta/casgn.rb +0 -3
  130. data/meta/cvasgn.rb +0 -1
  131. data/meta/def.rb +0 -7
  132. data/meta/ensure.rb +0 -1
  133. data/meta/false.rb +0 -1
  134. data/meta/gvasgn.rb +0 -1
  135. data/meta/hash.rb +0 -4
  136. data/meta/if.rb +0 -5
  137. data/meta/ivasgn.rb +0 -1
  138. data/meta/kwbegin.rb +0 -1
  139. data/meta/lvasgn.rb +0 -1
  140. data/meta/match_current_line.rb +0 -1
  141. data/meta/next.rb +0 -1
  142. data/meta/or.rb +0 -2
  143. data/meta/range.rb +24 -0
  144. data/meta/regexp.rb +0 -1
  145. data/meta/rescue.rb +0 -6
  146. data/meta/sclass.rb +12 -0
  147. data/meta/send.rb +0 -4
  148. data/meta/true.rb +0 -1
  149. data/meta/until.rb +0 -1
  150. data/meta/while.rb +0 -2
  151. data/meta/yield.rb +0 -1
  152. data/mutant.gemspec +7 -4
  153. data/mutant.sh +12 -0
  154. data/spec/spec_helper.rb +37 -22
  155. data/spec/unit/mutant/ast/find_metaclass_containing_spec.rb +64 -0
  156. data/spec/unit/mutant/expression/methods_spec.rb +7 -2
  157. data/spec/unit/mutant/license_spec.rb +15 -3
  158. data/spec/unit/mutant/matcher/method/metaclass_spec.rb +108 -0
  159. data/spec/unit/mutant/matcher/methods/metaclass_spec.rb +62 -0
  160. data/spec/unit/mutant/matcher/namespace_spec.rb +3 -1
  161. data/spec/unit/mutant/matcher/scope_spec.rb +11 -1
  162. data/spec/unit/mutant/meta/example_spec.rb +3 -3
  163. data/spec/unit/mutant/mutator/node_spec.rb +1 -6
  164. data/spec/unit/mutant/registry_spec.rb +52 -25
  165. data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +1 -1
  166. data/spec/unit/mutant/reporter/cli/printer/mutation_progress_result_spec.rb +2 -2
  167. data/spec/unit/mutant/reporter/cli/printer/mutation_result_spec.rb +12 -12
  168. data/spec/unit/mutant/reporter/cli/printer/subject_result_spec.rb +1 -1
  169. data/spec/unit/mutant/reporter/cli/printer_spec.rb +4 -4
  170. data/spec/unit/mutant/reporter/cli_spec.rb +1 -1
  171. data/spec/unit/mutant/subject/method/instance_spec.rb +117 -22
  172. data/spec/unit/mutant/subject/method/metaclass_spec.rb +63 -0
  173. data/test_app/Gemfile.minitest +2 -0
  174. data/test_app/lib/test_app.rb +5 -0
  175. data/test_app/lib/test_app/metaclasses.rb +108 -0
  176. metadata +74 -25
  177. data/.circleci/config.yml +0 -53
  178. data/config/rubocop.yml +0 -205
  179. data/lib/mutant/color.rb +0 -43
  180. data/lib/mutant/diff.rb +0 -114
  181. data/spec/shared/base_behavior.rb +0 -45
  182. data/spec/support/test_app.rb +0 -7
  183. data/spec/support/warnings.yml +0 -6
  184. data/spec/unit/mutant/diff_spec.rb +0 -189
@@ -25,20 +25,10 @@ module Mutant
25
25
 
26
26
  private
27
27
 
28
- # Test for node match
29
- #
30
- # @param [Parser::AST::Node] node
31
- #
32
- # @return [Boolean]
33
28
  def match?(node)
34
29
  n_defs?(node) && line?(node) && name?(node) && receiver?(node)
35
30
  end
36
31
 
37
- # Test for line match
38
- #
39
- # @param [Parser::AST::Node] node
40
- #
41
- # @return [Boolean]
42
32
  def line?(node)
43
33
  node
44
34
  .location
@@ -46,20 +36,10 @@ module Mutant
46
36
  .equal?(source_line)
47
37
  end
48
38
 
49
- # Test for name match
50
- #
51
- # @param [Parser::AST::Node] node
52
- #
53
- # @return [Boolean]
54
39
  def name?(node)
55
40
  node.children.fetch(NAME_INDEX).equal?(method_name)
56
41
  end
57
42
 
58
- # Test for receiver match
59
- #
60
- # @param [Parser::AST::Node] node
61
- #
62
- # @return [Boolean]
63
43
  def receiver?(node)
64
44
  receiver = node.children.fetch(RECEIVER_INDEX)
65
45
  case receiver.type
@@ -73,11 +53,6 @@ module Mutant
73
53
  end
74
54
  end
75
55
 
76
- # Test if receiver name matches context
77
- #
78
- # @param [Parser::AST::Node] node
79
- #
80
- # @return [Boolean]
81
56
  def receiver_name?(node)
82
57
  name = node.children.fetch(NAME_INDEX)
83
58
  name.to_s.eql?(context.unqualified_name)
@@ -27,16 +27,10 @@ module Mutant
27
27
 
28
28
  private
29
29
 
30
- # method matcher class
31
- #
32
- # @return [Class:Matcher::Method]
33
30
  def matcher
34
31
  self.class::MATCHER
35
32
  end
36
33
 
37
- # Available methods scope
38
- #
39
- # @return [Enumerable<Method, UnboundMethod>]
40
34
  def methods
41
35
  candidate_names.each_with_object([]) do |name, methods|
42
36
  method = access(name)
@@ -45,9 +39,6 @@ module Mutant
45
39
  end
46
40
  memoize :methods
47
41
 
48
- # Candidate method names on target scope
49
- #
50
- # @return [Enumerable<Symbol>]
51
42
  def candidate_names
52
43
  CANDIDATE_NAMES
53
44
  .map(&candidate_scope.method(:public_send))
@@ -55,10 +46,8 @@ module Mutant
55
46
  .sort
56
47
  end
57
48
 
58
- # Candidate scope
59
- #
60
- # @return [Class, Module]
61
49
  abstract_method :candidate_scope
50
+ private :candidate_scope
62
51
 
63
52
  # Matcher for singleton methods
64
53
  class Singleton < self
@@ -66,18 +55,10 @@ module Mutant
66
55
 
67
56
  private
68
57
 
69
- # Method object on scope
70
- #
71
- # @param [Symbol] method_name
72
- #
73
- # @return [Method]
74
58
  def access(method_name)
75
59
  scope.method(method_name)
76
60
  end
77
61
 
78
- # Candidate scope
79
- #
80
- # @return [Class]
81
62
  def candidate_scope
82
63
  scope.singleton_class
83
64
  end
@@ -85,24 +66,32 @@ module Mutant
85
66
 
86
67
  end # Singleton
87
68
 
69
+ # Matcher for metaclass methods
70
+ class Metaclass < self
71
+ MATCHER = Matcher::Method::Metaclass
72
+
73
+ private
74
+
75
+ def access(method_name)
76
+ scope.method(method_name)
77
+ end
78
+
79
+ def candidate_scope
80
+ scope.singleton_class
81
+ end
82
+ memoize :candidate_scope, freezer: :noop
83
+ end # Metaclass
84
+
88
85
  # Matcher for instance methods
89
86
  class Instance < self
90
87
  MATCHER = Matcher::Method::Instance
91
88
 
92
89
  private
93
90
 
94
- # Method object on scope
95
- #
96
- # @param [Symbol] method_name
97
- #
98
- # @return [UnboundMethod]
99
91
  def access(method_name)
100
92
  scope.instance_method(method_name)
101
93
  end
102
94
 
103
- # Candidate scope
104
- #
105
- # @return [Class, Module]
106
95
  def candidate_scope
107
96
  scope
108
97
  end
@@ -19,22 +19,12 @@ module Mutant
19
19
 
20
20
  private
21
21
 
22
- # The matched scopes
23
- #
24
- # @param [Env] env
25
- #
26
- # @return [Enumerable<Scope>]
27
22
  def matched_scopes(env)
28
23
  env
29
24
  .matchable_scopes
30
25
  .select(&method(:match?))
31
26
  end
32
27
 
33
- # Test scope if matches expression
34
- #
35
- # @param [Scope] scope
36
- #
37
- # @return [Boolean]
38
28
  def match?(scope)
39
29
  expression.prefix?(scope.expression)
40
30
  end
@@ -13,7 +13,8 @@ module Mutant
13
13
 
14
14
  MATCHERS = [
15
15
  Matcher::Methods::Singleton,
16
- Matcher::Methods::Instance
16
+ Matcher::Methods::Instance,
17
+ Matcher::Methods::Metaclass
17
18
  ].freeze
18
19
 
19
20
  private_constant(*constants(false))
@@ -29,9 +30,6 @@ module Mutant
29
30
 
30
31
  private
31
32
 
32
- # Effective matchers
33
- #
34
- # @return [Enumerable<Matcher>]
35
33
  def effective_matchers
36
34
  MATCHERS.map { |matcher| matcher.new(scope) }
37
35
  end
@@ -49,21 +49,11 @@ module Mutant
49
49
 
50
50
  private
51
51
 
52
- # Set original source
53
- #
54
- # @param [String,Parser::AST::Node] input
55
- #
56
- # @return [undefined]
57
52
  def source(input)
58
53
  fail 'source already defined' if @node
59
54
  @node = node(input)
60
55
  end
61
56
 
62
- # Add expected mutation
63
- #
64
- # @param [String,Parser::AST::Node] input
65
- #
66
- # @return [undefined]
67
57
  def mutation(input)
68
58
  node = node(input)
69
59
  if @expected.include?(node)
@@ -72,22 +62,11 @@ module Mutant
72
62
  @expected << node
73
63
  end
74
64
 
75
- # Add singleton mutations
76
- #
77
- # @return [undefined]
78
65
  def singleton_mutations
79
66
  mutation('nil')
80
67
  mutation('self')
81
68
  end
82
69
 
83
- # Helper method to coerce input to node
84
- #
85
- # @param [String,Parser::AST::Node] input
86
- #
87
- # @return [Parser::AST::Node]
88
- #
89
- # @raise [RuntimeError]
90
- # in case input cannot be coerced
91
70
  def node(input)
92
71
  case input
93
72
  when String
@@ -35,9 +35,6 @@ module Mutant
35
35
 
36
36
  private
37
37
 
38
- # Unexpected mutations
39
- #
40
- # @return [Array<Mutation>]
41
38
  def unexpected
42
39
  mutations.reject do |mutation|
43
40
  example.expected.include?(mutation.node)
@@ -45,9 +42,6 @@ module Mutant
45
42
  end
46
43
  memoize :unexpected
47
44
 
48
- # Missing mutations
49
- #
50
- # @return [Array<Mutation>]
51
45
  def missing
52
46
  (example.expected - mutations.map(&:node)).map do |node|
53
47
  Mutation::Evil.new(self, node)
@@ -55,9 +49,6 @@ module Mutant
55
49
  end
56
50
  memoize :missing
57
51
 
58
- # Mutations that generated invalid syntax
59
- #
60
- # @return [Enumerable<Mutation>]
61
52
  def invalid_syntax
62
53
  mutations.reject do |mutation|
63
54
  ::Parser::CurrentRuby.parse(mutation.source)
@@ -66,19 +57,11 @@ module Mutant
66
57
  end
67
58
  memoize :invalid_syntax
68
59
 
69
- # Mutations with no diff to original
70
- #
71
- # @return [Enumerable<Mutation>]
72
60
  def no_diffs
73
61
  mutations.select { |mutation| mutation.source.eql?(example.source) }
74
62
  end
75
63
  memoize :no_diffs
76
64
 
77
- # Mutation report
78
- #
79
- # @param [Array<Mutation>] mutations
80
- #
81
- # @return [Array<Hash>]
82
65
  def format_mutations(mutations)
83
66
  mutations.map do |mutation|
84
67
  {
@@ -88,9 +71,6 @@ module Mutant
88
71
  end
89
72
  end
90
73
 
91
- # No diff mutation report
92
- #
93
- # @return [Array, nil]
94
74
  def no_diff_report
95
75
  no_diffs.map do |mutation|
96
76
  {
@@ -74,9 +74,6 @@ module Mutant
74
74
 
75
75
  private
76
76
 
77
- # SHA1 sum of source and subject identification
78
- #
79
- # @return [String]
80
77
  def sha1
81
78
  Digest::SHA1.hexdigest(subject.identification + CODE_DELIMITER + source)
82
79
  end
@@ -18,9 +18,6 @@ module Mutant
18
18
  self::REGISTRY.lookup(node.type).call(node, parent)
19
19
  end
20
20
 
21
- # Register node class handler
22
- #
23
- # @return [undefined]
24
21
  def self.handle(*types)
25
22
  types.each do |type|
26
23
  self::REGISTRY.register(type, self)
@@ -35,13 +32,6 @@ module Mutant
35
32
 
36
33
  private
37
34
 
38
- # Initialize object
39
- #
40
- # @param [Object] input
41
- # @param [Object] parent
42
- # @param [#call(node)] block
43
- #
44
- # @return [undefined]
45
35
  def initialize(_input, _parent = nil)
46
36
  super
47
37
 
@@ -50,41 +40,23 @@ module Mutant
50
40
  dispatch
51
41
  end
52
42
 
53
- # Test if generated object is not guarded from emitting
54
- #
55
- # @param [Object] object
56
- #
57
- # @return [Boolean]
58
43
  def new?(object)
59
44
  !object.eql?(input)
60
45
  end
61
46
 
62
- # Dispatch node generations
63
- #
64
- # @return [undefined]
65
47
  abstract_method :dispatch
48
+ private :dispatch
66
49
 
67
- # Emit generated mutation if object is not equivalent to input
68
- #
69
- # @param [Object] object
70
- #
71
- # @return [undefined]
72
50
  def emit(object)
73
51
  return unless new?(object)
74
52
 
75
53
  output << object
76
54
  end
77
55
 
78
- # Run input with mutator
79
- #
80
- # @return [undefined]
81
56
  def run(mutator)
82
57
  mutator.call(input).each(&method(:emit))
83
58
  end
84
59
 
85
- # Shortcut to create a new unfrozen duplicate of input
86
- #
87
- # @return [Object]
88
60
  def dup_input
89
61
  input.dup
90
62
  end
@@ -34,21 +34,9 @@ module Mutant
34
34
 
35
35
  private
36
36
 
37
- # Node to mutate
38
- #
39
- # @return [Parser::AST::Node]
40
- alias_method :node, :input
41
-
42
- # Duplicate of original
43
- #
44
- # @return [Parser::AST::Node]
37
+ alias_method :node, :input
45
38
  alias_method :dup_node, :dup_input
46
39
 
47
- # Dispatch on child index
48
- #
49
- # @param [Integer] index
50
- #
51
- # @return [undefined]
52
40
  def mutate_child(index, &block)
53
41
  block ||= TAUTOLOGY
54
42
  Mutator.mutate(children.fetch(index), self).each do |mutation|
@@ -57,108 +45,55 @@ module Mutant
57
45
  end
58
46
  end
59
47
 
60
- # Emit delete child mutation
61
- #
62
- # @param [Integer] index
63
- #
64
- # @return [undefined]
65
48
  def delete_child(index)
66
49
  dup_children = children.dup
67
50
  dup_children.delete_at(index)
68
51
  emit_type(*dup_children)
69
52
  end
70
53
 
71
- # Emit updated child
72
- #
73
- # @param [Integer] index
74
- # @param [Parser::AST::Node] node
75
- #
76
- # @return [undefined]
77
54
  def emit_child_update(index, node)
78
55
  new_children = children.dup
79
56
  new_children[index] = node
80
57
  emit_type(*new_children)
81
58
  end
82
59
 
83
- # Emit a new AST node with same class as wrapped node
84
- #
85
- # @param [Array<Parser::AST::Node>] children
86
- #
87
- # @return [undefined]
88
60
  def emit_type(*children)
89
61
  emit(::Parser::AST::Node.new(node.type, children))
90
62
  end
91
63
 
92
- # Emit propagation if node can stand alone
93
- #
94
- # @return [undefined]
95
64
  def emit_propagation(node)
96
65
  emit(node) unless AST::Types::NOT_STANDALONE.include?(node.type)
97
66
  end
98
67
 
99
- # Emit singleton literals
100
- #
101
- # @return [undefined]
102
68
  def emit_singletons
103
69
  emit_nil
104
70
  emit_self
105
71
  end
106
72
 
107
- # Emit a literal self
108
- #
109
- # @return [undefined]
110
73
  def emit_self
111
74
  emit(N_SELF)
112
75
  end
113
76
 
114
- # Emit a literal nil
115
- #
116
- # @return [undefined]
117
77
  def emit_nil
118
78
  emit(N_NIL) unless left_assignment?
119
79
  end
120
80
 
121
- # Parent node
122
- #
123
- # @return [Parser::AST::Node] node
124
- # if parent with node is present
125
- #
126
- # @return [nil]
127
- # otherwise
128
81
  def parent_node
129
82
  parent&.node
130
83
  end
131
84
 
132
- # Parent type
133
- #
134
- # @return [Symbol] type
135
- # if parent with type is present
136
- #
137
- # @return [nil]
138
- # otherwise
139
85
  def parent_type
140
86
  parent_node&.type
141
87
  end
142
88
 
143
- # Test if the node is the left of an or_asgn or op_asgn
144
- #
145
- # @return [Boolean]
146
89
  def left_assignment?
147
90
  AST::Types::OP_ASSIGN.include?(parent_type) && parent.node.children.first.equal?(node)
148
91
  end
149
92
 
150
- # Children indices
151
- #
152
- # @param [Range] range
153
- #
154
- # @return [Enumerable<Integer>]
155
93
  def children_indices(range)
156
94
  range.begin.upto(children.length + range.end)
157
95
  end
158
96
 
159
- # Emit single child mutation
160
- #
161
- # @return [undefined]
162
97
  def mutate_single_child
163
98
  children.each_with_index do |child, index|
164
99
  mutate_child(index)