Merge branch 'master' into parallelAsyncTests

This commit is contained in:
Ron Buckton
2018-06-15 13:26:27 -07:00
2256 changed files with 440390 additions and 423675 deletions

View File

@@ -0,0 +1,30 @@
// @ts-check
const { lstatSync, readdirSync } = require("fs");
const { join } = require("path");
/**
* Find the size of a directory recursively.
* Symbolic links are counted once (same inode).
* @param {string} root
* @param {Set} seen
* @returns {number} bytes
*/
function getDirSize(root, seen = new Set()) {
const stats = lstatSync(root);
if (seen.has(stats.ino)) {
return 0;
}
seen.add(stats.ino);
if (!stats.isDirectory()) {
return stats.size;
}
return readdirSync(root)
.map(file => getDirSize(join(root, file), seen))
.reduce((acc, num) => acc + num, 0);
}
module.exports = getDirSize;

View File

@@ -0,0 +1,88 @@
// @ts-check
const path = require("path");
const child_process = require("child_process");
const tsc = require("gulp-typescript");
const Vinyl = require("vinyl");
const { Duplex, Readable } = require("stream");
/**
* @param {string} tsConfigFileName
* @param {tsc.Settings} settings
* @param {Object} options
* @param {string} [options.typescript]
*/
function createProject(tsConfigFileName, settings, options) {
settings = { ...settings };
options = { ...options };
if (settings.typescript) throw new Error();
const localSettings = { ...settings };
if (options.typescript) {
options.typescript = path.resolve(options.typescript);
localSettings.typescript = require(options.typescript);
}
const project = tsc.createProject(tsConfigFileName, localSettings);
const wrappedProject = /** @type {tsc.Project} */(() => {
const proc = child_process.fork(require.resolve("./main.js"));
/** @type {Duplex & { js?: Readable, dts?: Readable }} */
const compileStream = new Duplex({
objectMode: true,
read() {},
/** @param {*} file */
write(file, encoding, callback) {
proc.send({ method: "write", params: { path: file.path, cwd: file.cwd, base: file.base, sourceMap: file.sourceMap }});
callback();
},
final(callback) {
proc.send({ method: "final" });
callback();
}
});
const jsStream = compileStream.js = new Readable({
objectMode: true,
read() {}
});
const dtsStream = compileStream.dts = new Readable({
objectMode: true,
read() {}
});
proc.send({ method: "createProject", params: { tsConfigFileName, settings, options } });
proc.on("message", ({ method, params }) => {
if (method === "write") {
const file = new Vinyl({
path: params.path,
cwd: params.cwd,
base: params.base,
contents: Buffer.from(params.contents, "utf8")
});
if (params.sourceMap) file.sourceMap = params.sourceMap
compileStream.push(file);;
if (file.path.endsWith(".d.ts")) {
dtsStream.push(file);
}
else {
jsStream.push(file);
}
}
else if (method === "final") {
compileStream.push(null);
jsStream.push(null);
dtsStream.push(null);
proc.kill();
}
else if (method === "error") {
const error = new Error();
error.name = params.name;
error.message = params.message;
error.stack = params.stack;
compileStream.emit("error", error);
proc.kill();
}
});
return /** @type {*} */(compileStream);
});
return Object.assign(wrappedProject, project);
}
exports.createProject = createProject;

92
scripts/build/main.js Normal file
View File

@@ -0,0 +1,92 @@
// @ts-check
const path = require("path");
const fs = require("fs");
const tsc = require("gulp-typescript");
const Vinyl = require("vinyl");
const { Readable, Writable } = require("stream");
/** @type {tsc.Project} */
let project;
/** @type {Readable} */
let inputStream;
/** @type {Writable} */
let outputStream;
/** @type {tsc.CompileStream} */
let compileStream;
process.on("message", ({ method, params }) => {
try {
if (method === "createProject") {
const { tsConfigFileName, settings, options } = params;
if (options.typescript) {
settings.typescript = require(options.typescript);
}
project = tsc.createProject(tsConfigFileName, settings);
inputStream = new Readable({
objectMode: true,
read() {}
});
outputStream = new Writable({
objectMode: true,
/**
* @param {*} file
*/
write(file, encoding, callback) {
process.send({
method: "write",
params: {
path: file.path,
cwd: file.cwd,
base: file.base,
contents: file.contents.toString(),
sourceMap: file.sourceMap
}
});
callback();
},
final(callback) {
process.send({ method: "final" });
callback();
}
});
outputStream.on("error", error => {
process.send({
method: "error",
params: {
name: error.name,
message: error.message,
stack: error.stack
}
});
});
compileStream = project();
inputStream.pipe(compileStream).pipe(outputStream);
}
else if (method === "write") {
const file = new Vinyl({
path: params.path,
cwd: params.cwd,
base: params.base
});
file.contents = fs.readFileSync(file.path);
if (params.sourceMap) file.sourceMap = params.sourceMap;
inputStream.push(/** @type {*} */(file));
}
else if (method === "final") {
inputStream.push(null);
}
}
catch (e) {
process.send({
method: "error",
params: {
name: e.name,
message: e.message,
stack: e.stack
}
});
}
});

View File

@@ -46,7 +46,7 @@ class DeclarationsWalker {
if (!s) {
return;
}
if (s.name === "Array") {
if (s.name === "Array" || s.name === "ReadOnlyArray") {
// we should process type argument instead
return this.processType((<any>type).typeArguments[0]);
}
@@ -55,7 +55,7 @@ class DeclarationsWalker {
if (declarations) {
for (const decl of declarations) {
const sourceFile = decl.getSourceFile();
if (sourceFile === this.protocolFile || path.basename(sourceFile.fileName) === "lib.d.ts") {
if (sourceFile === this.protocolFile || /lib(\..+)?\.d.ts/.test(path.basename(sourceFile.fileName))) {
return;
}
if (decl.kind === ts.SyntaxKind.EnumDeclaration && !isStringEnum(decl as ts.EnumDeclaration)) {
@@ -121,23 +121,30 @@ class DeclarationsWalker {
}
function writeProtocolFile(outputFile: string, protocolTs: string, typeScriptServicesDts: string) {
const options = { target: ts.ScriptTarget.ES5, declaration: true, noResolve: true, types: <string[]>[], stripInternal: true };
const options = { target: ts.ScriptTarget.ES5, declaration: true, noResolve: false, types: <string[]>[], stripInternal: true };
/**
* 1st pass - generate a program from protocol.ts and typescriptservices.d.ts and emit core version of protocol.d.ts with all internal members stripped
* @return text of protocol.d.t.s
*/
function getInitialDtsFileForProtocol() {
const program = ts.createProgram([protocolTs, typeScriptServicesDts], options);
const program = ts.createProgram([protocolTs, typeScriptServicesDts, path.join(typeScriptServicesDts, "../lib.es5.d.ts")], options);
let protocolDts: string | undefined;
program.emit(program.getSourceFile(protocolTs), (file, content) => {
const emitResult = program.emit(program.getSourceFile(protocolTs), (file, content) => {
if (endsWith(file, ".d.ts")) {
protocolDts = content;
}
});
if (protocolDts === undefined) {
throw new Error(`Declaration file for protocol.ts is not generated`)
const diagHost: ts.FormatDiagnosticsHost = {
getCanonicalFileName: function (f) { return f; },
getCurrentDirectory: function() { return '.'; },
getNewLine: function() { return "\r\n"; }
}
const diags = emitResult.diagnostics.map(d => ts.formatDiagnostic(d, diagHost)).join("\r\n");
throw new Error(`Declaration file for protocol.ts is not generated:\r\n${diags}`);
}
return protocolDts;
}

View File

@@ -1,3 +1,6 @@
import path = require("path");
import fs = require("fs");
interface DiagnosticDetails {
category: string;
code: number;
@@ -5,32 +8,36 @@ interface DiagnosticDetails {
isEarly?: boolean;
}
type InputDiagnosticMessageTable = ts.Map<DiagnosticDetails>;
type InputDiagnosticMessageTable = Map<string, DiagnosticDetails>;
function main(): void {
const sys = ts.sys;
if (sys.args.length < 1) {
sys.write("Usage:" + sys.newLine);
sys.write("\tnode processDiagnosticMessages.js <diagnostic-json-input-file>" + sys.newLine);
if (process.argv.length < 3) {
console.log("Usage:");
console.log("\tnode processDiagnosticMessages.js <diagnostic-json-input-file>");
return;
}
function writeFile(fileName: string, contents: string) {
const inputDirectory = ts.getDirectoryPath(inputFilePath);
const fileOutputPath = ts.combinePaths(inputDirectory, fileName);
sys.writeFile(fileOutputPath, contents);
fs.writeFile(path.join(path.dirname(inputFilePath), fileName), contents, { encoding: "utf-8" }, err => {
if (err) throw err;
})
}
const inputFilePath = sys.args[0].replace(/\\/g, "/");
const inputStr = sys.readFile(inputFilePath)!;
const inputFilePath = process.argv[2].replace(/\\/g, "/");
console.log(`Reading diagnostics from ${inputFilePath}`);
const inputStr = fs.readFileSync(inputFilePath, { encoding: "utf-8" });
const diagnosticMessagesJson: { [key: string]: DiagnosticDetails } = JSON.parse(inputStr);
const diagnosticMessages: InputDiagnosticMessageTable = ts.createMapFromTemplate(diagnosticMessagesJson);
const diagnosticMessages: InputDiagnosticMessageTable = new Map();
for (const key in diagnosticMessagesJson) {
if (Object.hasOwnProperty.call(diagnosticMessagesJson, key)) {
diagnosticMessages.set(key, diagnosticMessagesJson[key]);
}
}
const outputFilesDir = ts.getDirectoryPath(inputFilePath);
const thisFilePathRel = ts.getRelativePathToDirectoryOrUrl(outputFilesDir, sys.getExecutingFilePath(),
sys.getCurrentDirectory(), ts.createGetCanonicalFileName(sys.useCaseSensitiveFileNames), /* isAbsolutePathAnUrl */ false);
const outputFilesDir = path.dirname(inputFilePath);
const thisFilePathRel = path.relative(process.cwd(), outputFilesDir);
const infoFileOutput = buildInfoFileOutput(diagnosticMessages, "./diagnosticInformationMap.generated.ts", thisFilePathRel);
checkForUniqueCodes(diagnosticMessages);
@@ -53,7 +60,7 @@ function checkForUniqueCodes(diagnosticTable: InputDiagnosticMessageTable) {
function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable, inputFilePathRel: string, thisFilePathRel: string): string {
let result =
"// <auto-generated />\r\n" +
"// generated from '" + inputFilePathRel + "' by '" + thisFilePathRel + "'\r\n" +
"// generated from '" + inputFilePathRel + "' by '" + thisFilePathRel.replace(/\\/g, '/') + "'\r\n" +
"/* @internal */\r\n" +
"namespace ts {\r\n" +
" function diag(code: number, category: DiagnosticCategory, key: string, message: string, reportsUnnecessary?: {}): DiagnosticMessage {\r\n" +
@@ -112,4 +119,4 @@ function convertPropertyName(origName: string): string {
return result;
}
main();
main();

View File

@@ -1,20 +1,15 @@
{
"compilerOptions": {
"removeComments": false,
"outFile": "processDiagnosticMessages.js",
"target": "es5",
"declaration": false,
"lib": [
"es6",
"scripthost"
]
],
"types": ["node"]
},
"files": [
"../src/compiler/types.ts",
"../src/compiler/performance.ts",
"../src/compiler/core.ts",
"../src/compiler/sys.ts",
"processDiagnosticMessages.ts"
]
}

100
scripts/produceLKG.ts Normal file
View File

@@ -0,0 +1,100 @@
/// <reference types="node" />
import childProcess = require('child_process');
import fs = require('fs-extra');
import path = require('path');
import removeInternal = require('remove-internal');
import glob = require('glob');
const root = path.join(__dirname, "..");
const source = path.join(root, "built/local");
const dest = path.join(root, "lib");
const copyright = fs.readFileSync(path.join(__dirname, "../CopyrightNotice.txt"), "utf-8");
async function produceLKG() {
console.log(`Building LKG from ${source} to ${dest}`);
await copyLibFiles();
await copyLocalizedDiagnostics();
await buildProtocol();
await copyScriptOutputs();
await buildTsc();
await copyDeclarationOutputs();
await writeGitAttributes();
}
async function copyLibFiles() {
await copyFilesWithGlob("lib?(.*).d.ts");
}
async function copyLocalizedDiagnostics() {
const dir = await fs.readdir(source);
for (const d of dir) {
const fileName = path.join(source, d);
if (fs.statSync(fileName).isDirectory()) {
if (d === 'tslint') continue;
await fs.copy(fileName, path.join(dest, d));
}
}
}
async function buildProtocol() {
const protocolScript = path.join(__dirname, "buildProtocol.js");
if (!fs.existsSync(protocolScript)) {
throw new Error(`Expected protocol script ${protocolScript} to exist`);
}
const protocolInput = path.join(__dirname, "../src/server/protocol.ts");
const protocolServices = path.join(source, "typescriptServices.d.ts");
const protocolOutput = path.join(dest, "protocol.d.ts");
console.log(`Building ${protocolOutput}...`);
await exec(protocolScript, [protocolInput, protocolServices, protocolOutput]);
}
async function copyScriptOutputs() {
await copyWithCopyright("tsserver.js");
await copyWithCopyright("tsc.js");
await copyWithCopyright("watchGuard.js");
await copyWithCopyright("cancellationToken.js");
await copyWithCopyright("typingsInstaller.js");
}
async function buildTsc() {
await exec(path.join(source, "tsc.js"), [`-b -f ${path.join(root, "src/tsc/tsconfig.release.json")}`]);
}
async function copyDeclarationOutputs() {
await copyWithCopyright("typescript.d.ts");
await copyWithCopyright("typescriptServices.d.ts");
await copyWithCopyright("tsserverlibrary.d.ts");
}
async function writeGitAttributes() {
await fs.writeFile(path.join(dest, ".gitattributes"), `* text eol=lf`, "utf-8");
}
async function copyWithCopyright(fileName: string) {
const content = await fs.readFile(path.join(source, fileName), "utf-8");
await fs.writeFile(path.join(dest, fileName), copyright + "\r\n" + content);
}
async function copyFromBuiltLocal(fileName: string) {
await fs.copy(path.join(source, fileName), path.join(dest, fileName));
}
async function copyFilesWithGlob(pattern: string) {
const files = glob.sync(path.join(source, pattern)).map(f => path.basename(f));
for (const f of files) {
await copyFromBuiltLocal(f);
}
console.log(`Copied ${files.length} files matching pattern ${pattern}`);
}
async function exec(path: string, args: string[] = []) {
const cmdLine = ["node", path, ...args].join(" ");
console.log(cmdLine);
childProcess.execSync(cmdLine);
}
process.on("unhandledRejection", err => { throw err; });
produceLKG().then(() => console.log("Done"), err => { throw err; });

20
scripts/tsconfig.json Normal file
View File

@@ -0,0 +1,20 @@
{
"compilerOptions": {
"removeComments": false,
"target": "es6",
"module": "commonjs",
"declaration": false,
"lib": [
"es6",
"scripthost"
],
"types": ["node"]
},
"files": [
"produceLKG.ts",
"buildProtocol.ts",
"processDiagnosticMessages.ts",
"generateLocalizedDiagnosticMessages.ts",
"configurePrerelease.ts"
]
}

View File

@@ -1,6 +1,8 @@
{
"compilerOptions": {
"lib": ["es6"],
"sourceMap": false,
"declaration": false,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
@@ -8,6 +10,10 @@
"noUnusedParameters": true,
"strictNullChecks": true,
"module": "commonjs",
"outDir": "../../built/local/tslint"
"outDir": "../../built/local/tslint",
"baseUrl": "../..",
"paths": {
"typescript": ["lib/typescript.d.ts"]
}
}
}