9df7344cd1732eea3740cbd52feb6bf7c67dd51a.svn-base
4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
'use strict';
const 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(k => {
const 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(v => {
if (v instanceof Visitor) {
return v;
}
return new Visitor(v);
});
}
util.inherits(CompositeVisitor, Visitor);
['Start', 'Summary', 'SummaryEnd', 'Detail', 'End'].forEach(k => {
const f = 'on' + k;
CompositeVisitor.prototype[f] = function(node, state) {
this.visitors.forEach(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) {
if (this.isSummary()) {
visitor.onSummary(this, state);
} else {
visitor.onDetail(this, state);
}
this.getChildren().forEach(child => {
child.visit(visitor, state);
});
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,
Node,
Visitor,
CompositeVisitor
};