vscode/build/lib/tsb/utils.ts
2022-06-08 17:49:21 +02:00

141 lines
4.3 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export module collections {
const hasOwnProperty = Object.prototype.hasOwnProperty;
export function lookup<T>(collection: { [keys: string]: T }, key: string): T | null {
if (hasOwnProperty.call(collection, key)) {
return collection[key];
}
return null;
}
export function insert<T>(collection: { [keys: string]: T }, key: string, value: T): void {
collection[key] = value;
}
export function lookupOrInsert<T>(collection: { [keys: string]: T }, key: string, value: T): T {
if (hasOwnProperty.call(collection, key)) {
return collection[key];
} else {
collection[key] = value;
return value;
}
}
export function forEach<T>(collection: { [keys: string]: T }, callback: (entry: { key: string; value: T }) => void): void {
for (const key in collection) {
if (hasOwnProperty.call(collection, key)) {
callback({
key: key,
value: collection[key]
});
}
}
}
export function contains(collection: { [keys: string]: any }, key: string): boolean {
return hasOwnProperty.call(collection, key);
}
}
export module strings {
/**
* The empty string. The one and only.
*/
export const empty = '';
export const eolUnix = '\r\n';
export function format(value: string, ...rest: any[]): string {
return value.replace(/({\d+})/g, function (match) {
const index = Number(match.substring(1, match.length - 1));
return String(rest[index]) || match;
});
}
}
export module graph {
export interface Node<T> {
data: T;
incoming: { [key: string]: Node<T> };
outgoing: { [key: string]: Node<T> };
}
export function newNode<T>(data: T): Node<T> {
return {
data: data,
incoming: {},
outgoing: {}
};
}
export class Graph<T> {
private _nodes: { [key: string]: Node<T> } = {};
constructor(private _hashFn: (element: T) => string) {
// empty
}
traverse(start: T, inwards: boolean, callback: (data: T) => void): void {
const startNode = this.lookup(start);
if (!startNode) {
return;
}
this._traverse(startNode, inwards, {}, callback);
}
private _traverse(node: Node<T>, inwards: boolean, seen: { [key: string]: boolean }, callback: (data: T) => void): void {
const key = this._hashFn(node.data);
if (collections.contains(seen, key)) {
return;
}
seen[key] = true;
callback(node.data);
const nodes = inwards ? node.outgoing : node.incoming;
collections.forEach(nodes, (entry) => this._traverse(entry.value, inwards, seen, callback));
}
inertEdge(from: T, to: T): void {
const fromNode = this.lookupOrInsertNode(from);
const toNode = this.lookupOrInsertNode(to);
fromNode.outgoing[this._hashFn(to)] = toNode;
toNode.incoming[this._hashFn(from)] = fromNode;
}
removeNode(data: T): void {
const key = this._hashFn(data);
delete this._nodes[key];
collections.forEach(this._nodes, (entry) => {
delete entry.value.outgoing[key];
delete entry.value.incoming[key];
});
}
lookupOrInsertNode(data: T): Node<T> {
const key = this._hashFn(data);
let node = collections.lookup(this._nodes, key);
if (!node) {
node = newNode(data);
this._nodes[key] = node;
}
return node;
}
lookup(data: T): Node<T> | null {
return collections.lookup(this._nodes, this._hashFn(data));
}
}
}