mirror of
https://github.com/azure/login.git
synced 2026-06-06 19:47:08 +00:00
* Bump lodash from 4.17.15 to 4.17.19 (#52) Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Amruta Kawade <65217380+AmrutaKawade@users.noreply.github.com> * Bump @actions/core from 1.1.3 to 1.2.6 (#60) Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.1.3 to 1.2.6. - [Release notes](https://github.com/actions/toolkit/releases) - [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md) - [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Amruta Kawade <65217380+AmrutaKawade@users.noreply.github.com> * updating node_nodules * updated package-lock Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
146 lines
4.4 KiB
TypeScript
146 lines
4.4 KiB
TypeScript
import { compareRangeCovs } from "./compare";
|
|
import { RangeCov } from "./types";
|
|
|
|
interface ReadonlyRangeTree {
|
|
readonly start: number;
|
|
readonly end: number;
|
|
readonly count: number;
|
|
readonly children: ReadonlyRangeTree[];
|
|
}
|
|
|
|
export function emitForest(trees: ReadonlyArray<ReadonlyRangeTree>): string {
|
|
return emitForestLines(trees).join("\n");
|
|
}
|
|
|
|
export function emitForestLines(trees: ReadonlyArray<ReadonlyRangeTree>): string[] {
|
|
const colMap: Map<number, number> = getColMap(trees);
|
|
const header: string = emitOffsets(colMap);
|
|
return [header, ...trees.map(tree => emitTree(tree, colMap).join("\n"))];
|
|
}
|
|
|
|
function getColMap(trees: Iterable<ReadonlyRangeTree>): Map<number, number> {
|
|
const eventSet: Set<number> = new Set();
|
|
for (const tree of trees) {
|
|
const stack: ReadonlyRangeTree[] = [tree];
|
|
while (stack.length > 0) {
|
|
const cur: ReadonlyRangeTree = stack.pop()!;
|
|
eventSet.add(cur.start);
|
|
eventSet.add(cur.end);
|
|
for (const child of cur.children) {
|
|
stack.push(child);
|
|
}
|
|
}
|
|
}
|
|
const events: number[] = [...eventSet];
|
|
events.sort((a, b) => a - b);
|
|
let maxDigits: number = 1;
|
|
for (const event of events) {
|
|
maxDigits = Math.max(maxDigits, event.toString(10).length);
|
|
}
|
|
const colWidth: number = maxDigits + 3;
|
|
const colMap: Map<number, number> = new Map();
|
|
for (const [i, event] of events.entries()) {
|
|
colMap.set(event, i * colWidth);
|
|
}
|
|
return colMap;
|
|
}
|
|
|
|
function emitTree(tree: ReadonlyRangeTree, colMap: Map<number, number>): string[] {
|
|
const layers: ReadonlyRangeTree[][] = [];
|
|
let nextLayer: ReadonlyRangeTree[] = [tree];
|
|
while (nextLayer.length > 0) {
|
|
const layer: ReadonlyRangeTree[] = nextLayer;
|
|
layers.push(layer);
|
|
nextLayer = [];
|
|
for (const node of layer) {
|
|
for (const child of node.children) {
|
|
nextLayer.push(child);
|
|
}
|
|
}
|
|
}
|
|
return layers.map(layer => emitTreeLayer(layer, colMap));
|
|
}
|
|
|
|
export function parseFunctionRanges(text: string, offsetMap: Map<number, number>): RangeCov[] {
|
|
const result: RangeCov[] = [];
|
|
for (const line of text.split("\n")) {
|
|
for (const range of parseTreeLayer(line, offsetMap)) {
|
|
result.push(range);
|
|
}
|
|
}
|
|
result.sort(compareRangeCovs);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param layer Sorted list of disjoint trees.
|
|
* @param colMap
|
|
*/
|
|
function emitTreeLayer(layer: ReadonlyRangeTree[], colMap: Map<number, number>): string {
|
|
const line: string[] = [];
|
|
let curIdx: number = 0;
|
|
for (const {start, end, count} of layer) {
|
|
const startIdx: number = colMap.get(start)!;
|
|
const endIdx: number = colMap.get(end)!;
|
|
if (startIdx > curIdx) {
|
|
line.push(" ".repeat(startIdx - curIdx));
|
|
}
|
|
line.push(emitRange(count, endIdx - startIdx));
|
|
curIdx = endIdx;
|
|
}
|
|
return line.join("");
|
|
}
|
|
|
|
function parseTreeLayer(text: string, offsetMap: Map<number, number>): RangeCov[] {
|
|
const result: RangeCov[] = [];
|
|
const regex: RegExp = /\[(\d+)-*\)/gs;
|
|
while (true) {
|
|
const match: RegExpMatchArray | null = regex.exec(text);
|
|
if (match === null) {
|
|
break;
|
|
}
|
|
const startIdx: number = match.index!;
|
|
const endIdx: number = startIdx + match[0].length;
|
|
const count: number = parseInt(match[1], 10);
|
|
const startOffset: number | undefined = offsetMap.get(startIdx);
|
|
const endOffset: number | undefined = offsetMap.get(endIdx);
|
|
if (startOffset === undefined || endOffset === undefined) {
|
|
throw new Error(`Invalid offsets for: ${JSON.stringify(text)}`);
|
|
}
|
|
result.push({startOffset, endOffset, count});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function emitRange(count: number, len: number): string {
|
|
const rangeStart: string = `[${count.toString(10)}`;
|
|
const rangeEnd: string = ")";
|
|
const hyphensLen: number = len - (rangeStart.length + rangeEnd.length);
|
|
const hyphens: string = "-".repeat(Math.max(0, hyphensLen));
|
|
return `${rangeStart}${hyphens}${rangeEnd}`;
|
|
}
|
|
|
|
function emitOffsets(colMap: Map<number, number>): string {
|
|
let line: string = "";
|
|
for (const [event, col] of colMap) {
|
|
if (line.length < col) {
|
|
line += " ".repeat(col - line.length);
|
|
}
|
|
line += event.toString(10);
|
|
}
|
|
return line;
|
|
}
|
|
|
|
export function parseOffsets(text: string): Map<number, number> {
|
|
const result: Map<number, number> = new Map();
|
|
const regex: RegExp = /\d+/gs;
|
|
while (true) {
|
|
const match: RegExpExecArray | null = regex.exec(text);
|
|
if (match === null) {
|
|
break;
|
|
}
|
|
result.set(match.index, parseInt(match[0], 10));
|
|
}
|
|
return result;
|
|
}
|