tree.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. Copyright 2012-2015, Yahoo Inc.
  3. Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
  4. */
  5. 'use strict';
  6. /**
  7. * An object with methods that are called during the traversal of the coverage tree.
  8. * A visitor has the following methods that are called during tree traversal.
  9. *
  10. * * `onStart(root, state)` - called before traversal begins
  11. * * `onSummary(node, state)` - called for every summary node
  12. * * `onDetail(node, state)` - called for every detail node
  13. * * `onSummaryEnd(node, state)` - called after all children have been visited for
  14. * a summary node.
  15. * * `onEnd(root, state)` - called after traversal ends
  16. *
  17. * @param delegate - a partial visitor that only implements the methods of interest
  18. * The visitor object supplies the missing methods as noops. For example, reports
  19. * that only need the final coverage summary need implement `onStart` and nothing
  20. * else. Reports that use only detailed coverage information need implement `onDetail`
  21. * and nothing else.
  22. * @constructor
  23. */
  24. class Visitor {
  25. constructor(delegate) {
  26. this.delegate = delegate;
  27. }
  28. }
  29. ['Start', 'End', 'Summary', 'SummaryEnd', 'Detail']
  30. .map(k => `on${k}`)
  31. .forEach(fn => {
  32. Object.defineProperty(Visitor.prototype, fn, {
  33. writable: true,
  34. value(node, state) {
  35. if (typeof this.delegate[fn] === 'function') {
  36. this.delegate[fn](node, state);
  37. }
  38. }
  39. });
  40. });
  41. class CompositeVisitor extends Visitor {
  42. constructor(visitors) {
  43. super();
  44. if (!Array.isArray(visitors)) {
  45. visitors = [visitors];
  46. }
  47. this.visitors = visitors.map(v => {
  48. if (v instanceof Visitor) {
  49. return v;
  50. }
  51. return new Visitor(v);
  52. });
  53. }
  54. }
  55. ['Start', 'Summary', 'SummaryEnd', 'Detail', 'End']
  56. .map(k => `on${k}`)
  57. .forEach(fn => {
  58. Object.defineProperty(CompositeVisitor.prototype, fn, {
  59. value(node, state) {
  60. this.visitors.forEach(v => {
  61. v[fn](node, state);
  62. });
  63. }
  64. });
  65. });
  66. class BaseNode {
  67. isRoot() {
  68. return !this.getParent();
  69. }
  70. /**
  71. * visit all nodes depth-first from this node down. Note that `onStart`
  72. * and `onEnd` are never called on the visitor even if the current
  73. * node is the root of the tree.
  74. * @param visitor a full visitor that is called during tree traversal
  75. * @param state optional state that is passed around
  76. */
  77. visit(visitor, state) {
  78. if (this.isSummary()) {
  79. visitor.onSummary(this, state);
  80. } else {
  81. visitor.onDetail(this, state);
  82. }
  83. this.getChildren().forEach(child => {
  84. child.visit(visitor, state);
  85. });
  86. if (this.isSummary()) {
  87. visitor.onSummaryEnd(this, state);
  88. }
  89. }
  90. }
  91. /**
  92. * abstract base class for a coverage tree.
  93. * @constructor
  94. */
  95. class BaseTree {
  96. constructor(root) {
  97. this.root = root;
  98. }
  99. /**
  100. * returns the root node of the tree
  101. */
  102. getRoot() {
  103. return this.root;
  104. }
  105. /**
  106. * visits the tree depth-first with the supplied partial visitor
  107. * @param visitor - a potentially partial visitor
  108. * @param state - the state to be passed around during tree traversal
  109. */
  110. visit(visitor, state) {
  111. if (!(visitor instanceof Visitor)) {
  112. visitor = new Visitor(visitor);
  113. }
  114. visitor.onStart(this.getRoot(), state);
  115. this.getRoot().visit(visitor, state);
  116. visitor.onEnd(this.getRoot(), state);
  117. }
  118. }
  119. module.exports = {
  120. BaseTree,
  121. BaseNode,
  122. Visitor,
  123. CompositeVisitor
  124. };