diff options
Diffstat (limited to 'node_modules/istanbul-lib-source-maps/lib/transformer.js')
-rw-r--r-- | node_modules/istanbul-lib-source-maps/lib/transformer.js | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/node_modules/istanbul-lib-source-maps/lib/transformer.js b/node_modules/istanbul-lib-source-maps/lib/transformer.js new file mode 100644 index 000000000..748805949 --- /dev/null +++ b/node_modules/istanbul-lib-source-maps/lib/transformer.js @@ -0,0 +1,181 @@ +/* + Copyright 2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +"use strict"; + +var debug = require('debug')('istanbuljs'), + pathutils = require('./pathutils'), + libCoverage = require('istanbul-lib-coverage'), + MappedCoverage = require('./mapped').MappedCoverage; + +function isInvalidPosition (pos) { + return !pos || typeof pos.line !== "number" || typeof pos.column !== "number" || pos.line < 0 || pos.column < 0; +} + +/** + * determines the original position for a given location + * @param {SourceMapConsumer} sourceMap the source map + * @param {Object} location the original location Object + * @returns {Object} the remapped location Object + */ +function getMapping(sourceMap, location, origFile) { + + if (!location) { + return null; + } + + if (isInvalidPosition(location.start) || isInvalidPosition(location.end)) { + return null; + } + + var start = sourceMap.originalPositionFor(location.start), + end = sourceMap.originalPositionFor(location.end); + + /* istanbul ignore if: edge case too hard to test for */ + if (!(start && end)) { + return null; + } + if (!(start.source && end.source)) { + return null; + } + if (start.source !== end.source) { + return null; + } + + /* istanbul ignore if: edge case too hard to test for */ + if (start.line === null || start.column === null) { + return null; + } + /* istanbul ignore if: edge case too hard to test for */ + if (end.line === null || end.column === null) { + return null; + } + + if (start.line === end.line && start.column === end.column) { + end = sourceMap.originalPositionFor({ + line: location.end.line, + column: location.end.column, + bias: 2 + }); + end.column = end.column - 1; + } + + return { + source: pathutils.relativeTo(start.source, origFile), + loc: { + start: { + line: start.line, + column: start.column + }, + end: { + line: end.line, + column: end.column + } + } + }; +} + +function SourceMapTransformer(finder, opts) { + opts = opts || {}; + this.finder = finder; + this.baseDir = opts.baseDir || process.cwd(); +} + +SourceMapTransformer.prototype.processFile = function (fc, sourceMap, coverageMapper) { + var changes = 0; + + Object.keys(fc.statementMap).forEach(function (s) { + var loc = fc.statementMap[s], + hits = fc.s[s], + mapping = getMapping(sourceMap, loc, fc.path), + mappedCoverage; + + if (mapping) { + changes += 1; + mappedCoverage = coverageMapper(mapping.source); + mappedCoverage.addStatement(mapping.loc, hits); + } + }); + + Object.keys(fc.fnMap).forEach(function (f) { + var fnMeta = fc.fnMap[f], + hits = fc.f[f], + mapping = getMapping(sourceMap, fnMeta.decl, fc.path), + spanMapping = getMapping(sourceMap, fnMeta.loc, fc.path), + mappedCoverage; + + if (mapping && spanMapping && mapping.source === spanMapping.source) { + changes += 1; + mappedCoverage = coverageMapper(mapping.source); + mappedCoverage.addFunction(fnMeta.name, mapping.loc, spanMapping.loc, hits); + } + }); + + Object.keys(fc.branchMap).forEach(function (b) { + var branchMeta = fc.branchMap[b], + source, + hits = fc.b[b], + mapping, + locs = [], + mappedHits = [], + mappedCoverage, + skip, + i; + for (i = 0; i < branchMeta.locations.length; i += 1) { + mapping = getMapping(sourceMap, branchMeta.locations[i], 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; + mappedCoverage = coverageMapper(source); + mappedCoverage.addBranch(branchMeta.type, locs[0] /* XXX */, locs, mappedHits); + } + }); + + return changes > 0; +}; + +SourceMapTransformer.prototype.transform = function (coverageMap) { + var that = this, + finder = this.finder, + output = {}, + getMappedCoverage = function (file) { + if (!output[file]) { + output[file] = new MappedCoverage(file); + } + return output[file]; + }; + + coverageMap.files().forEach(function (file) { + var fc = coverageMap.fileCoverageFor(file), + sourceMap = finder(file), + changed; + + if (!sourceMap) { + output[file] = fc; + return; + } + + changed = that.processFile(fc, sourceMap, getMappedCoverage); + if (!changed) { + debug('File [' + file + '] ignored, nothing could be mapped'); + } + }); + return libCoverage.createCoverageMap(output); +}; + +module.exports = { + create: function (finder, opts) { + return new SourceMapTransformer(finder, opts); + } +}; |