This app provides monitoring and information features for the common freifunk user and the technical stuff of a freifunk community.
Code base is taken from a TUM Practical Course project and added here to see if Freifunk Altdorf can use it.
https://www.freifunk-altdorf.de
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
5.2 KiB
181 lines
5.2 KiB
/* |
|
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); |
|
} |
|
};
|
|
|