monocart-coverage-reports 2.5.9 → 2.6.1
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/LICENSE +21 -21
- package/README.md +791 -778
- package/lib/cli.js +250 -215
- package/lib/converter/ast-visitor.js +675 -666
- package/lib/converter/ast.js +353 -353
- package/lib/converter/collect-source-maps.js +201 -201
- package/lib/converter/converter.js +1487 -1429
- package/lib/converter/find-original-range.js +737 -737
- package/lib/converter/ignore.js +163 -163
- package/lib/converter/info-branch.js +93 -93
- package/lib/converter/info-function.js +63 -63
- package/lib/converter/info-statement.js +43 -43
- package/lib/default/options.js +84 -84
- package/lib/default/template.html +47 -47
- package/lib/generate.js +720 -532
- package/lib/index.d.ts +360 -324
- package/lib/index.js +187 -180
- package/lib/index.mjs +5 -3
- package/lib/istanbul/istanbul-summary.js +70 -63
- package/lib/istanbul/istanbul.js +146 -146
- package/lib/packages/monocart-coverage-v8.js +1 -1
- package/lib/platform/concurrency.js +74 -74
- package/lib/platform/share.js +484 -484
- package/lib/utils/dedupe.js +118 -118
- package/lib/utils/request.js +62 -62
- package/lib/utils/snapshot.js +381 -0
- package/lib/utils/source-path.js +179 -179
- package/lib/utils/util.js +526 -526
- package/lib/v8/v8-summary.js +138 -138
- package/lib/v8/v8.js +400 -630
- package/package.json +81 -80
|
@@ -1,666 +1,675 @@
|
|
|
1
|
-
const Util = require('../utils/util.js');
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (!
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if (
|
|
260
|
-
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
//
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
group
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
//
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
//
|
|
466
|
-
//
|
|
467
|
-
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
//
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
};
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
const
|
|
617
|
-
start,
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
1
|
+
const Util = require('../utils/util.js');
|
|
2
|
+
|
|
3
|
+
const BranchTypes = {
|
|
4
|
+
ConditionalExpression: 'ConditionalExpression',
|
|
5
|
+
LogicalExpression: 'LogicalExpression',
|
|
6
|
+
IfStatement: 'IfStatement',
|
|
7
|
+
SwitchStatement: 'SwitchStatement',
|
|
8
|
+
AssignmentPattern: 'AssignmentPattern'
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const getParentFunctionState = (reverseParents) => {
|
|
12
|
+
const parentFunction = reverseParents.find((it) => it._state && it._state.isFunction);
|
|
13
|
+
if (!parentFunction) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
return parentFunction._state;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const getParentCount = (reverseParents, functionCount) => {
|
|
20
|
+
// parent count
|
|
21
|
+
const parent = reverseParents.find((it) => it._state);
|
|
22
|
+
if (parent) {
|
|
23
|
+
return parent._state.count;
|
|
24
|
+
}
|
|
25
|
+
// root function count
|
|
26
|
+
return functionCount;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const getFunctionRange = (start, end, coverageInfo) => {
|
|
30
|
+
|
|
31
|
+
const {
|
|
32
|
+
functionMap, functionNameMap, functionUncoveredRanges
|
|
33
|
+
} = coverageInfo;
|
|
34
|
+
|
|
35
|
+
// exact matched in functionMap
|
|
36
|
+
const range = functionMap.get(start);
|
|
37
|
+
if (range) {
|
|
38
|
+
return range;
|
|
39
|
+
}
|
|
40
|
+
// exact matched in functionNameMap
|
|
41
|
+
const nameRange = functionNameMap.get(start);
|
|
42
|
+
if (nameRange) {
|
|
43
|
+
return nameRange;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// find in uncoveredRanges
|
|
47
|
+
return Util.findInRanges(start, end, functionUncoveredRanges, 'startOffset', 'endOffset');
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const getFunctionBlock = (start, end, functionState) => {
|
|
51
|
+
if (!functionState) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const { range } = functionState;
|
|
56
|
+
if (!range) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const {
|
|
61
|
+
blockMap, blockUncoveredRanges, blockCoveredRanges
|
|
62
|
+
} = range;
|
|
63
|
+
|
|
64
|
+
if (!blockMap) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const block = blockMap.get(start);
|
|
69
|
+
if (block) {
|
|
70
|
+
return block;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const uncoveredBlock = Util.findInRanges(start, end, blockUncoveredRanges, 'startOffset', 'endOffset');
|
|
74
|
+
if (uncoveredBlock) {
|
|
75
|
+
return uncoveredBlock;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// the block is not exact correct, if there is a block wrapped
|
|
79
|
+
// [x8]{ var a = b || [x4]c }, b is no block, but it can be found in x8 block
|
|
80
|
+
const coveredBlocks = blockCoveredRanges.filter((it) => start >= it.startOffset && end <= it.endOffset);
|
|
81
|
+
if (coveredBlocks.length) {
|
|
82
|
+
return coveredBlocks.pop();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const addNodeCount = (item) => {
|
|
88
|
+
|
|
89
|
+
const { node, reverseParents } = item;
|
|
90
|
+
|
|
91
|
+
if (node._state) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const { start, end } = node;
|
|
96
|
+
const functionState = getParentFunctionState(reverseParents);
|
|
97
|
+
const block = getFunctionBlock(start, end, functionState);
|
|
98
|
+
if (block) {
|
|
99
|
+
node._state = {
|
|
100
|
+
count: block.count
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// =======================================================================================
|
|
107
|
+
|
|
108
|
+
const createBranchGroup = (type, node, parents, branchMap) => {
|
|
109
|
+
const { start, end } = node;
|
|
110
|
+
// clone and reverse parents
|
|
111
|
+
const reverseParents = [].concat(parents).reverse();
|
|
112
|
+
const group = {
|
|
113
|
+
type,
|
|
114
|
+
|
|
115
|
+
start,
|
|
116
|
+
// could be updated if multiple locations
|
|
117
|
+
end,
|
|
118
|
+
|
|
119
|
+
locations: [],
|
|
120
|
+
reverseParents
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
if (type === BranchTypes.LogicalExpression) {
|
|
124
|
+
// && or ||
|
|
125
|
+
group.operator = node.operator;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// could be same start
|
|
129
|
+
const branchKey = `${start}_${end}`;
|
|
130
|
+
|
|
131
|
+
branchMap.set(branchKey, group);
|
|
132
|
+
return group;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const addBranch = (group, node, locationMap) => {
|
|
136
|
+
const { start, end } = node;
|
|
137
|
+
|
|
138
|
+
const branchKey = `${group.start}_${group.end}`;
|
|
139
|
+
|
|
140
|
+
const branchInfo = {
|
|
141
|
+
// for get previous group for LogicalExpression
|
|
142
|
+
branchKey,
|
|
143
|
+
start,
|
|
144
|
+
end,
|
|
145
|
+
// branch count default to 0
|
|
146
|
+
count: 0
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
group.locations.push(branchInfo);
|
|
150
|
+
|
|
151
|
+
// update group end
|
|
152
|
+
if (end > group.end) {
|
|
153
|
+
group.end = end;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
locationMap.set(start, branchInfo);
|
|
157
|
+
|
|
158
|
+
return branchInfo;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const addNoneBranch = (group) => {
|
|
162
|
+
group.locations.push({
|
|
163
|
+
none: true,
|
|
164
|
+
count: 0
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// =======================================================================================
|
|
169
|
+
|
|
170
|
+
const updateBlockLocations = (locations) => {
|
|
171
|
+
const noBlockList = [];
|
|
172
|
+
let blockCount = 0;
|
|
173
|
+
locations.forEach((item) => {
|
|
174
|
+
if (item.block) {
|
|
175
|
+
item.count = item.block.count;
|
|
176
|
+
blockCount += item.count;
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
noBlockList.push(item);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
noBlockList,
|
|
184
|
+
blockCount
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// const a = tf1 ? 'true' : 'false';
|
|
189
|
+
const ConditionalExpression = (group, parentCount) => {
|
|
190
|
+
const { noBlockList, blockCount } = updateBlockLocations(group.locations);
|
|
191
|
+
if (!noBlockList.length) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
let count = parentCount - blockCount;
|
|
195
|
+
noBlockList.forEach((item) => {
|
|
196
|
+
item.count = count;
|
|
197
|
+
count = 0;
|
|
198
|
+
});
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const IfStatement = (group, parentCount) => {
|
|
202
|
+
const { noBlockList, blockCount } = updateBlockLocations(group.locations);
|
|
203
|
+
if (!noBlockList.length) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
// console.log(parentCount, 'uncovered list', noBlockList.length, group.start);
|
|
207
|
+
let count = parentCount - blockCount;
|
|
208
|
+
noBlockList.forEach((item) => {
|
|
209
|
+
item.count = count;
|
|
210
|
+
count = 0;
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// const b = tf2 || tf1 || a;
|
|
216
|
+
const LogicalExpression = (group, parentCount) => {
|
|
217
|
+
|
|
218
|
+
// from left to right
|
|
219
|
+
group.locations.forEach((item, i) => {
|
|
220
|
+
if (item.block) {
|
|
221
|
+
item.count = item.block.count;
|
|
222
|
+
} else {
|
|
223
|
+
item.count = parentCount;
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const SwitchStatement = (group, parentCount) => {
|
|
230
|
+
const { noBlockList, blockCount } = updateBlockLocations(group.locations);
|
|
231
|
+
if (!noBlockList.length) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const count = parentCount - blockCount;
|
|
235
|
+
noBlockList.forEach((item) => {
|
|
236
|
+
item.count = count;
|
|
237
|
+
});
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const AssignmentPattern = (group, parentCount) => {
|
|
241
|
+
group.locations.forEach((item) => {
|
|
242
|
+
item.count = parentCount;
|
|
243
|
+
});
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// =======================================================================================
|
|
247
|
+
|
|
248
|
+
const updateBranchCount = (group) => {
|
|
249
|
+
|
|
250
|
+
const {
|
|
251
|
+
type, locations, reverseParents
|
|
252
|
+
} = group;
|
|
253
|
+
|
|
254
|
+
const functionState = getParentFunctionState(reverseParents);
|
|
255
|
+
|
|
256
|
+
const functionCount = functionState.count;
|
|
257
|
+
|
|
258
|
+
// default is 0, no need continue
|
|
259
|
+
if (functionCount === 0) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// parent is block statement or function
|
|
264
|
+
let parentCount = getParentCount(reverseParents, functionCount);
|
|
265
|
+
// parent is group range
|
|
266
|
+
const groupBlock = getFunctionBlock(group.start, group.end, functionState);
|
|
267
|
+
if (groupBlock) {
|
|
268
|
+
parentCount = groupBlock.count;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// calculate branches count
|
|
272
|
+
locations.forEach((item) => {
|
|
273
|
+
const {
|
|
274
|
+
start, end, none
|
|
275
|
+
} = item;
|
|
276
|
+
if (none) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
item.block = getFunctionBlock(start, end, functionState);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
const handlers = {
|
|
284
|
+
ConditionalExpression,
|
|
285
|
+
LogicalExpression,
|
|
286
|
+
IfStatement,
|
|
287
|
+
SwitchStatement,
|
|
288
|
+
AssignmentPattern
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const handler = handlers[type];
|
|
292
|
+
if (handler) {
|
|
293
|
+
handler(group, parentCount);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
const generateBranches = (branchMap) => {
|
|
299
|
+
|
|
300
|
+
// calculate count for all branches
|
|
301
|
+
branchMap.forEach((group) => {
|
|
302
|
+
updateBranchCount(group);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// init branches
|
|
306
|
+
const branches = [];
|
|
307
|
+
branchMap.forEach((group) => {
|
|
308
|
+
|
|
309
|
+
// add start/end for none with group start/end
|
|
310
|
+
group.locations.forEach((item) => {
|
|
311
|
+
if (item.none) {
|
|
312
|
+
item.start = group.start;
|
|
313
|
+
item.end = group.end;
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
branches.push({
|
|
318
|
+
type: group.type,
|
|
319
|
+
start: group.start,
|
|
320
|
+
end: group.end,
|
|
321
|
+
locations: group.locations
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// sort branches
|
|
326
|
+
branches.sort((a, b) => {
|
|
327
|
+
return a.start - b.start;
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
return branches;
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
// =======================================================================================
|
|
334
|
+
// All programs in JavaScript are made of statements and they end with semicolons (;) except block statements which is used to group zero or more statements.
|
|
335
|
+
// Statements are just perform some actions but do not produce any value or output whereas expressions return some value.
|
|
336
|
+
// Expressions return value, statements do not.
|
|
337
|
+
const generateStatements = (statementNodes) => {
|
|
338
|
+
|
|
339
|
+
statementNodes.forEach((item) => {
|
|
340
|
+
const {
|
|
341
|
+
node,
|
|
342
|
+
reverseParents
|
|
343
|
+
} = item;
|
|
344
|
+
|
|
345
|
+
const { start, end } = node;
|
|
346
|
+
|
|
347
|
+
item.count = 1;
|
|
348
|
+
|
|
349
|
+
// isFunction
|
|
350
|
+
if (node._state) {
|
|
351
|
+
item.count = node._state.count;
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const functionState = getParentFunctionState(reverseParents);
|
|
356
|
+
if (!functionState) {
|
|
357
|
+
// there is a root range, it impossible not found
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// function uncovered
|
|
362
|
+
if (functionState.count === 0) {
|
|
363
|
+
item.count = 0;
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const block = getFunctionBlock(start, end, functionState);
|
|
368
|
+
if (block) {
|
|
369
|
+
item.count = block.count;
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
item.count = functionState.count;
|
|
374
|
+
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
// remove block statement
|
|
378
|
+
statementNodes = statementNodes.filter((item) => {
|
|
379
|
+
return item.node.type !== 'BlockStatement';
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
const statements = statementNodes.map((item) => {
|
|
383
|
+
const {
|
|
384
|
+
node,
|
|
385
|
+
count
|
|
386
|
+
} = item;
|
|
387
|
+
const { start, end } = node;
|
|
388
|
+
return {
|
|
389
|
+
start,
|
|
390
|
+
end,
|
|
391
|
+
count
|
|
392
|
+
};
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
return statements;
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
// =======================================================================================
|
|
399
|
+
|
|
400
|
+
const collectNodes = (ast) => {
|
|
401
|
+
const functionNodes = [];
|
|
402
|
+
const statementNodes = [];
|
|
403
|
+
const blockNodes = [];
|
|
404
|
+
const branchMap = new Map();
|
|
405
|
+
// locationMap for chain LogicalExpression locations
|
|
406
|
+
const locationMap = new Map();
|
|
407
|
+
|
|
408
|
+
Util.visitAst(ast, {
|
|
409
|
+
|
|
410
|
+
VariableDeclarator(node, parents) {
|
|
411
|
+
|
|
412
|
+
// =============================================================
|
|
413
|
+
// id: { type: 'Identifier', name: '__webpack_modules__' },
|
|
414
|
+
const name = node.id && node.id.name;
|
|
415
|
+
if (name === '__webpack_modules__' && node.init && node.init.properties) {
|
|
416
|
+
// mark all as wrap function
|
|
417
|
+
node.init.properties.forEach((it) => {
|
|
418
|
+
it.value._wrapKey = it.key && it.key.value;
|
|
419
|
+
});
|
|
420
|
+
// console.log('==========================', node.type);
|
|
421
|
+
// console.log(name, parents.length);
|
|
422
|
+
}
|
|
423
|
+
// =============================================================
|
|
424
|
+
|
|
425
|
+
},
|
|
426
|
+
|
|
427
|
+
// ===============================================================================
|
|
428
|
+
// statements
|
|
429
|
+
|
|
430
|
+
Statement: (node, parents) => {
|
|
431
|
+
const reverseParents = [].concat(parents).reverse();
|
|
432
|
+
statementNodes.push({
|
|
433
|
+
node,
|
|
434
|
+
reverseParents
|
|
435
|
+
});
|
|
436
|
+
},
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
// ===============================================================================
|
|
440
|
+
// functions
|
|
441
|
+
// Function include FunctionDeclaration, ArrowFunctionExpression, FunctionExpression
|
|
442
|
+
Function(node, parents) {
|
|
443
|
+
const reverseParents = [].concat(parents).reverse();
|
|
444
|
+
functionNodes.push({
|
|
445
|
+
node,
|
|
446
|
+
reverseParents
|
|
447
|
+
});
|
|
448
|
+
},
|
|
449
|
+
|
|
450
|
+
// ===============================================================================
|
|
451
|
+
// branches
|
|
452
|
+
|
|
453
|
+
// `for` block, the count not equal to parent
|
|
454
|
+
BlockStatement: (node, parents) => {
|
|
455
|
+
|
|
456
|
+
// fix branch count: BRDA
|
|
457
|
+
const reverseParents = [].concat(parents).reverse();
|
|
458
|
+
blockNodes.push({
|
|
459
|
+
node,
|
|
460
|
+
reverseParents
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
},
|
|
464
|
+
|
|
465
|
+
// default-arg assignment logic.
|
|
466
|
+
// function default arguments
|
|
467
|
+
AssignmentPattern: (node, parents) => {
|
|
468
|
+
const group = createBranchGroup(BranchTypes.AssignmentPattern, node, parents, branchMap);
|
|
469
|
+
addBranch(group, node, locationMap);
|
|
470
|
+
},
|
|
471
|
+
|
|
472
|
+
// cond-expr a ternary expression. e.g.: x ? y : z
|
|
473
|
+
// Ternary
|
|
474
|
+
// var b = a ? 'consequent' : 'alternate';
|
|
475
|
+
ConditionalExpression: (node, parents) => {
|
|
476
|
+
const { consequent, alternate } = node;
|
|
477
|
+
const group = createBranchGroup(BranchTypes.ConditionalExpression, node, parents, branchMap);
|
|
478
|
+
addBranch(group, consequent, locationMap);
|
|
479
|
+
addBranch(group, alternate, locationMap);
|
|
480
|
+
},
|
|
481
|
+
|
|
482
|
+
// if an if statement; can also be else if.
|
|
483
|
+
// An IF statement always has exactly two branches:
|
|
484
|
+
// one where the condition is FALSE and one where the condition is TRUE
|
|
485
|
+
IfStatement: (node, parents) => {
|
|
486
|
+
const { consequent, alternate } = node;
|
|
487
|
+
const group = createBranchGroup(BranchTypes.IfStatement, node, parents, branchMap);
|
|
488
|
+
addBranch(group, consequent, locationMap);
|
|
489
|
+
|
|
490
|
+
// console.log('if type', consequent.type);
|
|
491
|
+
|
|
492
|
+
if (alternate) {
|
|
493
|
+
addBranch(group, alternate, locationMap);
|
|
494
|
+
} else {
|
|
495
|
+
// add none branch
|
|
496
|
+
addNoneBranch(group);
|
|
497
|
+
// no need update group end, there is no end
|
|
498
|
+
}
|
|
499
|
+
},
|
|
500
|
+
|
|
501
|
+
// binary-expr a logical expression with a binary operand. e.g.: x && y
|
|
502
|
+
// var b = a || b || c;
|
|
503
|
+
// do not use BinaryExpression
|
|
504
|
+
LogicalExpression: (node, parents) => {
|
|
505
|
+
const { left, right } = node;
|
|
506
|
+
// console.log(left.start, right.start);
|
|
507
|
+
|
|
508
|
+
// could be same branch start
|
|
509
|
+
// const da = arguments.length > 1 && typeof arguments[1] !== 'undefined' ? arguments[1] : true;
|
|
510
|
+
|
|
511
|
+
let group;
|
|
512
|
+
// link to same branch start if LogicalExpression
|
|
513
|
+
const prevLocation = locationMap.get(node.start);
|
|
514
|
+
if (prevLocation) {
|
|
515
|
+
// console.log('link branch ==================', type);
|
|
516
|
+
group = branchMap.get(prevLocation.branchKey);
|
|
517
|
+
} else {
|
|
518
|
+
group = createBranchGroup(BranchTypes.LogicalExpression, node, parents, branchMap);
|
|
519
|
+
addBranch(group, left, locationMap);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
addBranch(group, right, locationMap);
|
|
523
|
+
|
|
524
|
+
// console.log(group.locations.map((it) => it.start));
|
|
525
|
+
|
|
526
|
+
// sort branch locations
|
|
527
|
+
// a || b || c
|
|
528
|
+
// first, left a and right c
|
|
529
|
+
// then, left a and right b
|
|
530
|
+
if (prevLocation) {
|
|
531
|
+
const { locations } = group;
|
|
532
|
+
locations.sort((a, b) => {
|
|
533
|
+
return a.start - b.start;
|
|
534
|
+
});
|
|
535
|
+
// update group end after sorted
|
|
536
|
+
const lastEnd = locations[locations.length - 1].end;
|
|
537
|
+
if (lastEnd > group.end) {
|
|
538
|
+
group.end = lastEnd;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
},
|
|
542
|
+
|
|
543
|
+
// switch a switch statement.
|
|
544
|
+
SwitchStatement: (node, parents) => {
|
|
545
|
+
const group = createBranchGroup(BranchTypes.SwitchStatement, node, parents, branchMap);
|
|
546
|
+
const cases = node.cases;
|
|
547
|
+
cases.forEach((switchCase) => {
|
|
548
|
+
// console.log('switchCase', switchCase.start);
|
|
549
|
+
addBranch(group, switchCase, locationMap);
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
return {
|
|
556
|
+
functionNodes,
|
|
557
|
+
statementNodes,
|
|
558
|
+
blockNodes,
|
|
559
|
+
branchMap
|
|
560
|
+
};
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
const getRootFunctionState = (ast, coverageInfo) => {
|
|
564
|
+
const rootState = {
|
|
565
|
+
isFunction: true,
|
|
566
|
+
count: 1
|
|
567
|
+
};
|
|
568
|
+
const rootRange = coverageInfo.rootRange;
|
|
569
|
+
if (rootRange) {
|
|
570
|
+
rootState.range = rootRange;
|
|
571
|
+
rootState.count = rootRange.count;
|
|
572
|
+
|
|
573
|
+
// could be not from 0
|
|
574
|
+
// 0 881 { startOffset: 77, endOffset: 881,
|
|
575
|
+
// const { start, end } = ast;
|
|
576
|
+
// console.log(start, end, rootRange);
|
|
577
|
+
|
|
578
|
+
}
|
|
579
|
+
ast._state = rootState;
|
|
580
|
+
|
|
581
|
+
return rootState;
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
const findFunctionRange = (item, coverageInfo) => {
|
|
585
|
+
|
|
586
|
+
const { node, reverseParents } = item;
|
|
587
|
+
const { start, end } = node;
|
|
588
|
+
|
|
589
|
+
// try function start/end
|
|
590
|
+
const functionRange = getFunctionRange(start, end, coverageInfo);
|
|
591
|
+
if (functionRange) {
|
|
592
|
+
return functionRange;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// try if class MethodDefinition
|
|
596
|
+
// 0 is function self
|
|
597
|
+
const parent = reverseParents[1];
|
|
598
|
+
if (parent && parent.type === 'MethodDefinition') {
|
|
599
|
+
return getFunctionRange(parent.start, parent.end, coverageInfo);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
const collectAstInfo = (ast, coverageInfo) => {
|
|
605
|
+
|
|
606
|
+
const {
|
|
607
|
+
functionNodes, statementNodes, blockNodes, branchMap
|
|
608
|
+
} = collectNodes(ast);
|
|
609
|
+
|
|
610
|
+
// root function state
|
|
611
|
+
const rootState = getRootFunctionState(ast, coverageInfo);
|
|
612
|
+
|
|
613
|
+
const functions = [];
|
|
614
|
+
functionNodes.forEach((item) => {
|
|
615
|
+
const { node } = item;
|
|
616
|
+
const {
|
|
617
|
+
start, end, id
|
|
618
|
+
} = node;
|
|
619
|
+
const bodyStart = node.body.start;
|
|
620
|
+
const bodyEnd = node.body.end;
|
|
621
|
+
const functionName = id && id.name;
|
|
622
|
+
const isWrap = Boolean(node._wrapKey);
|
|
623
|
+
|
|
624
|
+
const functionItem = {
|
|
625
|
+
start,
|
|
626
|
+
end,
|
|
627
|
+
bodyStart,
|
|
628
|
+
bodyEnd,
|
|
629
|
+
functionName,
|
|
630
|
+
count: rootState.count
|
|
631
|
+
};
|
|
632
|
+
if (isWrap) {
|
|
633
|
+
functionItem.wrap = true;
|
|
634
|
+
}
|
|
635
|
+
functions.push(functionItem);
|
|
636
|
+
|
|
637
|
+
const functionState = {
|
|
638
|
+
isFunction: true,
|
|
639
|
+
count: functionItem.count
|
|
640
|
+
};
|
|
641
|
+
|
|
642
|
+
const functionRange = findFunctionRange(item, coverageInfo);
|
|
643
|
+
if (functionRange) {
|
|
644
|
+
if (isWrap) {
|
|
645
|
+
functionRange.wrap = true;
|
|
646
|
+
}
|
|
647
|
+
functionState.range = functionRange;
|
|
648
|
+
functionState.count = functionRange.count;
|
|
649
|
+
functionItem.count = functionRange.count;
|
|
650
|
+
}
|
|
651
|
+
node._state = functionState;
|
|
652
|
+
|
|
653
|
+
// console.log(item.reverseParents.map((it) => it.type));
|
|
654
|
+
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
blockNodes.forEach((item) => {
|
|
658
|
+
addNodeCount(item);
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
const branches = generateBranches(branchMap);
|
|
662
|
+
const statements = generateStatements(statementNodes);
|
|
663
|
+
|
|
664
|
+
return {
|
|
665
|
+
functions,
|
|
666
|
+
branches,
|
|
667
|
+
statements
|
|
668
|
+
};
|
|
669
|
+
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
module.exports = {
|
|
673
|
+
BranchTypes,
|
|
674
|
+
collectAstInfo
|
|
675
|
+
};
|