diff options
Diffstat (limited to 'node_modules/istanbul-lib-report/lib/tree.js')
-rw-r--r-- | node_modules/istanbul-lib-report/lib/tree.js | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/node_modules/istanbul-lib-report/lib/tree.js b/node_modules/istanbul-lib-report/lib/tree.js new file mode 100644 index 000000000..190808d18 --- /dev/null +++ b/node_modules/istanbul-lib-report/lib/tree.js @@ -0,0 +1,167 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +"use strict"; + +var util = require('util'); +/** + * An object with methods that are called during the traversal of the coverage tree. + * A visitor has the following methods that are called during tree traversal. + * + * * `onStart(root, state)` - called before traversal begins + * * `onSummary(node, state)` - called for every summary node + * * `onDetail(node, state)` - called for every detail node + * * `onSummaryEnd(node, state)` - called after all children have been visited for + * a summary node. + * * `onEnd(root, state)` - called after traversal ends + * + * @param delegate - a partial visitor that only implements the methods of interest + * The visitor object supplies the missing methods as noops. For example, reports + * that only need the final coverage summary need implement `onStart` and nothing + * else. Reports that use only detailed coverage information need implement `onDetail` + * and nothing else. + * @constructor + */ +function Visitor(delegate) { + this.delegate = delegate; +} + +['Start', 'End', 'Summary', 'SummaryEnd', 'Detail' ].forEach(function (k) { + var f = 'on' + k; + Visitor.prototype[f] = function (node, state) { + if (this.delegate[f] && typeof this.delegate[f] === 'function') { + this.delegate[f].call(this.delegate, node, state); + } + }; +}); + +function CompositeVisitor(visitors) { + if (!Array.isArray(visitors)) { + visitors = [visitors]; + } + this.visitors = visitors.map(function (v) { + if (v instanceof Visitor) { + return v; + } + return new Visitor(v); + }); +} + +util.inherits(CompositeVisitor, Visitor); + +['Start', 'Summary', 'SummaryEnd', 'Detail', 'End'].forEach(function (k) { + var f = 'on' + k; + CompositeVisitor.prototype[f] = function (node, state) { + this.visitors.forEach(function (v) { + v[f](node, state); + }); + }; +}); + +function Node() { +} + +/* istanbul ignore next: abstract method */ +Node.prototype.getQualifiedName = function () { + throw new Error('getQualifiedName must be overridden'); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.getRelativeName = function () { + throw new Error('getRelativeName must be overridden'); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.isRoot = function () { + return !this.getParent(); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.getParent = function () { + throw new Error('getParent must be overridden'); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.getChildren = function () { + throw new Error('getChildren must be overridden'); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.isSummary = function () { + throw new Error('isSummary must be overridden'); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.getCoverageSummary = function (/* filesOnly */) { + throw new Error('getCoverageSummary must be overridden'); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.getFileCoverage = function () { + throw new Error('getFileCoverage must be overridden'); +}; +/** + * visit all nodes depth-first from this node down. Note that `onStart` + * and `onEnd` are never called on the visitor even if the current + * node is the root of the tree. + * @param visitor a full visitor that is called during tree traversal + * @param state optional state that is passed around + */ +Node.prototype.visit = function (visitor, state) { + + var that = this, + visitChildren = function () { + that.getChildren().forEach(function (child) { + child.visit(visitor, state); + }); + }; + + if (this.isSummary()) { + visitor.onSummary(this, state); + } else { + visitor.onDetail(this, state); + } + + visitChildren(); + + if (this.isSummary()) { + visitor.onSummaryEnd(this, state); + } +}; + +/** + * abstract base class for a coverage tree. + * @constructor + */ +function Tree() { +} + +/** + * returns the root node of the tree + */ +/* istanbul ignore next: abstract method */ +Tree.prototype.getRoot = function () { + throw new Error('getRoot must be overridden'); +}; + +/** + * visits the tree depth-first with the supplied partial visitor + * @param visitor - a potentially partial visitor + * @param state - the state to be passed around during tree traversal + */ +Tree.prototype.visit = function (visitor, state) { + if (!(visitor instanceof Visitor)) { + visitor = new Visitor(visitor); + } + visitor.onStart(this.getRoot(), state); + this.getRoot().visit(visitor, state); + visitor.onEnd(this.getRoot(), state); +}; + +module.exports = { + Tree: Tree, + Node: Node, + Visitor: Visitor, + CompositeVisitor: CompositeVisitor +}; |