| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- /*
- 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);
- }
- };
|