mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-03-15 14:05:47 -05:00
Migrate core.ts
This commit is contained in:
60
Gulpfile.ts
60
Gulpfile.ts
@@ -611,57 +611,23 @@ gulp.task("LKG", "Makes a new LKG out of the built js files", ["clean", "dontUse
|
||||
return runSequence("LKGInternal", "VerifyLKG");
|
||||
});
|
||||
|
||||
gulp.task("typemock", () => {
|
||||
const project = tsc.createProject("scripts/typemock/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/ false));
|
||||
function compilePrivatePackage(packageName) {
|
||||
const project = tsc.createProject(`scripts/${packageName}/tsconfig.json`, getCompilerSettings({}, /*useBuiltCompiler*/ false));
|
||||
return project.src()
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(newer("scripts/typemock/dist/index.js"))
|
||||
.pipe(newer(`scripts/${packageName}/dist/index.js`))
|
||||
.pipe(project())
|
||||
.pipe(sourcemaps.write(".", <any>{ sourceRoot: "../src", includeContent: false, destPath: "scripts/typemock/dist" }))
|
||||
.pipe(gulp.dest("scripts/typemock/dist"));
|
||||
});
|
||||
.pipe(sourcemaps.write(".", <any>{ sourceRoot: "../src", includeContent: false, destPath: `scripts/${packageName}/dist` }))
|
||||
.pipe(gulp.dest(`scripts/${packageName}/dist`));
|
||||
}
|
||||
|
||||
gulp.task("vfs-core", () => {
|
||||
const project = tsc.createProject("scripts/vfs-core/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/ false));
|
||||
return project.src()
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(newer("scripts/vfs-core/dist/index.js"))
|
||||
.pipe(project())
|
||||
.pipe(sourcemaps.write(".", <any>{ sourceRoot: "../src", includeContent: false, destPath: "scripts/vfs-core/dist" }))
|
||||
.pipe(gulp.dest("scripts/vfs-core/dist"));
|
||||
});
|
||||
|
||||
gulp.task("vfs-errors", () => {
|
||||
const project = tsc.createProject("scripts/vfs-errors/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/ false));
|
||||
return project.src()
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(newer("scripts/vfs-errors/dist/index.js"))
|
||||
.pipe(project())
|
||||
.pipe(sourcemaps.write(".", <any>{ sourceRoot: "../src", includeContent: false, destPath: "scripts/vfs-errors/dist" }))
|
||||
.pipe(gulp.dest("scripts/vfs-errors/dist"));
|
||||
});
|
||||
|
||||
gulp.task("vfs-path", ["vfs-core", "vfs-errors"], () => {
|
||||
const project = tsc.createProject("scripts/vfs-path/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/ false));
|
||||
return project.src()
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(newer("scripts/vfs-path/dist/index.js"))
|
||||
.pipe(project())
|
||||
.pipe(sourcemaps.write(".", <any>{ sourceRoot: "../src", includeContent: false, destPath: "scripts/vfs-path/dist" }))
|
||||
.pipe(gulp.dest("scripts/vfs-path/dist"));
|
||||
});
|
||||
|
||||
gulp.task("vfs", ["vfs-core", "vfs-errors", "vfs-path"], () => {
|
||||
const project = tsc.createProject("scripts/vfs/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/ false));
|
||||
return project.src()
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(newer("scripts/vfs/dist/index.js"))
|
||||
.pipe(project())
|
||||
.pipe(sourcemaps.write(".", <any>{ sourceRoot: "../src", includeContent: false, destPath: "scripts/vfs/dist" }))
|
||||
.pipe(gulp.dest("scripts/vfs/dist"));
|
||||
});
|
||||
|
||||
gulp.task("private-packages", ["typemock", "vfs"]);
|
||||
gulp.task("typemock", () => compilePrivatePackage("typemock"));
|
||||
gulp.task("vfs-core", () => compilePrivatePackage("vfs-core"));
|
||||
gulp.task("vfs-errors", () => compilePrivatePackage("vfs-errors"));
|
||||
gulp.task("vfs-path", ["vfs-core", "vfs-errors"], () => compilePrivatePackage("vfs-path"));
|
||||
gulp.task("vfs", ["vfs-core", "vfs-errors", "vfs-path", "typemock"], () => compilePrivatePackage("vfs"));
|
||||
gulp.task("harness-core", ["vfs-core"], () => compilePrivatePackage("harness-core"));
|
||||
gulp.task("private-packages", ["typemock", "vfs", "harness-core"]);
|
||||
|
||||
// Task to build the tests infrastructure using the built compiler
|
||||
const run = path.join(builtLocalDirectory, "run.js");
|
||||
|
||||
86
Jakefile.js
86
Jakefile.js
@@ -803,72 +803,28 @@ task("LKG", ["clean", "release", "local"].concat(libraryTargets), function () {
|
||||
// Test directory
|
||||
directory(builtLocalDirectory);
|
||||
|
||||
task("typemock", function () {
|
||||
var startCompileTime = mark();
|
||||
execCompiler(/*useBuiltCompiler*/ false, ["-p", "scripts/typemock/tsconfig.json"], function (error) {
|
||||
if (error) {
|
||||
fail("Compilation unsuccessful.");
|
||||
}
|
||||
else {
|
||||
complete();
|
||||
}
|
||||
measure(startCompileTime);
|
||||
});
|
||||
}, { async: true });
|
||||
function privatePackage(packageName, prereqs) {
|
||||
task(packageName, prereqs, function () {
|
||||
var startCompileTime = mark();
|
||||
execCompiler(/*useBuiltCompiler*/ false, ["-p", `scripts/${packageName}/tsconfig.json`], function (error) {
|
||||
if (error) {
|
||||
fail("Compilation unsuccessful.");
|
||||
}
|
||||
else {
|
||||
complete();
|
||||
}
|
||||
measure(startCompileTime);
|
||||
});
|
||||
}, { async: true });
|
||||
}
|
||||
|
||||
task("vfs-core", function () {
|
||||
var startCompileTime = mark();
|
||||
execCompiler(/*useBuiltCompiler*/ false, ["-p", "scripts/vfs-core/tsconfig.json"], function (error) {
|
||||
if (error) {
|
||||
fail("Compilation unsuccessful.");
|
||||
}
|
||||
else {
|
||||
complete();
|
||||
}
|
||||
measure(startCompileTime);
|
||||
});
|
||||
}, { async: true });
|
||||
|
||||
task("vfs-errors", function () {
|
||||
var startCompileTime = mark();
|
||||
execCompiler(/*useBuiltCompiler*/ false, ["-p", "scripts/vfs-errors/tsconfig.json"], function (error) {
|
||||
if (error) {
|
||||
fail("Compilation unsuccessful.");
|
||||
}
|
||||
else {
|
||||
complete();
|
||||
}
|
||||
measure(startCompileTime);
|
||||
});
|
||||
}, { async: true });
|
||||
|
||||
task("vfs-path", ["vfs-core", "vfs-errors"], function () {
|
||||
var startCompileTime = mark();
|
||||
execCompiler(/*useBuiltCompiler*/ false, ["-p", "scripts/vfs-path/tsconfig.json"], function (error) {
|
||||
if (error) {
|
||||
fail("Compilation unsuccessful.");
|
||||
}
|
||||
else {
|
||||
complete();
|
||||
}
|
||||
measure(startCompileTime);
|
||||
});
|
||||
}, { async: true });
|
||||
|
||||
task("vfs", ["vfs-core", "vfs-errors", "vfs-path", "typemock"], function () {
|
||||
var startCompileTime = mark();
|
||||
execCompiler(/*useBuiltCompiler*/ false, ["-p", "scripts/vfs/tsconfig.json"], function (error) {
|
||||
if (error) {
|
||||
fail("Compilation unsuccessful.");
|
||||
}
|
||||
else {
|
||||
complete();
|
||||
}
|
||||
measure(startCompileTime);
|
||||
});
|
||||
}, { async: true });
|
||||
|
||||
task("private-packages", ["typemock", "vfs"]);
|
||||
privatePackage("typemock");
|
||||
privatePackage("vfs-core");
|
||||
privatePackage("vfs-errors");
|
||||
privatePackage("vfs-path", ["vfs-core", "vfs-errors"]);
|
||||
privatePackage("vfs", ["vfs-path", "typemock"]);
|
||||
privatePackage("harness-core", ["vfs-core"]);
|
||||
task("private-packages", ["typemock", "vfs", "harness-core"]);
|
||||
|
||||
// Task to build the tests infrastructure using the built compiler
|
||||
var run = path.join(builtLocalDirectory, "run.js");
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
if [ "$1" = "6" ]; then
|
||||
echo "NodeJS v6 is no longer supported, build skipped.";
|
||||
exit;
|
||||
fi;
|
||||
|
||||
# Set up NVM
|
||||
export NVM_DIR="/home/dotnet-bot/.nvm"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
|
||||
|
||||
|
||||
nvm install $1
|
||||
|
||||
npm uninstall typescript --no-save
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
"@types/xml2js": "^0.4.0",
|
||||
"@typescript/vfs-path": "file:scripts/vfs-path",
|
||||
"@typescript/vfs": "file:scripts/vfs",
|
||||
"@typescript/harness-core": "file:scripts/harness-core",
|
||||
"browser-resolve": "^1.11.2",
|
||||
"browserify": "latest",
|
||||
"chai": "latest",
|
||||
|
||||
18
scripts/harness-core/gulpfile.js
Normal file
18
scripts/harness-core/gulpfile.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const gulp = require("gulp");
|
||||
const sourcemaps = require("gulp-sourcemaps");
|
||||
const tsb = require("gulp-tsb");
|
||||
const del = require("del");
|
||||
|
||||
const project = tsb.create("tsconfig.json")
|
||||
|
||||
gulp.task("clean", () => del(["dist/**/*"]));
|
||||
|
||||
gulp.task("build", () => gulp.src(["src/**/*.ts"])
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(project())
|
||||
.pipe(sourcemaps.write(".", { sourceRoot: "../src", includeContent: false, destPath: "dist" }))
|
||||
.pipe(gulp.dest("dist")));
|
||||
|
||||
gulp.task("watch", () => gulp.watch(["src/**/*", "tsconfig.json"], ["build"]));
|
||||
|
||||
gulp.task("default", ["build"]);
|
||||
23
scripts/harness-core/package.json
Normal file
23
scripts/harness-core/package.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@typescript/harness-core",
|
||||
"version": "0.0.0",
|
||||
"description": "TypeScript test harness core",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"author": "Ron Buckton (ron.buckton@microsoft.com)",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@typescript/vfs-core": "file:../vfs-core"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^8.0.20",
|
||||
"@types/source-map-support": "^0.4.0",
|
||||
"del": "^2.0.2",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-sourcemaps": "^2.6.1",
|
||||
"gulp-tsb": "^2.0.5",
|
||||
"source-map-support": "^0.5.0",
|
||||
"typescript": "^2.6.1"
|
||||
}
|
||||
}
|
||||
67
scripts/harness-core/src/crypto.ts
Normal file
67
scripts/harness-core/src/crypto.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
const H = new Uint32Array(5);
|
||||
const W = new Uint8Array(80);
|
||||
const B = new Uint8Array(64);
|
||||
const BLOCK_SIZE = 64;
|
||||
|
||||
export function sha1(message: string): string {
|
||||
let buffer = B;
|
||||
const textSize = message.length;
|
||||
const messageSize = textSize * 2;
|
||||
const finalBlockSize = messageSize % BLOCK_SIZE;
|
||||
const padSize = (finalBlockSize < BLOCK_SIZE - 8 - 1 ? BLOCK_SIZE : BLOCK_SIZE * 2) - finalBlockSize;
|
||||
const byteLength = messageSize + padSize;
|
||||
if (byteLength > BLOCK_SIZE) {
|
||||
buffer = new Uint8Array(byteLength);
|
||||
}
|
||||
|
||||
const bufferView = new DataView(buffer.buffer);
|
||||
for (let i = 0; i < textSize; ++i) {
|
||||
bufferView.setUint16(i * 2, message.charCodeAt(i));
|
||||
}
|
||||
|
||||
buffer[messageSize] = 0x80;
|
||||
bufferView.setUint32(byteLength - 4, messageSize * 8);
|
||||
H[0] = 0x67452301, H[1] = 0xefcdab89, H[2] = 0x98badcfe, H[3] = 0x10325476, H[4] = 0xc3d2e1f0;
|
||||
for (let offset = 0; offset < byteLength; offset += BLOCK_SIZE) {
|
||||
let a = H[0], b = H[1], c = H[2], d = H[3], e = H[4];
|
||||
for (let i = 0; i < 80; ++i) {
|
||||
if (i < 16) {
|
||||
const x = offset + i * 4;
|
||||
W[i] = buffer[x] << 24 | buffer[x + 1] << 16 | buffer[x + 2] << 8 | buffer[x + 3];
|
||||
}
|
||||
else {
|
||||
const x = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
|
||||
W[i] = (x << 1 | x >>> 31) >>> 0;
|
||||
}
|
||||
|
||||
let t = (a << 5 | a >>> 27) >>> 0 + e + W[i];
|
||||
if (i < 20) {
|
||||
t += ((b & c) | (~b & d)) + 0x5A827999;
|
||||
}
|
||||
else if (i < 40) {
|
||||
t += (b ^ c ^ d) + 0x6ED9EBA1;
|
||||
}
|
||||
else if (i < 60) {
|
||||
t += ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC;
|
||||
}
|
||||
else {
|
||||
t += (b ^ c ^ d) + 0xCA62C1D6;
|
||||
}
|
||||
|
||||
e = d, d = c, c = (b << 30 | b >>> 2) >>> 0, b = a, a = t;
|
||||
}
|
||||
|
||||
H[0] += a, H[1] += b, H[2] += c, H[3] += d, H[4] += e;
|
||||
}
|
||||
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
bufferView.setUint32(i * 4, H[i]);
|
||||
}
|
||||
|
||||
let result = "";
|
||||
for (let i = 0; i < 20; ++i) {
|
||||
result += (buffer[i] < 16 ? "0" : "") + buffer[i].toString(16);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
3
scripts/harness-core/src/index.ts
Normal file
3
scripts/harness-core/src/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from "@typescript/vfs-core";
|
||||
export * from "./strings";
|
||||
export * from "./crypto";
|
||||
132
scripts/harness-core/src/strings.ts
Normal file
132
scripts/harness-core/src/strings.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
export function padLeft(text: string, size: number, ch = " "): string {
|
||||
while (text.length < size) text = ch + text;
|
||||
return text;
|
||||
}
|
||||
|
||||
export function padRight(text: string, size: number, ch = " "): string {
|
||||
while (text.length < size) text += ch;
|
||||
return text;
|
||||
}
|
||||
|
||||
export function getByteOrderMark(text: string): string {
|
||||
const length = getByteOrderMarkLength(text);
|
||||
return length > 0 ? text.slice(0, length) : "";
|
||||
}
|
||||
|
||||
export function getByteOrderMarkLength(text: string): number {
|
||||
if (text.length >= 2) {
|
||||
const ch0 = text.charCodeAt(0);
|
||||
const ch1 = text.charCodeAt(1);
|
||||
if ((ch0 === 0xff && ch1 === 0xfe) ||
|
||||
(ch0 === 0xfe && ch1 === 0xff)) {
|
||||
return 2;
|
||||
}
|
||||
if (text.length >= 3 && ch0 === 0xef && ch1 === 0xbb && text.charCodeAt(2) === 0xbf) {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function removeByteOrderMark(text: string): string {
|
||||
const length = getByteOrderMarkLength(text);
|
||||
return length ? text.slice(length) : text;
|
||||
}
|
||||
|
||||
export function addUTF8ByteOrderMark(text: string) {
|
||||
return getByteOrderMarkLength(text) === 0 ? "\u00EF\u00BB\u00BF" + text : text;
|
||||
}
|
||||
|
||||
function splitLinesWorker(text: string, lineStarts: number[] | undefined, lines: string[] | undefined, removeEmptyElements: boolean) {
|
||||
let pos = 0;
|
||||
let end = 0;
|
||||
let lineStart = 0;
|
||||
let nonWhiteSpace = false;
|
||||
while (pos < text.length) {
|
||||
const ch = text.charCodeAt(pos);
|
||||
end = pos;
|
||||
pos++;
|
||||
switch (ch) {
|
||||
// LineTerminator
|
||||
case 0x000d: // <CR> carriage return
|
||||
if (pos < text.length && text.charCodeAt(pos) === 0x000a) {
|
||||
pos++;
|
||||
}
|
||||
// falls through
|
||||
|
||||
case 0x000a: // <LF> line feed
|
||||
case 0x2028: // <LS> line separator
|
||||
case 0x2029: // <PS> paragraph separator
|
||||
if (lineStarts) {
|
||||
lineStarts.push(lineStart);
|
||||
}
|
||||
if (lines && (!removeEmptyElements || nonWhiteSpace)) {
|
||||
lines.push(text.slice(lineStart, end));
|
||||
}
|
||||
lineStart = pos;
|
||||
nonWhiteSpace = false;
|
||||
break;
|
||||
|
||||
// WhiteSpace
|
||||
case 0x0009: // <TAB> tab
|
||||
case 0x000b: // <VT> vertical tab
|
||||
case 0x000c: // <FF> form feed
|
||||
case 0x0020: // <SP> space
|
||||
case 0x00a0: // <NBSP> no-break space
|
||||
case 0xfeff: // <ZWNBSP> zero width no-break space
|
||||
case 0x1680: // <USP> ogham space mark
|
||||
case 0x2000: // <USP> en quad
|
||||
case 0x2001: // <USP> em quad
|
||||
case 0x2002: // <USP> en space
|
||||
case 0x2003: // <USP> em space
|
||||
case 0x2004: // <USP> three-per-em space
|
||||
case 0x2005: // <USP> four-per-em space
|
||||
case 0x2006: // <USP> six-per-em space
|
||||
case 0x2007: // <USP> figure space
|
||||
case 0x2008: // <USP> punctuation space
|
||||
case 0x2009: // <USP> thin space
|
||||
case 0x200a: // <USP> hair space
|
||||
case 0x202f: // <USP> narrow no-break space
|
||||
case 0x205f: // <USP> medium mathematical space
|
||||
case 0x3000: // <USP> ideographic space
|
||||
case 0x0085: // next-line (not strictly per spec, but used by the compiler)
|
||||
break;
|
||||
|
||||
default:
|
||||
nonWhiteSpace = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lineStarts) {
|
||||
lineStarts.push(lineStart);
|
||||
}
|
||||
if (lines && (!removeEmptyElements || nonWhiteSpace)) {
|
||||
lines.push(text.slice(lineStart, text.length));
|
||||
}
|
||||
}
|
||||
|
||||
export type LineStarts = ReadonlyArray<number>;
|
||||
|
||||
export interface LinesAndLineStarts {
|
||||
readonly lines: ReadonlyArray<string>;
|
||||
readonly lineStarts: LineStarts;
|
||||
}
|
||||
|
||||
export function getLinesAndLineStarts(text: string): LinesAndLineStarts {
|
||||
const lines: string[] = [];
|
||||
const lineStarts: number[] = [];
|
||||
splitLinesWorker(text, lineStarts, lines, /*removeEmptyElements*/ false);
|
||||
return { lines, lineStarts };
|
||||
}
|
||||
|
||||
export function splitLines(text: string, removeEmptyElements = false): string[] {
|
||||
const lines: string[] = [];
|
||||
splitLinesWorker(text, /*lineStarts*/ undefined, lines, removeEmptyElements);
|
||||
return lines;
|
||||
}
|
||||
|
||||
export function computeLineStarts(text: string): LineStarts {
|
||||
const lineStarts: number[] = [];
|
||||
splitLinesWorker(text, lineStarts, /*lines*/ undefined, /*removeEmptyElements*/ false);
|
||||
return lineStarts;
|
||||
}
|
||||
15
scripts/harness-core/tsconfig.json
Normal file
15
scripts/harness-core/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2015",
|
||||
"module": "commonjs",
|
||||
"outDir": "dist",
|
||||
"types": ["node"],
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"preserveConstEnums": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
]
|
||||
}
|
||||
509
scripts/vfs-core/src/collections.ts
Normal file
509
scripts/vfs-core/src/collections.ts
Normal file
@@ -0,0 +1,509 @@
|
||||
import { identity } from "./functions";
|
||||
|
||||
export interface SortOptions<T> {
|
||||
comparer: (a: T, b: T) => number;
|
||||
sort: "insertion" | "comparison";
|
||||
}
|
||||
|
||||
export class SortedMap<K, V> {
|
||||
private _comparer: (a: K, b: K) => number;
|
||||
private _keys: K[] = [];
|
||||
private _values: V[] = [];
|
||||
private _order: number[] | undefined;
|
||||
private _version = 0;
|
||||
private _copyOnWrite = false;
|
||||
|
||||
constructor(comparer: ((a: K, b: K) => number) | SortOptions<K>, iterable?: Iterable<[K, V]>) {
|
||||
this._comparer = typeof comparer === "object" ? comparer.comparer : comparer;
|
||||
this._order = typeof comparer === "object" && comparer.sort === "insertion" ? [] : undefined;
|
||||
if (iterable) {
|
||||
for (const [key, value] of iterable) {
|
||||
this.set(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get size() {
|
||||
return this._keys.length;
|
||||
}
|
||||
|
||||
public get [Symbol.toStringTag]() {
|
||||
return "SortedMap";
|
||||
}
|
||||
|
||||
public has(key: K) {
|
||||
return binarySearch(this._keys, key, identity, this._comparer) >= 0;
|
||||
}
|
||||
|
||||
public get(key: K) {
|
||||
const index = binarySearch(this._keys, key, identity, this._comparer);
|
||||
return index >= 0 ? this._values[index] : undefined;
|
||||
}
|
||||
|
||||
public set(key: K, value: V) {
|
||||
const index = binarySearch(this._keys, key, identity, this._comparer);
|
||||
if (index >= 0) {
|
||||
this._values[index] = value;
|
||||
}
|
||||
else {
|
||||
this.writePreamble();
|
||||
insertAt(this._keys, ~index, key);
|
||||
insertAt(this._values, ~index, value);
|
||||
if (this._order) insertAt(this._order, ~index, this._version);
|
||||
this.writePostScript();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public delete(key: K) {
|
||||
const index = binarySearch(this._keys, key, identity, this._comparer);
|
||||
if (index >= 0) {
|
||||
this.writePreamble();
|
||||
removeAt(this._keys, index);
|
||||
removeAt(this._values, index);
|
||||
if (this._order) removeAt(this._order, index);
|
||||
this.writePostScript();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public clear() {
|
||||
if (this.size > 0) {
|
||||
this.writePreamble();
|
||||
this._keys.length = 0;
|
||||
this._values.length = 0;
|
||||
if (this._order) this._order.length = 0;
|
||||
this.writePostScript();
|
||||
}
|
||||
}
|
||||
|
||||
public forEach(callback: (value: V, key: K, collection: this) => void, thisArg?: any) {
|
||||
const keys = this._keys;
|
||||
const values = this._values;
|
||||
const indices = this.getIterationOrder();
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
if (indices) {
|
||||
for (const i of indices) {
|
||||
callback.call(thisArg, values[i], keys[i], this);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
callback.call(thisArg, values[i], keys[i], this);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public * keys() {
|
||||
const keys = this._keys;
|
||||
const indices = this.getIterationOrder();
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
if (indices) {
|
||||
for (const i of indices) {
|
||||
yield keys[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
yield keys[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public * values() {
|
||||
const values = this._values;
|
||||
const indices = this.getIterationOrder();
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
if (indices) {
|
||||
for (const i of indices) {
|
||||
yield values[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
yield values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public * entries() {
|
||||
const keys = this._keys;
|
||||
const values = this._values;
|
||||
const indices = this.getIterationOrder();
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
if (indices) {
|
||||
for (const i of indices) {
|
||||
yield [keys[i], values[i]] as [K, V];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
yield [keys[i], values[i]] as [K, V];
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public [Symbol.iterator]() {
|
||||
return this.entries();
|
||||
}
|
||||
|
||||
private writePreamble() {
|
||||
if (this._copyOnWrite) {
|
||||
this._keys = this._keys.slice();
|
||||
this._values = this._values.slice();
|
||||
if (this._order) this._order = this._order.slice();
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
private writePostScript() {
|
||||
this._version++;
|
||||
}
|
||||
|
||||
private getIterationOrder() {
|
||||
if (this._order) {
|
||||
const order = this._order;
|
||||
return this._order
|
||||
.map((_, i) => i)
|
||||
.sort((x, y) => order[x] - order[y]);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export class SortedSet<T> {
|
||||
private _comparer: (a: T, b: T) => number;
|
||||
private _values: T[] = [];
|
||||
private _order: number[] | undefined;
|
||||
private _version = 0;
|
||||
private _copyOnWrite = false;
|
||||
|
||||
constructor(comparer: ((a: T, b: T) => number) | SortOptions<T>, iterable?: Iterable<T>) {
|
||||
this._comparer = typeof comparer === "object" ? comparer.comparer : comparer;
|
||||
this._order = typeof comparer === "object" && comparer.sort === "insertion" ? [] : undefined;
|
||||
|
||||
if (iterable) {
|
||||
for (const value of iterable) {
|
||||
this.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get size() {
|
||||
return this._values.length;
|
||||
}
|
||||
|
||||
public get [Symbol.toStringTag]() {
|
||||
return "SortedSet";
|
||||
}
|
||||
|
||||
public has(value: T) {
|
||||
return binarySearch(this._values, value, identity, this._comparer) >= 0;
|
||||
}
|
||||
|
||||
public add(value: T) {
|
||||
const index = binarySearch(this._values, value, identity, this._comparer);
|
||||
if (index < 0) {
|
||||
this.writePreamble();
|
||||
insertAt(this._values, ~index, value);
|
||||
if (this._order) insertAt(this._order, ~index, this._version);
|
||||
this.writePostScript();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public delete(value: T) {
|
||||
const index = binarySearch(this._values, value, identity, this._comparer);
|
||||
if (index >= 0) {
|
||||
this.writePreamble();
|
||||
removeAt(this._values, index);
|
||||
if (this._order) removeAt(this._order, index);
|
||||
this.writePostScript();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public clear() {
|
||||
if (this.size > 0) {
|
||||
this.writePreamble();
|
||||
this._values.length = 0;
|
||||
if (this._order) this._order.length = 0;
|
||||
this.writePostScript();
|
||||
}
|
||||
}
|
||||
|
||||
public forEach(callback: (value: T, key: T, collection: this) => void, thisArg?: any) {
|
||||
const values = this._values;
|
||||
const indices = this.getIterationOrder();
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
if (indices) {
|
||||
for (const i of indices) {
|
||||
callback.call(thisArg, values[i], values[i], this);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const value of values) {
|
||||
callback.call(thisArg, value, value, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public keys() {
|
||||
return this.values();
|
||||
}
|
||||
|
||||
public * values() {
|
||||
const values = this._values;
|
||||
const indices = this.getIterationOrder();
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
if (indices) {
|
||||
for (const i of indices) {
|
||||
yield values[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const value of values) {
|
||||
yield value;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public * entries() {
|
||||
const values = this._values;
|
||||
const indices = this.getIterationOrder();
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
if (indices) {
|
||||
for (const i of indices) {
|
||||
yield [values[i], values[i]] as [T, T];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const value of values) {
|
||||
yield [value, value] as [T, T];
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public [Symbol.iterator]() {
|
||||
return this.values();
|
||||
}
|
||||
|
||||
private writePreamble() {
|
||||
if (this._copyOnWrite) {
|
||||
this._values = this._values.slice();
|
||||
if (this._order) this._order = this._order.slice();
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
private writePostScript() {
|
||||
this._version++;
|
||||
}
|
||||
|
||||
private getIterationOrder() {
|
||||
if (this._order) {
|
||||
const order = this._order;
|
||||
return this._order
|
||||
.map((_, i) => i)
|
||||
.sort((x, y) => order[x] - order[y]);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function binarySearch<T, U>(array: ReadonlyArray<T>, value: T, keySelector: (v: T) => U, keyComparer: (a: U, b: U) => number, offset?: number): number {
|
||||
if (!array || array.length === 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
let low = offset || 0;
|
||||
let high = array.length - 1;
|
||||
const key = keySelector(value);
|
||||
while (low <= high) {
|
||||
const middle = low + ((high - low) >> 1);
|
||||
const midKey = keySelector(array[middle]);
|
||||
const result = keyComparer(midKey, key);
|
||||
if (result < 0) {
|
||||
low = middle + 1;
|
||||
}
|
||||
else if (result > 0) {
|
||||
high = middle - 1;
|
||||
}
|
||||
else {
|
||||
return middle;
|
||||
}
|
||||
}
|
||||
|
||||
return ~low;
|
||||
}
|
||||
|
||||
export function removeAt<T>(array: T[], index: number): void {
|
||||
if (index < 0 || index >= array.length) {
|
||||
return;
|
||||
}
|
||||
else if (index === 0) {
|
||||
array.shift();
|
||||
}
|
||||
else if (index === array.length - 1) {
|
||||
array.pop();
|
||||
}
|
||||
else {
|
||||
for (let i = index; i < array.length - 1; i++) {
|
||||
array[i] = array[i + 1];
|
||||
}
|
||||
array.length--;
|
||||
}
|
||||
}
|
||||
|
||||
export function insertAt<T>(array: T[], index: number, value: T): void {
|
||||
if (index === 0) {
|
||||
array.unshift(value);
|
||||
}
|
||||
else if (index === array.length) {
|
||||
array.push(value);
|
||||
}
|
||||
else {
|
||||
for (let i = array.length; i > index; i--) {
|
||||
array[i] = array[i - 1];
|
||||
}
|
||||
array[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of metadata that supports inheritance.
|
||||
*/
|
||||
export class Metadata {
|
||||
private static readonly _undefinedValue = {};
|
||||
private _parent: Metadata | undefined;
|
||||
private _map: { [key: string]: any };
|
||||
private _version = 0;
|
||||
private _size = -1;
|
||||
private _parentVersion: number | undefined;
|
||||
|
||||
constructor(parent?: Metadata) {
|
||||
this._parent = parent;
|
||||
this._map = Object.create(parent ? parent._map : null); // tslint:disable-line:no-null-keyword
|
||||
}
|
||||
|
||||
public get size(): number {
|
||||
if (this._size === -1 || (this._parent && this._parent._version !== this._parentVersion)) {
|
||||
let size = 0;
|
||||
for (const _ in this._map) size++;
|
||||
this._size = size;
|
||||
if (this._parent) {
|
||||
this._parentVersion = this._parent._version;
|
||||
}
|
||||
}
|
||||
return this._size;
|
||||
}
|
||||
|
||||
public get parent() {
|
||||
return this._parent;
|
||||
}
|
||||
|
||||
public has(key: string): boolean {
|
||||
return this._map[Metadata._escapeKey(key)] !== undefined;
|
||||
}
|
||||
|
||||
public get(key: string): any {
|
||||
const value = this._map[Metadata._escapeKey(key)];
|
||||
return value === Metadata._undefinedValue ? undefined : value;
|
||||
}
|
||||
|
||||
public set(key: string, value: any): this {
|
||||
this._map[Metadata._escapeKey(key)] = value === undefined ? Metadata._undefinedValue : value;
|
||||
this._size = -1;
|
||||
this._version++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public delete(key: string): boolean {
|
||||
const escapedKey = Metadata._escapeKey(key);
|
||||
if (this._map[escapedKey] !== undefined) {
|
||||
delete this._map[escapedKey];
|
||||
this._size = -1;
|
||||
this._version++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
this._map = Object.create(this._parent ? this._parent._map : null); // tslint:disable-line:no-null-keyword
|
||||
this._size = -1;
|
||||
this._version++;
|
||||
}
|
||||
|
||||
public forEach(callback: (value: any, key: string, map: this) => void) {
|
||||
for (const key in this._map) {
|
||||
callback(this._map[key], Metadata._unescapeKey(key), this);
|
||||
}
|
||||
}
|
||||
|
||||
private static _escapeKey(text: string) {
|
||||
return (text.length >= 2 && text.charAt(0) === "_" && text.charAt(1) === "_" ? "_" + text : text);
|
||||
}
|
||||
|
||||
private static _unescapeKey(text: string) {
|
||||
return (text.length >= 3 && text.charAt(0) === "_" && text.charAt(1) === "_" && text.charAt(2) === "_" ? text.slice(1) : text);
|
||||
}
|
||||
}
|
||||
41
scripts/vfs-core/src/comparers.ts
Normal file
41
scripts/vfs-core/src/comparers.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
export function compareNumbers(a: number, b: number): number {
|
||||
if (a === b) return 0;
|
||||
if (a === undefined) return -1;
|
||||
if (b === undefined) return +1;
|
||||
return a < b ? -1 : +1;
|
||||
}
|
||||
|
||||
export function compareStrings(a: string, b: string, ignoreCase: boolean): number {
|
||||
return ignoreCase
|
||||
? compareStringsCaseInsensitive(a, b)
|
||||
: compareStringsCaseSensitive(a, b);
|
||||
}
|
||||
|
||||
// NOTE: This is a duplicate of `compareNumbers` above, but is intended to be used only with
|
||||
// strings to reduce polymorphism.
|
||||
export function compareStringsCaseSensitive(a: string, b: string): number {
|
||||
if (a === b) return 0;
|
||||
if (a === undefined) return -1;
|
||||
if (b === undefined) return +1;
|
||||
return a < b ? -1 : +1;
|
||||
}
|
||||
|
||||
export function compareStringsCaseInsensitive(a: string, b: string): number {
|
||||
if (a === b) return 0;
|
||||
if (a === undefined) return -1;
|
||||
if (b === undefined) return +1;
|
||||
a = a.toUpperCase();
|
||||
b = b.toUpperCase();
|
||||
return a < b ? -1 : a > b ? +1 : 0;
|
||||
}
|
||||
|
||||
export function equateStringsCaseSensitive(a: string, b: string): boolean {
|
||||
return a === b;
|
||||
}
|
||||
|
||||
export function equateStringsCaseInsensitive(a: string, b: string): boolean {
|
||||
return a === b
|
||||
|| a !== undefined
|
||||
&& b !== undefined
|
||||
&& a.toUpperCase() === b.toUpperCase();
|
||||
}
|
||||
1
scripts/vfs-core/src/functions.ts
Normal file
1
scripts/vfs-core/src/functions.ts
Normal file
@@ -0,0 +1 @@
|
||||
export function identity<T>(v: T): T { return v; }
|
||||
@@ -1,466 +1,3 @@
|
||||
export function identity<T>(v: T): T { return v; }
|
||||
|
||||
//
|
||||
// Comparers
|
||||
//
|
||||
|
||||
export function compareNumbers(a: number, b: number): number {
|
||||
if (a === b) return 0;
|
||||
if (a === undefined) return -1;
|
||||
if (b === undefined) return +1;
|
||||
return a < b ? -1 : +1;
|
||||
}
|
||||
|
||||
export function compareStrings(a: string, b: string, ignoreCase: boolean): number {
|
||||
return ignoreCase
|
||||
? compareStringsCaseInsensitive(a, b)
|
||||
: compareStringsCaseSensitive(a, b);
|
||||
}
|
||||
|
||||
// NOTE: This is a duplicate of `compareNumbers` above, but is intended to be used only with
|
||||
// strings to reduce polymorphism.
|
||||
export function compareStringsCaseSensitive(a: string, b: string): number {
|
||||
if (a === b) return 0;
|
||||
if (a === undefined) return -1;
|
||||
if (b === undefined) return +1;
|
||||
return a < b ? -1 : +1;
|
||||
}
|
||||
|
||||
export function compareStringsCaseInsensitive(a: string, b: string): number {
|
||||
if (a === b) return 0;
|
||||
if (a === undefined) return -1;
|
||||
if (b === undefined) return +1;
|
||||
a = a.toUpperCase();
|
||||
b = b.toUpperCase();
|
||||
return a < b ? -1 : a > b ? +1 : 0;
|
||||
}
|
||||
|
||||
export function equateStringsCaseSensitive(a: string, b: string): boolean {
|
||||
return a === b;
|
||||
}
|
||||
|
||||
export function equateStringsCaseInsensitive(a: string, b: string): boolean {
|
||||
return a === b
|
||||
|| a !== undefined
|
||||
&& b !== undefined
|
||||
&& a.toUpperCase() === b.toUpperCase();
|
||||
}
|
||||
|
||||
//
|
||||
// Collections
|
||||
//
|
||||
|
||||
export class SortedMap<K, V> {
|
||||
private _comparer: (a: K, b: K) => number;
|
||||
private _keys: K[] = [];
|
||||
private _values: V[] = [];
|
||||
private _version = 0;
|
||||
private _copyOnWrite = false;
|
||||
|
||||
constructor(comparer: (a: K, b: K) => number, iterable?: Iterable<[K, V]>) {
|
||||
this._comparer = comparer;
|
||||
if (iterable) {
|
||||
for (const [key, value] of iterable) {
|
||||
this.set(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get size() {
|
||||
return this._keys.length;
|
||||
}
|
||||
|
||||
public get [Symbol.toStringTag]() {
|
||||
return "SortedMap";
|
||||
}
|
||||
|
||||
public has(key: K) {
|
||||
return binarySearch(this._keys, key, identity, this._comparer) >= 0;
|
||||
}
|
||||
|
||||
public get(key: K) {
|
||||
const index = binarySearch(this._keys, key, identity, this._comparer);
|
||||
return index >= 0 ? this._values[index] : undefined;
|
||||
}
|
||||
|
||||
public set(key: K, value: V) {
|
||||
const index = binarySearch(this._keys, key, identity, this._comparer);
|
||||
if (index >= 0) {
|
||||
this._values[index] = value;
|
||||
}
|
||||
else {
|
||||
this.writePreamble();
|
||||
insertAt(this._keys, ~index, key);
|
||||
insertAt(this._values, ~index, value);
|
||||
this.writePostScript();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public delete(key: K) {
|
||||
const index = binarySearch(this._keys, key, identity, this._comparer);
|
||||
if (index >= 0) {
|
||||
this.writePreamble();
|
||||
removeAt(this._keys, index);
|
||||
removeAt(this._values, index);
|
||||
this.writePostScript();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public clear() {
|
||||
if (this.size > 0) {
|
||||
this.writePreamble();
|
||||
this._keys.length = 0;
|
||||
this._values.length = 0;
|
||||
this.writePostScript();
|
||||
}
|
||||
}
|
||||
|
||||
public forEach(callback: (value: V, key: K, collection: this) => void, thisArg?: any) {
|
||||
const keys = this._keys;
|
||||
const values = this._values;
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
callback.call(thisArg, values[i], keys[i], this);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public * keys() {
|
||||
const keys = this._keys;
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
yield keys[i];
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public * values() {
|
||||
const values = this._values;
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
yield values[i];
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public * entries() {
|
||||
const keys = this._keys;
|
||||
const values = this._values;
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
yield [keys[i], values[i]] as [K, V];
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public [Symbol.iterator]() {
|
||||
return this.entries();
|
||||
}
|
||||
|
||||
private writePreamble() {
|
||||
if (this._copyOnWrite) {
|
||||
this._keys = this._keys.slice();
|
||||
this._values = this._values.slice();
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
private writePostScript() {
|
||||
this._version++;
|
||||
}
|
||||
}
|
||||
|
||||
export class SortedSet<T> {
|
||||
private _comparer: (a: T, b: T) => number;
|
||||
private _values: T[] = [];
|
||||
private _version = 0;
|
||||
private _copyOnWrite = false;
|
||||
|
||||
constructor(comparer: (a: T, b: T) => number, iterable?: Iterable<T>) {
|
||||
this._comparer = comparer;
|
||||
|
||||
if (iterable) {
|
||||
for (const value of iterable) {
|
||||
this.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get size() {
|
||||
return this._values.length;
|
||||
}
|
||||
|
||||
public get [Symbol.toStringTag]() {
|
||||
return "SortedSet";
|
||||
}
|
||||
|
||||
public has(value: T) {
|
||||
return binarySearch(this._values, value, identity, this._comparer) >= 0;
|
||||
}
|
||||
|
||||
public add(value: T) {
|
||||
const index = binarySearch(this._values, value, identity, this._comparer);
|
||||
if (index < 0) {
|
||||
this.writePreamble();
|
||||
insertAt(this._values, ~index, value);
|
||||
this.writePostScript();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public delete(value: T) {
|
||||
const index = binarySearch(this._values, value, identity, this._comparer);
|
||||
if (index >= 0) {
|
||||
this.writePreamble();
|
||||
removeAt(this._values, index);
|
||||
this.writePostScript();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public clear() {
|
||||
if (this.size > 0) {
|
||||
this.writePreamble();
|
||||
this._values.length = 0;
|
||||
this.writePostScript();
|
||||
}
|
||||
}
|
||||
|
||||
public forEach(callback: (value: T, key: T, collection: this) => void, thisArg?: any) {
|
||||
const values = this._values;
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
for (const value of values) {
|
||||
callback.call(thisArg, value, value, this);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public keys() {
|
||||
return this.values();
|
||||
}
|
||||
|
||||
public * values() {
|
||||
const values = this._values;
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
for (const value of values) {
|
||||
yield value;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public * entries() {
|
||||
const values = this._values;
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
try {
|
||||
for (const value of values) {
|
||||
yield [value, value] as [T, T];
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public [Symbol.iterator]() {
|
||||
return this.values();
|
||||
}
|
||||
|
||||
private writePreamble() {
|
||||
if (this._copyOnWrite) {
|
||||
this._values = this._values.slice();
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
private writePostScript() {
|
||||
this._version++;
|
||||
}
|
||||
}
|
||||
|
||||
export function binarySearch<T, U>(array: ReadonlyArray<T>, value: T, keySelector: (v: T) => U, keyComparer: (a: U, b: U) => number, offset?: number): number {
|
||||
if (!array || array.length === 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
let low = offset || 0;
|
||||
let high = array.length - 1;
|
||||
const key = keySelector(value);
|
||||
while (low <= high) {
|
||||
const middle = low + ((high - low) >> 1);
|
||||
const midKey = keySelector(array[middle]);
|
||||
const result = keyComparer(midKey, key);
|
||||
if (result < 0) {
|
||||
low = middle + 1;
|
||||
}
|
||||
else if (result > 0) {
|
||||
high = middle - 1;
|
||||
}
|
||||
else {
|
||||
return middle;
|
||||
}
|
||||
}
|
||||
|
||||
return ~low;
|
||||
}
|
||||
|
||||
export function removeAt<T>(array: T[], index: number): void {
|
||||
if (index < 0 || index >= array.length) {
|
||||
return;
|
||||
}
|
||||
else if (index === 0) {
|
||||
array.shift();
|
||||
}
|
||||
else if (index === array.length - 1) {
|
||||
array.pop();
|
||||
}
|
||||
else {
|
||||
for (let i = index; i < array.length - 1; i++) {
|
||||
array[i] = array[i + 1];
|
||||
}
|
||||
array.length--;
|
||||
}
|
||||
}
|
||||
|
||||
export function insertAt<T>(array: T[], index: number, value: T): void {
|
||||
if (index === 0) {
|
||||
array.unshift(value);
|
||||
}
|
||||
else if (index === array.length) {
|
||||
array.push(value);
|
||||
}
|
||||
else {
|
||||
for (let i = array.length; i > index; i--) {
|
||||
array[i] = array[i - 1];
|
||||
}
|
||||
array[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of metadata that supports inheritance.
|
||||
*/
|
||||
export class Metadata {
|
||||
private static readonly _undefinedValue = {};
|
||||
private _parent: Metadata | undefined;
|
||||
private _map: { [key: string]: any };
|
||||
private _version = 0;
|
||||
private _size = -1;
|
||||
private _parentVersion: number | undefined;
|
||||
|
||||
constructor(parent?: Metadata) {
|
||||
this._parent = parent;
|
||||
this._map = Object.create(parent ? parent._map : null); // tslint:disable-line:no-null-keyword
|
||||
}
|
||||
|
||||
public get size(): number {
|
||||
if (this._size === -1 || (this._parent && this._parent._version !== this._parentVersion)) {
|
||||
let size = 0;
|
||||
for (const _ in this._map) size++;
|
||||
this._size = size;
|
||||
if (this._parent) {
|
||||
this._parentVersion = this._parent._version;
|
||||
}
|
||||
}
|
||||
return this._size;
|
||||
}
|
||||
|
||||
public get parent() {
|
||||
return this._parent;
|
||||
}
|
||||
|
||||
public has(key: string): boolean {
|
||||
return this._map[Metadata._escapeKey(key)] !== undefined;
|
||||
}
|
||||
|
||||
public get(key: string): any {
|
||||
const value = this._map[Metadata._escapeKey(key)];
|
||||
return value === Metadata._undefinedValue ? undefined : value;
|
||||
}
|
||||
|
||||
public set(key: string, value: any): this {
|
||||
this._map[Metadata._escapeKey(key)] = value === undefined ? Metadata._undefinedValue : value;
|
||||
this._size = -1;
|
||||
this._version++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public delete(key: string): boolean {
|
||||
const escapedKey = Metadata._escapeKey(key);
|
||||
if (this._map[escapedKey] !== undefined) {
|
||||
delete this._map[escapedKey];
|
||||
this._size = -1;
|
||||
this._version++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
this._map = Object.create(this._parent ? this._parent._map : null); // tslint:disable-line:no-null-keyword
|
||||
this._size = -1;
|
||||
this._version++;
|
||||
}
|
||||
|
||||
public forEach(callback: (value: any, key: string, map: this) => void) {
|
||||
for (const key in this._map) {
|
||||
callback(this._map[key], Metadata._unescapeKey(key), this);
|
||||
}
|
||||
}
|
||||
|
||||
private static _escapeKey(text: string) {
|
||||
return (text.length >= 2 && text.charAt(0) === "_" && text.charAt(1) === "_" ? "_" + text : text);
|
||||
}
|
||||
|
||||
private static _unescapeKey(text: string) {
|
||||
return (text.length >= 3 && text.charAt(0) === "_" && text.charAt(1) === "_" && text.charAt(2) === "_" ? text.slice(1) : text);
|
||||
}
|
||||
}
|
||||
export * from "./functions";
|
||||
export * from "./comparers";
|
||||
export * from "./collections";
|
||||
@@ -21,14 +21,14 @@ namespace compiler {
|
||||
public readonly shouldAssertInvariants = !Harness.lightMode;
|
||||
|
||||
private _setParentNodes: boolean;
|
||||
private _sourceFiles: core.KeyedCollection<string, ts.SourceFile>;
|
||||
private _sourceFiles: core.SortedMap<string, ts.SourceFile>;
|
||||
private _newLine: string;
|
||||
private _parseConfigHost: ParseConfigHost;
|
||||
|
||||
constructor(vfs: vfs.FileSystem, options: ts.CompilerOptions, setParentNodes = false) {
|
||||
this.vfs = vfs;
|
||||
this.defaultLibLocation = vfs.meta.get("defaultLibLocation") || "";
|
||||
this._sourceFiles = new core.KeyedCollection<string, ts.SourceFile>(this.vfs.stringComparer);
|
||||
this._sourceFiles = new core.SortedMap<string, ts.SourceFile>({ comparer: this.vfs.stringComparer, sort: "insertion" });
|
||||
this._newLine = options.newLine === ts.NewLineKind.LineFeed ? "\n" : "\r\n";
|
||||
this._setParentNodes = setParentNodes;
|
||||
}
|
||||
@@ -270,12 +270,12 @@ namespace compiler {
|
||||
public readonly result: ts.EmitResult | undefined;
|
||||
public readonly options: ts.CompilerOptions;
|
||||
public readonly diagnostics: ReadonlyArray<ts.Diagnostic>;
|
||||
public readonly js: core.ReadonlyKeyedCollection<string, documents.TextDocument>;
|
||||
public readonly dts: core.ReadonlyKeyedCollection<string, documents.TextDocument>;
|
||||
public readonly maps: core.ReadonlyKeyedCollection<string, documents.TextDocument>;
|
||||
public readonly js: ReadonlyMap<string, documents.TextDocument>;
|
||||
public readonly dts: ReadonlyMap<string, documents.TextDocument>;
|
||||
public readonly maps: ReadonlyMap<string, documents.TextDocument>;
|
||||
|
||||
private _inputs: documents.TextDocument[] = [];
|
||||
private _inputsAndOutputs: core.KeyedCollection<string, CompilationOutput>;
|
||||
private _inputsAndOutputs: core.SortedMap<string, CompilationOutput>;
|
||||
|
||||
constructor(host: CompilerHost, options: ts.CompilerOptions, program: ts.Program | undefined, result: ts.EmitResult | undefined, diagnostics: ts.Diagnostic[]) {
|
||||
this.host = host;
|
||||
@@ -285,9 +285,9 @@ namespace compiler {
|
||||
this.options = program ? program.getCompilerOptions() : options;
|
||||
|
||||
// collect outputs
|
||||
const js = this.js = new core.KeyedCollection<string, documents.TextDocument>(this.vfs.stringComparer);
|
||||
const dts = this.dts = new core.KeyedCollection<string, documents.TextDocument>(this.vfs.stringComparer);
|
||||
const maps = this.maps = new core.KeyedCollection<string, documents.TextDocument>(this.vfs.stringComparer);
|
||||
const js = this.js = new core.SortedMap<string, documents.TextDocument>({ comparer: this.vfs.stringComparer, sort: "insertion" });
|
||||
const dts = this.dts = new core.SortedMap<string, documents.TextDocument>({ comparer: this.vfs.stringComparer, sort: "insertion" });
|
||||
const maps = this.maps = new core.SortedMap<string, documents.TextDocument>({ comparer: this.vfs.stringComparer, sort: "insertion" });
|
||||
for (const document of this.host.outputs) {
|
||||
if (vfsutils.isJavaScript(document.file)) {
|
||||
js.set(document.file, document);
|
||||
@@ -301,7 +301,7 @@ namespace compiler {
|
||||
}
|
||||
|
||||
// correlate inputs and outputs
|
||||
this._inputsAndOutputs = new core.KeyedCollection<string, CompilationOutput>(this.vfs.stringComparer);
|
||||
this._inputsAndOutputs = new core.SortedMap<string, CompilationOutput>({ comparer: this.vfs.stringComparer, sort: "insertion" });
|
||||
if (program) {
|
||||
if (this.options.out || this.options.outFile) {
|
||||
const outFile = vpath.resolve(this.vfs.cwd(), this.options.outFile || this.options.out);
|
||||
|
||||
@@ -1,671 +1,62 @@
|
||||
// NOTE: The contents of this file are all exported from the namespace 'core'. This is to
|
||||
// support the eventual conversion of harness into a modular system.
|
||||
|
||||
// NOTE: Some of the functions here duplicate functionality from compiler/core.ts. They have been added
|
||||
// to reduce the number of direct dependencies on compiler and services to eventually break away
|
||||
// from depending directly on the compiler to speed up compilation time.
|
||||
// NOTE: This namespace re-exports all of the exports from the @typescript/harness-core private package.
|
||||
|
||||
namespace core {
|
||||
export function identity<T>(v: T): T { return v; }
|
||||
const _core = require("@typescript/harness-core");
|
||||
core.identity = _core.identity;
|
||||
core.compareNumbers = _core.compareNumbers;
|
||||
core.compareStrings = _core.compareStrings;
|
||||
core.compareStringsCaseSensitive = _core.compareStringsCaseSensitive;
|
||||
core.compareStringsCaseInsensitive = _core.compareStringsCaseInsensitive;
|
||||
core.equateStringsCaseSensitive = _core.equateStringsCaseSensitive;
|
||||
core.equateStringsCaseInsensitive = _core.equateStringsCaseInsensitive;
|
||||
core.SortedMap = _core.SortedMap;
|
||||
core.SortedSet = _core.SortedSet;
|
||||
core.binarySearch = _core.binarySearch;
|
||||
core.removeAt = _core.removeAt;
|
||||
core.insertAt = _core.insertAt;
|
||||
core.Metadata = _core.Metadata;
|
||||
core.padLeft = _core.padLeft;
|
||||
core.padRight = _core.padRight;
|
||||
core.getByteOrderMark = _core.getByteOrderMark;
|
||||
core.getByteOrderMarkLength = _core.getByteOrderMarkLength;
|
||||
core.removeByteOrderMark = _core.removeByteOrderMark;
|
||||
core.addUTF8ByteOrderMark = _core.addUTF8ByteOrderMark;
|
||||
core.getLinesAndLineStarts = _core.getLinesAndLineStarts;
|
||||
core.splitLines = _core.splitLines;
|
||||
core.computeLineStarts = _core.computeLineStarts;
|
||||
core.sha1 = _core.sha1;
|
||||
}
|
||||
|
||||
//
|
||||
// Comparers
|
||||
//
|
||||
|
||||
export type Comparer<T> = (x: T, y: T) => number;
|
||||
export type EqualityComparer<T> = (x: T, y: T) => boolean;
|
||||
|
||||
export function compareNumbers(a: number, b: number): number {
|
||||
if (a === b) return 0;
|
||||
if (a === undefined) return -1;
|
||||
if (b === undefined) return +1;
|
||||
return a < b ? -1 : +1;
|
||||
}
|
||||
|
||||
export function compareStrings(a: string, b: string, ignoreCase: boolean): number {
|
||||
return ignoreCase
|
||||
? compareStringsCaseInsensitive(a, b)
|
||||
: compareStringsCaseSensitive(a, b);
|
||||
}
|
||||
|
||||
// NOTE: This is a duplicate of `compareNumbers` above, but is intended to be used only with
|
||||
// strings to reduce polymorphism.
|
||||
export function compareStringsCaseSensitive(a: string, b: string): number {
|
||||
if (a === b) return 0;
|
||||
if (a === undefined) return -1;
|
||||
if (b === undefined) return +1;
|
||||
return a < b ? -1 : +1;
|
||||
}
|
||||
|
||||
export function compareStringsCaseInsensitive(a: string, b: string): number {
|
||||
if (a === b) return 0;
|
||||
if (a === undefined) return -1;
|
||||
if (b === undefined) return +1;
|
||||
a = a.toUpperCase();
|
||||
b = b.toUpperCase();
|
||||
return a < b ? -1 : a > b ? +1 : 0;
|
||||
}
|
||||
|
||||
export function equateStringsCaseSensitive(a: string, b: string): boolean {
|
||||
return a === b;
|
||||
}
|
||||
|
||||
export function equateStringsCaseInsensitive(a: string, b: string): boolean {
|
||||
return a === b
|
||||
|| a !== undefined
|
||||
&& b !== undefined
|
||||
&& a.toUpperCase() === b.toUpperCase();
|
||||
}
|
||||
|
||||
//
|
||||
// Collections
|
||||
//
|
||||
|
||||
export interface ReadonlyKeyedCollection<K, V> {
|
||||
readonly size: number;
|
||||
has(key: K): boolean;
|
||||
get(key: K): V | undefined;
|
||||
forEach(callback: (value: V, key: K, collection: this) => void): void;
|
||||
keys(): IterableIterator<K>;
|
||||
values(): IterableIterator<V>;
|
||||
entries(): IterableIterator<[K, V]>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of key/value pairs internally sorted by key.
|
||||
*/
|
||||
export class KeyedCollection<K, V> implements ReadonlyKeyedCollection<K, V> {
|
||||
private _comparer: (a: K, b: K) => number;
|
||||
private _keys: K[] = [];
|
||||
private _values: V[] = [];
|
||||
private _order: number[] = [];
|
||||
private _version = 0;
|
||||
private _copyOnWrite = false;
|
||||
|
||||
constructor(comparer: (a: K, b: K) => number) {
|
||||
this._comparer = comparer;
|
||||
declare module "_core" {
|
||||
import * as _core from "@typescript/harness-core";
|
||||
global {
|
||||
namespace core {
|
||||
export import identity = _core.identity;
|
||||
export import compareNumbers = _core.compareNumbers;
|
||||
export import compareStrings = _core.compareStrings;
|
||||
export import compareStringsCaseSensitive = _core.compareStringsCaseSensitive;
|
||||
export import compareStringsCaseInsensitive = _core.compareStringsCaseInsensitive;
|
||||
export import equateStringsCaseSensitive = _core.equateStringsCaseSensitive;
|
||||
export import equateStringsCaseInsensitive = _core.equateStringsCaseInsensitive;
|
||||
export import SortOptions = _core.SortOptions;
|
||||
export import SortedMap = _core.SortedMap;
|
||||
export import SortedSet = _core.SortedSet;
|
||||
export import binarySearch = _core.binarySearch;
|
||||
export import removeAt = _core.removeAt;
|
||||
export import insertAt = _core.insertAt;
|
||||
export import Metadata = _core.Metadata;
|
||||
export import padLeft = _core.padLeft;
|
||||
export import padRight = _core.padRight;
|
||||
export import getByteOrderMark = _core.getByteOrderMark;
|
||||
export import getByteOrderMarkLength = _core.getByteOrderMarkLength;
|
||||
export import removeByteOrderMark = _core.removeByteOrderMark;
|
||||
export import addUTF8ByteOrderMark = _core.addUTF8ByteOrderMark;
|
||||
export import LineStarts = _core.LineStarts;
|
||||
export import LinesAndLineStarts = _core.LinesAndLineStarts;
|
||||
export import getLinesAndLineStarts = _core.getLinesAndLineStarts;
|
||||
export import splitLines = _core.splitLines;
|
||||
export import computeLineStarts = _core.computeLineStarts;
|
||||
export import sha1 = _core.sha1;
|
||||
}
|
||||
|
||||
public get size() {
|
||||
return this._keys.length;
|
||||
}
|
||||
|
||||
public has(key: K) {
|
||||
return binarySearch(this._keys, key, identity, this._comparer) >= 0;
|
||||
}
|
||||
|
||||
public get(key: K) {
|
||||
const index = binarySearch(this._keys, key, identity, this._comparer);
|
||||
return index >= 0 ? this._values[index] : undefined;
|
||||
}
|
||||
|
||||
public set(key: K, value: V) {
|
||||
const index = binarySearch(this._keys, key, identity, this._comparer);
|
||||
if (index >= 0) {
|
||||
this._values[index] = value;
|
||||
}
|
||||
else {
|
||||
this.writePreamble();
|
||||
insertAt(this._keys, ~index, key);
|
||||
insertAt(this._values, ~index, value);
|
||||
insertAt(this._order, ~index, this._version);
|
||||
this.writePostScript();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public delete(key: K) {
|
||||
const index = binarySearch(this._keys, key, identity, this._comparer);
|
||||
if (index >= 0) {
|
||||
this.writePreamble();
|
||||
removeAt(this._keys, index);
|
||||
removeAt(this._values, index);
|
||||
removeAt(this._order, index);
|
||||
this.writePostScript();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public clear() {
|
||||
if (this.size > 0) {
|
||||
this.writePreamble();
|
||||
this._keys.length = 0;
|
||||
this._values.length = 0;
|
||||
this._order.length = 0;
|
||||
this.writePostScript();
|
||||
}
|
||||
}
|
||||
|
||||
public forEach(callback: (value: V, key: K, collection: this) => void) {
|
||||
const keys = this._keys;
|
||||
const values = this._values;
|
||||
const order = this.getInsertionOrder();
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
for (const index of order) {
|
||||
callback(values[index], keys[index], this);
|
||||
}
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
public * keys() {
|
||||
const keys = this._keys;
|
||||
const order = this.getInsertionOrder();
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
for (const index of order) {
|
||||
yield keys[index];
|
||||
}
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
public * values() {
|
||||
const values = this._values;
|
||||
const order = this.getInsertionOrder();
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
for (const index of order) {
|
||||
yield values[index];
|
||||
}
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
public * entries() {
|
||||
const keys = this._keys;
|
||||
const values = this._values;
|
||||
const order = this.getInsertionOrder();
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
for (const index of order) {
|
||||
yield [keys[index], values[index]] as [K, V];
|
||||
}
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
public [Symbol.iterator]() {
|
||||
return this.entries();
|
||||
}
|
||||
|
||||
private writePreamble() {
|
||||
if (this._copyOnWrite) {
|
||||
this._keys = this._keys.slice();
|
||||
this._values = this._values.slice();
|
||||
this._order = this._order.slice();
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
private writePostScript() {
|
||||
this._version++;
|
||||
}
|
||||
|
||||
private getInsertionOrder() {
|
||||
return this._order
|
||||
.map((_, i) => i)
|
||||
.sort((x, y) => this._order[x] - this._order[y]);
|
||||
}
|
||||
}
|
||||
|
||||
export class SortedSet<T> implements ReadonlySet<T> {
|
||||
private _comparer: (a: T, b: T) => number;
|
||||
private _values: T[] = [];
|
||||
private _version = 0;
|
||||
private _copyOnWrite = false;
|
||||
|
||||
constructor(comparer: (a: T, b: T) => number) {
|
||||
this._comparer = comparer;
|
||||
}
|
||||
|
||||
public get size() {
|
||||
return this._values.length;
|
||||
}
|
||||
|
||||
public has(value: T) {
|
||||
return binarySearch(this._values, value, identity, this._comparer) >= 0;
|
||||
}
|
||||
|
||||
public add(value: T) {
|
||||
const index = binarySearch(this._values, value, identity, this._comparer);
|
||||
if (index < 0) {
|
||||
this.writePreamble();
|
||||
insertAt(this._values, ~index, value);
|
||||
this.writePostScript();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public delete(value: T) {
|
||||
const index = binarySearch(this._values, value, identity, this._comparer);
|
||||
if (index >= 0) {
|
||||
this.writePreamble();
|
||||
removeAt(this._values, index);
|
||||
this.writePostScript();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public clear() {
|
||||
if (this.size > 0) {
|
||||
this.writePreamble();
|
||||
this._values.length = 0;
|
||||
this.writePostScript();
|
||||
}
|
||||
}
|
||||
|
||||
public forEach(callback: (value: T, key: T, collection: this) => void) {
|
||||
const values = this._values;
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
for (const value of values) {
|
||||
callback(value, value, this);
|
||||
}
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
public keys() {
|
||||
return this.values();
|
||||
}
|
||||
|
||||
public * values() {
|
||||
const values = this._values;
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
for (const value of values) {
|
||||
yield value;
|
||||
}
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
public * entries() {
|
||||
const values = this._values;
|
||||
const version = this._version;
|
||||
this._copyOnWrite = true;
|
||||
for (const value of values) {
|
||||
yield [value, value] as [T, T];
|
||||
}
|
||||
if (version === this._version) {
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
public [Symbol.iterator]() {
|
||||
return this.values();
|
||||
}
|
||||
|
||||
private writePreamble() {
|
||||
if (this._copyOnWrite) {
|
||||
this._values = this._values.slice();
|
||||
this._copyOnWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
private writePostScript() {
|
||||
this._version++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of metadata that supports inheritance.
|
||||
*/
|
||||
export class Metadata {
|
||||
private static readonly _undefinedValue = {};
|
||||
private _parent: Metadata | undefined;
|
||||
private _map: { [key: string]: any };
|
||||
private _version = 0;
|
||||
private _size = -1;
|
||||
private _parentVersion: number | undefined;
|
||||
|
||||
constructor(parent?: Metadata) {
|
||||
this._parent = parent;
|
||||
this._map = Object.create(parent ? parent._map : null); // tslint:disable-line:no-null-keyword
|
||||
}
|
||||
|
||||
public get size(): number {
|
||||
if (this._size === -1 || (this._parent && this._parent._version !== this._parentVersion)) {
|
||||
let size = 0;
|
||||
for (const _ in this._map) size++;
|
||||
this._size = size;
|
||||
if (this._parent) {
|
||||
this._parentVersion = this._parent._version;
|
||||
}
|
||||
}
|
||||
return this._size;
|
||||
}
|
||||
|
||||
public has(key: string): boolean {
|
||||
return this._map[Metadata._escapeKey(key)] !== undefined;
|
||||
}
|
||||
|
||||
public get(key: string): any {
|
||||
const value = this._map[Metadata._escapeKey(key)];
|
||||
return value === Metadata._undefinedValue ? undefined : value;
|
||||
}
|
||||
|
||||
public set(key: string, value: any): this {
|
||||
this._map[Metadata._escapeKey(key)] = value === undefined ? Metadata._undefinedValue : value;
|
||||
this._size = -1;
|
||||
this._version++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public delete(key: string): boolean {
|
||||
const escapedKey = Metadata._escapeKey(key);
|
||||
if (this._map[escapedKey] !== undefined) {
|
||||
delete this._map[escapedKey];
|
||||
this._size = -1;
|
||||
this._version++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
this._map = Object.create(this._parent ? this._parent._map : null); // tslint:disable-line:no-null-keyword
|
||||
this._size = -1;
|
||||
this._version++;
|
||||
}
|
||||
|
||||
public forEach(callback: (value: any, key: string, map: this) => void) {
|
||||
for (const key in this._map) {
|
||||
callback(this._map[key], Metadata._unescapeKey(key), this);
|
||||
}
|
||||
}
|
||||
|
||||
private static _escapeKey(text: string) {
|
||||
return (text.length >= 2 && text.charAt(0) === "_" && text.charAt(1) === "_" ? "_" + text : text);
|
||||
}
|
||||
|
||||
private static _unescapeKey(text: string) {
|
||||
return (text.length >= 3 && text.charAt(0) === "_" && text.charAt(1) === "_" && text.charAt(2) === "_" ? text.slice(1) : text);
|
||||
}
|
||||
}
|
||||
|
||||
export function binarySearch<T, U>(array: ReadonlyArray<T>, value: T, keySelector: (v: T) => U, keyComparer: Comparer<U>, offset?: number): number {
|
||||
if (!array || array.length === 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
let low = offset || 0;
|
||||
let high = array.length - 1;
|
||||
const key = keySelector(value);
|
||||
while (low <= high) {
|
||||
const middle = low + ((high - low) >> 1);
|
||||
const midKey = keySelector(array[middle]);
|
||||
const result = keyComparer(midKey, key);
|
||||
if (result < 0) {
|
||||
low = middle + 1;
|
||||
}
|
||||
else if (result > 0) {
|
||||
high = middle - 1;
|
||||
}
|
||||
else {
|
||||
return middle;
|
||||
}
|
||||
}
|
||||
|
||||
return ~low;
|
||||
}
|
||||
|
||||
export function removeAt<T>(array: T[], index: number): void {
|
||||
if (index < 0 || index >= array.length) {
|
||||
return;
|
||||
}
|
||||
else if (index === 0) {
|
||||
array.shift();
|
||||
}
|
||||
else if (index === array.length - 1) {
|
||||
array.pop();
|
||||
}
|
||||
else {
|
||||
for (let i = index; i < array.length - 1; i++) {
|
||||
array[i] = array[i + 1];
|
||||
}
|
||||
array.length--;
|
||||
}
|
||||
}
|
||||
|
||||
export function insertAt<T>(array: T[], index: number, value: T): void {
|
||||
if (index === 0) {
|
||||
array.unshift(value);
|
||||
}
|
||||
else if (index === array.length) {
|
||||
array.push(value);
|
||||
}
|
||||
else {
|
||||
for (let i = array.length; i > index; i--) {
|
||||
array[i] = array[i - 1];
|
||||
}
|
||||
array[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
export function stableSort<T>(array: T[], comparer: (x: T, y: T) => number): T[] {
|
||||
return array
|
||||
.map((_, i) => i) // create array of indices
|
||||
.sort((x, y) => comparer(array[x], array[y]) || x - y) // sort indices by value then position
|
||||
.map(i => array[i]); // get sorted array
|
||||
}
|
||||
|
||||
//
|
||||
// Strings
|
||||
//
|
||||
|
||||
export function padLeft(text: string, size: number, ch = " "): string {
|
||||
while (text.length < size) text = ch + text;
|
||||
return text;
|
||||
}
|
||||
|
||||
export function padRight(text: string, size: number, ch = " "): string {
|
||||
while (text.length < size) text += ch;
|
||||
return text;
|
||||
}
|
||||
|
||||
export function getByteOrderMark(text: string): string {
|
||||
const length = getByteOrderMarkLength(text);
|
||||
return length > 0 ? text.slice(0, length) : "";
|
||||
}
|
||||
|
||||
export function getByteOrderMarkLength(text: string): number {
|
||||
if (text.length >= 2) {
|
||||
const ch0 = text.charCodeAt(0);
|
||||
const ch1 = text.charCodeAt(1);
|
||||
if ((ch0 === 0xff && ch1 === 0xfe) ||
|
||||
(ch0 === 0xfe && ch1 === 0xff)) {
|
||||
return 2;
|
||||
}
|
||||
if (text.length >= 3 && ch0 === 0xef && ch1 === 0xbb && text.charCodeAt(2) === 0xbf) {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function removeByteOrderMark(text: string): string {
|
||||
const length = getByteOrderMarkLength(text);
|
||||
return length ? text.slice(length) : text;
|
||||
}
|
||||
|
||||
export function addUTF8ByteOrderMark(text: string) {
|
||||
return getByteOrderMarkLength(text) === 0 ? "\u00EF\u00BB\u00BF" + text : text;
|
||||
}
|
||||
|
||||
function splitLinesWorker(text: string, lineStarts: number[] | undefined, lines: string[] | undefined, removeEmptyElements: boolean) {
|
||||
let pos = 0;
|
||||
let end = 0;
|
||||
let lineStart = 0;
|
||||
let nonWhiteSpace = false;
|
||||
while (pos < text.length) {
|
||||
const ch = text.charCodeAt(pos);
|
||||
end = pos;
|
||||
pos++;
|
||||
switch (ch) {
|
||||
// LineTerminator
|
||||
case 0x000d: // <CR> carriage return
|
||||
if (pos < text.length && text.charCodeAt(pos) === 0x000a) {
|
||||
pos++;
|
||||
}
|
||||
// falls through
|
||||
|
||||
case 0x000a: // <LF> line feed
|
||||
case 0x2028: // <LS> line separator
|
||||
case 0x2029: // <PS> paragraph separator
|
||||
if (lineStarts) {
|
||||
lineStarts.push(lineStart);
|
||||
}
|
||||
if (lines && (!removeEmptyElements || nonWhiteSpace)) {
|
||||
lines.push(text.slice(lineStart, end));
|
||||
}
|
||||
lineStart = pos;
|
||||
nonWhiteSpace = false;
|
||||
break;
|
||||
|
||||
// WhiteSpace
|
||||
case 0x0009: // <TAB> tab
|
||||
case 0x000b: // <VT> vertical tab
|
||||
case 0x000c: // <FF> form feed
|
||||
case 0x0020: // <SP> space
|
||||
case 0x00a0: // <NBSP> no-break space
|
||||
case 0xfeff: // <ZWNBSP> zero width no-break space
|
||||
case 0x1680: // <USP> ogham space mark
|
||||
case 0x2000: // <USP> en quad
|
||||
case 0x2001: // <USP> em quad
|
||||
case 0x2002: // <USP> en space
|
||||
case 0x2003: // <USP> em space
|
||||
case 0x2004: // <USP> three-per-em space
|
||||
case 0x2005: // <USP> four-per-em space
|
||||
case 0x2006: // <USP> six-per-em space
|
||||
case 0x2007: // <USP> figure space
|
||||
case 0x2008: // <USP> punctuation space
|
||||
case 0x2009: // <USP> thin space
|
||||
case 0x200a: // <USP> hair space
|
||||
case 0x202f: // <USP> narrow no-break space
|
||||
case 0x205f: // <USP> medium mathematical space
|
||||
case 0x3000: // <USP> ideographic space
|
||||
case 0x0085: // next-line (not strictly per spec, but used by the compiler)
|
||||
break;
|
||||
|
||||
default:
|
||||
nonWhiteSpace = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lineStarts) {
|
||||
lineStarts.push(lineStart);
|
||||
}
|
||||
if (lines && (!removeEmptyElements || nonWhiteSpace)) {
|
||||
lines.push(text.slice(lineStart, text.length));
|
||||
}
|
||||
}
|
||||
|
||||
export type LineStarts = ReadonlyArray<number>;
|
||||
|
||||
export interface LinesAndLineStarts {
|
||||
readonly lines: ReadonlyArray<string>;
|
||||
readonly lineStarts: LineStarts;
|
||||
}
|
||||
|
||||
export function getLinesAndLineStarts(text: string): LinesAndLineStarts {
|
||||
const lines: string[] = [];
|
||||
const lineStarts: number[] = [];
|
||||
splitLinesWorker(text, lineStarts, lines, /*removeEmptyElements*/ false);
|
||||
return { lines, lineStarts };
|
||||
}
|
||||
|
||||
export function splitLines(text: string, removeEmptyElements = false): string[] {
|
||||
const lines: string[] = [];
|
||||
splitLinesWorker(text, /*lineStarts*/ undefined, lines, removeEmptyElements);
|
||||
return lines;
|
||||
}
|
||||
|
||||
export function computeLineStarts(text: string): LineStarts {
|
||||
const lineStarts: number[] = [];
|
||||
splitLinesWorker(text, lineStarts, /*lines*/ undefined, /*removeEmptyElements*/ false);
|
||||
return lineStarts;
|
||||
}
|
||||
|
||||
//
|
||||
// Cryptography
|
||||
//
|
||||
|
||||
const H = new Uint32Array(5);
|
||||
const W = new Uint8Array(80);
|
||||
const B = new Uint8Array(64);
|
||||
const BLOCK_SIZE = 64;
|
||||
|
||||
export function sha1(message: string): string {
|
||||
let buffer = B;
|
||||
const textSize = message.length;
|
||||
const messageSize = textSize * 2;
|
||||
const finalBlockSize = messageSize % BLOCK_SIZE;
|
||||
const padSize = (finalBlockSize < BLOCK_SIZE - 8 - 1 ? BLOCK_SIZE : BLOCK_SIZE * 2) - finalBlockSize;
|
||||
const byteLength = messageSize + padSize;
|
||||
if (byteLength > BLOCK_SIZE) {
|
||||
buffer = new Uint8Array(byteLength);
|
||||
}
|
||||
|
||||
const bufferView = new DataView(buffer.buffer);
|
||||
for (let i = 0; i < textSize; ++i) {
|
||||
bufferView.setUint16(i * 2, message.charCodeAt(i));
|
||||
}
|
||||
|
||||
buffer[messageSize] = 0x80;
|
||||
bufferView.setUint32(byteLength - 4, messageSize * 8);
|
||||
H[0] = 0x67452301, H[1] = 0xefcdab89, H[2] = 0x98badcfe, H[3] = 0x10325476, H[4] = 0xc3d2e1f0;
|
||||
for (let offset = 0; offset < byteLength; offset += BLOCK_SIZE) {
|
||||
let a = H[0], b = H[1], c = H[2], d = H[3], e = H[4];
|
||||
for (let i = 0; i < 80; ++i) {
|
||||
if (i < 16) {
|
||||
const x = offset + i * 4;
|
||||
W[i] = buffer[x] << 24 | buffer[x + 1] << 16 | buffer[x + 2] << 8 | buffer[x + 3];
|
||||
}
|
||||
else {
|
||||
const x = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
|
||||
W[i] = (x << 1 | x >>> 31) >>> 0;
|
||||
}
|
||||
|
||||
let t = (a << 5 | a >>> 27) >>> 0 + e + W[i];
|
||||
if (i < 20) {
|
||||
t += ((b & c) | (~b & d)) + 0x5A827999;
|
||||
}
|
||||
else if (i < 40) {
|
||||
t += (b ^ c ^ d) + 0x6ED9EBA1;
|
||||
}
|
||||
else if (i < 60) {
|
||||
t += ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC;
|
||||
}
|
||||
else {
|
||||
t += (b ^ c ^ d) + 0xCA62C1D6;
|
||||
}
|
||||
|
||||
e = d, d = c, c = (b << 30 | b >>> 2) >>> 0, b = a, a = t;
|
||||
}
|
||||
|
||||
H[0] += a, H[1] += b, H[2] += c, H[3] += d, H[4] += e;
|
||||
}
|
||||
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
bufferView.setUint32(i * 4, H[i]);
|
||||
}
|
||||
|
||||
let result = "";
|
||||
for (let i = 0; i < 20; ++i) {
|
||||
result += (buffer[i] < 16 ? "0" : "") + buffer[i].toString(16);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -78,11 +78,11 @@ namespace fakes {
|
||||
private readonly _executingFilePath: string;
|
||||
private readonly _getCanonicalFileName: (file: string) => string;
|
||||
private _screenClears = 0;
|
||||
private _watchedFiles: core.KeyedCollection<string, number> | undefined;
|
||||
private _watchedFiles: core.SortedMap<string, number> | undefined;
|
||||
private _watchedFilesSet: core.SortedSet<string> | undefined;
|
||||
private _watchedRecursiveDirectories: core.KeyedCollection<string, number> | undefined;
|
||||
private _watchedRecursiveDirectories: core.SortedMap<string, number> | undefined;
|
||||
private _watchedRecursiveDirectoriesSet: core.SortedSet<string> | undefined;
|
||||
private _watchedNonRecursiveDirectories: core.KeyedCollection<string, number> | undefined;
|
||||
private _watchedNonRecursiveDirectories: core.SortedMap<string, number> | undefined;
|
||||
private _watchedNonRecursiveDirectoriesSet: core.SortedSet<string> | undefined;
|
||||
|
||||
constructor(options: FakeServerHostOptions = {}, files?: vfs.FileSet) {
|
||||
@@ -201,7 +201,7 @@ namespace fakes {
|
||||
}
|
||||
|
||||
public watchFile(path: string, cb: ts.FileWatcherCallback) {
|
||||
if (!this._watchedFiles) this._watchedFiles = new core.KeyedCollection<string, number>(this.vfs.stringComparer);
|
||||
if (!this._watchedFiles) this._watchedFiles = new core.SortedMap<string, number>({ comparer: this.vfs.stringComparer, sort: "insertion" });
|
||||
if (!this._watchedFilesSet) this._watchedFilesSet = new core.SortedSet<string>(this.vfs.stringComparer);
|
||||
|
||||
const previousCount = this._watchedFiles.get(path) || 0;
|
||||
@@ -235,8 +235,8 @@ namespace fakes {
|
||||
|
||||
public watchDirectory(path: string, cb: ts.DirectoryWatcherCallback, recursive?: boolean): ts.FileWatcher {
|
||||
const watchedDirectories = recursive
|
||||
? this._watchedRecursiveDirectories || (this._watchedRecursiveDirectories = new core.KeyedCollection(this.vfs.stringComparer))
|
||||
: this._watchedNonRecursiveDirectories || (this._watchedNonRecursiveDirectories = new core.KeyedCollection(this.vfs.stringComparer));
|
||||
? this._watchedRecursiveDirectories || (this._watchedRecursiveDirectories = new core.SortedMap({ comparer: this.vfs.stringComparer, sort: "insertion" }))
|
||||
: this._watchedNonRecursiveDirectories || (this._watchedNonRecursiveDirectories = new core.SortedMap({ comparer: this.vfs.stringComparer, sort: "insertion" }));
|
||||
|
||||
const watchedDirectoriesSet = recursive
|
||||
? this._watchedRecursiveDirectoriesSet || (this._watchedRecursiveDirectoriesSet = new core.SortedSet(this.vfs.stringComparer))
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
/// <reference path="./core.ts" />
|
||||
/// <reference path="./utils.ts" />
|
||||
/// <reference path="./vfs.ts" />
|
||||
|
||||
// NOTE: The contents of this file are all exported from the namespace 'typemock'. This is to
|
||||
// support the eventual conversion of harness into a modular system.
|
||||
// NOTE: This namespace re-exports all of the exports from the typemock private package.
|
||||
|
||||
// typemock library
|
||||
namespace typemock {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path="./core.ts" />
|
||||
|
||||
// NOTE: The contents of this file are all exported from the namespace 'core'. This is to
|
||||
// NOTE: The contents of this file are all exported from the namespace 'utils'. This is to
|
||||
// support the eventual conversion of harness into a modular system.
|
||||
|
||||
namespace utils {
|
||||
|
||||
@@ -1,43 +1,35 @@
|
||||
/// <reference path="../compiler/commandLineParser.ts"/>
|
||||
/// <reference path="./harness.ts" />
|
||||
/// <reference path="./core.ts" />
|
||||
/// <reference path="./events.ts" />
|
||||
/// <reference path="./vpath.ts" />
|
||||
/// <reference path="./documents.ts" />
|
||||
|
||||
// NOTE: The contents of this file are all exported from the namespace 'vfs'. This is to
|
||||
// support the eventual conversion of harness into a modular system.
|
||||
// NOTE: This namespace re-exports all of the exports from the @typescript/vfs private package.
|
||||
|
||||
namespace vfs {
|
||||
const module = require("@typescript/vfs");
|
||||
vfs.Directory = module.Directory;
|
||||
vfs.File = module.File;
|
||||
vfs.Link = module.Link;
|
||||
vfs.Symlink = module.Symlink;
|
||||
vfs.Mount = module.Mount;
|
||||
vfs.FileSystem = module.FileSystem;
|
||||
vfs.Stats = module.Stats;
|
||||
vfs.FSWatcher = module.FSWatcher;
|
||||
const _vfs = require("@typescript/vfs");
|
||||
vfs.Directory = _vfs.Directory;
|
||||
vfs.File = _vfs.File;
|
||||
vfs.Link = _vfs.Link;
|
||||
vfs.Symlink = _vfs.Symlink;
|
||||
vfs.Mount = _vfs.Mount;
|
||||
vfs.FileSystem = _vfs.FileSystem;
|
||||
vfs.Stats = _vfs.Stats;
|
||||
vfs.FSWatcher = _vfs.FSWatcher;
|
||||
}
|
||||
|
||||
declare module "vfs_" {
|
||||
import * as vfs_ from "@typescript/vfs";
|
||||
declare module "_vfs" {
|
||||
import * as _vfs from "@typescript/vfs";
|
||||
global {
|
||||
namespace vfs {
|
||||
export import FileSystemResolver = vfs_.FileSystemResolver;
|
||||
export import FileSystemTimers = vfs_.FileSystemTimers;
|
||||
export import FileSet = vfs_.FileSet;
|
||||
export import Directory = vfs_.Directory;
|
||||
export import DirectoryLike = vfs_.DirectoryLike;
|
||||
export import File = vfs_.File;
|
||||
export import FileLike = vfs_.FileLike;
|
||||
export import Link = vfs_.Link;
|
||||
export import Symlink = vfs_.Symlink;
|
||||
export import Mount = vfs_.Mount;
|
||||
export import FileSystemOptions = vfs_.FileSystemOptions;
|
||||
export import FileSystem = vfs_.FileSystem;
|
||||
export import Stats = vfs_.Stats;
|
||||
export import FSWatcher = vfs_.FSWatcher;
|
||||
export import FileSystemResolver = _vfs.FileSystemResolver;
|
||||
export import FileSystemTimers = _vfs.FileSystemTimers;
|
||||
export import FileSet = _vfs.FileSet;
|
||||
export import Directory = _vfs.Directory;
|
||||
export import DirectoryLike = _vfs.DirectoryLike;
|
||||
export import File = _vfs.File;
|
||||
export import FileLike = _vfs.FileLike;
|
||||
export import Link = _vfs.Link;
|
||||
export import Symlink = _vfs.Symlink;
|
||||
export import Mount = _vfs.Mount;
|
||||
export import FileSystemOptions = _vfs.FileSystemOptions;
|
||||
export import FileSystem = _vfs.FileSystem;
|
||||
export import Stats = _vfs.Stats;
|
||||
export import FSWatcher = _vfs.FSWatcher;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,66 +1,61 @@
|
||||
// NOTE: The contents of this file are all exported from the namespace 'vpath'. This is to
|
||||
// support the eventual conversion of harness into a modular system.
|
||||
|
||||
// NOTE: Some of the functions here duplicate functionality from compiler/core.ts. They have been
|
||||
// added to reduce the number of direct dependencies on compiler and services to eventually
|
||||
// break away from depending directly on the compiler to speed up compilation time.
|
||||
// NOTE: This namespace re-exports all of the exports from the @typescript/vfs-path private package.
|
||||
|
||||
namespace vpath {
|
||||
const module = require("@typescript/vfs-path");
|
||||
vpath.sep = module.sep;
|
||||
vpath.normalizeSeparators = module.normalizeSeparators;
|
||||
(<any>vpath).ValidationFlags = module.ValidationFlags;
|
||||
vpath.valid = module.valid;
|
||||
vpath.validate = module.validate;
|
||||
vpath.isAbsolute = module.isAbsolute;
|
||||
vpath.hasTrailingSeparator = module.hasTrailingSeparator;
|
||||
vpath.addTrailingSeparator = module.addTrailingSeparator;
|
||||
vpath.removeTrailingSeparator = module.removeTrailingSeparator;
|
||||
vpath.normalize = module.normalize;
|
||||
vpath.combine = module.combine;
|
||||
vpath.resolve = module.resolve;
|
||||
vpath.relative = module.relative;
|
||||
vpath.compareCaseSensitive = module.compareCaseSensitive;
|
||||
vpath.compareCaseInsensitive = module.compareCaseInsensitive;
|
||||
vpath.compare = module.compare;
|
||||
vpath.equals = module.equals;
|
||||
vpath.beneath = module.beneath;
|
||||
vpath.parse = module.parse;
|
||||
vpath.format = module.format;
|
||||
vpath.dirname = module.dirname;
|
||||
vpath.basename = module.basename;
|
||||
vpath.extname = module.extname;
|
||||
vpath.changeExtension = module.changeExtension;
|
||||
const _vpath = require("@typescript/vfs-path") as typeof vpath;
|
||||
vpath.sep = _vpath.sep;
|
||||
vpath.normalizeSeparators = _vpath.normalizeSeparators;
|
||||
(<any>vpath).ValidationFlags = (<any>_vpath).ValidationFlags;
|
||||
vpath.valid = _vpath.valid;
|
||||
vpath.validate = _vpath.validate;
|
||||
vpath.isAbsolute = _vpath.isAbsolute;
|
||||
vpath.hasTrailingSeparator = _vpath.hasTrailingSeparator;
|
||||
vpath.addTrailingSeparator = _vpath.addTrailingSeparator;
|
||||
vpath.removeTrailingSeparator = _vpath.removeTrailingSeparator;
|
||||
vpath.normalize = _vpath.normalize;
|
||||
vpath.combine = _vpath.combine;
|
||||
vpath.resolve = _vpath.resolve;
|
||||
vpath.relative = _vpath.relative;
|
||||
vpath.compareCaseSensitive = _vpath.compareCaseSensitive;
|
||||
vpath.compareCaseInsensitive = _vpath.compareCaseInsensitive;
|
||||
vpath.compare = _vpath.compare;
|
||||
vpath.equals = _vpath.equals;
|
||||
vpath.beneath = _vpath.beneath;
|
||||
vpath.parse = _vpath.parse;
|
||||
vpath.format = _vpath.format;
|
||||
vpath.dirname = _vpath.dirname;
|
||||
vpath.basename = _vpath.basename;
|
||||
vpath.extname = _vpath.extname;
|
||||
vpath.changeExtension = _vpath.changeExtension;
|
||||
}
|
||||
|
||||
declare module "vpath_" {
|
||||
import * as vpath_ from "@typescript/vfs-path";
|
||||
declare module "_vpath" {
|
||||
import * as _vpath from "@typescript/vfs-path";
|
||||
global {
|
||||
namespace vpath {
|
||||
export import sep = vpath_.sep;
|
||||
export import normalizeSeparators = vpath_.normalizeSeparators;
|
||||
export import ValidationFlags = vpath_.ValidationFlags;
|
||||
export import valid = vpath_.valid;
|
||||
export import validate = vpath_.validate;
|
||||
export import isAbsolute = vpath_.isAbsolute;
|
||||
export import hasTrailingSeparator = vpath_.hasTrailingSeparator;
|
||||
export import addTrailingSeparator = vpath_.addTrailingSeparator;
|
||||
export import removeTrailingSeparator = vpath_.removeTrailingSeparator;
|
||||
export import normalize = vpath_.normalize;
|
||||
export import combine = vpath_.combine;
|
||||
export import resolve = vpath_.resolve;
|
||||
export import relative = vpath_.relative;
|
||||
export import compareCaseSensitive = vpath_.compareCaseSensitive;
|
||||
export import compareCaseInsensitive = vpath_.compareCaseInsensitive;
|
||||
export import compare = vpath_.compare;
|
||||
export import equals = vpath_.equals;
|
||||
export import beneath = vpath_.beneath;
|
||||
export import parse = vpath_.parse;
|
||||
export import format = vpath_.format;
|
||||
export import dirname = vpath_.dirname;
|
||||
export import basename = vpath_.basename;
|
||||
export import extname = vpath_.extname;
|
||||
export import changeExtension = vpath_.changeExtension;
|
||||
export import sep = _vpath.sep;
|
||||
export import normalizeSeparators = _vpath.normalizeSeparators;
|
||||
export import ValidationFlags = _vpath.ValidationFlags;
|
||||
export import valid = _vpath.valid;
|
||||
export import validate = _vpath.validate;
|
||||
export import isAbsolute = _vpath.isAbsolute;
|
||||
export import hasTrailingSeparator = _vpath.hasTrailingSeparator;
|
||||
export import addTrailingSeparator = _vpath.addTrailingSeparator;
|
||||
export import removeTrailingSeparator = _vpath.removeTrailingSeparator;
|
||||
export import normalize = _vpath.normalize;
|
||||
export import combine = _vpath.combine;
|
||||
export import resolve = _vpath.resolve;
|
||||
export import relative = _vpath.relative;
|
||||
export import compareCaseSensitive = _vpath.compareCaseSensitive;
|
||||
export import compareCaseInsensitive = _vpath.compareCaseInsensitive;
|
||||
export import compare = _vpath.compare;
|
||||
export import equals = _vpath.equals;
|
||||
export import beneath = _vpath.beneath;
|
||||
export import parse = _vpath.parse;
|
||||
export import format = _vpath.format;
|
||||
export import dirname = _vpath.dirname;
|
||||
export import basename = _vpath.basename;
|
||||
export import extname = _vpath.extname;
|
||||
export import changeExtension = _vpath.changeExtension;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user