| Line | Hits | Source |
|---|---|---|
| 1 | /** | |
| 2 | * Core dependencies. | |
| 3 | */ | |
| 4 | ||
| 5 | 1 | var path = require('path'); |
| 6 | 1 | var find = require('fine'); |
| 7 | ||
| 8 | /** | |
| 9 | * Internal dependencies. | |
| 10 | */ | |
| 11 | ||
| 12 | 1 | var Runner = require('./curiosity/runner'); |
| 13 | 1 | var bundler = require('./curiosity/bundler'); |
| 14 | 1 | var Formatter = require('./curiosity/formatter'); |
| 15 | ||
| 16 | /** | |
| 17 | * Analyze given `files`. | |
| 18 | * | |
| 19 | * @param {Array} files | |
| 20 | * @api public | |
| 21 | */ | |
| 22 | ||
| 23 | 1 | exports.analyzeFiles = function(files) { |
| 24 | 5 | var runner = new Runner(files); |
| 25 | 5 | var results = runner.run(); |
| 26 | 5 | return bundler.bundle(results); |
| 27 | }; | |
| 28 | ||
| 29 | /** | |
| 30 | * Lookup & filter production and test files. | |
| 31 | * | |
| 32 | * @param {Array} files | |
| 33 | * @param {Array} ignored | |
| 34 | * @returns {Object} | |
| 35 | * @api public | |
| 36 | */ | |
| 37 | ||
| 38 | 1 | exports.lookup = function(dirs, ignore) { |
| 39 | 6 | var lib = []; |
| 40 | 6 | ignore = (ignore || []).map(function(dir) { |
| 41 | 1 | return path.normalize(dir); |
| 42 | }); | |
| 43 | ||
| 44 | 6 | dirs.forEach(function(dir) { |
| 45 | 6 | var files = find(path.normalize(dir), { ext: '.js', ignore: ignore }); |
| 46 | 6 | lib = lib.concat(files); |
| 47 | }); | |
| 48 | ||
| 49 | 6 | return lib; |
| 50 | }; | |
| 51 | ||
| 52 | /** | |
| 53 | * Load given formatter. | |
| 54 | * | |
| 55 | * @param {String} name | |
| 56 | * @returns {Function} | |
| 57 | * @api public | |
| 58 | */ | |
| 59 | ||
| 60 | 1 | exports.loadFormatter = function(name) { |
| 61 | 3 | return require('./curiosity/formatter/' + name); |
| 62 | }; | |
| 63 | ||
| 64 | /** | |
| 65 | * Export `Formatter`. | |
| 66 | */ | |
| 67 | ||
| 68 | 1 | exports.Formatter = Formatter; |
| 69 |
| Line | Hits | Source |
|---|---|---|
| 1 | /** | |
| 2 | * Bundle an array of stats. | |
| 3 | * | |
| 4 | * @param {Array} stats | |
| 5 | * @returns {Object} | |
| 6 | * @api public | |
| 7 | */ | |
| 8 | ||
| 9 | 1 | exports.bundle = function(stats) { |
| 10 | 5 | var len = stats.length; |
| 11 | 5 | var ret = {}; |
| 12 | 5 | var files = []; |
| 13 | 5 | var total = {}; |
| 14 | ||
| 15 | 5 | stats.forEach(function(stat) { |
| 16 | 6 | var result = stat.result(); |
| 17 | ||
| 18 | 6 | Object.keys(result).forEach(function(key) { |
| 19 | 186 | total[key] = total[key] || { count: 0 }; |
| 20 | 186 | total[key].count += result[key].count; |
| 21 | }); | |
| 22 | ||
| 23 | 6 | files.push({ filename: stat.file, result: result }); |
| 24 | }); | |
| 25 | ||
| 26 | 5 | Object.keys(total).forEach(function(key) { |
| 27 | 155 | total[key].average = +(total[key].count / len).toFixed(2); |
| 28 | }); | |
| 29 | ||
| 30 | 5 | return { |
| 31 | files: files, | |
| 32 | total: { files: len, result: total } | |
| 33 | }; | |
| 34 | }; | |
| 35 |
| Line | Hits | Source |
|---|---|---|
| 1 | 1 | module.exports = { |
| 2 | 'AssignmentExpression': 1, | |
| 3 | 'VariableDeclarator': 1, | |
| 4 | 'FunctionDeclaration': 1, | |
| 5 | 'FunctionExpression': 1, | |
| 6 | 'ReturnStatement': 1, | |
| 7 | ||
| 8 | 'IfStatement': 2, | |
| 9 | 'ConditionalExpression': 2, | |
| 10 | 'SwitchStatement': 2, | |
| 11 | ||
| 12 | 'DoWhileStatement': 3, | |
| 13 | 'WhileStatement': 3, | |
| 14 | 'ForStatement': 3, | |
| 15 | 'LabelStatement': 3, | |
| 16 | 'ForInStatement': 3, | |
| 17 | 'BreakStatement': 3, | |
| 18 | 'ContinueStatement': 3, | |
| 19 | ||
| 20 | 'ArrayExpression': 4, | |
| 21 | 'ObjectExpression': 4, | |
| 22 | ||
| 23 | 'TryStatement': 5, | |
| 24 | 'ThrowStatement': 5, | |
| 25 | ||
| 26 | 'String': 6, | |
| 27 | 'RegularExpression': 6, | |
| 28 | 'Boolean': 6, | |
| 29 | 'Numeric': 6, | |
| 30 | 'Null': 6, | |
| 31 | 'Identifier': 6, | |
| 32 | 'Semicolon': 6, | |
| 33 | ||
| 34 | 'EmptyStatement': 7, | |
| 35 | 'RequireCall': 7, | |
| 36 | 'FileLine': 7, | |
| 37 | 'Comment': 7, | |
| 38 | 'CallExpression': 7, | |
| 39 | }; | |
| 40 |
| Line | Hits | Source |
|---|---|---|
| 1 | /** | |
| 2 | * Base formatter. | |
| 3 | * | |
| 4 | * @param {String} data | |
| 5 | * @param {WritableStream} out | |
| 6 | * @constructor | |
| 7 | */ | |
| 8 | ||
| 9 | function Formatter(data, out) { | |
| 10 | 3 | this.data = data; |
| 11 | 3 | this.out = out; |
| 12 | } | |
| 13 | ||
| 14 | /** | |
| 15 | * Print given `msg`. | |
| 16 | * | |
| 17 | * @param {String} msg | |
| 18 | * @param {Number} padding | |
| 19 | * @api private | |
| 20 | */ | |
| 21 | ||
| 22 | 1 | Formatter.prototype.print = function(msg, padding) { |
| 23 | 13 | padding = padding || 0; |
| 24 | 13 | msg = msg || ''; |
| 25 | 13 | this.out.write(Array(padding).join(' ') + msg + '\n'); |
| 26 | }; | |
| 27 | ||
| 28 | /** | |
| 29 | * Print with left padding. | |
| 30 | * | |
| 31 | * @param {String} msg | |
| 32 | * @api private | |
| 33 | */ | |
| 34 | ||
| 35 | 1 | Formatter.prototype.iprint = function(msg) { |
| 36 | 8 | this.print(msg, 8); |
| 37 | }; | |
| 38 | ||
| 39 | /** | |
| 40 | * If `width` is greater than the length of `str`, return a new string of length `width` | |
| 41 | * with `str` left justified | |
| 42 | * | |
| 43 | * @param {String} str | |
| 44 | * @param {Number} width | |
| 45 | * @returns {String} | |
| 46 | * @api private | |
| 47 | */ | |
| 48 | ||
| 49 | 1 | Formatter.prototype.ljust = function(str, width) { |
| 50 | 9 | str += ''; |
| 51 | 9 | var len = Math.max(0, width - str.length); |
| 52 | 9 | return str + Array(len + 1).join(' '); |
| 53 | }; | |
| 54 | ||
| 55 | /** | |
| 56 | * Humanize the `key`. | |
| 57 | * | |
| 58 | * AssignmentExpression -> Assignment Expressions | |
| 59 | * | |
| 60 | * @returns {String} | |
| 61 | * @api private | |
| 62 | */ | |
| 63 | ||
| 64 | 1 | Formatter.prototype.name = function(key) { |
| 65 | 1 | return key.split(/(?=[A-Z])/).join(' ') + 's'; |
| 66 | }; | |
| 67 | ||
| 68 | /** | |
| 69 | * Primary exports. | |
| 70 | */ | |
| 71 | ||
| 72 | 1 | module.exports = Formatter; |
| 73 |
| Line | Hits | Source |
|---|---|---|
| 1 | /** | |
| 2 | * Core dependencies. | |
| 3 | */ | |
| 4 | ||
| 5 | 1 | var inherits = require('util').inherits; |
| 6 | ||
| 7 | /** | |
| 8 | * Internal dependencies. | |
| 9 | */ | |
| 10 | ||
| 11 | 1 | var Formattter = require('../formatter'); |
| 12 | ||
| 13 | /** | |
| 14 | * JSON formatter. | |
| 15 | * | |
| 16 | * @constructor | |
| 17 | */ | |
| 18 | ||
| 19 | function Json() { | |
| 20 | 1 | Formattter.apply(this, arguments); |
| 21 | } | |
| 22 | ||
| 23 | /** | |
| 24 | * Inherit from `Formattter`. | |
| 25 | */ | |
| 26 | ||
| 27 | 1 | inherits(Json, Formattter); |
| 28 | ||
| 29 | /** | |
| 30 | * Print the result. | |
| 31 | * | |
| 32 | * @api public | |
| 33 | */ | |
| 34 | ||
| 35 | 1 | Json.prototype.run = function() { |
| 36 | 1 | this.print(JSON.stringify(this.data, null, 2)); |
| 37 | }; | |
| 38 | ||
| 39 | /** | |
| 40 | * Primary exports. | |
| 41 | */ | |
| 42 | ||
| 43 | 1 | module.exports = Json; |
| 44 |
| Line | Hits | Source |
|---|---|---|
| 1 | /** | |
| 2 | * Core dependencies. | |
| 3 | */ | |
| 4 | ||
| 5 | 1 | var inherits = require('util').inherits; |
| 6 | ||
| 7 | /** | |
| 8 | * Internal dependencies. | |
| 9 | */ | |
| 10 | ||
| 11 | 1 | var Formattter = require('../formatter'); |
| 12 | ||
| 13 | /** | |
| 14 | * Summary formatter. | |
| 15 | * | |
| 16 | * @constructor | |
| 17 | */ | |
| 18 | ||
| 19 | function Summary() { | |
| 20 | 1 | Formattter.apply(this, arguments); |
| 21 | } | |
| 22 | ||
| 23 | /** | |
| 24 | * Inherit from `Formattter`. | |
| 25 | */ | |
| 26 | ||
| 27 | 1 | inherits(Summary, Formattter); |
| 28 | ||
| 29 | /** | |
| 30 | * Print the result. | |
| 31 | * | |
| 32 | * @api public | |
| 33 | */ | |
| 34 | ||
| 35 | 1 | Summary.prototype.run = function() { |
| 36 | 1 | var files = this.data.files; |
| 37 | 1 | var longest = 4; |
| 38 | 1 | var out = []; |
| 39 | ||
| 40 | 1 | files.forEach(function(file, i) { |
| 41 | 2 | var arr = []; |
| 42 | 2 | arr[0] = file.filename; |
| 43 | 2 | longest = Math.max(longest, file.filename.length); |
| 44 | 2 | arr[1] = 0; |
| 45 | 2 | Object.keys(file.result).forEach(function(key) { |
| 46 | 4 | arr[1] += file.result[key].count; |
| 47 | }); | |
| 48 | 2 | out.push(arr); |
| 49 | }, this); | |
| 50 | ||
| 51 | 1 | this.print(); |
| 52 | ||
| 53 | 1 | this.iprint(this.ljust('File', longest) + ' Sum of all metrics'); |
| 54 | ||
| 55 | 1 | out.sort(function(a, b) { |
| 56 | 1 | if (a[1] < b[1]) return 1; |
| 57 | 1 | if (a[1] > b[1]) return -1; |
| 58 | 1 | return 0; |
| 59 | }).forEach(function(line) { | |
| 60 | 2 | this.iprint(this.ljust(line[0], longest) + ' ' + line[1]); |
| 61 | }, this); | |
| 62 | ||
| 63 | 1 | this.print(); |
| 64 | }; | |
| 65 | ||
| 66 | /** | |
| 67 | * Primary exports. | |
| 68 | */ | |
| 69 | ||
| 70 | 1 | module.exports = Summary; |
| 71 |
| Line | Hits | Source |
|---|---|---|
| 1 | /** | |
| 2 | * Core dependencies. | |
| 3 | */ | |
| 4 | ||
| 5 | 1 | var inherits = require('util').inherits; |
| 6 | ||
| 7 | /** | |
| 8 | * Internal dependencies. | |
| 9 | */ | |
| 10 | ||
| 11 | 1 | var Formattter = require('../formatter'); |
| 12 | 1 | var countable = require('../countable'); |
| 13 | ||
| 14 | /** | |
| 15 | * Total formatter. | |
| 16 | * | |
| 17 | * @constructor | |
| 18 | */ | |
| 19 | ||
| 20 | function Total() { | |
| 21 | 1 | Formattter.apply(this, arguments); |
| 22 | } | |
| 23 | ||
| 24 | /** | |
| 25 | * Inherit from `Formattter`. | |
| 26 | */ | |
| 27 | ||
| 28 | 1 | inherits(Total, Formattter); |
| 29 | ||
| 30 | /** | |
| 31 | * Print the result. | |
| 32 | * | |
| 33 | * @api public | |
| 34 | */ | |
| 35 | ||
| 36 | 1 | Total.prototype.run = function() { |
| 37 | 1 | var metrics = this.data.total.result; |
| 38 | 1 | var lens = {}; |
| 39 | 1 | var group; |
| 40 | ||
| 41 | 1 | var out = [ |
| 42 | [ 'Metric', 'Total', 'Average/file' ], | |
| 43 | [ '------', '-----', '------------' ] | |
| 44 | ]; | |
| 45 | ||
| 46 | 1 | lens.name = out[0][0].length; |
| 47 | 1 | lens.count = out[0][1].length; |
| 48 | ||
| 49 | 1 | Object.keys(metrics).forEach(function(key) { |
| 50 | 1 | var name = this.name(key); |
| 51 | 1 | lens.name = Math.max(lens.name, name.length); |
| 52 | 1 | lens.count = Math.max(lens.count, ('' + metrics[key].count).length); |
| 53 | 1 | out.push([ name, metrics[key].count, metrics[key].average, key ]); |
| 54 | }, this); | |
| 55 | ||
| 56 | 1 | this.print(); |
| 57 | ||
| 58 | 1 | for (var i = 0, len = out.length; i < len; i++) { |
| 59 | 3 | var key = out[i][3]; |
| 60 | 3 | if (typeof group !== 'undefined' && group != countable[key]) this.print(); |
| 61 | 3 | group = countable[key]; |
| 62 | ||
| 63 | 3 | this.iprint([ |
| 64 | this.ljust(out[i][0], lens.name), | |
| 65 | this.ljust(out[i][1], lens.count), | |
| 66 | out[i][2] | |
| 67 | ].join(' ')); | |
| 68 | } | |
| 69 | ||
| 70 | 1 | this.iprint('----------------------'); |
| 71 | 1 | this.iprint('Files: ' + this.data.total.files); |
| 72 | 1 | this.print(); |
| 73 | }; | |
| 74 | ||
| 75 | /** | |
| 76 | * Primary export. | |
| 77 | */ | |
| 78 | ||
| 79 | 1 | module.exports = Total; |
| 80 |
| Line | Hits | Source |
|---|---|---|
| 1 | /** | |
| 2 | * Core dependencies. | |
| 3 | */ | |
| 4 | ||
| 5 | 1 | var fs = require('fs'); |
| 6 | ||
| 7 | /** | |
| 8 | * External dependencies. | |
| 9 | */ | |
| 10 | ||
| 11 | 1 | var parse = require('esprima').parse; |
| 12 | ||
| 13 | /** | |
| 14 | * Group of files. | |
| 15 | * | |
| 16 | * @param {Array} files | |
| 17 | * @constructor | |
| 18 | */ | |
| 19 | ||
| 20 | function Group(files) { | |
| 21 | 5 | this.files = files; |
| 22 | } | |
| 23 | ||
| 24 | /** | |
| 25 | * Parse and execute `fn` for every file. | |
| 26 | * | |
| 27 | * @param {Function} fn | |
| 28 | * @param {Object} context | |
| 29 | * @api public | |
| 30 | */ | |
| 31 | ||
| 32 | 1 | Group.prototype.each = function(fn, ctx) { |
| 33 | 5 | this.files.forEach(function(file) { |
| 34 | 6 | var data = fs.readFileSync(file, 'utf8'); |
| 35 | 6 | var ast = null; |
| 36 | ||
| 37 | 6 | try { |
| 38 | 6 | ast = parse(data, { tokens: true, comment: true }); |
| 39 | } catch (e) {} | |
| 40 | ||
| 41 | 12 | if (ast) fn.call(ctx, ast, file, data); |
| 42 | }); | |
| 43 | }; | |
| 44 | ||
| 45 | /** | |
| 46 | * Primary export. | |
| 47 | */ | |
| 48 | ||
| 49 | 1 | module.exports = Group; |
| 50 |
| Line | Hits | Source |
|---|---|---|
| 1 | /** | |
| 2 | * Core dependencies. | |
| 3 | */ | |
| 4 | ||
| 5 | 1 | var basename = require('path').basename; |
| 6 | ||
| 7 | /** | |
| 8 | * Internal dependencies. | |
| 9 | */ | |
| 10 | ||
| 11 | 1 | var countable = require('./countable'); |
| 12 | ||
| 13 | /** | |
| 14 | * Researcher. | |
| 15 | * | |
| 16 | * @param {Stats} stats | |
| 17 | * @constructor | |
| 18 | */ | |
| 19 | ||
| 20 | function Researcher(stats) { | |
| 21 | 6 | this.stats = stats; |
| 22 | ||
| 23 | 6 | Object.keys(countable).forEach(function(key) { |
| 24 | 186 | this.inc(key, 0); |
| 25 | }, this); | |
| 26 | } | |
| 27 | ||
| 28 | /** | |
| 29 | * Analyze nodes and tokens. | |
| 30 | * | |
| 31 | * @param {Object} node or token | |
| 32 | * @api public | |
| 33 | */ | |
| 34 | ||
| 35 | 1 | Researcher.prototype.node = function(node) { |
| 36 | 65 | switch (node.type) { |
| 37 | case 'AssignmentExpression': | |
| 38 | case 'ArrayExpression': | |
| 39 | case 'ConditionalExpression': | |
| 40 | case 'DoWhileStatement': | |
| 41 | case 'ForStatement': | |
| 42 | case 'ForInStatement': | |
| 43 | case 'FunctionDeclaration': | |
| 44 | case 'FunctionExpression': | |
| 45 | case 'IfStatement': | |
| 46 | case 'ObjectExpression': | |
| 47 | case 'SwitchStatement': | |
| 48 | case 'ReturnStatement': | |
| 49 | case 'ThrowStatement': | |
| 50 | case 'TryStatement': | |
| 51 | case 'VariableDeclarator': | |
| 52 | case 'WhileStatement': | |
| 53 | case 'LabelStatement': | |
| 54 | case 'BreakStatement': | |
| 55 | case 'ContinueStatement': | |
| 56 | case 'EmptyStatement': | |
| 57 | case 'Boolean': | |
| 58 | case 'Identifier': | |
| 59 | case 'Null': | |
| 60 | case 'Numeric': | |
| 61 | case 'RegularExpression': | |
| 62 | case 'String': | |
| 63 | 23 | return this.inc(node); |
| 64 | ||
| 65 | case 'Line': | |
| 66 | case 'Block': | |
| 67 | 3 | return this.inc('Comment'); |
| 68 | ||
| 69 | case 'CallExpression': | |
| 70 | 3 | return this.fncall(node); |
| 71 | ||
| 72 | case 'Punctuator': | |
| 73 | 17 | return this.punctuator(node); |
| 74 | } | |
| 75 | }; | |
| 76 | ||
| 77 | /** | |
| 78 | * Analyze a file. | |
| 79 | * | |
| 80 | * @param {String} filename | |
| 81 | * @param {String} file contents | |
| 82 | * @api public | |
| 83 | */ | |
| 84 | ||
| 85 | 1 | Researcher.prototype.file = function(filename, data) { |
| 86 | 6 | this.inc('FileLine', linesLen(data)); |
| 87 | }; | |
| 88 | ||
| 89 | /** | |
| 90 | * Increment a counter. | |
| 91 | * | |
| 92 | * @param {String|Object} type / node | |
| 93 | * @api private | |
| 94 | */ | |
| 95 | ||
| 96 | 1 | Researcher.prototype.inc = function(node, inc) { |
| 97 | 232 | this.stats.inc(Object(node) === node ? node.type : node, inc); |
| 98 | }; | |
| 99 | ||
| 100 | /** | |
| 101 | * Handle semicolons. | |
| 102 | * | |
| 103 | * @param {Object} token | |
| 104 | * @api private | |
| 105 | */ | |
| 106 | ||
| 107 | 1 | Researcher.prototype.punctuator = function(token) { |
| 108 | 26 | if (token.value !== ';') return; |
| 109 | 8 | this.inc('Semicolon'); |
| 110 | }; | |
| 111 | ||
| 112 | /** | |
| 113 | * Handle function calls and count requires. | |
| 114 | * | |
| 115 | * This assumes quite a bit. For instance it simply thinks | |
| 116 | * that any `require` call is the Node `require`. While | |
| 117 | * this might not be true, a proper detection would be a little | |
| 118 | * bit too much for the purposes of this library. | |
| 119 | * | |
| 120 | * @param {Object} node | |
| 121 | * @api private | |
| 122 | */ | |
| 123 | ||
| 124 | 1 | Researcher.prototype.fncall = function(node) { |
| 125 | 3 | var callee = node.callee; |
| 126 | ||
| 127 | 3 | if (callee.type === 'Identifier' && callee.name === 'require') { |
| 128 | 3 | this.inc('RequireCall'); |
| 129 | } | |
| 130 | ||
| 131 | 3 | this.inc(node.type); |
| 132 | }; | |
| 133 | ||
| 134 | /** | |
| 135 | * Split `str` into lines and return its size. | |
| 136 | * | |
| 137 | * @param {String} str | |
| 138 | * @returns {Number} | |
| 139 | * @api private | |
| 140 | */ | |
| 141 | ||
| 142 | function linesLen(str) { | |
| 143 | 6 | return str.split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/).length - 1; |
| 144 | } | |
| 145 | ||
| 146 | /** | |
| 147 | * Primary export. | |
| 148 | */ | |
| 149 | ||
| 150 | 1 | module.exports = Researcher; |
| 151 |
| Line | Hits | Source |
|---|---|---|
| 1 | /** | |
| 2 | * Internal dependencies. | |
| 3 | */ | |
| 4 | ||
| 5 | 1 | var Group = require('./group'); |
| 6 | 1 | var Stats = require('./stats'); |
| 7 | 1 | var Researcher = require('./researcher'); |
| 8 | ||
| 9 | /** | |
| 10 | * Runner. | |
| 11 | * | |
| 12 | * @param {Array} files | |
| 13 | * @constructor | |
| 14 | */ | |
| 15 | ||
| 16 | function Runner(files) { | |
| 17 | 5 | this.files = files; |
| 18 | } | |
| 19 | ||
| 20 | /** | |
| 21 | * Iterate over all files and collect | |
| 22 | * the needed statistics | |
| 23 | * | |
| 24 | * @api public | |
| 25 | */ | |
| 26 | ||
| 27 | 1 | Runner.prototype.run = function() { |
| 28 | 5 | var group = new Group(this.files); |
| 29 | 5 | var results = []; |
| 30 | ||
| 31 | 5 | group.each(function(ast, file, data) { |
| 32 | 6 | var stats = new Stats(file); |
| 33 | 6 | var researcher = new Researcher(stats); |
| 34 | 6 | researcher.file(file, data); |
| 35 | ||
| 36 | 6 | (function walk(node) { |
| 37 | 89 | var key = null; |
| 38 | 89 | var child = null; |
| 39 | ||
| 40 | 154 | if (node.type) researcher.node(node); |
| 41 | ||
| 42 | 89 | Object.keys(node).forEach(function(key) { |
| 43 | 196 | child = node[key]; |
| 44 | 279 | if (Object(child) === child) walk(child); |
| 45 | }); | |
| 46 | })(ast); | |
| 47 | ||
| 48 | 6 | results.push(stats); |
| 49 | }); | |
| 50 | ||
| 51 | 5 | return results; |
| 52 | }; | |
| 53 | ||
| 54 | /** | |
| 55 | * Primary export. | |
| 56 | */ | |
| 57 | ||
| 58 | 1 | module.exports = Runner; |
| 59 |
| Line | Hits | Source |
|---|---|---|
| 1 | /** | |
| 2 | * Stats. | |
| 3 | * | |
| 4 | * @param {String} file | |
| 5 | * @constructor | |
| 6 | */ | |
| 7 | ||
| 8 | function Stats(file) { | |
| 9 | 6 | this.file = file; |
| 10 | 6 | this.counters = {}; |
| 11 | 6 | this.keys = []; |
| 12 | } | |
| 13 | ||
| 14 | /** | |
| 15 | * Increment a counter. | |
| 16 | * | |
| 17 | * @param {String} type | |
| 18 | * @param {Number} | |
| 19 | * @api public | |
| 20 | */ | |
| 21 | ||
| 22 | 1 | Stats.prototype.inc = function(type, inc) { |
| 23 | 232 | inc = typeof inc === 'undefined' ? 1 : inc; |
| 24 | 232 | this.counters[type] = this.counters[type] || 0; |
| 25 | 232 | this.counters[type] += inc; |
| 26 | 232 | this.key(type); |
| 27 | }; | |
| 28 | ||
| 29 | /** | |
| 30 | * Return the stored data. | |
| 31 | * | |
| 32 | * @returns {Object} | |
| 33 | * @api public | |
| 34 | */ | |
| 35 | ||
| 36 | 1 | Stats.prototype.result = function() { |
| 37 | 6 | var ret = {}; |
| 38 | ||
| 39 | 6 | this.keys.forEach(function(key) { |
| 40 | 186 | ret[key] = { count: this.counter(key) }; |
| 41 | }, this); | |
| 42 | ||
| 43 | 6 | return ret; |
| 44 | }; | |
| 45 | ||
| 46 | /** | |
| 47 | * Register a new key. | |
| 48 | * | |
| 49 | * @param {String} key | |
| 50 | * @api private | |
| 51 | */ | |
| 52 | ||
| 53 | 1 | Stats.prototype.key = function(key) { |
| 54 | 278 | if (~this.keys.indexOf(key)) return; |
| 55 | 186 | this.keys.push(key); |
| 56 | }; | |
| 57 | ||
| 58 | /** | |
| 59 | * Return counter for `type`. | |
| 60 | * | |
| 61 | * @param {String} type | |
| 62 | * @returns {Number} | |
| 63 | * @api private | |
| 64 | */ | |
| 65 | ||
| 66 | 1 | Stats.prototype.counter = function(type) { |
| 67 | 186 | return this.counters[type] || 0; |
| 68 | }; | |
| 69 | ||
| 70 | /** | |
| 71 | * Primary export. | |
| 72 | */ | |
| 73 | ||
| 74 | 1 | module.exports = Stats; |
| 75 |