@@ -9,16 +9,15 @@ const Path = require('path');
9
9
10
10
const ESLint = require ( 'eslint' ) ;
11
11
const ESLintParser = require ( '@babel/eslint-parser' ) ;
12
- const SourceMap = require ( 'source-map' ) ;
13
12
const SourceMapSupport = require ( 'source-map-support' ) ;
14
13
15
14
const Eslintrc = require ( '../linter/.eslintrc' ) ;
15
+ const SourceMap = require ( '../source-map' ) ;
16
16
const Transform = require ( './transform' ) ;
17
17
18
18
const internals = {
19
- ext : Symbol . for ( '@hapi/lab/coverage/initialize' ) ,
20
19
_state : Symbol . for ( '@hapi/lab/coverage/_state' ) ,
21
- EslintEngine : new ESLint . CLIEngine ( { baseConfig : Eslintrc } )
20
+ eslint : new ESLint . ESLint ( { baseConfig : Eslintrc } )
22
21
} ;
23
22
24
23
@@ -31,8 +30,6 @@ global[internals._state] = global[internals._state] || {
31
30
32
31
predicates : { } ,
33
32
34
- externals : new Set ( ) ,
35
-
36
33
files : { } ,
37
34
38
35
_line : function ( name , line ) {
@@ -55,17 +52,6 @@ global[internals._state] = global[internals._state] || {
55
52
statement . hit [ ! ! source ] = true ;
56
53
}
57
54
58
- return source ;
59
- } ,
60
-
61
- _external : function ( name , line , source ) {
62
-
63
- const initialize = source [ Symbol . for ( '@hapi/lab/coverage/initialize' ) ] ;
64
- if ( typeof initialize !== 'function' ) {
65
- throw new Error ( 'Failed to find a compatible external coverage method in ' + name + ':' + line ) ;
66
- }
67
-
68
- internals . state . externals . add ( initialize ( ) ) ;
69
55
return source ;
70
56
}
71
57
} ;
@@ -78,17 +64,13 @@ if (typeof global.__$$labCov === 'undefined') {
78
64
// $lab:coverage:on$
79
65
80
66
81
- exports . instrument = function ( options ) {
67
+ exports . instrument = async function ( options ) {
82
68
83
- if ( options [ 'coverage-module' ] ) {
84
- for ( const name of options [ 'coverage-module' ] ) {
85
- internals . state . modules . add ( name ) ;
86
- }
87
- }
69
+ const ctx = await internals . context ( options ) ;
88
70
89
71
internals . state . patterns . unshift ( internals . pattern ( options ) ) ;
90
72
internals . state . predicates = options [ 'coverage-predicates' ] || { } ;
91
- Transform . install ( options , internals . prime ) ;
73
+ Transform . install ( options , ( ext ) => internals . prime ( ext , ctx ) ) ;
92
74
} ;
93
75
94
76
@@ -124,15 +106,15 @@ internals.escape = function (string) {
124
106
} ;
125
107
126
108
127
- internals . prime = function ( extension ) {
109
+ internals . prime = function ( extension , ctx ) {
128
110
129
111
require . extensions [ extension ] = function ( localModule , filename ) {
130
112
131
113
// We never want to instrument eslint configs in order to avoid infinite recursion
132
114
if ( Path . basename ( filename , extension ) !== '.eslintrc' ) {
133
115
for ( let i = 0 ; i < internals . state . patterns . length ; ++ i ) {
134
116
if ( internals . state . patterns [ i ] . test ( filename . replace ( / \\ / g, '/' ) ) ) {
135
- return localModule . _compile ( internals . instrument ( filename ) , filename ) ;
117
+ return localModule . _compile ( internals . instrument ( filename , ctx ) , filename ) ;
136
118
}
137
119
}
138
120
}
@@ -143,7 +125,7 @@ internals.prime = function (extension) {
143
125
} ;
144
126
145
127
146
- internals . instrument = function ( filename ) {
128
+ internals . instrument = function ( filename , ctx ) {
147
129
148
130
filename = filename . replace ( / \\ / g, '/' ) ;
149
131
@@ -297,8 +279,7 @@ internals.instrument = function (filename) {
297
279
'LabeledStatement'
298
280
] ;
299
281
300
- if ( node . parent &&
301
- node . parent . type === 'BlockStatement' &&
282
+ if ( node . parent ?. type === 'BlockStatement' &&
302
283
node . parent . parent . type . includes ( 'FunctionExpression' ) &&
303
284
node . parent . body [ 0 ] === node ) {
304
285
@@ -325,37 +306,26 @@ internals.instrument = function (filename) {
325
306
326
307
node . set ( `(global.__$$labCov._statement(\'${ filename } \',${ left } ,${ line } ,${ node . left . source ( ) } )${ node . operator } global.__$$labCov._statement(\'${ filename } \',${ right } ,${ line } ,${ node . right . source ( ) } ))` ) ;
327
308
}
328
- else if ( node . parent &&
329
- node . parent . type === 'ArrowFunctionExpression' &&
309
+ else if ( node . parent ?. type === 'ArrowFunctionExpression' &&
330
310
node . type . includes ( 'Expression' ) ) {
331
311
332
312
const id = addStatement ( line , node , false ) ;
333
313
334
314
node . set ( `global.__$$labCov._statement('${ filename } ', ${ id } , ${ line } , ${ node . source ( ) } )` ) ;
335
315
}
336
- else if ( node . parent &&
337
- node . parent . test === node &&
316
+ else if ( node . parent ?. test === node &&
338
317
node . parent . type !== 'SwitchCase' ) {
339
318
340
319
const test = addStatement ( line , node , true ) ;
341
320
342
321
node . set ( `global.__$$labCov._statement(\'${ filename } \',${ test } ,${ line } ,${ node . source ( ) } )` ) ;
343
322
}
344
- else if ( node . type === 'CallExpression' &&
345
- node . callee . name === 'require' ) {
346
-
347
- const name = node . arguments [ 0 ] . value ;
348
- if ( internals . state . modules . has ( name ) ) {
349
- node . set ( `global.__$$labCov._external(\'${ filename } \',${ line } ,${ node . source ( ) } )` ) ;
350
- }
351
- }
352
323
} ;
353
324
354
325
// Parse tree
355
326
356
- const eslintConfig = internals . EslintEngine . getConfigForFile ( filename ) ;
357
327
const tree = ESLintParser . parse ( content , {
358
- ...eslintConfig . parserOptions ,
328
+ ...ctx . parserOptions ,
359
329
loc : true ,
360
330
range : true ,
361
331
comment : true
@@ -551,13 +521,13 @@ exports.analyze = async function (options) {
551
521
552
522
const report = internals . state . files ;
553
523
const pattern = internals . pattern ( options ) ;
524
+ const ctx = await internals . context ( options ) ;
554
525
555
526
const cov = {
556
527
sloc : 0 ,
557
528
hits : 0 ,
558
529
misses : 0 ,
559
530
percent : 0 ,
560
- externals : 0 ,
561
531
files : [ ]
562
532
} ;
563
533
@@ -568,7 +538,7 @@ exports.analyze = async function (options) {
568
538
const filename = file . replace ( / \\ / g, '/' ) ;
569
539
if ( pattern . test ( filename ) ) {
570
540
if ( ! report [ filename ] ) {
571
- internals . instrument ( filename ) ;
541
+ internals . instrument ( filename , ctx ) ;
572
542
}
573
543
574
544
report [ filename ] . source = internals . state . sources [ filename ] || [ ] ;
@@ -578,7 +548,6 @@ exports.analyze = async function (options) {
578
548
cov . hits += data . hits ;
579
549
cov . misses += data . misses ;
580
550
cov . sloc += data . sloc ;
581
- cov . externals += data . externals ? data . externals . length : 0 ;
582
551
}
583
552
}
584
553
@@ -630,8 +599,7 @@ internals.file = async function (filename, data, options) {
630
599
hits : 0 ,
631
600
misses : 0 ,
632
601
sloc : data . sloc ,
633
- source : { } ,
634
- externals : internals . external ( filename )
602
+ source : { }
635
603
} ;
636
604
637
605
// Use sourcemap consumer rather than SourceMapSupport.mapSourcePosition itself which perform path transformations
@@ -691,7 +659,7 @@ internals.file = async function (filename, data, options) {
691
659
} ;
692
660
693
661
const originalPosition = smc . originalPositionFor ( position ) ;
694
- source . originalFilename = originalPosition . source && originalPosition . source . replace ( / \\ / g, '/' ) ; // Ensure folder separator to be url-friendly
662
+ source . originalFilename = originalPosition . source ? .replace ( / \\ / g, '/' ) ; // Ensure folder separator to be url-friendly
695
663
source . originalLine = originalPosition . line ;
696
664
if ( ! originalPosition . source ) {
697
665
if ( isValidLine ) {
@@ -791,21 +759,13 @@ internals.file = async function (filename, data, options) {
791
759
return ret ;
792
760
} ;
793
761
762
+ internals . context = async ( options ) => {
794
763
795
- internals . external = function ( filename ) {
796
-
797
- filename = Path . normalize ( filename ) ;
798
-
799
- const reports = [ ] ;
800
- for ( const external of internals . state . externals ) {
801
- const report = external . report ( filename ) ;
802
- if ( report ) {
803
- const items = [ ] . concat ( report ) ;
804
- for ( const item of items ) {
805
- reports . push ( Object . assign ( { } , item , { source : external . name } ) ) ;
806
- }
807
- }
808
- }
764
+ // The parserOptions are shared by all files for coverage purposes, based on
765
+ // the effective eslint config for a hypothetical file {coveragePath}/x.js
766
+ const { parserOptions } = await internals . eslint . calculateConfigForFile (
767
+ Path . join ( options . coveragePath || '' , 'x.js' )
768
+ ) ;
809
769
810
- return reports . length ? reports : null ;
770
+ return { parserOptions } ;
811
771
} ;
0 commit comments