Module: SimpleCov::Combine::BranchesCombiner
- Defined in:
- lib/simplecov/combine/branches_combiner.rb
Overview
Combine different branch coverage results on single file.
Should be called through CoverageAccumulator.
Class Method Summary collapse
-
.absorb(target, coverage) ⇒ Hash
Folds
coverageintotarget, an interned table keyed by condition identity. -
.combine(coverage_a, coverage_b) ⇒ Hash
Return merged branches or the existed branch if other is missing.
-
.identities ⇒ Object
Bounded by the project's branch count, like
RubyDataParser's parse cache. -
.materialize(target) ⇒ Hash
Turns an interned table back into the tuple-keyed hash the rest of SimpleCov reads.
-
.new_condition(condition) ⇒ Object
Split out so the empty arm table has somewhere to carry its type annotation.
-
.tuple_identity(tuple) ⇒ Object
Branches match on source span, whatever ids the recording processes handed them (issue #1233).
Class Method Details
.absorb(target, coverage) ⇒ Hash
Folds coverage into target, an interned table keyed by condition
identity. Kept interned (rather than turned back into tuple keys per
merge) so a fold over N resultsets interns each condition once
instead of re-interning the whole accumulated table N times.
39 40 41 42 43 44 45 46 47 48 |
# File 'lib/simplecov/combine/branches_combiner.rb', line 39 def absorb(target, coverage) return target unless coverage coverage.each do |condition, branches_inside| entry = target[identities[condition]] ||= new_condition(condition) InternedCounts.absorb_counts(entry[1], branches_inside, identities) end target end |
.combine(coverage_a, coverage_b) ⇒ Hash
Return merged branches or the existed branch if other is missing.
Branches inside files are always same if they exist, the difference only in coverage count. Branch coverage report for any conditional case is built from hash, it's key is a condition and it's body is a hash << keys from condition and value is coverage rate >>. ex: branches => { [:if, 3, 8, 6, 8, 36] => 4, 8, 6, 8, 12] => 1, [:else, 5, 8, 6, 8, 36] => 2, ... } We create copy of result and update it values depending on the combined branches coverage values.
28 29 30 31 |
# File 'lib/simplecov/combine/branches_combiner.rb', line 28 def combine(coverage_a, coverage_b) merged = absorb({}, coverage_a) #: Hash[untyped, [untyped, Hash[untyped, untyped]]] materialize(absorb(merged, coverage_b)) end |
.identities ⇒ Object
Bounded by the project's branch count, like RubyDataParser's parse
cache.
67 68 69 |
# File 'lib/simplecov/combine/branches_combiner.rb', line 67 def identities @identities ||= IdentityInterner.build { |tuple| tuple_identity(tuple) } end |
.materialize(target) ⇒ Hash
Turns an interned table back into the tuple-keyed hash the rest of SimpleCov reads. Done once, at the end of a fold.
61 62 63 |
# File 'lib/simplecov/combine/branches_combiner.rb', line 61 def materialize(target) target.values.to_h { |condition, branches| [condition, branches.values.to_h] } end |
.new_condition(condition) ⇒ Object
Split out so the empty arm table has somewhere to carry its type annotation. Only allocated the first time a condition is seen.
52 53 54 55 |
# File 'lib/simplecov/combine/branches_combiner.rb', line 52 def new_condition(condition) arms = {} #: Hash[untyped, untyped] [condition, arms] end |
.tuple_identity(tuple) ⇒ Object
Branches match on source span, whatever ids the recording processes handed them (issue #1233).
73 74 75 76 |
# File 'lib/simplecov/combine/branches_combiner.rb', line 73 def tuple_identity(tuple) type, _id, start_line, start_column, end_line, end_column = SourceFile::RubyDataParser.call(tuple) [type, start_line, start_column, end_line, end_column].freeze end |