Merge pull request #25250 from Microsoft/gulpTypeScriptReporter
Report errors in corrrect process for gulp-typescript-oop
This commit is contained in:
commit
f4a2ee456d
67
Gulpfile.js
67
Gulpfile.js
|
@ -46,7 +46,7 @@ const produceLKGJs = "scripts/produceLKG.js";
|
|||
const word2mdJs = "scripts/word2md.js";
|
||||
gulp.task("scripts", /*help*/ false, () => project.compile(scriptsProject), {
|
||||
aliases: [
|
||||
configurePrereleaseJs,
|
||||
configurePrereleaseJs,
|
||||
processDiagnosticMessagesJs,
|
||||
generateLocalizedDiagnosticMessagesJs,
|
||||
produceLKGJs,
|
||||
|
@ -134,10 +134,11 @@ gulp.task(generatedLCGFile, /*help*/ false, [generateLocalizedDiagnosticMessages
|
|||
|
||||
gulp.task("localize", /*help*/ false, [generatedLCGFile]);
|
||||
|
||||
const servicesProject = "src/services/tsconfig.json";
|
||||
const typescriptServicesProject = "built/local/typescriptServices.tsconfig.json";
|
||||
gulp.task(typescriptServicesProject, /*help*/ false, () => {
|
||||
// NOTE: flatten services so that we can properly strip @internal
|
||||
project.flatten("src/services/tsconfig.json", typescriptServicesProject, {
|
||||
project.flatten(servicesProject, typescriptServicesProject, {
|
||||
compilerOptions: {
|
||||
"removeComments": true,
|
||||
"stripInternal": true,
|
||||
|
@ -148,7 +149,7 @@ gulp.task(typescriptServicesProject, /*help*/ false, () => {
|
|||
|
||||
const typescriptServicesJs = "built/local/typescriptServices.js";
|
||||
const typescriptServicesDts = "built/local/typescriptServices.d.ts";
|
||||
gulp.task(typescriptServicesJs, /*help*/ false, ["lib", "generate-diagnostics", typescriptServicesProject], () =>
|
||||
gulp.task(typescriptServicesJs, /*help*/ false, ["lib", "generate-diagnostics", typescriptServicesProject], () =>
|
||||
project.compile(typescriptServicesProject, { dts: files => files.pipe(convertConstEnums()) }),
|
||||
{ aliases: [typescriptServicesDts] });
|
||||
|
||||
|
@ -225,7 +226,7 @@ gulp.task(tsserverlibraryProject, /*help*/ false, () => {
|
|||
const tsserverlibraryJs = "built/local/tsserverlibrary.js";
|
||||
const tsserverlibraryDts = "built/local/tsserverlibrary.d.ts";
|
||||
gulp.task(tsserverlibraryJs, /*help*/ false, [typescriptServicesJs, tsserverlibraryProject], () =>
|
||||
project.compile(tsserverlibraryProject, {
|
||||
project.compile(tsserverlibraryProject, {
|
||||
dts: files => files
|
||||
.pipe(convertConstEnums())
|
||||
.pipe(append("\nexport = ts;\nexport as namespace ts;")),
|
||||
|
@ -253,21 +254,21 @@ gulp.task(specMd, /*help*/ false, [word2mdJs], () =>
|
|||
exec("cscript", ["//nologo", word2mdJs, path.resolve(specMd), path.resolve("doc/TypeScript Language Specification.docx")]));
|
||||
|
||||
gulp.task(
|
||||
"generate-spec",
|
||||
"Generates a Markdown version of the Language Specification",
|
||||
"generate-spec",
|
||||
"Generates a Markdown version of the Language Specification",
|
||||
[specMd]);
|
||||
|
||||
gulp.task("produce-LKG", /*help*/ false, ["scripts", "local", cancellationTokenJs, typingsInstallerJs, watchGuardJs, tscReleaseJs], () => {
|
||||
const expectedFiles = [
|
||||
tscReleaseJs,
|
||||
typescriptServicesJs,
|
||||
tsserverJs,
|
||||
typescriptJs,
|
||||
typescriptDts,
|
||||
typescriptServicesDts,
|
||||
tsserverlibraryDts,
|
||||
tsserverlibraryDts,
|
||||
typingsInstallerJs,
|
||||
tscReleaseJs,
|
||||
typescriptServicesJs,
|
||||
tsserverJs,
|
||||
typescriptJs,
|
||||
typescriptDts,
|
||||
typescriptServicesDts,
|
||||
tsserverlibraryDts,
|
||||
tsserverlibraryDts,
|
||||
typingsInstallerJs,
|
||||
cancellationTokenJs
|
||||
].concat(libraryTargets);
|
||||
const missingFiles = expectedFiles
|
||||
|
@ -286,8 +287,8 @@ gulp.task("produce-LKG", /*help*/ false, ["scripts", "local", cancellationTokenJ
|
|||
});
|
||||
|
||||
gulp.task(
|
||||
"LKG",
|
||||
"Makes a new LKG out of the built js files",
|
||||
"LKG",
|
||||
"Makes a new LKG out of the built js files",
|
||||
() => runSequence("clean-built", "produce-LKG"));
|
||||
|
||||
// Task to build the tests infrastructure using the built compiler
|
||||
|
@ -464,12 +465,40 @@ gulp.task(
|
|||
"Runs 'local'",
|
||||
["local"]);
|
||||
|
||||
gulp.task(
|
||||
"watch-diagnostics",
|
||||
/*help*/ false,
|
||||
[processDiagnosticMessagesJs],
|
||||
() => gulp.watch([diagnosticMessagesJson], [diagnosticInformationMapTs, builtGeneratedDiagnosticMessagesJson]));
|
||||
|
||||
gulp.task(
|
||||
"watch-lib",
|
||||
/*help*/ false,
|
||||
() => gulp.watch(["src/lib/**/*"], ["lib"]));
|
||||
|
||||
gulp.task(
|
||||
"watch-tsc",
|
||||
"Watches for changes to the build inputs for built/local/tsc.js",
|
||||
[typescriptServicesJs],
|
||||
/*help*/ false,
|
||||
["watch-diagnostics", "watch-lib", typescriptServicesJs],
|
||||
() => project.watch(tscProject, { typescript: "built" }));
|
||||
|
||||
gulp.task(
|
||||
"watch-services",
|
||||
/*help*/ false,
|
||||
["watch-diagnostics", "watch-lib", typescriptServicesJs],
|
||||
() => project.watch(servicesProject, { typescript: "built" }));
|
||||
|
||||
gulp.task(
|
||||
"watch-server",
|
||||
/*help*/ false,
|
||||
["watch-diagnostics", "watch-lib", typescriptServicesJs],
|
||||
() => project.watch(tsserverProject, { typescript: "built" }));
|
||||
|
||||
gulp.task(
|
||||
"watch-local",
|
||||
/*help*/ false,
|
||||
["watch-lib", "watch-tsc", "watch-services", "watch-server"]);
|
||||
|
||||
gulp.task(
|
||||
"watch",
|
||||
"Watches for changes to the build inputs for built/local/run.js executes runtests-parallel.",
|
||||
|
|
6
package-lock.json
generated
6
package-lock.json
generated
|
@ -5801,9 +5801,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.0.0-dev.20180609",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.0-dev.20180609.tgz",
|
||||
"integrity": "sha512-bqO5mSGbxZoiY/9Y1bnnU36dC5CfnrA9I9WKf3QB0qMuJakoofO2DNTDRwsypyhCThlNtF2Ls/OMj3Txglu4Xg==",
|
||||
"version": "3.0.0-dev.20180626",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.0-dev.20180626.tgz",
|
||||
"integrity": "sha512-OQH9osIC4CdsVzVvsb2RenRTVPRKwSIMIpRy2J42XNOEUP+vhX56BX1Z47K3l//LEGY0xG7zF7qVKCDlUhhrlg==",
|
||||
"dev": true
|
||||
},
|
||||
"uglify-js": {
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
// @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 | undefined} tsConfigFileName
|
||||
* @param {tsc.Settings} settings
|
||||
* @param {Object} options
|
||||
* @param {string} [options.typescript]
|
||||
*/
|
||||
function createProject(tsConfigFileName, settings, options) {
|
||||
settings = Object.assign({}, settings);
|
||||
options = Object.assign({}, options);
|
||||
if (settings.typescript) throw new Error();
|
||||
|
||||
const localSettings = Object.assign({}, settings);
|
||||
if (options.typescript) {
|
||||
options.typescript = path.resolve(options.typescript);
|
||||
localSettings.typescript = require(options.typescript);
|
||||
}
|
||||
|
||||
const project = tsConfigFileName === undefined ? tsc.createProject(localSettings) : tsc.createProject(tsConfigFileName, localSettings);
|
||||
const wrappedProject = /** @type {tsc.Project} */(() => {
|
||||
const proc = child_process.fork(require.resolve("./main.js"), [], {
|
||||
// Prevent errors when debugging gulpfile due to the same debug port being passed to forked children.
|
||||
execArgv: []
|
||||
});
|
||||
/** @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;
|
145
scripts/build/gulp-typescript-oop/index.js
Normal file
145
scripts/build/gulp-typescript-oop/index.js
Normal file
|
@ -0,0 +1,145 @@
|
|||
// @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");
|
||||
const protocol = require("./protocol");
|
||||
|
||||
/**
|
||||
* @param {string | undefined} tsConfigFileName
|
||||
* @param {tsc.Settings} settings
|
||||
* @param {CreateProjectOptions} options
|
||||
*
|
||||
* @typedef CreateProjectOptions
|
||||
* @property {string} [typescript]
|
||||
* @property {boolean} [parse]
|
||||
*/
|
||||
function createProject(tsConfigFileName, settings, options) {
|
||||
settings = Object.assign({}, settings);
|
||||
options = Object.assign({}, options);
|
||||
if (settings.typescript) throw new Error();
|
||||
|
||||
const localSettings = Object.assign({}, settings);
|
||||
if (options.typescript) {
|
||||
options.typescript = path.resolve(options.typescript);
|
||||
localSettings.typescript = require(options.typescript);
|
||||
}
|
||||
|
||||
const project = tsConfigFileName === undefined ? tsc.createProject(localSettings) : tsc.createProject(tsConfigFileName, localSettings);
|
||||
const wrappedProject = /** @type {tsc.Project} */((reporter = tsc.reporter.defaultReporter()) => {
|
||||
const ts = project.typescript;
|
||||
const proc = child_process.fork(require.resolve("./worker.js"), [], {
|
||||
// Prevent errors when debugging gulpfile due to the same debug port being passed to forked children.
|
||||
execArgv: []
|
||||
});
|
||||
/** @type {Map<string, import("vinyl")>} */
|
||||
const inputs = new Map();
|
||||
/** @type {Map<string, *>} */
|
||||
const sourceFiles = new Map();
|
||||
/** @type {protocol.SourceFileHost & protocol.VinylHost} */
|
||||
const host = {
|
||||
getVinyl(path) { return inputs.get(path); },
|
||||
getSourceFile(fileName) { return sourceFiles.get(fileName); },
|
||||
createSourceFile(fileName, text, languageVersion) {
|
||||
if (text === undefined) throw new Error("File not cached.");
|
||||
/** @type {protocol.SourceFile} */
|
||||
let file;
|
||||
if (options.parse) {
|
||||
file = ts.createSourceFile(fileName, text, languageVersion, /*setParentNodes*/ true);
|
||||
}
|
||||
else {
|
||||
// NOTE: the built-in reporters in gulp-typescript don't actually need a full
|
||||
// source file, so save time by faking one unless requested.
|
||||
file = /**@type {protocol.SourceFile}*/({
|
||||
pos: 0,
|
||||
end: text.length,
|
||||
kind: ts.SyntaxKind.SourceFile,
|
||||
fileName,
|
||||
text,
|
||||
languageVersion,
|
||||
statements: /**@type {*} */([]),
|
||||
endOfFileToken: { pos: text.length, end: text.length, kind: ts.SyntaxKind.EndOfFileToken },
|
||||
amdDependencies: /**@type {*} */([]),
|
||||
referencedFiles: /**@type {*} */([]),
|
||||
typeReferenceDirectives: /**@type {*} */([]),
|
||||
libReferenceDirectives: /**@type {*} */([]),
|
||||
languageVariant: ts.LanguageVariant.Standard,
|
||||
isDeclarationFile: /\.d\.ts$/.test(fileName),
|
||||
hasNoDefaultLib: /[\\/]lib\.[^\\/]+\.d\.ts$/.test(fileName)
|
||||
});
|
||||
}
|
||||
sourceFiles.set(fileName, file);
|
||||
return file;
|
||||
}
|
||||
};
|
||||
/** @type {Duplex & { js?: Readable, dts?: Readable }} */
|
||||
const compileStream = new Duplex({
|
||||
objectMode: true,
|
||||
read() {},
|
||||
/** @param {*} file */
|
||||
write(file, _encoding, callback) {
|
||||
inputs.set(file.path, file);
|
||||
proc.send(protocol.message.write(file));
|
||||
callback();
|
||||
},
|
||||
final(callback) {
|
||||
proc.send(protocol.message.final());
|
||||
callback();
|
||||
}
|
||||
});
|
||||
const jsStream = compileStream.js = new Readable({
|
||||
objectMode: true,
|
||||
read() {}
|
||||
});
|
||||
const dtsStream = compileStream.dts = new Readable({
|
||||
objectMode: true,
|
||||
read() {}
|
||||
});
|
||||
proc.send(protocol.message.createProject(tsConfigFileName, settings, options));
|
||||
proc.on("message", (/**@type {protocol.WorkerMessage}*/ message) => {
|
||||
switch (message.method) {
|
||||
case "write": {
|
||||
const file = protocol.vinylFromJson(message.params);
|
||||
compileStream.push(file);
|
||||
if (file.path.endsWith(".d.ts")) {
|
||||
dtsStream.push(file);
|
||||
}
|
||||
else {
|
||||
jsStream.push(file);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "final": {
|
||||
compileStream.push(null);
|
||||
jsStream.push(null);
|
||||
dtsStream.push(null);
|
||||
proc.kill(); // TODO(rbuckton): pool workers? may not be feasible due to gulp-typescript holding onto memory
|
||||
break;
|
||||
}
|
||||
case "error": {
|
||||
const error = protocol.errorFromJson(message.params);
|
||||
compileStream.emit("error", error);
|
||||
proc.kill(); // TODO(rbuckton): pool workers? may not be feasible due to gulp-typescript holding onto memory
|
||||
break;
|
||||
}
|
||||
case "reporter.error": {
|
||||
if (reporter.error) {
|
||||
const error = protocol.typeScriptErrorFromJson(message.params, host);
|
||||
reporter.error(error, project.typescript);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "reporter.finish": {
|
||||
if (reporter.finish) {
|
||||
reporter.finish(message.params);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return /** @type {*} */(compileStream);
|
||||
});
|
||||
return Object.assign(wrappedProject, project);
|
||||
}
|
||||
|
||||
exports.createProject = createProject;
|
279
scripts/build/gulp-typescript-oop/protocol.js
Normal file
279
scripts/build/gulp-typescript-oop/protocol.js
Normal file
|
@ -0,0 +1,279 @@
|
|||
// @ts-check
|
||||
const Vinyl = require("vinyl");
|
||||
|
||||
/**
|
||||
* @param {File} file
|
||||
* @returns {*}
|
||||
*/
|
||||
function vinylToJson(file) {
|
||||
if (file.isStream()) throw new TypeError("Streams not supported.");
|
||||
return {
|
||||
path: file.path,
|
||||
cwd: file.cwd,
|
||||
base: file.base,
|
||||
contents: file.isBuffer() ? file.contents.toString("utf8") : undefined,
|
||||
sourceMap: file.sourceMap
|
||||
};
|
||||
}
|
||||
exports.vinylToJson = vinylToJson;
|
||||
|
||||
/**
|
||||
* @param {*} json
|
||||
* @returns {File}
|
||||
*/
|
||||
function vinylFromJson(json) {
|
||||
return new Vinyl({
|
||||
path: json.path,
|
||||
cwd: json.cwd,
|
||||
base: json.base,
|
||||
contents: typeof json.contents === "string" ? Buffer.from(json.contents, "utf8") : undefined,
|
||||
sourceMap: json.sourceMap
|
||||
});
|
||||
}
|
||||
exports.vinylFromJson = vinylFromJson;
|
||||
|
||||
/**
|
||||
* @param {Error} error
|
||||
* @returns {*}
|
||||
*/
|
||||
function errorToJson(error) {
|
||||
return {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
stack: error.stack
|
||||
};
|
||||
}
|
||||
exports.errorToJson = errorToJson;
|
||||
|
||||
/**
|
||||
* @param {*} json
|
||||
* @returns {Error}
|
||||
*/
|
||||
function errorFromJson(json) {
|
||||
const error = new Error();
|
||||
error.name = json.name;
|
||||
error.message = json.message;
|
||||
error.stack = json.stack;
|
||||
return error;
|
||||
}
|
||||
exports.errorFromJson = errorFromJson;
|
||||
|
||||
/**
|
||||
* @param {TypeScriptError} error
|
||||
* @returns {*}
|
||||
*/
|
||||
function typeScriptErrorToJson(error) {
|
||||
return Object.assign({}, errorToJson(error), {
|
||||
fullFilename: error.fullFilename,
|
||||
relativeFilename: error.relativeFilename,
|
||||
file: error.file && { path: error.file.path },
|
||||
tsFile: error.tsFile && sourceFileToJson(error.tsFile),
|
||||
diagnostic: diagnosticToJson(error.diagnostic),
|
||||
startPosition: error.startPosition,
|
||||
endPosition: error.endPosition
|
||||
});
|
||||
}
|
||||
exports.typeScriptErrorToJson = typeScriptErrorToJson;
|
||||
|
||||
/**
|
||||
* @param {*} json
|
||||
* @param {SourceFileHost & VinylHost} host
|
||||
* @returns {TypeScriptError}
|
||||
*/
|
||||
function typeScriptErrorFromJson(json, host) {
|
||||
const error = /**@type {TypeScriptError}*/(errorFromJson(json));
|
||||
error.fullFilename = json.fullFilename;
|
||||
error.relativeFilename = json.relativeFilename;
|
||||
error.file = json.file && host.getVinyl(json.file.path);
|
||||
error.tsFile = json.tsFile && sourceFileFromJson(json.tsFile, host);
|
||||
error.diagnostic = diagnosticFromJson(json.diagnostic, host);
|
||||
error.startPosition = json.startPosition;
|
||||
error.endPosition = json.endPosition;
|
||||
return error;
|
||||
}
|
||||
exports.typeScriptErrorFromJson = typeScriptErrorFromJson;
|
||||
|
||||
/**
|
||||
* @param {SourceFile} file
|
||||
* @returns {*}
|
||||
*/
|
||||
function sourceFileToJson(file) {
|
||||
return {
|
||||
fileName: file.fileName,
|
||||
text: file.text,
|
||||
languageVersion: file.languageVersion
|
||||
};
|
||||
}
|
||||
exports.sourceFileToJson = sourceFileToJson;
|
||||
|
||||
/**
|
||||
* @param {*} json
|
||||
* @param {SourceFileHost} host
|
||||
*/
|
||||
function sourceFileFromJson(json, host) {
|
||||
return host.getSourceFile(json.fileName)
|
||||
|| host.createSourceFile(json.fileName, json.text, json.languageVersion);
|
||||
}
|
||||
exports.sourceFileFromJson = sourceFileFromJson;
|
||||
|
||||
/**
|
||||
* @param {Diagnostic} diagnostic
|
||||
* @returns {*}
|
||||
*/
|
||||
function diagnosticToJson(diagnostic) {
|
||||
return Object.assign({}, diagnosticRelatedInformationToJson(diagnostic), {
|
||||
category: diagnostic.category,
|
||||
code: diagnostic.code,
|
||||
source: diagnostic.source,
|
||||
relatedInformation: diagnostic.relatedInformation && diagnostic.relatedInformation.map(diagnosticRelatedInformationToJson)
|
||||
});
|
||||
}
|
||||
exports.diagnosticToJson = diagnosticToJson;
|
||||
|
||||
/**
|
||||
* @param {*} json
|
||||
* @param {SourceFileHost} host
|
||||
* @returns {Diagnostic}
|
||||
*/
|
||||
function diagnosticFromJson(json, host) {
|
||||
return Object.assign({}, diagnosticRelatedInformationFromJson(json, host), {
|
||||
category: json.category,
|
||||
code: json.code,
|
||||
source: json.source,
|
||||
relatedInformation: json.relatedInformation && json.relatedInformation.map(diagnosticRelatedInformationFromJson, host)
|
||||
});
|
||||
}
|
||||
exports.diagnosticFromJson = diagnosticFromJson;
|
||||
|
||||
/**
|
||||
* @param {DiagnosticRelatedInformation} diagnostic
|
||||
* @returns {*}
|
||||
*/
|
||||
function diagnosticRelatedInformationToJson(diagnostic) {
|
||||
return {
|
||||
file: diagnostic.file && { fileName: diagnostic.file.fileName },
|
||||
start: diagnostic.start,
|
||||
length: diagnostic.length,
|
||||
messageText: diagnostic.messageText
|
||||
};
|
||||
}
|
||||
exports.diagnosticRelatedInformationToJson = diagnosticRelatedInformationToJson;
|
||||
|
||||
/**
|
||||
* @param {*} json
|
||||
* @param {SourceFileHost} host
|
||||
* @returns {DiagnosticRelatedInformation}
|
||||
*/
|
||||
function diagnosticRelatedInformationFromJson(json, host) {
|
||||
return {
|
||||
file: json.file && sourceFileFromJson(json.file, host),
|
||||
start: json.start,
|
||||
length: json.length,
|
||||
messageText: json.messageText
|
||||
};
|
||||
}
|
||||
exports.diagnosticRelatedInformationFromJson = diagnosticRelatedInformationFromJson;
|
||||
|
||||
exports.message = {};
|
||||
|
||||
/**
|
||||
* @param {string | undefined} tsConfigFileName
|
||||
* @param {import("gulp-typescript").Settings} settings
|
||||
* @param {Object} options
|
||||
* @param {string} [options.typescript]
|
||||
* @returns {CreateProjectMessage}
|
||||
*
|
||||
* @typedef CreateProjectMessage
|
||||
* @property {"createProject"} method
|
||||
* @property {CreateProjectParams} params
|
||||
*
|
||||
* @typedef CreateProjectParams
|
||||
* @property {string | undefined} tsConfigFileName
|
||||
* @property {import("gulp-typescript").Settings} settings
|
||||
* @property {CreateProjectOptions} options
|
||||
*
|
||||
* @typedef CreateProjectOptions
|
||||
* @property {string} [typescript]
|
||||
*/
|
||||
exports.message.createProject = function(tsConfigFileName, settings, options) {
|
||||
return { method: "createProject", params: { tsConfigFileName, settings, options } };
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {File} file
|
||||
* @returns {WriteMessage}
|
||||
*
|
||||
* @typedef WriteMessage
|
||||
* @property {"write"} method
|
||||
* @property {*} params
|
||||
*/
|
||||
exports.message.write = function(file) {
|
||||
return { method: "write", params: vinylToJson(file) };
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {FinalMessage}
|
||||
*
|
||||
* @typedef FinalMessage
|
||||
* @property {"final"} method
|
||||
*/
|
||||
exports.message.final = function() {
|
||||
return { method: "final" };
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Error} error
|
||||
* @returns {ErrorMessage}
|
||||
*
|
||||
* @typedef ErrorMessage
|
||||
* @property {"error"} method
|
||||
* @property {*} params
|
||||
*/
|
||||
exports.message.error = function(error) {
|
||||
return { method: "error", params: errorToJson(error) };
|
||||
};
|
||||
|
||||
exports.message.reporter = {};
|
||||
|
||||
/**
|
||||
* @param {TypeScriptError} error
|
||||
* @returns {reporter.ErrorMessage}
|
||||
*
|
||||
* @typedef reporter.ErrorMessage
|
||||
* @property {"reporter.error"} method
|
||||
* @property {*} params
|
||||
*/
|
||||
exports.message.reporter.error = function(error) {
|
||||
return { method: "reporter.error", params: typeScriptErrorToJson(error) };
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {*} results
|
||||
* @returns {reporter.FinishMessage}
|
||||
*
|
||||
* @typedef reporter.FinishMessage
|
||||
* @property {"reporter.finish"} method
|
||||
* @property {*} params
|
||||
*/
|
||||
exports.message.reporter.finish = function(results) {
|
||||
return { method: "reporter.finish", params: results };
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {import("vinyl")} File
|
||||
* @typedef {typeof import("typescript")} TypeScriptModule
|
||||
* @typedef {import("typescript").SourceFile} SourceFile
|
||||
* @typedef {import("typescript").Diagnostic} Diagnostic
|
||||
* @typedef {import("typescript").DiagnosticRelatedInformation} DiagnosticRelatedInformation
|
||||
* @typedef {import("gulp-typescript").reporter.TypeScriptError} TypeScriptError
|
||||
* @typedef {WriteMessage | FinalMessage | CreateProjectMessage} HostMessage
|
||||
* @typedef {WriteMessage | FinalMessage | ErrorMessage | reporter.ErrorMessage | reporter.FinishMessage} WorkerMessage
|
||||
*
|
||||
* @typedef SourceFileHost
|
||||
* @property {(fileName: string) => SourceFile | undefined} getSourceFile
|
||||
* @property {(fileName: string, text: string, languageVersion: number) => SourceFile} createSourceFile
|
||||
*
|
||||
* @typedef VinylHost
|
||||
* @property {(path: string) => File | undefined} getVinyl
|
||||
*/
|
||||
void 0;
|
79
scripts/build/gulp-typescript-oop/worker.js
Normal file
79
scripts/build/gulp-typescript-oop/worker.js
Normal file
|
@ -0,0 +1,79 @@
|
|||
// @ts-check
|
||||
const fs = require("fs");
|
||||
const tsc = require("gulp-typescript");
|
||||
const { Readable, Writable } = require("stream");
|
||||
const protocol = require("./protocol");
|
||||
|
||||
/** @type {tsc.Project} */
|
||||
let project;
|
||||
|
||||
/** @type {Readable} */
|
||||
let inputStream;
|
||||
|
||||
/** @type {Writable} */
|
||||
let outputStream;
|
||||
|
||||
/** @type {tsc.CompileStream} */
|
||||
let compileStream;
|
||||
|
||||
process.on("message", (/**@type {protocol.HostMessage}*/ message) => {
|
||||
try {
|
||||
switch (message.method) {
|
||||
case "createProject": {
|
||||
const { tsConfigFileName, settings, options } = message.params;
|
||||
if (options.typescript) {
|
||||
settings.typescript = require(options.typescript);
|
||||
}
|
||||
|
||||
project = tsConfigFileName === undefined
|
||||
? tsc.createProject(settings)
|
||||
: tsc.createProject(tsConfigFileName, settings);
|
||||
|
||||
inputStream = new Readable({
|
||||
objectMode: true,
|
||||
read() {}
|
||||
});
|
||||
|
||||
outputStream = new Writable({
|
||||
objectMode: true,
|
||||
/**
|
||||
* @param {*} file
|
||||
*/
|
||||
write(file, _, callback) {
|
||||
process.send(protocol.message.write(file));
|
||||
callback();
|
||||
},
|
||||
final(callback) {
|
||||
process.send(protocol.message.final());
|
||||
callback();
|
||||
}
|
||||
});
|
||||
compileStream = project({
|
||||
error(error) { process.send(protocol.message.reporter.error(error)); },
|
||||
finish(results) { process.send(protocol.message.reporter.finish(results)); }
|
||||
});
|
||||
compileStream.on("error", error => {
|
||||
process.send(protocol.message.error(error));
|
||||
});
|
||||
outputStream.on("error", () => {
|
||||
/* do nothing */
|
||||
});
|
||||
inputStream.pipe(compileStream).pipe(outputStream);
|
||||
break;
|
||||
}
|
||||
case "write": {
|
||||
const file = protocol.vinylFromJson(message.params);
|
||||
if (!file.isBuffer()) file.contents = fs.readFileSync(file.path);
|
||||
inputStream.push(file);
|
||||
break;
|
||||
}
|
||||
case "final": {
|
||||
inputStream.push(null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
process.send(protocol.message.error(e));
|
||||
}
|
||||
});
|
|
@ -1,91 +0,0 @@
|
|||
// @ts-check
|
||||
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 = tsConfigFileName === undefined ? tsc.createProject(settings) : tsc.createProject(tsConfigFileName, settings);
|
||||
inputStream = new Readable({
|
||||
objectMode: true,
|
||||
read() {}
|
||||
});
|
||||
outputStream = new Writable({
|
||||
objectMode: true,
|
||||
/**
|
||||
* @param {*} file
|
||||
*/
|
||||
write(file, _, 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
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
|
@ -137,6 +137,7 @@ function watch(projectSpec, options, tasks, callback) {
|
|||
if (typeof options === "function") callback = options, tasks = /**@type {string[] | undefined}*/(undefined), options = /**@type {CompileOptions | undefined}*/(undefined);
|
||||
if (Array.isArray(options)) tasks = options, options = /**@type {CompileOptions | undefined}*/(undefined);
|
||||
const resolvedOptions = resolveCompileOptions(options);
|
||||
resolvedOptions.watch = true;
|
||||
const resolvedProjectSpec = resolveProjectSpec(projectSpec, resolvedOptions.paths, /*referrer*/ undefined);
|
||||
const projectGraph = getOrCreateProjectGraph(resolvedProjectSpec, resolvedOptions.paths);
|
||||
projectGraph.isRoot = true;
|
||||
|
@ -284,6 +285,7 @@ function resolvePathOptions(options) {
|
|||
* @property {boolean} [verbose] Indicates whether verbose logging is enabled.
|
||||
* @property {boolean} [force] Force recompilation (no up-to-date check).
|
||||
* @property {boolean} [inProcess] Indicates whether to run gulp-typescript in-process or out-of-process (default).
|
||||
* @property {boolean} [watch] Indicates the project was created in watch mode
|
||||
*/
|
||||
function resolveCompileOptions(options = {}) {
|
||||
const paths = resolvePathOptions(options);
|
||||
|
@ -305,7 +307,7 @@ function resolveCompileOptions(options = {}) {
|
|||
* @returns {ResolvedCompileOptions}
|
||||
*/
|
||||
function mergeCompileOptions(left, right) {
|
||||
if (left.typescript !== right.typescript) throw new Error("Cannot merge project options targeting different TypeScript packages");
|
||||
if (left.typescript.typescript !== right.typescript.typescript) throw new Error("Cannot merge project options targeting different TypeScript packages");
|
||||
if (tryReuseCompileOptions(left, right)) return left;
|
||||
return {
|
||||
paths: left.paths,
|
||||
|
@ -314,7 +316,8 @@ function mergeCompileOptions(left, right) {
|
|||
dts: right.dts || left.dts,
|
||||
verbose: right.verbose || left.verbose,
|
||||
force: right.force || left.force,
|
||||
inProcess: right.inProcess || left.inProcess
|
||||
inProcess: right.inProcess || left.inProcess,
|
||||
watch: right.watch || left.watch
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -599,30 +602,40 @@ function resolveDestPath(projectGraph, paths) {
|
|||
*/
|
||||
function ensureCompileTask(projectGraph, options) {
|
||||
const projectGraphConfig = getOrCreateProjectGraphConfiguration(projectGraph, options);
|
||||
projectGraphConfig.resolvedOptions = options = mergeCompileOptions(options, options);
|
||||
if (!projectGraphConfig.compileTaskCreated) {
|
||||
const deps = makeProjectReferenceCompileTasks(projectGraph, options.typescript, options.paths);
|
||||
compilationGulp.task(compileTaskName(projectGraph, options.typescript), deps, () => {
|
||||
const destPath = resolveDestPath(projectGraph, options.paths);
|
||||
projectGraphConfig.resolvedOptions = mergeCompileOptions(projectGraphConfig.resolvedOptions, options);
|
||||
const hasCompileTask = projectGraphConfig.compileTaskCreated;
|
||||
projectGraphConfig.compileTaskCreated = true;
|
||||
const deps = makeProjectReferenceCompileTasks(projectGraph, projectGraphConfig.resolvedOptions.typescript, projectGraphConfig.resolvedOptions.paths, projectGraphConfig.resolvedOptions.watch);
|
||||
if (!hasCompileTask) {
|
||||
compilationGulp.task(compileTaskName(projectGraph, projectGraphConfig.resolvedOptions.typescript), deps, () => {
|
||||
const destPath = resolveDestPath(projectGraph, projectGraphConfig.resolvedOptions.paths);
|
||||
const { sourceMap, inlineSourceMap, inlineSources = false, sourceRoot, declarationMap } = projectGraph.project.options;
|
||||
const configFilePath = projectGraph.project.options.configFilePath;
|
||||
const sourceMapPath = inlineSourceMap ? undefined : ".";
|
||||
const sourceMapOptions = { includeContent: inlineSources, sourceRoot, destPath };
|
||||
const project = options.inProcess
|
||||
? tsc.createProject(configFilePath, { typescript: require(options.typescript.typescript) })
|
||||
: tsc_oop.createProject(configFilePath, {}, { typescript: options.typescript.typescript });
|
||||
const project = projectGraphConfig.resolvedOptions.inProcess
|
||||
? tsc.createProject(configFilePath, { typescript: require(projectGraphConfig.resolvedOptions.typescript.typescript) })
|
||||
: tsc_oop.createProject(configFilePath, {}, { typescript: projectGraphConfig.resolvedOptions.typescript.typescript });
|
||||
const stream = project.src()
|
||||
.pipe(gulpif(!options.force, upToDate(projectGraph.project, { verbose: options.verbose, parseProject: createParseProject(options.paths) })))
|
||||
.pipe(gulpif(!projectGraphConfig.resolvedOptions.force, upToDate(projectGraph.project, { verbose: projectGraphConfig.resolvedOptions.verbose, parseProject: createParseProject(projectGraphConfig.resolvedOptions.paths) })))
|
||||
.pipe(gulpif(sourceMap || inlineSourceMap, sourcemaps.init()))
|
||||
.pipe(project());
|
||||
const js = (options.js ? options.js(stream.js) : stream.js)
|
||||
if (projectGraphConfig.resolvedOptions.watch) {
|
||||
stream.on("error", error => {
|
||||
if (error.message === "TypeScript: Compilation failed") {
|
||||
stream.emit("end");
|
||||
stream.js.emit("end");
|
||||
stream.dts.emit("end");
|
||||
}
|
||||
});
|
||||
}
|
||||
const js = (projectGraphConfig.resolvedOptions.js ? projectGraphConfig.resolvedOptions.js(stream.js) : stream.js)
|
||||
.pipe(gulpif(sourceMap || inlineSourceMap, sourcemaps.write(sourceMapPath, sourceMapOptions)));
|
||||
const dts = (options.dts ? options.dts(stream.dts) : stream.dts)
|
||||
const dts = (projectGraphConfig.resolvedOptions.dts ? projectGraphConfig.resolvedOptions.dts(stream.dts) : stream.dts)
|
||||
.pipe(gulpif(declarationMap, sourcemaps.write(sourceMapPath, sourceMapOptions)));
|
||||
return merge2([js, dts])
|
||||
.pipe(gulp.dest(destPath));
|
||||
});
|
||||
projectGraphConfig.compileTaskCreated = true;
|
||||
}
|
||||
return projectGraph;
|
||||
}
|
||||
|
@ -631,9 +644,10 @@ function ensureCompileTask(projectGraph, options) {
|
|||
* @param {ProjectGraph} projectGraph
|
||||
* @param {ResolvedTypeScript} typescript
|
||||
* @param {ResolvedPathOptions} paths
|
||||
* @param {boolean} watch
|
||||
*/
|
||||
function makeProjectReferenceCompileTasks(projectGraph, typescript, paths) {
|
||||
return projectGraph.references.map(({target}) => compileTaskName(ensureCompileTask(target, { paths, typescript }), typescript));
|
||||
function makeProjectReferenceCompileTasks(projectGraph, typescript, paths, watch) {
|
||||
return projectGraph.references.map(({target}) => compileTaskName(ensureCompileTask(target, { paths, typescript, watch }), typescript));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -715,7 +729,7 @@ function ensureWatcher(projectGraph, options, tasks, callback) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {ProjectGraphConfiguration} config
|
||||
* @param {ProjectGraphConfiguration} config
|
||||
* @param {import("orchestrator").Task} task
|
||||
*/
|
||||
function possiblyTriggerRecompilation(config, task) {
|
||||
|
@ -732,7 +746,7 @@ function possiblyTriggerRecompilation(config, task) {
|
|||
|
||||
/**
|
||||
* @param {import("orchestrator").Task} task
|
||||
* @param {ProjectGraphConfiguration} config
|
||||
* @param {ProjectGraphConfiguration} config
|
||||
*/
|
||||
function triggerRecompilation(task, config) {
|
||||
compilationGulp._resetTask(task);
|
||||
|
|
Loading…
Reference in a new issue