Module: SimpleCov::Combine::LinesCombiner
- Defined in:
- lib/simplecov/combine/lines_combiner.rb
Overview
Combine two different lines coverage results on same file
Should be called through CoverageAccumulator.
Class Method Summary collapse
-
.coerce_add(existing, value) ⇒ Object
The rare arm:
existingis nil (line not yet relevant in the target) or malformed external input. -
.merge_into(target, source) ⇒ Array
Folds
sourceintotargetrather than building a third array. -
.sum_into(target, source, size) ⇒ Object
Split out only to keep
merge_intoshort; it is the same loop.
Class Method Details
.coerce_add(existing, value) ⇒ Object
The rare arm: existing is nil (line not yet relevant in the
target) or malformed external input.
68 69 70 |
# File 'lib/simplecov/combine/lines_combiner.rb', line 68 def coerce_add(existing, value) existing.nil? ? value : existing.to_i + value end |
.merge_into(target, source) ⇒ Array
Folds source into target rather than building a third array.
Only for a target the caller owns outright: a caller holding a
reference to it (e.g. the parsed coverage key of a resultset
hash being passed into a second merge) would see it change.
source is never touched.
Two runs of the same source file should agree on which lines
are coverage-relevant (nil for comments / whitespace, 0+
for executable). When they don't, treat "relevant on either
side" as relevant rather than masking a real 0 as nil,
which would silently drop an uncovered line from the
denominator and inflate the percentage:
=> nil + nil = nil => nil + int = int (preserves a relevant-but-uncovered 0) => int + int = int (sum)
The loop is written out rather than dispatching a block per element because this is the innermost loop of a merge: a 160-worker run over ~1,800 files folds tens of millions of line counts through it, and a call per count is a measurable share of that.
36 37 38 39 40 41 42 43 |
# File 'lib/simplecov/combine/lines_combiner.rb', line 36 def merge_into(target, source) return target unless source return source.dup unless target size = source.size target.concat(Array.new(size - target.size)) if target.size < size sum_into(target, source, size) end |
.sum_into(target, source, size) ⇒ Object
Split out only to keep merge_into short; it is the same loop.
The Integer tests coerce malformed counts (a "3" written by a
hand-edited or foreign resultset, a JSON float) with to_i, so
external input merges to a wrong answer instead of raising out of
the middle of a merge. An is_a? per count is far cheaper than
the block dispatch this loop exists to avoid, and the well-formed
fast path stays branch-for-branch what it was.
53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/simplecov/combine/lines_combiner.rb', line 53 def sum_into(target, source, size) index = 0 while index < size if (value = source[index]) value = value.to_i unless value.is_a?(Integer) existing = target[index] target[index] = existing.is_a?(Integer) ? existing + value : coerce_add(existing, value) end index += 1 end target end |