source: frontend/node_modules/@bcoe/v8-coverage/src/lib/ascii.ts

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 4.4 KB
Line 
1import { compareRangeCovs } from "./compare";
2import { RangeCov } from "./types";
3
4interface ReadonlyRangeTree {
5 readonly start: number;
6 readonly end: number;
7 readonly count: number;
8 readonly children: ReadonlyRangeTree[];
9}
10
11export function emitForest(trees: ReadonlyArray<ReadonlyRangeTree>): string {
12 return emitForestLines(trees).join("\n");
13}
14
15export function emitForestLines(trees: ReadonlyArray<ReadonlyRangeTree>): string[] {
16 const colMap: Map<number, number> = getColMap(trees);
17 const header: string = emitOffsets(colMap);
18 return [header, ...trees.map(tree => emitTree(tree, colMap).join("\n"))];
19}
20
21function getColMap(trees: Iterable<ReadonlyRangeTree>): Map<number, number> {
22 const eventSet: Set<number> = new Set();
23 for (const tree of trees) {
24 const stack: ReadonlyRangeTree[] = [tree];
25 while (stack.length > 0) {
26 const cur: ReadonlyRangeTree = stack.pop()!;
27 eventSet.add(cur.start);
28 eventSet.add(cur.end);
29 for (const child of cur.children) {
30 stack.push(child);
31 }
32 }
33 }
34 const events: number[] = [...eventSet];
35 events.sort((a, b) => a - b);
36 let maxDigits: number = 1;
37 for (const event of events) {
38 maxDigits = Math.max(maxDigits, event.toString(10).length);
39 }
40 const colWidth: number = maxDigits + 3;
41 const colMap: Map<number, number> = new Map();
42 for (const [i, event] of events.entries()) {
43 colMap.set(event, i * colWidth);
44 }
45 return colMap;
46}
47
48function emitTree(tree: ReadonlyRangeTree, colMap: Map<number, number>): string[] {
49 const layers: ReadonlyRangeTree[][] = [];
50 let nextLayer: ReadonlyRangeTree[] = [tree];
51 while (nextLayer.length > 0) {
52 const layer: ReadonlyRangeTree[] = nextLayer;
53 layers.push(layer);
54 nextLayer = [];
55 for (const node of layer) {
56 for (const child of node.children) {
57 nextLayer.push(child);
58 }
59 }
60 }
61 return layers.map(layer => emitTreeLayer(layer, colMap));
62}
63
64export function parseFunctionRanges(text: string, offsetMap: Map<number, number>): RangeCov[] {
65 const result: RangeCov[] = [];
66 for (const line of text.split("\n")) {
67 for (const range of parseTreeLayer(line, offsetMap)) {
68 result.push(range);
69 }
70 }
71 result.sort(compareRangeCovs);
72 return result;
73}
74
75/**
76 *
77 * @param layer Sorted list of disjoint trees.
78 * @param colMap
79 */
80function emitTreeLayer(layer: ReadonlyRangeTree[], colMap: Map<number, number>): string {
81 const line: string[] = [];
82 let curIdx: number = 0;
83 for (const {start, end, count} of layer) {
84 const startIdx: number = colMap.get(start)!;
85 const endIdx: number = colMap.get(end)!;
86 if (startIdx > curIdx) {
87 line.push(" ".repeat(startIdx - curIdx));
88 }
89 line.push(emitRange(count, endIdx - startIdx));
90 curIdx = endIdx;
91 }
92 return line.join("");
93}
94
95function parseTreeLayer(text: string, offsetMap: Map<number, number>): RangeCov[] {
96 const result: RangeCov[] = [];
97 const regex: RegExp = /\[(\d+)-*\)/gs;
98 while (true) {
99 const match: RegExpMatchArray | null = regex.exec(text);
100 if (match === null) {
101 break;
102 }
103 const startIdx: number = match.index!;
104 const endIdx: number = startIdx + match[0].length;
105 const count: number = parseInt(match[1], 10);
106 const startOffset: number | undefined = offsetMap.get(startIdx);
107 const endOffset: number | undefined = offsetMap.get(endIdx);
108 if (startOffset === undefined || endOffset === undefined) {
109 throw new Error(`Invalid offsets for: ${JSON.stringify(text)}`);
110 }
111 result.push({startOffset, endOffset, count});
112 }
113 return result;
114}
115
116function emitRange(count: number, len: number): string {
117 const rangeStart: string = `[${count.toString(10)}`;
118 const rangeEnd: string = ")";
119 const hyphensLen: number = len - (rangeStart.length + rangeEnd.length);
120 const hyphens: string = "-".repeat(Math.max(0, hyphensLen));
121 return `${rangeStart}${hyphens}${rangeEnd}`;
122}
123
124function emitOffsets(colMap: Map<number, number>): string {
125 let line: string = "";
126 for (const [event, col] of colMap) {
127 if (line.length < col) {
128 line += " ".repeat(col - line.length);
129 }
130 line += event.toString(10);
131 }
132 return line;
133}
134
135export function parseOffsets(text: string): Map<number, number> {
136 const result: Map<number, number> = new Map();
137 const regex: RegExp = /\d+/gs;
138 while (true) {
139 const match: RegExpExecArray | null = regex.exec(text);
140 if (match === null) {
141 break;
142 }
143 result.set(match.index, parseInt(match[0], 10));
144 }
145 return result;
146}
Note: See TracBrowser for help on using the repository browser.