2 Copyright (c) 2012, Yahoo! Inc. All rights reserved.
3 Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
6 var path = require('path'),
8 utils = require('../object-utils');
10 function commonArrayPrefix(first, second) {
11 var len = first.length < second.length ? first.length : second.length,
14 for (i = 0; i < len; i += 1) {
15 if (first[i] === second[i]) {
24 function findCommonArrayPrefix(args) {
25 if (args.length === 0) {
29 var separated = args.map(function (arg) { return arg.split(SEP); }),
30 ret = separated.pop();
32 if (separated.length === 0) {
33 return ret.slice(0, ret.length - 1);
35 return separated.reduce(commonArrayPrefix, ret);
39 function Node(fullName, kind, metrics) {
41 this.fullName = fullName;
43 this.metrics = metrics || null;
49 displayShortName: function () {
50 return this.relativeName;
52 fullPath: function () {
55 addChild: function (child) {
56 this.children.push(child);
62 relativeName: this.relativeName,
63 fullName: this.fullName,
65 metrics: this.metrics,
66 parent: this.parent === null ? null : this.parent.name,
67 children: this.children.map(function (node) { return node.toJSON(); })
72 function TreeSummary(summaryMap, commonPrefix) {
73 this.prefix = commonPrefix;
74 this.convertToTree(summaryMap, commonPrefix);
77 TreeSummary.prototype = {
78 getNode: function (shortName) {
79 return this.map[shortName];
81 convertToTree: function (summaryMap, arrayPrefix) {
83 rootPath = arrayPrefix.join(SEP) + SEP,
84 root = new Node(rootPath, 'dir'),
88 filesUnderRoot = false;
90 seen[rootPath] = root;
91 Object.keys(summaryMap).forEach(function (key) {
92 var metrics = summaryMap[key],
96 node = new Node(key, 'file', metrics);
99 parentPath = path.dirname(key) + SEP;
100 if (parentPath === SEP + SEP || parentPath === '.' + SEP) {
101 parentPath = SEP + '__root__' + SEP;
103 parent = seen[parentPath];
105 parent = new Node(parentPath, 'dir');
106 root.addChild(parent);
107 seen[parentPath] = parent;
109 parent.addChild(node);
110 if (parent === root) { filesUnderRoot = true; }
113 if (filesUnderRoot && arrayPrefix.length > 0) {
114 arrayPrefix.pop(); //start at one level above
116 tmpChildren = tmp.children;
118 root = new Node(arrayPrefix.join(SEP) + SEP, 'dir');
120 tmpChildren.forEach(function (child) {
121 if (child.kind === 'dir') {
122 root.addChild(child);
128 this.fixupNodes(root, arrayPrefix.join(SEP) + SEP);
129 this.calculateMetrics(root);
132 this.indexAndSortTree(root, this.map);
135 fixupNodes: function (node, prefix, parent) {
137 if (node.name.indexOf(prefix) === 0) {
138 node.name = node.name.substring(prefix.length);
140 if (node.name.charAt(0) === SEP) {
141 node.name = node.name.substring(1);
144 if (parent.name !== '__root__' + SEP) {
145 node.relativeName = node.name.substring(parent.name.length);
147 node.relativeName = node.name;
150 node.relativeName = node.name.substring(prefix.length);
152 node.children.forEach(function (child) {
153 that.fixupNodes(child, prefix, node);
156 calculateMetrics: function (entry) {
159 if (entry.kind !== 'dir') {return; }
160 entry.children.forEach(function (child) {
161 that.calculateMetrics(child);
163 entry.metrics = utils.mergeSummaryObjects.apply(
165 entry.children.map(function (child) { return child.metrics; })
167 // calclulate "java-style" package metrics where there is no hierarchy
169 fileChildren = entry.children.filter(function (n) { return n.kind !== 'dir'; });
170 if (fileChildren.length > 0) {
171 entry.packageMetrics = utils.mergeSummaryObjects.apply(
173 fileChildren.map(function (child) { return child.metrics; })
176 entry.packageMetrics = null;
179 indexAndSortTree: function (node, map) {
181 map[node.name] = node;
182 node.children.sort(function (a, b) {
185 return a < b ? -1 : a > b ? 1 : 0;
187 node.children.forEach(function (child) {
188 that.indexAndSortTree(child, map);
191 toJSON: function () {
194 root: this.root.toJSON()
199 function TreeSummarizer() {
200 this.summaryMap = {};
203 TreeSummarizer.prototype = {
204 addFileCoverageSummary: function (filePath, metrics) {
205 this.summaryMap[filePath] = metrics;
207 getTreeSummary: function () {
208 var commonArrayPrefix = findCommonArrayPrefix(Object.keys(this.summaryMap));
209 return new TreeSummary(this.summaryMap, commonArrayPrefix);
213 module.exports = TreeSummarizer;