135 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			135 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | /* | ||
|  |  Copyright 2015, Yahoo Inc. | ||
|  |  Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. | ||
|  |  */ | ||
|  | 'use strict'; | ||
|  | 
 | ||
|  | const debug = require('debug')('istanbuljs'); | ||
|  | const libCoverage = require('istanbul-lib-coverage'); | ||
|  | const { MappedCoverage } = require('./mapped'); | ||
|  | const getMapping = require('./get-mapping'); | ||
|  | const { getUniqueKey, getOutput } = require('./transform-utils'); | ||
|  | 
 | ||
|  | class SourceMapTransformer { | ||
|  |     constructor(finder, opts = {}) { | ||
|  |         this.finder = finder; | ||
|  |         this.baseDir = opts.baseDir || process.cwd(); | ||
|  |     } | ||
|  | 
 | ||
|  |     processFile(fc, sourceMap, coverageMapper) { | ||
|  |         let changes = 0; | ||
|  | 
 | ||
|  |         Object.keys(fc.statementMap).forEach(s => { | ||
|  |             const loc = fc.statementMap[s]; | ||
|  |             const hits = fc.s[s]; | ||
|  |             const mapping = getMapping(sourceMap, loc, fc.path); | ||
|  | 
 | ||
|  |             if (mapping) { | ||
|  |                 changes += 1; | ||
|  |                 const mappedCoverage = coverageMapper(mapping.source); | ||
|  |                 mappedCoverage.addStatement(mapping.loc, hits); | ||
|  |             } | ||
|  |         }); | ||
|  | 
 | ||
|  |         Object.keys(fc.fnMap).forEach(f => { | ||
|  |             const fnMeta = fc.fnMap[f]; | ||
|  |             const hits = fc.f[f]; | ||
|  |             const mapping = getMapping(sourceMap, fnMeta.decl, fc.path); | ||
|  |             const spanMapping = getMapping(sourceMap, fnMeta.loc, fc.path); | ||
|  | 
 | ||
|  |             if ( | ||
|  |                 mapping && | ||
|  |                 spanMapping && | ||
|  |                 mapping.source === spanMapping.source | ||
|  |             ) { | ||
|  |                 changes += 1; | ||
|  |                 const mappedCoverage = coverageMapper(mapping.source); | ||
|  |                 mappedCoverage.addFunction( | ||
|  |                     fnMeta.name, | ||
|  |                     mapping.loc, | ||
|  |                     spanMapping.loc, | ||
|  |                     hits | ||
|  |                 ); | ||
|  |             } | ||
|  |         }); | ||
|  | 
 | ||
|  |         Object.keys(fc.branchMap).forEach(b => { | ||
|  |             const branchMeta = fc.branchMap[b]; | ||
|  |             const hits = fc.b[b]; | ||
|  |             const locs = []; | ||
|  |             const mappedHits = []; | ||
|  |             let source; | ||
|  |             let skip; | ||
|  | 
 | ||
|  |             branchMeta.locations.forEach((loc, i) => { | ||
|  |                 const mapping = getMapping(sourceMap, loc, fc.path); | ||
|  |                 if (mapping) { | ||
|  |                     if (!source) { | ||
|  |                         source = mapping.source; | ||
|  |                     } | ||
|  | 
 | ||
|  |                     if (mapping.source !== source) { | ||
|  |                         skip = true; | ||
|  |                     } | ||
|  | 
 | ||
|  |                     locs.push(mapping.loc); | ||
|  |                     mappedHits.push(hits[i]); | ||
|  |                 } | ||
|  |             }); | ||
|  | 
 | ||
|  |             if (!skip && locs.length > 0) { | ||
|  |                 changes += 1; | ||
|  |                 const mappedCoverage = coverageMapper(source); | ||
|  |                 mappedCoverage.addBranch( | ||
|  |                     branchMeta.type, | ||
|  |                     locs[0] /* XXX */, | ||
|  |                     locs, | ||
|  |                     mappedHits | ||
|  |                 ); | ||
|  |             } | ||
|  |         }); | ||
|  | 
 | ||
|  |         return changes > 0; | ||
|  |     } | ||
|  | 
 | ||
|  |     transform(coverageMap) { | ||
|  |         const uniqueFiles = {}; | ||
|  |         const getMappedCoverage = file => { | ||
|  |             const key = getUniqueKey(file); | ||
|  |             if (!uniqueFiles[key]) { | ||
|  |                 uniqueFiles[key] = { | ||
|  |                     file, | ||
|  |                     mappedCoverage: new MappedCoverage(file) | ||
|  |                 }; | ||
|  |             } | ||
|  | 
 | ||
|  |             return uniqueFiles[key].mappedCoverage; | ||
|  |         }; | ||
|  | 
 | ||
|  |         coverageMap.files().forEach(file => { | ||
|  |             const fc = coverageMap.fileCoverageFor(file); | ||
|  |             const sourceMap = this.finder(file); | ||
|  |             if (!sourceMap) { | ||
|  |                 uniqueFiles[getUniqueKey(file)] = { | ||
|  |                     file, | ||
|  |                     mappedCoverage: fc | ||
|  |                 }; | ||
|  |                 return; | ||
|  |             } | ||
|  | 
 | ||
|  |             const changed = this.processFile(fc, sourceMap, getMappedCoverage); | ||
|  |             if (!changed) { | ||
|  |                 debug(`File [${file}] ignored, nothing could be mapped`); | ||
|  |             } | ||
|  |         }); | ||
|  | 
 | ||
|  |         return libCoverage.createCoverageMap(getOutput(uniqueFiles)); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | module.exports = { | ||
|  |     create(finder, opts) { | ||
|  |         return new SourceMapTransformer(finder, opts); | ||
|  |     } | ||
|  | }; |