monocart-coverage-reports 2.3.3 → 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 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
- > If the `js` file is loaded with `addScriptTag` [API](https://playwright.dev/docs/api/class-page#page-add-script-tag), then its sourcemap file may not work. You can try to manually read the sourcemap file before the coverage data is added to the report.
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`, and the cache will be removed after reports generated.
374
- - sub process 1
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
- const coverageReport = MCR(options);
379
- await coverageReport.add(coverageData1);
379
+ MCR(options).cleanCache();
380
380
  ```
381
381
 
382
- - sub process 2
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
- const coverageReport = MCR(options);
387
- await coverageReport.add(coverageData2);
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
- - main process
396
+ - Main process, after the completion of testing
391
397
  ```js
392
- // after all sub processes finished
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.info('hello linux');
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
+ ![](./test/debug-coverage.png)
600
+
601
+ - Check sourcemap with [Source Map Visualization](https://evanw.github.io/source-map-visualization/)
602
+
603
+ ![](./test/debug-sourcemap.png)
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
  - [![Coverage Status](https://coveralls.io/repos/github/cenfun/monocart-coverage-reports/badge.svg?branch=main)](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
- ## Istanbul Introduction
633
- - [Istanbul coverage report](https://istanbul.js.org/) - Instrumenting source codes and generating coverage reports
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)
@@ -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 = (group, parentCount, noBlockList, blockCount) => {
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 = (group, parentCount, noBlockList, blockCount) => {
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 = (group, parentCount, noBlockList, blockCount) => {
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 = (group, parentCount, noBlockList, blockCount) => {
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(group, parentCount, noBlockList, blockCount);
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 updateLinesCount = (bytes, locator, lineMap) => {
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 line = lineMap.get(it.line);
57
- if (!line) {
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
- // from outside into inside, uncovered is certain
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
- if (!ignored) {
76
- if (count > 0) {
77
- line.count = count;
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
- locator.lines.forEach((it) => {
92
+ // line 1 based
93
+ const lineMap = new Map();
94
+ locator.lines.forEach((lineItem) => {
112
95
  // exclude blank and comment
113
- if (it.blank) {
96
+ if (lineItem.blank) {
114
97
  blankCount += 1;
115
98
  return;
116
99
  }
117
- if (it.comment) {
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 = it.line + 1;
123
- // default count to 1, both js and css
124
- const lineInfo = new InfoLine(line, it.length, 1);
125
- lineMap.set(line, lineInfo);
126
- lines.push(lineInfo);
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
- updateLinesCount(bytes, locator, lineMap);
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
- // for codecov https://docs.codecov.com/docs/codecov-custom-coverage-format
305
- data.lines = {};
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) => {
@@ -2,7 +2,7 @@ const Util = require('../utils/util.js');
2
2
 
3
3
  const getNextN = (content, currentLine, item, locator) => {
4
4
 
5
- // v8 ignore next N
5
+ // v-8 ignore next N
6
6
  if (content) {
7
7
  const n = parseInt(content);
8
8
  if (n && n > 0) {
@@ -20,19 +20,32 @@ const getNextN = (content, currentLine, item, locator) => {
20
20
  }
21
21
  }
22
22
 
23
- // v8 ignore next
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
45
  const { lineParser, source } = locator;
30
46
  const maxLength = source.length;
31
- let startOffset = item.start;
32
- // extend left
33
- while (startOffset > 0 && Util.isBlank(source[startOffset - 1])) {
34
- startOffset -= 1;
35
- }
47
+
48
+ const start = extendStart(item.start, source);
36
49
 
37
50
  // findLine 0-base
38
51
  const currentLine = lineParser.findLine(item.end);
@@ -43,17 +56,13 @@ const addNextIgnore = (list, content, item, locator) => {
43
56
  // getLine 1-base
44
57
  const line = currentLine.line + 1;
45
58
  const endLine = locator.getLine(line + n);
46
- let endOffset = endLine ? endLine.end : maxLength;
47
- // extend right
48
- while (endOffset < maxLength && Util.isBlank(source[endOffset + 1])) {
49
- endOffset += 1;
50
- }
59
+ const end = extendEnd(endLine ? endLine.end : maxLength, source, maxLength);
51
60
 
52
61
  const nextItem = {
53
62
  type: 'next',
54
63
  n,
55
- startOffset,
56
- endOffset
64
+ start,
65
+ end
57
66
  };
58
67
 
59
68
  list.push(nextItem);
@@ -69,6 +78,7 @@ const hasIgnoreKey = (content) => {
69
78
  if (content.startsWith(c8Key)) {
70
79
  return c8Key.length;
71
80
  }
81
+ // istanbul ignore has different rules, can not support it
72
82
  };
73
83
 
74
84
  const getIgnoredRanges = (locator, options) => {
@@ -76,7 +86,8 @@ const getIgnoredRanges = (locator, options) => {
76
86
  return;
77
87
  }
78
88
 
79
- const { lineParser } = locator;
89
+ const { lineParser, source } = locator;
90
+ const maxLength = source.length;
80
91
 
81
92
  const comments = lineParser.comments;
82
93
  if (!Util.isList(comments)) {
@@ -101,27 +112,27 @@ const getIgnoredRanges = (locator, options) => {
101
112
  content = content.slice(ignoreKey).trim();
102
113
 
103
114
  if (ignoreStart) {
104
- // v8 ignore stop
115
+ // v-8 ignore stop
105
116
  if (content === 'stop') {
106
- ignoreStart.endOffset = end;
117
+ ignoreStart.end = extendEnd(end, source, maxLength);
107
118
  ignoreStart = null;
108
119
  }
109
120
  return;
110
121
  }
111
122
 
112
- // v8 ignore start
123
+ // v-8 ignore start
113
124
  if (content === 'start') {
114
125
  // add first for sort by start
115
126
  ignoreStart = {
116
127
  type: 'start-stop',
117
- startOffset: start,
118
- endOffset: start
128
+ start: extendStart(start, source),
129
+ end: start
119
130
  };
120
131
  list.push(ignoreStart);
121
132
  return;
122
133
  }
123
134
 
124
- // v8 ignore next N
135
+ // v-8 ignore next N
125
136
  const nextKey = 'next';
126
137
  if (content.startsWith(nextKey)) {
127
138
  content = content.slice(nextKey.length).trim();
@@ -132,7 +143,7 @@ const getIgnoredRanges = (locator, options) => {
132
143
 
133
144
  // ignore not stop
134
145
  if (ignoreStart) {
135
- ignoreStart.endOffset = locator.source.length;
146
+ ignoreStart.end = locator.source.length;
136
147
  ignoreStart = null;
137
148
  }
138
149
 
@@ -1,11 +1,11 @@
1
1
  module.exports = class InfoLine {
2
- constructor(line, column, count = 1) {
2
+ constructor(line, column, count, covered) {
3
3
  // 1 based
4
4
  this.line = line;
5
5
  this.column = column;
6
6
  this.count = count;
7
7
  // covered full line, could be false even count > 0
8
- this.covered = count > 0;
8
+ this.covered = covered;
9
9
  }
10
10
 
11
11
  generate() {