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.
@@ -1,353 +1,353 @@
1
- const {
2
- acorn, acornLoose, parseCss
3
- } = require('../packages/monocart-coverage-vendor.js');
4
- const Util = require('../utils/util.js');
5
-
6
- const { collectAstInfo } = require('./ast-visitor.js');
7
-
8
- const getCoverageInfo = (coverageList) => {
9
- const functionMap = new Map();
10
- const functionNameMap = new Map();
11
- const functionUncoveredRanges = [];
12
- let rootRange;
13
- coverageList.forEach((block) => {
14
- const {
15
- functionName, ranges, root
16
- } = block;
17
-
18
- let functionRange;
19
- const blockRanges = [];
20
-
21
- ranges.forEach((range, i) => {
22
- if (i === 0) {
23
- // function range
24
- functionRange = range;
25
- return;
26
- }
27
- blockRanges.push(range);
28
- });
29
-
30
- functionRange.functionName = functionName;
31
-
32
- // blocks
33
- if (blockRanges.length) {
34
- const blockMap = new Map();
35
- blockRanges.forEach((item) => {
36
- blockMap.set(item.startOffset, item);
37
- });
38
- functionRange.blockMap = blockMap;
39
- // uncovered is unique
40
- const blockUncoveredRanges = blockRanges.filter((it) => it.count === 0);
41
- blockUncoveredRanges.sort((a, b) => {
42
- return a.startOffset - b.startOffset;
43
- });
44
- functionRange.blockUncoveredRanges = blockUncoveredRanges;
45
- functionRange.blockCoveredRanges = blockRanges.filter((it) => it.count > 0);
46
- }
47
-
48
- // root function from vm
49
- if (root) {
50
- rootRange = functionRange;
51
- return;
52
- }
53
-
54
- // root function from first range
55
- if (!rootRange) {
56
- rootRange = functionRange;
57
- }
58
-
59
- functionMap.set(functionRange.startOffset, functionRange);
60
- if (functionName) {
61
- functionNameMap.set(functionRange.startOffset + functionName.length, functionRange);
62
- }
63
-
64
- // uncovered is unique
65
- if (functionRange.count === 0) {
66
- functionUncoveredRanges.push(functionRange);
67
- }
68
-
69
- });
70
-
71
- // sort ranges
72
- functionUncoveredRanges.sort((a, b) => {
73
- return a.startOffset - b.startOffset;
74
- });
75
-
76
- return {
77
- functionMap,
78
- functionNameMap,
79
- functionUncoveredRanges,
80
- rootRange
81
- };
82
-
83
- };
84
-
85
- const getFakeAstInfo = (coverageList) => {
86
- const functions = [];
87
- const branches = [];
88
- const statements = [];
89
- coverageList.forEach((block) => {
90
- const {
91
- isBlockCoverage, functionName, ranges, root
92
- } = block;
93
-
94
- ranges.forEach((range, i) => {
95
-
96
- const {
97
- startOffset, endOffset, count
98
- } = range;
99
-
100
- if (i === 0 && root) {
101
- return;
102
- }
103
-
104
- statements.push({
105
- start: startOffset,
106
- end: endOffset,
107
- count
108
- });
109
-
110
- if (isBlockCoverage) {
111
- // branches
112
- branches.push({
113
- type: 'branch',
114
- start: startOffset,
115
- end: endOffset,
116
- locations: [{
117
- start: startOffset,
118
- end: endOffset,
119
- count
120
- }]
121
- });
122
- }
123
-
124
- if (i === 0) {
125
- // function range
126
- functions.push({
127
- start: startOffset,
128
- end: endOffset,
129
- bodyStart: startOffset,
130
- bodyEnd: endOffset,
131
- count,
132
- functionName
133
- });
134
-
135
- }
136
- });
137
-
138
- });
139
-
140
- // console.log('fake functions', functions.map((it) => it));
141
-
142
- return {
143
- functions,
144
- branches,
145
- statements
146
- };
147
- };
148
-
149
- const getJsAstInfo = (item, coverageList) => {
150
-
151
- const {
152
- source, fake, empty
153
- } = item;
154
-
155
- if (fake) {
156
- return getFakeAstInfo(coverageList);
157
- }
158
-
159
- const options = {
160
- ecmaVersion: 'latest',
161
- // most time for node.js file
162
- allowReturnOutsideFunction: true,
163
- allowImportExportEverywhere: true,
164
- allowAwaitOutsideFunction: true,
165
- allowSuperOutsideMethod: true,
166
- // first line: #!/usr/bin/env node
167
- allowHashBang: true
168
- };
169
-
170
- let err;
171
- let ast;
172
- try {
173
- ast = acorn.parse(source, options);
174
- } catch (e) {
175
- err = e;
176
- }
177
-
178
- if (err) {
179
-
180
- // empty = untested file
181
- // could be .ts, .vue and so on, that can not be parsed normally
182
- if (empty) {
183
- return {
184
- functions: [],
185
- branches: [],
186
- statements: []
187
- };
188
- }
189
-
190
- // runtime code should be parsed successful
191
- Util.logInfo(`failed to parse source file: ${item.sourcePath} ${err.message}`);
192
-
193
- // https://github.com/acornjs/acorn/tree/master/acorn-loose
194
- // It is recommended to always try a parse with the regular acorn parser first,
195
- // and only fall back to this parser when that one finds syntax errors.
196
- ast = acornLoose.parse(source, options);
197
-
198
- }
199
-
200
- const coverageInfo = getCoverageInfo(coverageList);
201
- coverageInfo.item = item;
202
-
203
- return collectAstInfo(ast, coverageInfo);
204
- };
205
-
206
- // =========================================================================================================
207
-
208
- const addRule = (item, coverageList, coveredRanges, count = 0) => {
209
-
210
- const { source } = item;
211
- const { start, end } = source;
212
- const startOffset = start.offset;
213
- const endOffset = end.offset;
214
-
215
- if (!count) {
216
- const coveredRange = Util.findInRanges(startOffset, endOffset, coveredRanges, 'startOffset', 'endOffset');
217
- if (coveredRange) {
218
- count = 1;
219
- }
220
- }
221
-
222
- coverageList.push({
223
- start: startOffset,
224
- end: endOffset,
225
- count
226
- });
227
-
228
- return count;
229
-
230
- };
231
-
232
- const addAtRule = (item, coverageList, coveredRanges, empty) => {
233
- const { name, nodes } = item;
234
-
235
- const defaultCount = empty ? 0 : 1;
236
-
237
- if (['charset', 'import', 'namespace'].includes(name)) {
238
- addRule(item, coverageList, coveredRanges, defaultCount);
239
- return;
240
- }
241
-
242
- if (['media', 'supports', 'container', 'layer'].includes(name)) {
243
-
244
- const childCoverageList = [];
245
- const count = addCssRules(nodes, childCoverageList, coveredRanges, empty);
246
- if (count) {
247
-
248
- coverageList.push({
249
- start: item.source.start.offset,
250
- end: childCoverageList[0].start,
251
- count: 1
252
- });
253
-
254
- let end;
255
- childCoverageList.forEach((it) => {
256
- coverageList.push(it);
257
- end = it.end;
258
- });
259
-
260
- coverageList.push({
261
- start: end,
262
- end: item.source.end.offset,
263
- count: 1
264
- });
265
-
266
- return;
267
- }
268
-
269
- }
270
-
271
- addRule(item, coverageList, coveredRanges);
272
-
273
- };
274
-
275
- const addCssRules = (list, coverageList, coveredRanges, empty) => {
276
-
277
- let count = 0;
278
-
279
- // line and line is 1-base
280
- list.forEach((item) => {
281
-
282
- const { type } = item;
283
-
284
- if (type === 'comment') {
285
- return;
286
- }
287
-
288
- if (type === 'rule') {
289
- count += addRule(item, coverageList, coveredRanges);
290
- return;
291
- }
292
-
293
- // console.log('=============================================================================');
294
- // Object.keys(item).forEach((k) => {
295
- // if (k === 'parent') {
296
- // return;
297
- // }
298
- // if (k === 'raws') {
299
- // return;
300
- // }
301
- // if (k === 'nodes') {
302
- // console.log(k, item[k].length);
303
- // return;
304
- // }
305
- // if (k === 'source') {
306
- // console.log(k, item[k].start, item[k].end);
307
- // return;
308
- // }
309
- // console.log(k, item[k]);
310
- // });
311
-
312
- if (type === 'atrule') {
313
- addAtRule(item, coverageList, coveredRanges, empty);
314
- }
315
-
316
- });
317
-
318
- return count;
319
- };
320
-
321
- const getCssAstInfo = (item, coverageList) => {
322
-
323
- const {
324
- source, ranges, empty
325
- } = item;
326
-
327
- // sort covered ranges
328
- ranges.sort((a, b) => a.start - b.start);
329
-
330
- // to offset covered ranges
331
- const coveredRanges = ranges.map((it) => {
332
- return {
333
- startOffset: it.start,
334
- endOffset: it.end
335
- };
336
- });
337
-
338
- const ast = parseCss(source);
339
-
340
- addCssRules(ast.nodes, coverageList, coveredRanges, empty);
341
-
342
- return {
343
- functions: [],
344
- branches: [],
345
- statements: []
346
- };
347
- };
348
-
349
-
350
- module.exports = {
351
- getJsAstInfo,
352
- getCssAstInfo
353
- };
1
+ const {
2
+ acorn, acornLoose, parseCss
3
+ } = require('../packages/monocart-coverage-vendor.js');
4
+ const Util = require('../utils/util.js');
5
+
6
+ const { collectAstInfo } = require('./ast-visitor.js');
7
+
8
+ const getCoverageInfo = (coverageList) => {
9
+ const functionMap = new Map();
10
+ const functionNameMap = new Map();
11
+ const functionUncoveredRanges = [];
12
+ let rootRange;
13
+ coverageList.forEach((block) => {
14
+ const {
15
+ functionName, ranges, root
16
+ } = block;
17
+
18
+ let functionRange;
19
+ const blockRanges = [];
20
+
21
+ ranges.forEach((range, i) => {
22
+ if (i === 0) {
23
+ // function range
24
+ functionRange = range;
25
+ return;
26
+ }
27
+ blockRanges.push(range);
28
+ });
29
+
30
+ functionRange.functionName = functionName;
31
+
32
+ // blocks
33
+ if (blockRanges.length) {
34
+ const blockMap = new Map();
35
+ blockRanges.forEach((item) => {
36
+ blockMap.set(item.startOffset, item);
37
+ });
38
+ functionRange.blockMap = blockMap;
39
+ // uncovered is unique
40
+ const blockUncoveredRanges = blockRanges.filter((it) => it.count === 0);
41
+ blockUncoveredRanges.sort((a, b) => {
42
+ return a.startOffset - b.startOffset;
43
+ });
44
+ functionRange.blockUncoveredRanges = blockUncoveredRanges;
45
+ functionRange.blockCoveredRanges = blockRanges.filter((it) => it.count > 0);
46
+ }
47
+
48
+ // root function from vm
49
+ if (root) {
50
+ rootRange = functionRange;
51
+ return;
52
+ }
53
+
54
+ // root function from first range
55
+ if (!rootRange) {
56
+ rootRange = functionRange;
57
+ }
58
+
59
+ functionMap.set(functionRange.startOffset, functionRange);
60
+ if (functionName) {
61
+ functionNameMap.set(functionRange.startOffset + functionName.length, functionRange);
62
+ }
63
+
64
+ // uncovered is unique
65
+ if (functionRange.count === 0) {
66
+ functionUncoveredRanges.push(functionRange);
67
+ }
68
+
69
+ });
70
+
71
+ // sort ranges
72
+ functionUncoveredRanges.sort((a, b) => {
73
+ return a.startOffset - b.startOffset;
74
+ });
75
+
76
+ return {
77
+ functionMap,
78
+ functionNameMap,
79
+ functionUncoveredRanges,
80
+ rootRange
81
+ };
82
+
83
+ };
84
+
85
+ const getFakeAstInfo = (coverageList) => {
86
+ const functions = [];
87
+ const branches = [];
88
+ const statements = [];
89
+ coverageList.forEach((block) => {
90
+ const {
91
+ isBlockCoverage, functionName, ranges, root
92
+ } = block;
93
+
94
+ ranges.forEach((range, i) => {
95
+
96
+ const {
97
+ startOffset, endOffset, count
98
+ } = range;
99
+
100
+ if (i === 0 && root) {
101
+ return;
102
+ }
103
+
104
+ statements.push({
105
+ start: startOffset,
106
+ end: endOffset,
107
+ count
108
+ });
109
+
110
+ if (isBlockCoverage) {
111
+ // branches
112
+ branches.push({
113
+ type: 'branch',
114
+ start: startOffset,
115
+ end: endOffset,
116
+ locations: [{
117
+ start: startOffset,
118
+ end: endOffset,
119
+ count
120
+ }]
121
+ });
122
+ }
123
+
124
+ if (i === 0) {
125
+ // function range
126
+ functions.push({
127
+ start: startOffset,
128
+ end: endOffset,
129
+ bodyStart: startOffset,
130
+ bodyEnd: endOffset,
131
+ count,
132
+ functionName
133
+ });
134
+
135
+ }
136
+ });
137
+
138
+ });
139
+
140
+ // console.log('fake functions', functions.map((it) => it));
141
+
142
+ return {
143
+ functions,
144
+ branches,
145
+ statements
146
+ };
147
+ };
148
+
149
+ const getJsAstInfo = (item, coverageList) => {
150
+
151
+ const {
152
+ source, fake, empty
153
+ } = item;
154
+
155
+ if (fake) {
156
+ return getFakeAstInfo(coverageList);
157
+ }
158
+
159
+ const options = {
160
+ ecmaVersion: 'latest',
161
+ // most time for node.js file
162
+ allowReturnOutsideFunction: true,
163
+ allowImportExportEverywhere: true,
164
+ allowAwaitOutsideFunction: true,
165
+ allowSuperOutsideMethod: true,
166
+ // first line: #!/usr/bin/env node
167
+ allowHashBang: true
168
+ };
169
+
170
+ let err;
171
+ let ast;
172
+ try {
173
+ ast = acorn.parse(source, options);
174
+ } catch (e) {
175
+ err = e;
176
+ }
177
+
178
+ if (err) {
179
+
180
+ // empty = untested file
181
+ // could be .ts, .vue and so on, that can not be parsed normally
182
+ if (empty) {
183
+ return {
184
+ functions: [],
185
+ branches: [],
186
+ statements: []
187
+ };
188
+ }
189
+
190
+ // runtime code should be parsed successful
191
+ Util.logInfo(`failed to parse source file: ${item.sourcePath} ${err.message}`);
192
+
193
+ // https://github.com/acornjs/acorn/tree/master/acorn-loose
194
+ // It is recommended to always try a parse with the regular acorn parser first,
195
+ // and only fall back to this parser when that one finds syntax errors.
196
+ ast = acornLoose.parse(source, options);
197
+
198
+ }
199
+
200
+ const coverageInfo = getCoverageInfo(coverageList);
201
+ coverageInfo.item = item;
202
+
203
+ return collectAstInfo(ast, coverageInfo);
204
+ };
205
+
206
+ // =========================================================================================================
207
+
208
+ const addRule = (item, coverageList, coveredRanges, count = 0) => {
209
+
210
+ const { source } = item;
211
+ const { start, end } = source;
212
+ const startOffset = start.offset;
213
+ const endOffset = end.offset;
214
+
215
+ if (!count) {
216
+ const coveredRange = Util.findInRanges(startOffset, endOffset, coveredRanges, 'startOffset', 'endOffset');
217
+ if (coveredRange) {
218
+ count = 1;
219
+ }
220
+ }
221
+
222
+ coverageList.push({
223
+ start: startOffset,
224
+ end: endOffset,
225
+ count
226
+ });
227
+
228
+ return count;
229
+
230
+ };
231
+
232
+ const addAtRule = (item, coverageList, coveredRanges, empty) => {
233
+ const { name, nodes } = item;
234
+
235
+ const defaultCount = empty ? 0 : 1;
236
+
237
+ if (['charset', 'import', 'namespace'].includes(name)) {
238
+ addRule(item, coverageList, coveredRanges, defaultCount);
239
+ return;
240
+ }
241
+
242
+ if (['media', 'supports', 'container', 'layer'].includes(name)) {
243
+
244
+ const childCoverageList = [];
245
+ const count = addCssRules(nodes, childCoverageList, coveredRanges, empty);
246
+ if (count) {
247
+
248
+ coverageList.push({
249
+ start: item.source.start.offset,
250
+ end: childCoverageList[0].start,
251
+ count: 1
252
+ });
253
+
254
+ let end;
255
+ childCoverageList.forEach((it) => {
256
+ coverageList.push(it);
257
+ end = it.end;
258
+ });
259
+
260
+ coverageList.push({
261
+ start: end,
262
+ end: item.source.end.offset,
263
+ count: 1
264
+ });
265
+
266
+ return;
267
+ }
268
+
269
+ }
270
+
271
+ addRule(item, coverageList, coveredRanges);
272
+
273
+ };
274
+
275
+ const addCssRules = (list, coverageList, coveredRanges, empty) => {
276
+
277
+ let count = 0;
278
+
279
+ // line and line is 1-base
280
+ list.forEach((item) => {
281
+
282
+ const { type } = item;
283
+
284
+ if (type === 'comment') {
285
+ return;
286
+ }
287
+
288
+ if (type === 'rule') {
289
+ count += addRule(item, coverageList, coveredRanges);
290
+ return;
291
+ }
292
+
293
+ // console.log('=============================================================================');
294
+ // Object.keys(item).forEach((k) => {
295
+ // if (k === 'parent') {
296
+ // return;
297
+ // }
298
+ // if (k === 'raws') {
299
+ // return;
300
+ // }
301
+ // if (k === 'nodes') {
302
+ // console.log(k, item[k].length);
303
+ // return;
304
+ // }
305
+ // if (k === 'source') {
306
+ // console.log(k, item[k].start, item[k].end);
307
+ // return;
308
+ // }
309
+ // console.log(k, item[k]);
310
+ // });
311
+
312
+ if (type === 'atrule') {
313
+ addAtRule(item, coverageList, coveredRanges, empty);
314
+ }
315
+
316
+ });
317
+
318
+ return count;
319
+ };
320
+
321
+ const getCssAstInfo = (item, coverageList) => {
322
+
323
+ const {
324
+ source, ranges, empty
325
+ } = item;
326
+
327
+ // sort covered ranges
328
+ ranges.sort((a, b) => a.start - b.start);
329
+
330
+ // to offset covered ranges
331
+ const coveredRanges = ranges.map((it) => {
332
+ return {
333
+ startOffset: it.start,
334
+ endOffset: it.end
335
+ };
336
+ });
337
+
338
+ const ast = parseCss(source);
339
+
340
+ addCssRules(ast.nodes, coverageList, coveredRanges, empty);
341
+
342
+ return {
343
+ functions: [],
344
+ branches: [],
345
+ statements: []
346
+ };
347
+ };
348
+
349
+
350
+ module.exports = {
351
+ getJsAstInfo,
352
+ getCssAstInfo
353
+ };