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
@@ -12,7 +12,6 @@ module Mutant
12
12
  # @return [Parser::AST::Node]
13
13
  #
14
14
  # @api private
15
- #
16
15
  def s(type, *children)
17
16
  Parser::AST::Node.new(type, children)
18
17
  end
@@ -24,7 +23,6 @@ module Mutant
24
23
  # @return [Parser::AST::Node]
25
24
  #
26
25
  # @api private
27
- #
28
26
  def n_not(node)
29
27
  s(:send, node, :!)
30
28
  end
@@ -8,19 +8,17 @@ module Mutant
8
8
  # @return [undefined]
9
9
  #
10
10
  # @api private
11
- #
12
11
  def initialize
13
12
  @cache = {}
14
13
  end
15
14
 
16
- # Return node for file
15
+ # Root node parsed from file
17
16
  #
18
17
  # @param [#to_s] path
19
18
  #
20
19
  # @return [AST::Node]
21
20
  #
22
21
  # @api private
23
- #
24
22
  def parse(path)
25
23
  @cache.fetch(path) do
26
24
  @cache[path] = Parser::CurrentRuby.parse(File.read(path))
@@ -18,7 +18,6 @@ module Mutant
18
18
  # the exit status
19
19
  #
20
20
  # @api private
21
- #
22
21
  def self.run(arguments)
23
22
  Runner.call(Env::Bootstrap.call(call(arguments))).success? ? EXIT_SUCCESS : EXIT_FAILURE
24
23
  rescue Error => exception
@@ -33,19 +32,17 @@ module Mutant
33
32
  # @return [undefined]
34
33
  #
35
34
  # @api private
36
- #
37
35
  def initialize(arguments)
38
36
  @config = Config::DEFAULT
39
37
 
40
38
  parse(arguments)
41
39
  end
42
40
 
43
- # Return config
41
+ # Config parsed from CLI
44
42
  #
45
43
  # @return [Config]
46
44
  #
47
45
  # @api private
48
- #
49
46
  attr_reader :config
50
47
 
51
48
  private
@@ -61,7 +58,6 @@ module Mutant
61
58
  # @return [undefined]
62
59
  #
63
60
  # @api private
64
- #
65
61
  def parse(arguments)
66
62
  opts = OptionParser.new do |builder|
67
63
  builder.banner = 'usage: mutant [options] MATCH_EXPRESSION ...'
@@ -82,12 +78,11 @@ module Mutant
82
78
  # @return [undefined]
83
79
  #
84
80
  # @api private
85
- #
86
81
  def parse_match_expressions(expressions)
87
82
  fail Error, 'No expressions given' if expressions.empty?
88
83
 
89
- expressions.map(&Expression.method(:parse)).each do |expression|
90
- add_matcher(:match_expressions, expression)
84
+ expressions.each do |expression|
85
+ add_matcher(:match_expressions, config.expression_parser.(expression))
91
86
  end
92
87
  end
93
88
 
@@ -97,10 +92,9 @@ module Mutant
97
92
  #
98
93
  # @return [undefined]
99
94
  #
100
- # @api private
101
- #
102
95
  # rubocop:disable MethodLength
103
96
  #
97
+ # @api private
104
98
  def add_environment_options(opts)
105
99
  opts.separator('Environment:')
106
100
  opts.on('--zombie', 'Run mutant zombified') do
@@ -124,7 +118,6 @@ module Mutant
124
118
  # @return [undefined]
125
119
  #
126
120
  # @api private
127
- #
128
121
  def setup_integration(name)
129
122
  update(integration: Integration.setup(name))
130
123
  rescue LoadError
@@ -138,7 +131,6 @@ module Mutant
138
131
  # @return [undefined]
139
132
  #
140
133
  # @api private
141
- #
142
134
  def add_mutation_options(opts)
143
135
  opts.separator(nil)
144
136
  opts.separator('Options:')
@@ -159,10 +151,12 @@ module Mutant
159
151
  # @return [undefined]
160
152
  #
161
153
  # @api private
162
- #
163
154
  def add_filter_options(opts)
164
- opts.on('--ignore-subject PATTERN', 'Ignore subjects that match PATTERN') do |pattern|
165
- add_matcher(:subject_ignores, Expression.parse(pattern))
155
+ opts.on('--ignore-subject EXPRESSION', 'Ignore subjects that match EXPRESSION as prefix') do |pattern|
156
+ add_matcher(:ignore_expressions, config.expression_parser.(pattern))
157
+ end
158
+ opts.on('--since REVISION', 'Only select subjects touched since REVISION') do |revision|
159
+ add_matcher(:subject_filters, Repository::SubjectFilter.new(Repository::Diff.from_head(revision)))
166
160
  end
167
161
  end
168
162
 
@@ -173,7 +167,6 @@ module Mutant
173
167
  # @return [undefined]
174
168
  #
175
169
  # @api private
176
- #
177
170
  def add_debug_options(opts)
178
171
  opts.on('--fail-fast', 'Fail fast') do
179
172
  update(fail_fast: true)
@@ -198,7 +191,6 @@ module Mutant
198
191
  # @return [undefined]
199
192
  #
200
193
  # @api private
201
- #
202
194
  def update(attributes)
203
195
  @config = @config.update(attributes)
204
196
  end
@@ -214,7 +206,6 @@ module Mutant
214
206
  # @return [undefined]
215
207
  #
216
208
  # @api private
217
- #
218
209
  def add(attribute, value)
219
210
  update(attribute => config.public_send(attribute).dup << value)
220
211
  end
@@ -230,7 +221,6 @@ module Mutant
230
221
  # @return [undefined]
231
222
  #
232
223
  # @api private
233
- #
234
224
  def add_matcher(attribute, value)
235
225
  update(matcher: config.matcher.add(attribute, value))
236
226
  end
@@ -10,7 +10,6 @@ module Mutant
10
10
  # @return [String]
11
11
  #
12
12
  # @api private
13
- #
14
13
  def format(text)
15
14
  "\e[#{@code}m#{text}\e[0m"
16
15
  end
@@ -25,7 +24,6 @@ module Mutant
25
24
  # the argument string
26
25
  #
27
26
  # @api private
28
- #
29
27
  def format(text)
30
28
  text
31
29
  end
@@ -37,7 +35,6 @@ module Mutant
37
35
  # @return [undefined]
38
36
  #
39
37
  # @api private
40
- #
41
38
  def initialize
42
39
  end
43
40
 
@@ -1,5 +1,8 @@
1
1
  module Mutant
2
- # The configuration of a mutator run
2
+ # Standalone configuration of a mutant execution.
3
+ #
4
+ # Does not reference any "external" volatile state. The configuration applied
5
+ # to current environment is being represented by the Mutant::Env object.
3
6
  class Config
4
7
  include Adamantium::Flat, Anima::Update, Anima.new(
5
8
  :debug,
@@ -12,7 +15,8 @@ module Mutant
12
15
  :fail_fast,
13
16
  :jobs,
14
17
  :zombie,
15
- :expected_coverage
18
+ :expected_coverage,
19
+ :expression_parser
16
20
  )
17
21
 
18
22
  %i[fail_fast zombie debug].each do |name|
@@ -3,22 +3,20 @@ module Mutant
3
3
  class Context
4
4
  include Adamantium::Flat, AbstractType, Concord::Public.new(:source_path)
5
5
 
6
- # Return root ast node
6
+ # Root ast node
7
7
  #
8
8
  # @param [Parser::AST::Node] node
9
9
  #
10
10
  # @return [Parser::AST::Node]
11
11
  #
12
12
  # @api private
13
- #
14
13
  abstract_method :root
15
14
 
16
- # Return identification
15
+ # Identification string
17
16
  #
18
17
  # @return [String]
19
18
  #
20
19
  # @api private
21
- #
22
20
  abstract_method :identification
23
21
 
24
22
  end # Context
@@ -7,24 +7,22 @@ module Mutant
7
7
 
8
8
  NAMESPACE_DELIMITER = '::'.freeze
9
9
 
10
- # Return AST wrapping mutated node
10
+ # Return root node for mutation
11
11
  #
12
12
  # @return [Parser::AST::Node]
13
13
  #
14
14
  # @api private
15
- #
16
15
  def root(node)
17
16
  nesting.reverse.reduce(node) do |current, scope|
18
17
  self.class.wrap(scope, current)
19
18
  end
20
19
  end
21
20
 
22
- # Return identification
21
+ # Identification string
23
22
  #
24
23
  # @return [String]
25
24
  #
26
25
  # @api private
27
- #
28
26
  def identification
29
27
  scope.name
30
28
  end
@@ -41,7 +39,6 @@ module Mutant
41
39
  # if scope is of kind module
42
40
  #
43
41
  # @api private
44
- #
45
42
  def self.wrap(scope, node)
46
43
  name = s(:const, nil, scope.name.split(NAMESPACE_DELIMITER).last.to_sym)
47
44
  case scope
@@ -54,12 +51,11 @@ module Mutant
54
51
  end
55
52
  end
56
53
 
57
- # Return nesting
54
+ # Nesting of scope
58
55
  #
59
56
  # @return [Enumerable<Class,Module>]
60
57
  #
61
58
  # @api private
62
- #
63
59
  def nesting
64
60
  const = ::Object
65
61
  name_nesting.each_with_object([]) do |name, nesting|
@@ -69,45 +65,43 @@ module Mutant
69
65
  end
70
66
  memoize :nesting
71
67
 
72
- # Return unqualified name of scope
68
+ # Unqualified name of scope
73
69
  #
74
70
  # @return [String]
75
71
  #
76
72
  # @api private
77
- #
78
73
  def unqualified_name
79
74
  name_nesting.last
80
75
  end
81
76
 
82
- # Return match expressions
77
+ # Match expressions for scope
83
78
  #
84
79
  # @return [Enumerable<Expression>]
85
80
  #
86
81
  # @api private
87
- #
88
82
  def match_expressions
89
83
  name_nesting.each_index.reverse_each.map do |index|
90
- Expression.parse("#{name_nesting.take(index.succ).join(NAMESPACE_DELIMITER)}*")
84
+ Expression::Namespace::Recursive.new(
85
+ scope_name: name_nesting.take(index.succ).join(NAMESPACE_DELIMITER)
86
+ )
91
87
  end
92
88
  end
93
89
  memoize :match_expressions
94
90
 
95
- # Return scope wrapped by context
91
+ # Scope wrapped by context
96
92
  #
97
93
  # @return [::Module|::Class]
98
94
  #
99
95
  # @api private
100
- #
101
96
  attr_reader :scope
102
97
 
103
98
  private
104
99
 
105
- # Return nesting of names of scope
100
+ # Nesting of names in scope
106
101
  #
107
102
  # @return [Array<String>]
108
103
  #
109
104
  # @api private
110
- #
111
105
  def name_nesting
112
106
  scope.name.split(NAMESPACE_DELIMITER)
113
107
  end
@@ -11,7 +11,6 @@ module Mutant
11
11
  # @return [undefined]
12
12
  #
13
13
  # @api private
14
- #
15
14
  def delegate(*names)
16
15
  names.each(&method(:define_delegator))
17
16
  end
@@ -23,7 +22,6 @@ module Mutant
23
22
  # @return [undefined]
24
23
  #
25
24
  # @api private
26
- #
27
25
  def define_delegator(name)
28
26
  fail "method #{name} already defined" if instance_methods.include?(name)
29
27
  define_method(name) do
@@ -41,7 +39,6 @@ module Mutant
41
39
  # @return [undefined]
42
40
  #
43
41
  # @api private
44
- #
45
42
  def self.included(host)
46
43
  super
47
44
 
@@ -7,7 +7,7 @@ module Mutant
7
7
  DELETION = '-'.freeze
8
8
  NEWLINE = "\n".freeze
9
9
 
10
- # Return source diff
10
+ # Unified source diff between old and new
11
11
  #
12
12
  # @return [String]
13
13
  # if there is exactly one diff
@@ -16,7 +16,6 @@ module Mutant
16
16
  # otherwise
17
17
  #
18
18
  # @api private
19
- #
20
19
  def diff
21
20
  return if diffs.empty?
22
21
 
@@ -26,7 +25,7 @@ module Mutant
26
25
  end
27
26
  memoize :diff
28
27
 
29
- # Return colorized source diff
28
+ # Colorized unified source diff between old and new
30
29
  #
31
30
  # @return [String]
32
31
  # if there is a diff
@@ -35,14 +34,13 @@ module Mutant
35
34
  # otherwise
36
35
  #
37
36
  # @api private
38
- #
39
37
  def colorized_diff
40
38
  return unless diff
41
39
  diff.lines.map(&self.class.method(:colorize_line)).join
42
40
  end
43
41
  memoize :colorized_diff
44
42
 
45
- # Return new object
43
+ # Build new object from source strings
46
44
  #
47
45
  # @param [String] old
48
46
  # @param [String] new
@@ -50,7 +48,6 @@ module Mutant
50
48
  # @return [Diff]
51
49
  #
52
50
  # @api private
53
- #
54
51
  def self.build(old, new)
55
52
  new(lines(old), lines(new))
56
53
  end
@@ -62,7 +59,6 @@ module Mutant
62
59
  # @return [Array<String>]
63
60
  #
64
61
  # @api private
65
- #
66
62
  def self.lines(source)
67
63
  source.lines.map(&:chomp)
68
64
  end
@@ -70,34 +66,31 @@ module Mutant
70
66
 
71
67
  private
72
68
 
73
- # Return diffs
69
+ # Diffs between old and new
74
70
  #
75
71
  # @return [Array<Array>]
76
72
  #
77
73
  # @api private
78
- #
79
74
  def diffs
80
75
  ::Diff::LCS.diff(old, new)
81
76
  end
82
77
 
83
- # Return hunks
78
+ # Raw diff-lcs hunks
84
79
  #
85
80
  # @return [Array<Diff::LCS::Hunk>]
86
81
  #
87
82
  # @api private
88
- #
89
83
  def hunks
90
84
  diffs.map do |diff|
91
85
  ::Diff::LCS::Hunk.new(old, new, diff, max_length, 0)
92
86
  end
93
87
  end
94
88
 
95
- # Return minimized hunks
89
+ # Minimized hunks
96
90
  #
97
91
  # @return [Array<Diff::LCS::Hunk>]
98
92
  #
99
93
  # @api private
100
- #
101
94
  def minimized_hunks
102
95
  head, *tail = hunks
103
96
 
@@ -111,24 +104,22 @@ module Mutant
111
104
  end
112
105
  end
113
106
 
114
- # Return max length
107
+ # Max length of source line in new and old
115
108
  #
116
109
  # @return [Fixnum]
117
110
  #
118
111
  # @api private
119
- #
120
112
  def max_length
121
113
  [old, new].map(&:length).max
122
114
  end
123
115
 
124
- # Return colorized diff line
116
+ # Colorized a unified diff line
125
117
  #
126
118
  # @param [String] line
127
119
  #
128
120
  # @return [String]
129
121
  #
130
122
  # @api private
131
- #
132
123
  def self.colorize_line(line)
133
124
  case line[0]
134
125
  when ADDITION