parentAutogroupNode.tsx 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import {isSpanNode} from '../traceGuards';
  2. import type {TraceTree} from './traceTree';
  3. import {TraceTreeNode} from './traceTreeNode';
  4. export class ParentAutogroupNode extends TraceTreeNode<TraceTree.ChildrenAutogroup> {
  5. head: TraceTreeNode<TraceTree.Span>;
  6. tail: TraceTreeNode<TraceTree.Span>;
  7. groupCount: number = 0;
  8. profiles: TraceTree.Profile[] = [];
  9. private _autogroupedSegments: [number, number][] | undefined;
  10. constructor(
  11. parent: TraceTreeNode<TraceTree.NodeValue> | null,
  12. node: TraceTree.ChildrenAutogroup,
  13. metadata: TraceTree.Metadata,
  14. head: TraceTreeNode<TraceTree.Span>,
  15. tail: TraceTreeNode<TraceTree.Span>
  16. ) {
  17. super(parent, node, metadata);
  18. this.expanded = false;
  19. this.head = head;
  20. this.tail = tail;
  21. }
  22. get autogroupedSegments(): [number, number][] {
  23. if (this._autogroupedSegments) {
  24. return this._autogroupedSegments;
  25. }
  26. const children: TraceTreeNode<TraceTree.NodeValue>[] = [];
  27. let start: TraceTreeNode<TraceTree.NodeValue> | undefined = this.head;
  28. while (start && start !== this.tail) {
  29. children.push(start);
  30. start = start.children[0];
  31. }
  32. children.push(this.tail);
  33. this._autogroupedSegments = computeCollapsedBarSpace(children);
  34. return this._autogroupedSegments;
  35. }
  36. }
  37. // Returns a list of segments from a grouping sequence that can be used to render a span bar chart
  38. // It looks for gaps between spans and creates a segment for each gap. If there are no gaps, it
  39. // merges the n and n+1 segments.
  40. export function computeCollapsedBarSpace(
  41. nodes: TraceTreeNode<TraceTree.NodeValue>[]
  42. ): [number, number][] {
  43. if (nodes.length === 0) {
  44. return [];
  45. }
  46. const first = nodes[0];
  47. if (!isSpanNode(first)) {
  48. throw new Error('Autogrouped node must have span children');
  49. }
  50. const segments: [number, number][] = [];
  51. let start = first.space[0];
  52. let end = first.space[0] + first.space[1];
  53. let i = 1;
  54. while (i < nodes.length) {
  55. const next = nodes[i];
  56. if (!isSpanNode(next)) {
  57. throw new Error('Autogrouped node must have span children');
  58. }
  59. if (next.space[0] > end) {
  60. segments.push([start, end - start]);
  61. start = next.space[0];
  62. end = next.space[0] + next.space[1];
  63. i++;
  64. } else {
  65. end = next.space[0] + next.space[1];
  66. i++;
  67. }
  68. }
  69. segments.push([start, end - start]);
  70. return segments;
  71. }