/*1Copyright (c) 2012, Yahoo! Inc. All rights reserved.2Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.3*/4"use strict";5var MemoryStore = require('./store/memory'),6utils = require('./object-utils');78/**9* a mechanism to merge multiple coverage objects into one. Handles the use case10* of overlapping coverage information for the same files in multiple coverage11* objects and does not double-count in this situation. For example, if12* you pass the same coverage object multiple times, the final merged object will be13* no different that any of the objects passed in (except for execution counts).14*15* The `Collector` is built for scale to handle thousands of coverage objects.16* By default, all processing is done in memory since the common use-case is of17* one or a few coverage objects. You can work around memory18* issues by passing in a `Store` implementation that stores temporary computations19* on disk (the `tmp` store, for example).20*21* The `getFinalCoverage` method returns an object with merged coverage information22* and is provided as a convenience for implementors working with coverage information23* that can fit into memory. Reporters, in the interest of generality, should *not* use this method for24* creating reports.25*26* Usage27* -----28*29* var collector = new require('istanbul').Collector();30*31* files.forEach(function (f) {32* //each coverage object can have overlapping information about multiple files33* collector.add(JSON.parse(fs.readFileSync(f, 'utf8')));34* });35*36* collector.files().forEach(function(file) {37* var fileCoverage = collector.fileCoverageFor(file);38* console.log('Coverage for ' + file + ' is:' + JSON.stringify(fileCoverage));39* });40*41* // convenience method: do not use this when dealing with a large number of files42* var finalCoverage = collector.getFinalCoverage();43*44* @class Collector45* @module main46* @constructor47* @param {Object} options Optional. Configuration options.48* @param {Store} options.store - an implementation of `Store` to use for temporary49* calculations.50*/51function Collector(options) {52options = options || {};53this.store = options.store || new MemoryStore();54}5556Collector.prototype = {57/**58* adds a coverage object to the collector.59*60* @method add61* @param {Object} coverage the coverage object.62* @param {String} testName Optional. The name of the test used to produce the object.63* This is currently not used.64*/65add: function (coverage /*, testName */) {66var store = this.store;67Object.keys(coverage).forEach(function (key) {68var fileCoverage = coverage[key];69if (store.hasKey(key)) {70store.setObject(key, utils.mergeFileCoverage(fileCoverage, store.getObject(key)));71} else {72store.setObject(key, fileCoverage);73}74});75},76/**77* returns a list of unique file paths for which coverage information has been added.78* @method files79* @return {Array} an array of file paths for which coverage information is present.80*/81files: function () {82return this.store.keys();83},84/**85* return file coverage information for a single file86* @method fileCoverageFor87* @param {String} fileName the path for the file for which coverage information is88* required. Must be one of the values returned in the `files()` method.89* @return {Object} the coverage information for the specified file.90*/91fileCoverageFor: function (fileName) {92var ret = this.store.getObject(fileName);93utils.addDerivedInfoForFile(ret);94return ret;95},96/**97* returns file coverage information for all files. This has the same format as98* any of the objects passed in to the `add` method. The number of keys in this99* object will be a superset of all keys found in the objects passed to `add()`100* @method getFinalCoverage101* @return {Object} the merged coverage information102*/103getFinalCoverage: function () {104var ret = {},105that = this;106this.files().forEach(function (file) {107ret[file] = that.fileCoverageFor(file);108});109return ret;110},111/**112* disposes this collector and reclaims temporary resources used in the113* computation. Calls `dispose()` on the underlying store.114* @method dispose115*/116dispose: function () {117this.store.dispose();118}119};120121module.exports = Collector;122123