From 4d8d51452c746094cf6356722296236c2c2a9465 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 30 Jan 2018 11:57:47 -0800 Subject: [PATCH] Migrate core.ts --- Gulpfile.ts | 60 +-- Jakefile.js | 86 +--- jenkins.sh | 5 + package.json | 1 + scripts/harness-core/gulpfile.js | 18 + scripts/harness-core/package.json | 23 + scripts/harness-core/src/crypto.ts | 67 +++ scripts/harness-core/src/index.ts | 3 + scripts/harness-core/src/strings.ts | 132 +++++ scripts/harness-core/tsconfig.json | 15 + scripts/vfs-core/src/collections.ts | 509 ++++++++++++++++++++ scripts/vfs-core/src/comparers.ts | 41 ++ scripts/vfs-core/src/functions.ts | 1 + scripts/vfs-core/src/index.ts | 469 +----------------- src/harness/compiler.ts | 20 +- src/harness/core.ts | 721 +++------------------------- src/harness/fakes.ts | 12 +- src/harness/typemock.ts | 7 +- src/harness/utils.ts | 2 +- src/harness/vfs.ts | 60 +-- src/harness/vpath.ts | 109 ++--- 21 files changed, 1004 insertions(+), 1357 deletions(-) create mode 100644 scripts/harness-core/gulpfile.js create mode 100644 scripts/harness-core/package.json create mode 100644 scripts/harness-core/src/crypto.ts create mode 100644 scripts/harness-core/src/index.ts create mode 100644 scripts/harness-core/src/strings.ts create mode 100644 scripts/harness-core/tsconfig.json create mode 100644 scripts/vfs-core/src/collections.ts create mode 100644 scripts/vfs-core/src/comparers.ts create mode 100644 scripts/vfs-core/src/functions.ts diff --git a/Gulpfile.ts b/Gulpfile.ts index 75acd182561..e34bc2b5c26 100644 --- a/Gulpfile.ts +++ b/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(".", { sourceRoot: "../src", includeContent: false, destPath: "scripts/typemock/dist" })) - .pipe(gulp.dest("scripts/typemock/dist")); -}); + .pipe(sourcemaps.write(".", { 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(".", { 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(".", { 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(".", { 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(".", { 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"); diff --git a/Jakefile.js b/Jakefile.js index aff71dc7be3..ddae2021484 100644 --- a/Jakefile.js +++ b/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"); diff --git a/jenkins.sh b/jenkins.sh index b716f5bbeb2..62d0b6e1509 100755 --- a/jenkins.sh +++ b/jenkins.sh @@ -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 diff --git a/package.json b/package.json index e670760663d..cf109417b9f 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/scripts/harness-core/gulpfile.js b/scripts/harness-core/gulpfile.js new file mode 100644 index 00000000000..31c28436446 --- /dev/null +++ b/scripts/harness-core/gulpfile.js @@ -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"]); \ No newline at end of file diff --git a/scripts/harness-core/package.json b/scripts/harness-core/package.json new file mode 100644 index 00000000000..6967fcdb792 --- /dev/null +++ b/scripts/harness-core/package.json @@ -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" + } +} diff --git a/scripts/harness-core/src/crypto.ts b/scripts/harness-core/src/crypto.ts new file mode 100644 index 00000000000..b74413b0f2b --- /dev/null +++ b/scripts/harness-core/src/crypto.ts @@ -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; +} \ No newline at end of file diff --git a/scripts/harness-core/src/index.ts b/scripts/harness-core/src/index.ts new file mode 100644 index 00000000000..6047bb0716e --- /dev/null +++ b/scripts/harness-core/src/index.ts @@ -0,0 +1,3 @@ +export * from "@typescript/vfs-core"; +export * from "./strings"; +export * from "./crypto"; \ No newline at end of file diff --git a/scripts/harness-core/src/strings.ts b/scripts/harness-core/src/strings.ts new file mode 100644 index 00000000000..23ae7ef4467 --- /dev/null +++ b/scripts/harness-core/src/strings.ts @@ -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: // carriage return + if (pos < text.length && text.charCodeAt(pos) === 0x000a) { + pos++; + } + // falls through + + case 0x000a: // line feed + case 0x2028: // line separator + case 0x2029: // 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 + case 0x000b: // vertical tab + case 0x000c: // form feed + case 0x0020: // space + case 0x00a0: // no-break space + case 0xfeff: // zero width no-break space + case 0x1680: // ogham space mark + case 0x2000: // en quad + case 0x2001: // em quad + case 0x2002: // en space + case 0x2003: // em space + case 0x2004: // three-per-em space + case 0x2005: // four-per-em space + case 0x2006: // six-per-em space + case 0x2007: // figure space + case 0x2008: // punctuation space + case 0x2009: // thin space + case 0x200a: // hair space + case 0x202f: // narrow no-break space + case 0x205f: // medium mathematical space + case 0x3000: // 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; + +export interface LinesAndLineStarts { + readonly lines: ReadonlyArray; + 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; +} \ No newline at end of file diff --git a/scripts/harness-core/tsconfig.json b/scripts/harness-core/tsconfig.json new file mode 100644 index 00000000000..637d5c89c31 --- /dev/null +++ b/scripts/harness-core/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "es2015", + "module": "commonjs", + "outDir": "dist", + "types": ["node"], + "declaration": true, + "sourceMap": true, + "strict": true, + "preserveConstEnums": true + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file diff --git a/scripts/vfs-core/src/collections.ts b/scripts/vfs-core/src/collections.ts new file mode 100644 index 00000000000..5c4fa94d5d5 --- /dev/null +++ b/scripts/vfs-core/src/collections.ts @@ -0,0 +1,509 @@ +import { identity } from "./functions"; + +export interface SortOptions { + comparer: (a: T, b: T) => number; + sort: "insertion" | "comparison"; +} + +export class SortedMap { + 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, 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 { + 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, iterable?: Iterable) { + 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(array: ReadonlyArray, 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(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(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); + } +} \ No newline at end of file diff --git a/scripts/vfs-core/src/comparers.ts b/scripts/vfs-core/src/comparers.ts new file mode 100644 index 00000000000..589a631c7c7 --- /dev/null +++ b/scripts/vfs-core/src/comparers.ts @@ -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(); +} diff --git a/scripts/vfs-core/src/functions.ts b/scripts/vfs-core/src/functions.ts new file mode 100644 index 00000000000..c8fd7fb1305 --- /dev/null +++ b/scripts/vfs-core/src/functions.ts @@ -0,0 +1 @@ +export function identity(v: T): T { return v; } diff --git a/scripts/vfs-core/src/index.ts b/scripts/vfs-core/src/index.ts index 966c050b0bf..7d7770a5a3d 100644 --- a/scripts/vfs-core/src/index.ts +++ b/scripts/vfs-core/src/index.ts @@ -1,466 +1,3 @@ -export function identity(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 { - 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 { - 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) { - 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(array: ReadonlyArray, 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(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(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); - } -} \ No newline at end of file +export * from "./functions"; +export * from "./comparers"; +export * from "./collections"; \ No newline at end of file diff --git a/src/harness/compiler.ts b/src/harness/compiler.ts index b6481612d80..6c38edb37ef 100644 --- a/src/harness/compiler.ts +++ b/src/harness/compiler.ts @@ -21,14 +21,14 @@ namespace compiler { public readonly shouldAssertInvariants = !Harness.lightMode; private _setParentNodes: boolean; - private _sourceFiles: core.KeyedCollection; + private _sourceFiles: core.SortedMap; 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(this.vfs.stringComparer); + this._sourceFiles = new core.SortedMap({ 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; - public readonly js: core.ReadonlyKeyedCollection; - public readonly dts: core.ReadonlyKeyedCollection; - public readonly maps: core.ReadonlyKeyedCollection; + public readonly js: ReadonlyMap; + public readonly dts: ReadonlyMap; + public readonly maps: ReadonlyMap; private _inputs: documents.TextDocument[] = []; - private _inputsAndOutputs: core.KeyedCollection; + private _inputsAndOutputs: core.SortedMap; 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(this.vfs.stringComparer); - const dts = this.dts = new core.KeyedCollection(this.vfs.stringComparer); - const maps = this.maps = new core.KeyedCollection(this.vfs.stringComparer); + const js = this.js = new core.SortedMap({ comparer: this.vfs.stringComparer, sort: "insertion" }); + const dts = this.dts = new core.SortedMap({ comparer: this.vfs.stringComparer, sort: "insertion" }); + const maps = this.maps = new core.SortedMap({ 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(this.vfs.stringComparer); + this._inputsAndOutputs = new core.SortedMap({ 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); diff --git a/src/harness/core.ts b/src/harness/core.ts index 94988774955..7a85d8c93e3 100644 --- a/src/harness/core.ts +++ b/src/harness/core.ts @@ -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(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 = (x: T, y: T) => number; - export type EqualityComparer = (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 { - readonly size: number; - has(key: K): boolean; - get(key: K): V | undefined; - forEach(callback: (value: V, key: K, collection: this) => void): void; - keys(): IterableIterator; - values(): IterableIterator; - entries(): IterableIterator<[K, V]>; - } - - /** - * A collection of key/value pairs internally sorted by key. - */ - export class KeyedCollection implements ReadonlyKeyedCollection { - 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 implements ReadonlySet { - 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(array: ReadonlyArray, value: T, keySelector: (v: T) => U, keyComparer: Comparer, 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(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(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(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: // carriage return - if (pos < text.length && text.charCodeAt(pos) === 0x000a) { - pos++; - } - // falls through - - case 0x000a: // line feed - case 0x2028: // line separator - case 0x2029: // 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 - case 0x000b: // vertical tab - case 0x000c: // form feed - case 0x0020: // space - case 0x00a0: // no-break space - case 0xfeff: // zero width no-break space - case 0x1680: // ogham space mark - case 0x2000: // en quad - case 0x2001: // em quad - case 0x2002: // en space - case 0x2003: // em space - case 0x2004: // three-per-em space - case 0x2005: // four-per-em space - case 0x2006: // six-per-em space - case 0x2007: // figure space - case 0x2008: // punctuation space - case 0x2009: // thin space - case 0x200a: // hair space - case 0x202f: // narrow no-break space - case 0x205f: // medium mathematical space - case 0x3000: // 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; - - export interface LinesAndLineStarts { - readonly lines: ReadonlyArray; - 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; } } \ No newline at end of file diff --git a/src/harness/fakes.ts b/src/harness/fakes.ts index 56687e6d12c..23b34109788 100644 --- a/src/harness/fakes.ts +++ b/src/harness/fakes.ts @@ -78,11 +78,11 @@ namespace fakes { private readonly _executingFilePath: string; private readonly _getCanonicalFileName: (file: string) => string; private _screenClears = 0; - private _watchedFiles: core.KeyedCollection | undefined; + private _watchedFiles: core.SortedMap | undefined; private _watchedFilesSet: core.SortedSet | undefined; - private _watchedRecursiveDirectories: core.KeyedCollection | undefined; + private _watchedRecursiveDirectories: core.SortedMap | undefined; private _watchedRecursiveDirectoriesSet: core.SortedSet | undefined; - private _watchedNonRecursiveDirectories: core.KeyedCollection | undefined; + private _watchedNonRecursiveDirectories: core.SortedMap | undefined; private _watchedNonRecursiveDirectoriesSet: core.SortedSet | 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(this.vfs.stringComparer); + if (!this._watchedFiles) this._watchedFiles = new core.SortedMap({ comparer: this.vfs.stringComparer, sort: "insertion" }); if (!this._watchedFilesSet) this._watchedFilesSet = new core.SortedSet(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)) diff --git a/src/harness/typemock.ts b/src/harness/typemock.ts index f64af2bffb3..c8609c125d2 100644 --- a/src/harness/typemock.ts +++ b/src/harness/typemock.ts @@ -1,9 +1,4 @@ -/// -/// -/// - -// 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 { diff --git a/src/harness/utils.ts b/src/harness/utils.ts index 195ae691c7e..7212a6e6480 100644 --- a/src/harness/utils.ts +++ b/src/harness/utils.ts @@ -1,6 +1,6 @@ /// -// 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 { diff --git a/src/harness/vfs.ts b/src/harness/vfs.ts index 18778df7f56..fc2e247c43f 100644 --- a/src/harness/vfs.ts +++ b/src/harness/vfs.ts @@ -1,43 +1,35 @@ -/// -/// -/// -/// -/// -/// - -// 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; } } } \ No newline at end of file diff --git a/src/harness/vpath.ts b/src/harness/vpath.ts index 8fe94181f94..c7b5daca8bc 100644 --- a/src/harness/vpath.ts +++ b/src/harness/vpath.ts @@ -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; - (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; + (vpath).ValidationFlags = (_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; } } }