istanbul-lib-coverage
Advanced tools
Comparing version 3.2.0 to 3.2.1
@@ -49,2 +49,10 @@ # Change Log | ||
## [3.2.1](https://github.com/istanbuljs/istanbuljs/compare/istanbul-lib-coverage-v3.2.0...istanbul-lib-coverage-v3.2.1) (2023-11-04) | ||
### Bug Fixes | ||
* https://github.com/istanbuljs/v8-to-istanbul/issues/233 ([288888f](https://github.com/istanbuljs/istanbuljs/commit/288888fef02ea35baf536bdd4d390ee12233ceb3)) | ||
* merge ranges properly when contained by other ranges in set ([#750](https://github.com/istanbuljs/istanbuljs/issues/750)) ([288888f](https://github.com/istanbuljs/istanbuljs/commit/288888fef02ea35baf536bdd4d390ee12233ceb3)) | ||
## [3.2.0](https://www.github.com/istanbuljs/istanbuljs/compare/istanbul-lib-coverage-v3.1.0...istanbul-lib-coverage-v3.2.0) (2021-10-17) | ||
@@ -51,0 +59,0 @@ |
@@ -48,2 +48,79 @@ /* | ||
// When merging, we can have a case where two ranges cover | ||
// the same block of code with `hits=1`, and each carve out a | ||
// different range with `hits=0` to indicate it's uncovered. | ||
// Find the nearest container so that we can properly indicate | ||
// that both sections are hit. | ||
// Returns null if no containing item is found. | ||
const findNearestContainer = (item, map) => { | ||
// the B item is not an identified range in the A set, BUT | ||
// it may be contained by an identified A range. If so, then | ||
// any hit of that containing A range counts as a hit of this | ||
// B range as well. We have to find the *narrowest* containing | ||
// range to be accurate, since ranges can be hit and un-hit | ||
// in a nested fashion. | ||
let nearestContainingItem = null; | ||
let containerDistance = null; | ||
let containerKey = null; | ||
for (const [i, mapItem] of Object.entries(map)) { | ||
const mapLoc = mapItem.loc; | ||
const itemLoc = item.loc; | ||
// contained if all of line distances are > 0 | ||
// or line distance is 0 and col dist is >= 0 | ||
const distance = [ | ||
itemLoc.start.line - mapLoc.start.line, | ||
itemLoc.start.column - mapLoc.start.column, | ||
mapLoc.end.line - itemLoc.end.line, | ||
mapLoc.end.column - itemLoc.end.column | ||
]; | ||
if ( | ||
distance[0] < 0 || | ||
distance[2] < 0 || | ||
(distance[0] === 0 && distance[1] < 0) || | ||
(distance[2] === 0 && distance[3] < 0) | ||
) { | ||
continue; | ||
} | ||
if (nearestContainingItem === null) { | ||
containerDistance = distance; | ||
nearestContainingItem = mapItem; | ||
containerKey = i; | ||
continue; | ||
} | ||
// closer line more relevant than closer column | ||
const closerBefore = | ||
distance[0] < containerDistance[0] || | ||
(distance[0] === 0 && distance[1] < containerDistance[1]); | ||
const closerAfter = | ||
distance[2] < containerDistance[2] || | ||
(distance[2] === 0 && distance[3] < containerDistance[3]); | ||
if (closerBefore || closerAfter) { | ||
// closer | ||
containerDistance = distance; | ||
nearestContainingItem = mapItem; | ||
containerKey = i; | ||
} | ||
} | ||
return containerKey; | ||
}; | ||
// either add two numbers, or all matching entries in a number[] | ||
const addHits = (aHits, bHits) => { | ||
if (typeof aHits === 'number' && typeof bHits === 'number') { | ||
return aHits + bHits; | ||
} else if (Array.isArray(aHits) && Array.isArray(bHits)) { | ||
return aHits.map((a, i) => (a || 0) + (bHits[i] || 0)); | ||
} | ||
return null; | ||
}; | ||
const addNearestContainerHits = (item, itemHits, map, mapHits) => { | ||
const container = findNearestContainer(item, map); | ||
if (container) { | ||
return addHits(itemHits, mapHits[container]); | ||
} else { | ||
return itemHits; | ||
} | ||
}; | ||
const mergeProp = (aHits, aMap, bHits, bMap, itemKey = keyFromLoc) => { | ||
@@ -55,25 +132,35 @@ const aItems = {}; | ||
} | ||
for (const [key, bItemHits] of Object.entries(bHits)) { | ||
const bItem = bMap[key]; | ||
const k = itemKey(bItem); | ||
if (aItems[k]) { | ||
const aPair = aItems[k]; | ||
if (bItemHits.forEach) { | ||
// should this throw an exception if aPair[0] is not an array? | ||
bItemHits.forEach((hits, h) => { | ||
if (aPair[0][h] !== undefined) aPair[0][h] += hits; | ||
else aPair[0][h] = hits; | ||
}); | ||
} else { | ||
aPair[0] += bItemHits; | ||
} | ||
const bItems = {}; | ||
for (const [key, itemHits] of Object.entries(bHits)) { | ||
const item = bMap[key]; | ||
bItems[itemKey(item)] = [itemHits, item]; | ||
} | ||
const mergedItems = {}; | ||
for (const [key, aValue] of Object.entries(aItems)) { | ||
let aItemHits = aValue[0]; | ||
const aItem = aValue[1]; | ||
const bValue = bItems[key]; | ||
if (!bValue) { | ||
// not an identified range in b, but might be contained by one | ||
aItemHits = addNearestContainerHits(aItem, aItemHits, bMap, bHits); | ||
} else { | ||
aItems[k] = [bItemHits, bItem]; | ||
// is an identified range in b, so add the hits together | ||
aItemHits = addHits(aItemHits, bValue[0]); | ||
} | ||
mergedItems[key] = [aItemHits, aItem]; | ||
} | ||
// now find the items in b that are not in a. already added matches. | ||
for (const [key, bValue] of Object.entries(bItems)) { | ||
let bItemHits = bValue[0]; | ||
const bItem = bValue[1]; | ||
if (mergedItems[key]) continue; | ||
// not an identified range in b, but might be contained by one | ||
bItemHits = addNearestContainerHits(bItem, bItemHits, aMap, aHits); | ||
mergedItems[key] = [bItemHits, bItem]; | ||
} | ||
const hits = {}; | ||
const map = {}; | ||
Object.values(aItems).forEach(([itemHits, item], i) => { | ||
Object.values(mergedItems).forEach(([itemHits, item], i) => { | ||
hits[i] = itemHits; | ||
@@ -325,3 +412,3 @@ map[i] = item; | ||
// can be optionally enabled: | ||
if (this['bt']) { | ||
if (this.bT) { | ||
ret.branchesTrue = this.computeBranchTotals('bT'); | ||
@@ -347,3 +434,7 @@ } | ||
module.exports = { | ||
FileCoverage | ||
FileCoverage, | ||
// exported for testing | ||
findNearestContainer, | ||
addHits, | ||
addNearestContainerHits | ||
}; |
{ | ||
"name": "istanbul-lib-coverage", | ||
"version": "3.2.0", | ||
"version": "3.2.1", | ||
"description": "Data library for istanbul coverage objects", | ||
@@ -5,0 +5,0 @@ "author": "Krishnan Anantheswaran <kananthmail-github@yahoo.com>", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
33418
708