react / wstein / node_modules / jest-cli / node_modules / istanbul / lib / util / tree-summarizer.js
80680 views/*1Copyright (c) 2012, Yahoo! Inc. All rights reserved.2Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.3*/45var path = require('path'),6SEP = path.sep || '/',7utils = require('../object-utils');89function commonArrayPrefix(first, second) {10var len = first.length < second.length ? first.length : second.length,11i,12ret = [];13for (i = 0; i < len; i += 1) {14if (first[i] === second[i]) {15ret.push(first[i]);16} else {17break;18}19}20return ret;21}2223function findCommonArrayPrefix(args) {24if (args.length === 0) {25return [];26}2728var separated = args.map(function (arg) { return arg.split(SEP); }),29ret = separated.pop();3031if (separated.length === 0) {32return ret.slice(0, ret.length - 1);33} else {34return separated.reduce(commonArrayPrefix, ret);35}36}3738function Node(fullName, kind, metrics) {39this.name = fullName;40this.fullName = fullName;41this.kind = kind;42this.metrics = metrics || null;43this.parent = null;44this.children = [];45}4647Node.prototype = {48displayShortName: function () {49return this.relativeName;50},51fullPath: function () {52return this.fullName;53},54addChild: function (child) {55this.children.push(child);56child.parent = this;57},58toJSON: function () {59return {60name: this.name,61relativeName: this.relativeName,62fullName: this.fullName,63kind: this.kind,64metrics: this.metrics,65parent: this.parent === null ? null : this.parent.name,66children: this.children.map(function (node) { return node.toJSON(); })67};68}69};7071function TreeSummary(summaryMap, commonPrefix) {72this.prefix = commonPrefix;73this.convertToTree(summaryMap, commonPrefix);74}7576TreeSummary.prototype = {77getNode: function (shortName) {78return this.map[shortName];79},80convertToTree: function (summaryMap, arrayPrefix) {81var nodes = [],82rootPath = arrayPrefix.join(SEP) + SEP,83root = new Node(rootPath, 'dir'),84tmp,85tmpChildren,86seen = {},87filesUnderRoot = false;8889seen[rootPath] = root;90Object.keys(summaryMap).forEach(function (key) {91var metrics = summaryMap[key],92node,93parentPath,94parent;95node = new Node(key, 'file', metrics);96seen[key] = node;97nodes.push(node);98parentPath = path.dirname(key) + SEP;99if (parentPath === SEP + SEP) {100parentPath = SEP + '__root__' + SEP;101}102parent = seen[parentPath];103if (!parent) {104parent = new Node(parentPath, 'dir');105root.addChild(parent);106seen[parentPath] = parent;107}108parent.addChild(node);109if (parent === root) { filesUnderRoot = true; }110});111112if (filesUnderRoot && arrayPrefix.length > 0) {113arrayPrefix.pop(); //start at one level above114tmp = root;115tmpChildren = tmp.children;116tmp.children = [];117root = new Node(arrayPrefix.join(SEP) + SEP, 'dir');118root.addChild(tmp);119tmpChildren.forEach(function (child) {120if (child.kind === 'dir') {121root.addChild(child);122} else {123tmp.addChild(child);124}125});126}127this.fixupNodes(root, arrayPrefix.join(SEP) + SEP);128this.calculateMetrics(root);129this.root = root;130this.map = {};131this.indexAndSortTree(root, this.map);132},133134fixupNodes: function (node, prefix, parent) {135var that = this;136if (node.name.indexOf(prefix) === 0) {137node.name = node.name.substring(prefix.length);138}139if (node.name.charAt(0) === SEP) {140node.name = node.name.substring(1);141}142if (parent) {143if (parent.name !== '__root__' + SEP) {144node.relativeName = node.name.substring(parent.name.length);145} else {146node.relativeName = node.name;147}148} else {149node.relativeName = node.name.substring(prefix.length);150}151node.children.forEach(function (child) {152that.fixupNodes(child, prefix, node);153});154},155calculateMetrics: function (entry) {156var that = this,157fileChildren;158if (entry.kind !== 'dir') {return; }159entry.children.forEach(function (child) {160that.calculateMetrics(child);161});162entry.metrics = utils.mergeSummaryObjects.apply(163null,164entry.children.map(function (child) { return child.metrics; })165);166// calclulate "java-style" package metrics where there is no hierarchy167// across packages168fileChildren = entry.children.filter(function (n) { return n.kind !== 'dir'; });169if (fileChildren.length > 0) {170entry.packageMetrics = utils.mergeSummaryObjects.apply(171null,172fileChildren.map(function (child) { return child.metrics; })173);174} else {175entry.packageMetrics = null;176}177},178indexAndSortTree: function (node, map) {179var that = this;180map[node.name] = node;181node.children.sort(function (a, b) {182a = a.relativeName;183b = b.relativeName;184return a < b ? -1 : a > b ? 1 : 0;185});186node.children.forEach(function (child) {187that.indexAndSortTree(child, map);188});189},190toJSON: function () {191return {192prefix: this.prefix,193root: this.root.toJSON()194};195}196};197198function TreeSummarizer() {199this.summaryMap = {};200}201202TreeSummarizer.prototype = {203addFileCoverageSummary: function (filePath, metrics) {204this.summaryMap[filePath] = metrics;205},206getTreeSummary: function () {207var commonArrayPrefix = findCommonArrayPrefix(Object.keys(this.summaryMap));208return new TreeSummary(this.summaryMap, commonArrayPrefix);209}210};211212module.exports = TreeSummarizer;213214215