monocart-coverage-reports 2.3.2 → 2.3.4
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.
- package/README.md +47 -19
- package/lib/converter/ast.js +2 -3
- package/lib/converter/branches.js +37 -26
- package/lib/converter/converter.js +91 -71
- package/lib/converter/ignore.js +51 -18
- package/lib/converter/info-line.js +2 -2
- package/lib/packages/monocart-coverage-v8.js +1 -1
- package/lib/platform/share.js +44 -6
- package/package.json +1 -1
- package/lib/converter/find-in-ranges.js +0 -39
package/README.md
CHANGED
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
* [How to convert V8 to Istanbul](#how-to-convert-v8-to-istanbul)
|
|
30
30
|
- [Using `v8-to-istanbul`](#using-v8-to-istanbul)
|
|
31
31
|
- [How Monocart Works](#how-monocart-works)
|
|
32
|
+
* [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap)
|
|
32
33
|
* [Integration](#integration) - Playwright, Jest, Vitest, Codecov, Coveralls, Sonar Cloud
|
|
33
|
-
* [Istanbul Introduction](#istanbul-introduction)
|
|
34
34
|
* [Thanks](#thanks)
|
|
35
35
|
|
|
36
36
|
## Usage
|
|
@@ -302,7 +302,7 @@ mcr "node ./test/test-node-env.js" -c test/cli-options.js
|
|
|
302
302
|
- see [Node.js V8 Coverage Report for Server Side](#nodejs-v8-coverage-report-for-server-side)
|
|
303
303
|
|
|
304
304
|
## Manually Resolve the Sourcemap
|
|
305
|
-
>
|
|
305
|
+
> Sometimes, the sourcemap file cannot be successfully loaded with the `sourceMappingURL`, you can try to manually read the sourcemap file before the coverage data is added to the report.
|
|
306
306
|
```js
|
|
307
307
|
const jsCoverage = await page.coverage.stopJSCoverage();
|
|
308
308
|
jsCoverage.forEach((entry) => {
|
|
@@ -370,26 +370,32 @@ Possible solutions:
|
|
|
370
370
|
- see [`mcr` CLI](#mcr-cli)
|
|
371
371
|
|
|
372
372
|
## Multiprocessing Support
|
|
373
|
-
The data will be added to `[outputDir]/.cache`,
|
|
374
|
-
-
|
|
373
|
+
> The data will be added to `[outputDir]/.cache`, After the generation of the report, this data will be removed unless debugging has been enabled or a raw report has been used, see [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap)
|
|
374
|
+
- Main process, before the start of testing
|
|
375
375
|
```js
|
|
376
|
+
// clean previous cache before the start of testing (option)
|
|
376
377
|
const MCR = require('monocart-coverage-reports');
|
|
377
378
|
const options = require('path-to/same-options.js');
|
|
378
|
-
|
|
379
|
-
await coverageReport.add(coverageData1);
|
|
379
|
+
MCR(options).cleanCache();
|
|
380
380
|
```
|
|
381
381
|
|
|
382
|
-
-
|
|
382
|
+
- Sub process 1, testing stage 1
|
|
383
383
|
```js
|
|
384
384
|
const MCR = require('monocart-coverage-reports');
|
|
385
385
|
const options = require('path-to/same-options.js');
|
|
386
|
-
|
|
387
|
-
|
|
386
|
+
await MCR(options).add(coverageData1);
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
- Sub process 2, testing stage 2
|
|
390
|
+
```js
|
|
391
|
+
const MCR = require('monocart-coverage-reports');
|
|
392
|
+
const options = require('path-to/same-options.js');
|
|
393
|
+
await MCR(options).add(coverageData2);
|
|
388
394
|
```
|
|
389
395
|
|
|
390
|
-
-
|
|
396
|
+
- Main process, after the completion of testing
|
|
391
397
|
```js
|
|
392
|
-
// after
|
|
398
|
+
// generate coverage reports after the completion of testing
|
|
393
399
|
const MCR = require('monocart-coverage-reports');
|
|
394
400
|
const options = require('path-to/same-options.js');
|
|
395
401
|
const coverageReport = MCR(options);
|
|
@@ -478,7 +484,7 @@ const os = platform === 'wind32' ? 'Windows' /* v8 ignore next */ : 'Other';
|
|
|
478
484
|
|
|
479
485
|
// v8 ignore next 3
|
|
480
486
|
if (platform === 'linux') {
|
|
481
|
-
console.
|
|
487
|
+
console.log('hello linux');
|
|
482
488
|
}
|
|
483
489
|
```
|
|
484
490
|
|
|
@@ -577,6 +583,25 @@ We implemented new converter instead of v8-to-istanbul:
|
|
|
577
583
|
| LogicalExpression | ✔ Not Perfect |
|
|
578
584
|
| SwitchStatement | ✔ Not Perfect |
|
|
579
585
|
|
|
586
|
+
## Debug for Coverage and Sourcemap
|
|
587
|
+
> Sometimes, the coverage is not what we expect. The next step is to figure out why, and we can easily find out the answer step by step through debugging.
|
|
588
|
+
- Start debugging for v8 report with option `logging: 'debug'`
|
|
589
|
+
```js
|
|
590
|
+
const coverageOptions = {
|
|
591
|
+
logging: 'debug',
|
|
592
|
+
reports: [
|
|
593
|
+
['v8'],
|
|
594
|
+
['console-summary']
|
|
595
|
+
]
|
|
596
|
+
};
|
|
597
|
+
```
|
|
598
|
+
When `logging` is `debug`, the raw report data will be preserved in `[outputDir]/.cache` or `[outputDir]/raw` if `raw` report is used. And the dist file will be preserved in the V8 list, and by opening the browser's devtool, it makes data verification visualization effortless.
|
|
599
|
+

|
|
600
|
+
|
|
601
|
+
- Check sourcemap with [Source Map Visualization](https://evanw.github.io/source-map-visualization/)
|
|
602
|
+
|
|
603
|
+

|
|
604
|
+
|
|
580
605
|
## Integration
|
|
581
606
|
- [monocart-reporter](https://github.com/cenfun/monocart-reporter) - A [Playwright](https://github.com/microsoft/playwright) custom reporter, supports generating [Code Coverage Report](https://github.com/cenfun/monocart-reporter?#code-coverage-report)
|
|
582
607
|
- [jest-monocart-coverage](https://github.com/cenfun/jest-monocart-coverage) - A [Jest](https://github.com/jestjs/jest/) custom reporter for coverage reports
|
|
@@ -601,6 +626,12 @@ We implemented new converter instead of v8-to-istanbul:
|
|
|
601
626
|
```
|
|
602
627
|
- [Coveralls](https://coveralls.io/)
|
|
603
628
|
- [](https://coveralls.io/github/cenfun/monocart-coverage-reports?branch=main)
|
|
629
|
+
```js
|
|
630
|
+
const coverageOptions = {
|
|
631
|
+
outputDir: "./coverage-reports",
|
|
632
|
+
lcov: true
|
|
633
|
+
};
|
|
634
|
+
```
|
|
604
635
|
- Github Actions example:
|
|
605
636
|
```yml
|
|
606
637
|
- name: Coveralls
|
|
@@ -627,13 +658,10 @@ We implemented new converter instead of v8-to-istanbul:
|
|
|
627
658
|
-Dsonar.tests=test
|
|
628
659
|
-Dsonar.exclusions=dist/*,packages/*
|
|
629
660
|
```
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
- [
|
|
634
|
-
- [babel-plugin-istanbul](https://github.com/istanbuljs/babel-plugin-istanbul)
|
|
635
|
-
- [istanbul-reports](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-reports/lib)
|
|
636
|
-
- [Code Coverage Introduction](https://docs.cypress.io/guides/tooling/code-coverage)
|
|
661
|
+
- Integration with any testing framework
|
|
662
|
+
- First, you need to collect coverage data when any stage of the test is completed. Then, add the coverage data to the coverage report.
|
|
663
|
+
- Upon the completion of all tests, generate the coverage report.
|
|
664
|
+
- see [Multiprocessing Support](#multiprocessing-support)
|
|
637
665
|
|
|
638
666
|
## Thanks
|
|
639
667
|
- Special thanks to [@edumserrano](https://github.com/edumserrano)
|
package/lib/converter/ast.js
CHANGED
|
@@ -4,7 +4,6 @@ const {
|
|
|
4
4
|
const Util = require('../utils/util.js');
|
|
5
5
|
|
|
6
6
|
const { createBranches, collectBranches } = require('./branches.js');
|
|
7
|
-
const findInRanges = require('./find-in-ranges.js');
|
|
8
7
|
|
|
9
8
|
const getFunctionRange = (start, end, state) => {
|
|
10
9
|
|
|
@@ -28,7 +27,7 @@ const getFunctionRange = (start, end, state) => {
|
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
// find in functionRanges
|
|
31
|
-
return findInRanges(start, end, functionRanges);
|
|
30
|
+
return Util.findInRanges(start, end, functionRanges, 'startOffset', 'endOffset');
|
|
32
31
|
};
|
|
33
32
|
|
|
34
33
|
const collectAstInfo = (ast, state) => {
|
|
@@ -214,7 +213,7 @@ const addRule = (item, coverageList, coveredRanges, count = 0) => {
|
|
|
214
213
|
const endOffset = end.offset;
|
|
215
214
|
|
|
216
215
|
if (!count) {
|
|
217
|
-
const coveredRange = findInRanges(startOffset, endOffset, coveredRanges);
|
|
216
|
+
const coveredRange = Util.findInRanges(startOffset, endOffset, coveredRanges, 'startOffset', 'endOffset');
|
|
218
217
|
if (coveredRange) {
|
|
219
218
|
count = 1;
|
|
220
219
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const Util = require('../utils/util.js');
|
|
2
|
-
const findInRanges = require('./find-in-ranges.js');
|
|
3
2
|
|
|
4
3
|
const findBranchBlock = (start, end, functionInfo) => {
|
|
5
4
|
const { range } = functionInfo;
|
|
@@ -14,7 +13,7 @@ const findBranchBlock = (start, end, functionInfo) => {
|
|
|
14
13
|
|
|
15
14
|
// support for tf2 || a || 1;
|
|
16
15
|
// "a" is in "|| a"
|
|
17
|
-
const blockItem = findInRanges(start, end, blockRanges);
|
|
16
|
+
const blockItem = Util.findInRanges(start, end, blockRanges, 'startOffset', 'endOffset');
|
|
18
17
|
if (blockItem) {
|
|
19
18
|
return blockItem;
|
|
20
19
|
}
|
|
@@ -108,7 +107,7 @@ const addNodeCount = (node, parents, functionInfo) => {
|
|
|
108
107
|
return;
|
|
109
108
|
}
|
|
110
109
|
|
|
111
|
-
const blockItem = findInRanges(start, end, blockRanges);
|
|
110
|
+
const blockItem = Util.findInRanges(start, end, blockRanges, 'startOffset', 'endOffset');
|
|
112
111
|
if (blockItem) {
|
|
113
112
|
node._state = {
|
|
114
113
|
count: blockItem.count
|
|
@@ -270,8 +269,27 @@ const createBranches = (functionInfo, branchMap, body, params, functionParents =
|
|
|
270
269
|
|
|
271
270
|
// =======================================================================================
|
|
272
271
|
|
|
272
|
+
const updateBlockLocations = (locations) => {
|
|
273
|
+
const noBlockList = [];
|
|
274
|
+
let blockCount = 0;
|
|
275
|
+
locations.forEach((item) => {
|
|
276
|
+
if (item.block) {
|
|
277
|
+
item.count = item.block.count;
|
|
278
|
+
blockCount += item.count;
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
noBlockList.push(item);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
return {
|
|
285
|
+
noBlockList,
|
|
286
|
+
blockCount
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
|
|
273
290
|
// const a = tf1 ? 'true' : 'false';
|
|
274
|
-
const ConditionalExpression = (
|
|
291
|
+
const ConditionalExpression = (locations, parentCount) => {
|
|
292
|
+
const { noBlockList, blockCount } = updateBlockLocations(locations);
|
|
275
293
|
if (!noBlockList.length) {
|
|
276
294
|
return;
|
|
277
295
|
}
|
|
@@ -282,7 +300,8 @@ const ConditionalExpression = (group, parentCount, noBlockList, blockCount) => {
|
|
|
282
300
|
});
|
|
283
301
|
};
|
|
284
302
|
|
|
285
|
-
const IfStatement = (
|
|
303
|
+
const IfStatement = (locations, parentCount) => {
|
|
304
|
+
const { noBlockList, blockCount } = updateBlockLocations(locations);
|
|
286
305
|
if (!noBlockList.length) {
|
|
287
306
|
return;
|
|
288
307
|
}
|
|
@@ -296,7 +315,8 @@ const IfStatement = (group, parentCount, noBlockList, blockCount) => {
|
|
|
296
315
|
};
|
|
297
316
|
|
|
298
317
|
// const b = tf2 || tf1 || a;
|
|
299
|
-
const LogicalExpression = (
|
|
318
|
+
const LogicalExpression = (locations, parentCount) => {
|
|
319
|
+
const { noBlockList, blockCount } = updateBlockLocations(locations);
|
|
300
320
|
if (!noBlockList.length) {
|
|
301
321
|
return;
|
|
302
322
|
}
|
|
@@ -304,15 +324,10 @@ const LogicalExpression = (group, parentCount, noBlockList, blockCount) => {
|
|
|
304
324
|
noBlockList.forEach((item) => {
|
|
305
325
|
item.count = count;
|
|
306
326
|
});
|
|
307
|
-
|
|
308
|
-
// const start = group.start;
|
|
309
|
-
// if (start > 7874 && start < 7922) {
|
|
310
|
-
// console.log(group.type, parentCount, 'locations', group.locations);
|
|
311
|
-
// }
|
|
312
|
-
|
|
313
327
|
};
|
|
314
328
|
|
|
315
|
-
const SwitchStatement = (
|
|
329
|
+
const SwitchStatement = (locations, parentCount) => {
|
|
330
|
+
const { noBlockList, blockCount } = updateBlockLocations(locations);
|
|
316
331
|
if (!noBlockList.length) {
|
|
317
332
|
return;
|
|
318
333
|
}
|
|
@@ -322,6 +337,12 @@ const SwitchStatement = (group, parentCount, noBlockList, blockCount) => {
|
|
|
322
337
|
});
|
|
323
338
|
};
|
|
324
339
|
|
|
340
|
+
const AssignmentPattern = (locations, parentCount) => {
|
|
341
|
+
locations.forEach((item) => {
|
|
342
|
+
item.count = parentCount;
|
|
343
|
+
});
|
|
344
|
+
};
|
|
345
|
+
|
|
325
346
|
// =======================================================================================
|
|
326
347
|
|
|
327
348
|
const getBranchParentCount = (reverseParents, functionCount) => {
|
|
@@ -363,27 +384,17 @@ const updateBranchCount = (group) => {
|
|
|
363
384
|
// calculate branches count
|
|
364
385
|
// > 1
|
|
365
386
|
|
|
366
|
-
const noBlockList = [];
|
|
367
|
-
let blockCount = 0;
|
|
368
|
-
locations.forEach((item) => {
|
|
369
|
-
if (item.block) {
|
|
370
|
-
item.count = item.block.count;
|
|
371
|
-
blockCount += item.count;
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
noBlockList.push(item);
|
|
375
|
-
});
|
|
376
|
-
|
|
377
387
|
const handlers = {
|
|
378
388
|
ConditionalExpression,
|
|
379
389
|
IfStatement,
|
|
380
390
|
LogicalExpression,
|
|
381
|
-
SwitchStatement
|
|
391
|
+
SwitchStatement,
|
|
392
|
+
AssignmentPattern
|
|
382
393
|
};
|
|
383
394
|
|
|
384
395
|
const handler = handlers[type];
|
|
385
396
|
if (handler) {
|
|
386
|
-
handler(
|
|
397
|
+
handler(locations, parentCount);
|
|
387
398
|
}
|
|
388
399
|
|
|
389
400
|
};
|
|
@@ -20,7 +20,6 @@ const { decode } = require('../packages/monocart-coverage-vendor.js');
|
|
|
20
20
|
const InfoLine = require('./info-line.js');
|
|
21
21
|
const InfoBranch = require('./info-branch.js');
|
|
22
22
|
const InfoFunction = require('./info-function.js');
|
|
23
|
-
const findInRanges = require('./find-in-ranges.js');
|
|
24
23
|
|
|
25
24
|
// ========================================================================================================
|
|
26
25
|
|
|
@@ -29,7 +28,7 @@ const handleIgnoredRanges = (list, ignoredRanges) => {
|
|
|
29
28
|
if (item.count > 0) {
|
|
30
29
|
return;
|
|
31
30
|
}
|
|
32
|
-
const range = findInRanges(item.start, item.end, ignoredRanges);
|
|
31
|
+
const range = Util.findInRanges(item.start, item.end, ignoredRanges, 'start', 'end');
|
|
33
32
|
if (range) {
|
|
34
33
|
// console.log(item, range);
|
|
35
34
|
item.ignored = true;
|
|
@@ -39,13 +38,17 @@ const handleIgnoredRanges = (list, ignoredRanges) => {
|
|
|
39
38
|
|
|
40
39
|
// ========================================================================================================
|
|
41
40
|
|
|
42
|
-
const
|
|
41
|
+
const applyBytesToLines = (bytes, locator, lineMap) => {
|
|
43
42
|
bytes.forEach((range) => {
|
|
44
|
-
|
|
45
43
|
const {
|
|
46
44
|
start, end, count, ignored
|
|
47
45
|
} = range;
|
|
48
46
|
|
|
47
|
+
// no need handle ignored and uncovered byte
|
|
48
|
+
if (count === 0 && ignored) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
49
52
|
const sLoc = locator.offsetToLocation(start);
|
|
50
53
|
const eLoc = locator.offsetToLocation(end);
|
|
51
54
|
|
|
@@ -53,83 +56,110 @@ const updateLinesCount = (bytes, locator, lineMap) => {
|
|
|
53
56
|
const lines = Util.getRangeLines(sLoc, eLoc);
|
|
54
57
|
|
|
55
58
|
lines.forEach((it) => {
|
|
56
|
-
const
|
|
57
|
-
if (!
|
|
59
|
+
const lineItem = lineMap.get(it.line);
|
|
60
|
+
if (!lineItem) {
|
|
61
|
+
// not found line, could be comment or blank line
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (lineItem.ignored) {
|
|
58
65
|
return;
|
|
59
66
|
}
|
|
60
67
|
|
|
61
|
-
|
|
62
|
-
// default is covered
|
|
63
|
-
if (it.entire) {
|
|
64
|
-
line.covered = count > 0;
|
|
65
|
-
line.count = count;
|
|
66
|
-
|
|
67
|
-
if (ignored) {
|
|
68
|
-
if (!line.covered) {
|
|
69
|
-
line.ignored = true;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
68
|
+
it.count = count;
|
|
72
69
|
|
|
70
|
+
// default is covered, so only focus on
|
|
71
|
+
// 1, last covered count
|
|
72
|
+
// 2, uncovered entire and pieces
|
|
73
|
+
if (count > 0) {
|
|
74
|
+
lineItem.coveredCount = count;
|
|
73
75
|
} else {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
} else {
|
|
79
|
-
// not covered if any count = 0
|
|
80
|
-
line.covered = false;
|
|
81
|
-
}
|
|
76
|
+
if (it.entire) {
|
|
77
|
+
lineItem.uncoveredEntire = it;
|
|
78
|
+
} else {
|
|
79
|
+
lineItem.uncoveredPieces.push(it);
|
|
82
80
|
}
|
|
83
|
-
|
|
84
81
|
}
|
|
85
|
-
|
|
86
|
-
// if (!line.history) {
|
|
87
|
-
// line.history = [];
|
|
88
|
-
// }
|
|
89
|
-
// line.history.push(`${it.entire}-${count}`);
|
|
90
|
-
|
|
91
82
|
});
|
|
92
83
|
|
|
93
84
|
});
|
|
94
|
-
|
|
95
|
-
// if (state.sourcePath.endsWith('component.js')) {
|
|
96
|
-
// console.log('===========================================', state.sourcePath);
|
|
97
|
-
// }
|
|
98
|
-
|
|
99
85
|
};
|
|
100
86
|
|
|
101
|
-
const handleLinesCoverage = (bytes, locator) => {
|
|
102
|
-
|
|
103
|
-
const lines = [];
|
|
104
|
-
// line 1 based
|
|
105
|
-
const lineMap = new Map();
|
|
87
|
+
const handleLinesCoverage = (bytes, locator, ignoredRanges) => {
|
|
106
88
|
|
|
107
89
|
// init lines
|
|
108
90
|
let blankCount = 0;
|
|
109
91
|
let commentCount = 0;
|
|
110
|
-
|
|
111
|
-
|
|
92
|
+
// line 1 based
|
|
93
|
+
const lineMap = new Map();
|
|
94
|
+
locator.lines.forEach((lineItem) => {
|
|
112
95
|
// exclude blank and comment
|
|
113
|
-
if (
|
|
96
|
+
if (lineItem.blank) {
|
|
114
97
|
blankCount += 1;
|
|
115
98
|
return;
|
|
116
99
|
}
|
|
117
|
-
if (
|
|
100
|
+
if (lineItem.comment) {
|
|
118
101
|
commentCount += 1;
|
|
119
102
|
return;
|
|
120
103
|
}
|
|
104
|
+
const ignored = Util.findInRanges(lineItem.start, lineItem.end, ignoredRanges);
|
|
105
|
+
if (ignored) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
121
108
|
// line 1-base
|
|
122
|
-
const line =
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
109
|
+
const line = lineItem.line + 1;
|
|
110
|
+
lineItem.coveredCount = 1;
|
|
111
|
+
lineItem.uncoveredEntire = null;
|
|
112
|
+
lineItem.uncoveredPieces = [];
|
|
113
|
+
lineMap.set(line, lineItem);
|
|
127
114
|
});
|
|
128
115
|
|
|
129
|
-
|
|
116
|
+
applyBytesToLines(bytes, locator, lineMap);
|
|
117
|
+
|
|
118
|
+
const lines = [];
|
|
119
|
+
// data lines for codecov
|
|
120
|
+
// https://docs.codecov.com/docs/codecov-custom-coverage-format
|
|
121
|
+
const dataLines = {};
|
|
122
|
+
|
|
123
|
+
// no ignore items
|
|
124
|
+
lineMap.forEach((lineItem, line) => {
|
|
125
|
+
|
|
126
|
+
const {
|
|
127
|
+
uncoveredEntire, uncoveredPieces, coveredCount
|
|
128
|
+
} = lineItem;
|
|
129
|
+
|
|
130
|
+
// default count to 1, both js and css
|
|
131
|
+
let count = 1;
|
|
132
|
+
// full covered true/false for entire line
|
|
133
|
+
let covered = true;
|
|
134
|
+
|
|
135
|
+
if (uncoveredEntire) {
|
|
136
|
+
count = 0;
|
|
137
|
+
covered = false;
|
|
138
|
+
} else {
|
|
139
|
+
|
|
140
|
+
count = coveredCount;
|
|
141
|
+
const uncoveredLen = uncoveredPieces.length;
|
|
142
|
+
if (uncoveredLen > 0) {
|
|
143
|
+
covered = false;
|
|
144
|
+
|
|
145
|
+
// uncovered
|
|
146
|
+
count = `1/${uncoveredLen + 1}`;
|
|
147
|
+
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// data lines
|
|
153
|
+
dataLines[line] = count;
|
|
154
|
+
|
|
155
|
+
// exclude indent?
|
|
156
|
+
const infoLine = new InfoLine(line, lineItem.length, count, covered);
|
|
157
|
+
lines.push(infoLine);
|
|
158
|
+
});
|
|
130
159
|
|
|
131
160
|
return {
|
|
132
161
|
lines,
|
|
162
|
+
dataLines,
|
|
133
163
|
blankCount,
|
|
134
164
|
commentCount
|
|
135
165
|
};
|
|
@@ -185,11 +215,8 @@ const calculateV8Lines = (lines, blankCount, commentCount) => {
|
|
|
185
215
|
comment: commentCount
|
|
186
216
|
};
|
|
187
217
|
|
|
218
|
+
// the lines not includes ignored
|
|
188
219
|
lines.forEach((ln) => {
|
|
189
|
-
if (ln.ignored) {
|
|
190
|
-
// console.log(ln);
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
220
|
v8Lines.total += 1;
|
|
194
221
|
// full line covered
|
|
195
222
|
if (ln.covered) {
|
|
@@ -235,6 +262,8 @@ const collectFileCoverage = (v8Data, state, options) => {
|
|
|
235
262
|
const ignoredRanges = getIgnoredRanges(locator, options);
|
|
236
263
|
if (ignoredRanges) {
|
|
237
264
|
|
|
265
|
+
data.ignores = ignoredRanges;
|
|
266
|
+
|
|
238
267
|
// data bytes is start/end/count object
|
|
239
268
|
handleIgnoredRanges(data.bytes, ignoredRanges);
|
|
240
269
|
|
|
@@ -275,8 +304,10 @@ const collectFileCoverage = (v8Data, state, options) => {
|
|
|
275
304
|
// lines
|
|
276
305
|
// after bytes with ignored, before calculateV8Lines
|
|
277
306
|
const {
|
|
278
|
-
lines, blankCount, commentCount
|
|
279
|
-
} = handleLinesCoverage(data.bytes, locator);
|
|
307
|
+
lines, dataLines, blankCount, commentCount
|
|
308
|
+
} = handleLinesCoverage(data.bytes, locator, ignoredRanges);
|
|
309
|
+
|
|
310
|
+
data.lines = dataLines;
|
|
280
311
|
|
|
281
312
|
// ==========================================
|
|
282
313
|
// v8 data and summary
|
|
@@ -301,21 +332,10 @@ const collectFileCoverage = (v8Data, state, options) => {
|
|
|
301
332
|
b: {}
|
|
302
333
|
};
|
|
303
334
|
|
|
304
|
-
//
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
lines.filter((it) => !it.ignored).forEach((line, index) => {
|
|
335
|
+
// the lines not includes ignored
|
|
336
|
+
lines.forEach((line, index) => {
|
|
308
337
|
istanbulData.statementMap[`${index}`] = line.generate();
|
|
309
338
|
istanbulData.s[`${index}`] = line.count;
|
|
310
|
-
|
|
311
|
-
let count = 0;
|
|
312
|
-
if (line.covered) {
|
|
313
|
-
count = line.count;
|
|
314
|
-
} else if (!line.covered && line.count > 0) {
|
|
315
|
-
count = '1/2';
|
|
316
|
-
}
|
|
317
|
-
// 1-base
|
|
318
|
-
data.lines[`${line.line}`] = count;
|
|
319
339
|
});
|
|
320
340
|
|
|
321
341
|
functions.filter((it) => !it.ignored).forEach((fn, index) => {
|
package/lib/converter/ignore.js
CHANGED
|
@@ -2,7 +2,7 @@ const Util = require('../utils/util.js');
|
|
|
2
2
|
|
|
3
3
|
const getNextN = (content, currentLine, item, locator) => {
|
|
4
4
|
|
|
5
|
-
//
|
|
5
|
+
// v-8 ignore next N
|
|
6
6
|
if (content) {
|
|
7
7
|
const n = parseInt(content);
|
|
8
8
|
if (n && n > 0) {
|
|
@@ -20,13 +20,32 @@ const getNextN = (content, currentLine, item, locator) => {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
//
|
|
23
|
+
// v-8 ignore next
|
|
24
24
|
return 1;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
+
const extendStart = (start, source) => {
|
|
28
|
+
// extend left, include
|
|
29
|
+
while (start > 0 && Util.isBlank(source[start - 1])) {
|
|
30
|
+
start -= 1;
|
|
31
|
+
}
|
|
32
|
+
return start;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const extendEnd = (end, source, maxLength) => {
|
|
36
|
+
// extend right, exclude
|
|
37
|
+
while (end < maxLength && Util.isBlank(source[end])) {
|
|
38
|
+
end += 1;
|
|
39
|
+
}
|
|
40
|
+
return end;
|
|
41
|
+
};
|
|
42
|
+
|
|
27
43
|
const addNextIgnore = (list, content, item, locator) => {
|
|
28
44
|
|
|
29
|
-
const { lineParser } = locator;
|
|
45
|
+
const { lineParser, source } = locator;
|
|
46
|
+
const maxLength = source.length;
|
|
47
|
+
|
|
48
|
+
const start = extendStart(item.start, source);
|
|
30
49
|
|
|
31
50
|
// findLine 0-base
|
|
32
51
|
const currentLine = lineParser.findLine(item.end);
|
|
@@ -37,24 +56,38 @@ const addNextIgnore = (list, content, item, locator) => {
|
|
|
37
56
|
// getLine 1-base
|
|
38
57
|
const line = currentLine.line + 1;
|
|
39
58
|
const endLine = locator.getLine(line + n);
|
|
40
|
-
const
|
|
59
|
+
const end = extendEnd(endLine ? endLine.end : maxLength, source, maxLength);
|
|
41
60
|
|
|
42
61
|
const nextItem = {
|
|
43
62
|
type: 'next',
|
|
44
63
|
n,
|
|
45
|
-
|
|
46
|
-
|
|
64
|
+
start,
|
|
65
|
+
end
|
|
47
66
|
};
|
|
48
67
|
|
|
49
68
|
list.push(nextItem);
|
|
50
69
|
};
|
|
51
70
|
|
|
71
|
+
// both v8 or c8
|
|
72
|
+
const hasIgnoreKey = (content) => {
|
|
73
|
+
const v8Key = 'v8 ignore';
|
|
74
|
+
if (content.startsWith(v8Key)) {
|
|
75
|
+
return v8Key.length;
|
|
76
|
+
}
|
|
77
|
+
const c8Key = 'c8 ignore';
|
|
78
|
+
if (content.startsWith(c8Key)) {
|
|
79
|
+
return c8Key.length;
|
|
80
|
+
}
|
|
81
|
+
// istanbul ignore has different rules, can not support it
|
|
82
|
+
};
|
|
83
|
+
|
|
52
84
|
const getIgnoredRanges = (locator, options) => {
|
|
53
85
|
if (!options.v8Ignore) {
|
|
54
86
|
return;
|
|
55
87
|
}
|
|
56
88
|
|
|
57
|
-
const { lineParser } = locator;
|
|
89
|
+
const { lineParser, source } = locator;
|
|
90
|
+
const maxLength = source.length;
|
|
58
91
|
|
|
59
92
|
const comments = lineParser.comments;
|
|
60
93
|
if (!Util.isList(comments)) {
|
|
@@ -71,35 +104,35 @@ const getIgnoredRanges = (locator, options) => {
|
|
|
71
104
|
let content = block ? text.slice(2, -2) : text.slice(2);
|
|
72
105
|
content = content.trim();
|
|
73
106
|
|
|
74
|
-
const
|
|
75
|
-
if (!
|
|
107
|
+
const ignoreKey = hasIgnoreKey(content);
|
|
108
|
+
if (!ignoreKey) {
|
|
76
109
|
return;
|
|
77
110
|
}
|
|
78
111
|
|
|
79
|
-
content = content.slice(
|
|
112
|
+
content = content.slice(ignoreKey).trim();
|
|
80
113
|
|
|
81
114
|
if (ignoreStart) {
|
|
82
|
-
//
|
|
115
|
+
// v-8 ignore stop
|
|
83
116
|
if (content === 'stop') {
|
|
84
|
-
ignoreStart.
|
|
117
|
+
ignoreStart.end = extendEnd(end, source, maxLength);
|
|
85
118
|
ignoreStart = null;
|
|
86
119
|
}
|
|
87
120
|
return;
|
|
88
121
|
}
|
|
89
122
|
|
|
90
|
-
//
|
|
123
|
+
// v-8 ignore start
|
|
91
124
|
if (content === 'start') {
|
|
92
125
|
// add first for sort by start
|
|
93
126
|
ignoreStart = {
|
|
94
|
-
type: 'start',
|
|
95
|
-
|
|
96
|
-
|
|
127
|
+
type: 'start-stop',
|
|
128
|
+
start: extendStart(start, source),
|
|
129
|
+
end: start
|
|
97
130
|
};
|
|
98
131
|
list.push(ignoreStart);
|
|
99
132
|
return;
|
|
100
133
|
}
|
|
101
134
|
|
|
102
|
-
//
|
|
135
|
+
// v-8 ignore next N
|
|
103
136
|
const nextKey = 'next';
|
|
104
137
|
if (content.startsWith(nextKey)) {
|
|
105
138
|
content = content.slice(nextKey.length).trim();
|
|
@@ -110,7 +143,7 @@ const getIgnoredRanges = (locator, options) => {
|
|
|
110
143
|
|
|
111
144
|
// ignore not stop
|
|
112
145
|
if (ignoreStart) {
|
|
113
|
-
ignoreStart.
|
|
146
|
+
ignoreStart.end = locator.source.length;
|
|
114
147
|
ignoreStart = null;
|
|
115
148
|
}
|
|
116
149
|
|