加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
Gulpfile.js 17.42 KB
一键复制 编辑 原始数据 按行查看 历史
372681370@QQ.com 提交于 2021-08-09 08:49 . tj
// @ts-check
const path = require("path");
const fs = require("fs");
const newer = require("gulp-newer");
const del = require("del");
const rename = require("gulp-rename");
const merge2 = require("merge2");
const mkdirp = require("mkdirp");
const { src, dest, task, parallel, series, watch } = require("gulp");
const { transform } = require("gulp-insert");
const { exec, readJson, needsUpdate, getDiffTool, rm } = require("./scripts/build/utils");
const { runConsoleTests, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline } = require("./scripts/build/tests");
const { buildProject, cleanProject, watchProject } = require("./scripts/build/projects");
const cmdLineOptions = require("./scripts/build/options");
const cleanTasks = [];
const buildScripts = () => buildProject("scripts");
task("scripts", buildScripts);
task("scripts").description = "Builds files in the 'scripts' folder.";
const cleanScripts = () => cleanProject("scripts");
cleanTasks.push(cleanScripts);
const diagnosticInformationMapTs = "src/compiler/diagnosticInformationMap.generated.ts";
const diagnosticMessagesJson = "src/compiler/diagnosticMessages.json";
const diagnosticMessagesGeneratedJson = "src/compiler/diagnosticMessages.generated.json";
const generateDiagnostics = async () => {
if (needsUpdate(diagnosticMessagesJson, [diagnosticMessagesGeneratedJson, diagnosticInformationMapTs])) {
await exec(process.execPath, ["scripts/processDiagnosticMessages.js", diagnosticMessagesJson]);
}
};
task("generate-diagnostics", series(buildScripts, generateDiagnostics));
task("generate-diagnostics").description = "Generates a diagnostic file in TypeScript based on an input JSON file";
const cleanDiagnostics = () => del([diagnosticInformationMapTs, diagnosticMessagesGeneratedJson]);
cleanTasks.push(cleanDiagnostics);
const watchDiagnostics = () => watch(["src/compiler/diagnosticMessages.json"], task("generate-diagnostics"));
// Localize diagnostics
/**
* .lcg file is what localization team uses to know what messages to localize.
* The file is always generated in 'enu/diagnosticMessages.generated.json.lcg'
*/
const generatedLCGFile = "built/local/enu/diagnosticMessages.generated.json.lcg";
/**
* The localization target produces the two following transformations:
* 1. 'src\loc\lcl\<locale>\diagnosticMessages.generated.json.lcl' => 'built\local\<locale>\diagnosticMessages.generated.json'
* convert localized resources into a .json file the compiler can understand
* 2. 'src\compiler\diagnosticMessages.generated.json' => 'built\local\ENU\diagnosticMessages.generated.json.lcg'
* generate the lcg file (source of messages to localize) from the diagnosticMessages.generated.json
*/
const localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-br", "ru", "tr", "zh-cn", "zh-tw"]
.map(f => f.toLowerCase())
.map(f => `built/local/${f}/diagnosticMessages.generated.json`)
.concat(generatedLCGFile);
const localize = async () => {
if (needsUpdate(diagnosticMessagesGeneratedJson, generatedLCGFile)) {
return exec(process.execPath, ["scripts/generateLocalizedDiagnosticMessages.js", "src/loc/lcl", "built/local", diagnosticMessagesGeneratedJson], { ignoreExitCode: true });
}
};
// Pre-build steps when targeting the LKG compiler
const lkgPreBuild = parallel(series(buildScripts, generateDiagnostics));
const buildTsc = () => buildProject("src/compiler");
task("tsc", series(lkgPreBuild, buildTsc));
task("tsc").description = "Builds the command-line compiler";
const cleanTsc = () => cleanProject("src/compiler");
cleanTasks.push(cleanTsc);
task("clean-tsc", cleanTsc);
task("clean-tsc").description = "Cleans outputs for the command-line compiler";
const watchTsc = () => watchProject("src/compiler");
task("watch-tsc", series(lkgPreBuild, parallel(watchDiagnostics, watchTsc)));
task("watch-tsc").description = "Watch for changes and rebuild the command-line compiler only.";
// Pre-build steps when targeting the built/local compiler.
const localPreBuild = parallel(series(buildScripts, generateDiagnostics, buildTsc));
// Pre-build steps to use based on supplied options.
const preBuild = cmdLineOptions.lkg ? lkgPreBuild : localPreBuild;
task("min", series(preBuild, parallel(buildTsc)));
task("min").description = "Builds only tsc and tsserver";
task("min").flags = {
" --built": "Compile using the built version of the compiler."
};
task("clean-min", series(cleanTsc));
task("clean-min").description = "Cleans outputs for tsc and tsserver";
task("watch-min", series(preBuild, parallel(watchDiagnostics, watchTsc)));
task("watch-min").description = "Watches for changes to a tsc and tsserver only";
task("watch-min").flags = {
" --built": "Compile using the built version of the compiler."
};
// Drop a copy of diagnosticMessages.generated.json into the built/local folder. This allows
// it to be synced to the Azure DevOps repo, so that it can get picked up by the build
// pipeline that generates the localization artifacts that are then fed into the translation process.
const builtLocalDiagnosticMessagesGeneratedJson = "built/local/diagnosticMessages.generated.json";
const copyBuiltLocalDiagnosticMessages = () => src(diagnosticMessagesGeneratedJson)
.pipe(newer(builtLocalDiagnosticMessagesGeneratedJson))
.pipe(dest("built/local"));
const cleanBuiltLocalDiagnosticMessages = () => del(builtLocalDiagnosticMessagesGeneratedJson);
cleanTasks.push(cleanBuiltLocalDiagnosticMessages);
const buildOtherOutputs = parallel(copyBuiltLocalDiagnosticMessages);
task("other-outputs", series(preBuild, buildOtherOutputs));
task("other-outputs").description = "Builds miscelaneous scripts and documents distributed with the LKG";
task("local", series(preBuild, parallel(localize, buildTsc, buildOtherOutputs)));
task("local").description = "Builds the full compiler and services";
task("local").flags = {
" --built": "Compile using the built version of the compiler."
};
task("watch-local", series(preBuild, parallel(watchDiagnostics, watchTsc)));
task("watch-local").description = "Watches for changes to projects in src/ (but does not execute tests).";
task("watch-local").flags = {
" --built": "Compile using the built version of the compiler."
};
const generateCodeCoverage = () => exec("istanbul", ["cover", "node_modules/mocha/bin/_mocha", "--", "-R", "min", "-t", "" + cmdLineOptions.testTimeout, "built/local/run.js"]);
task("generate-code-coverage", series(preBuild, generateCodeCoverage));
task("generate-code-coverage").description = "Generates code coverage data via istanbul";
const runTests = () => runConsoleTests("built/local/run.js", "mocha-fivemat-progress-reporter", /*runInParallel*/ false, /*watchMode*/ false);
task("runtests", series(preBuild, runTests));
task("runtests").description = "Runs the tests using the built run.js file.";
task("runtests").flags = {
"-t --tests=<regex>": "Pattern for tests to run.",
" --failed": "Runs tests listed in '.failed-tests'.",
"-r --reporter=<reporter>": "The mocha reporter to use.",
"-i --break": "Runs tests in inspector mode (NodeJS 8 and later)",
" --keepFailed": "Keep tests in .failed-tests even if they pass",
" --light": "Run tests in light mode (fewer verifications, but tests run faster)",
" --dirty": "Run tests without first cleaning test output directories",
" --stackTraceLimit=<limit>": "Sets the maximum number of stack frames to display. Use 'full' to show all frames.",
" --no-color": "Disables color",
" --no-lint": "Disables lint",
" --timeout=<ms>": "Overrides the default test timeout.",
" --built": "Compile using the built version of the compiler.",
" --shards": "Total number of shards running tests (default: 1)",
" --shardId": "1-based ID of this shard (default: 1)",
};
const runTestsParallel = () => runConsoleTests("built/local/run.js", "min", /*runInParallel*/ cmdLineOptions.workers > 1, /*watchMode*/ false);
task("runtests-parallel", series(preBuild, runTestsParallel));
task("runtests-parallel").description = "Runs all the tests in parallel using the built run.js file.";
task("runtests-parallel").flags = {
" --no-lint": "disables lint.",
" --light": "Run tests in light mode (fewer verifications, but tests run faster).",
" --keepFailed": "Keep tests in .failed-tests even if they pass.",
" --dirty": "Run tests without first cleaning test output directories.",
" --stackTraceLimit=<limit>": "Sets the maximum number of stack frames to display. Use 'full' to show all frames.",
" --workers=<number>": "The number of parallel workers to use.",
" --timeout=<ms>": "Overrides the default test timeout.",
" --built": "Compile using the built version of the compiler.",
" --shards": "Total number of shards running tests (default: 1)",
" --shardId": "1-based ID of this shard (default: 1)",
};
task("test-browser-integration", () => exec(process.execPath, ["scripts/browserIntegrationTest.js"]));
task("test-browser-integration").description = "Runs scripts/browserIntegrationTest.ts which tests that typescript.js loads in a browser";
task("diff", () => exec(getDiffTool(), [refBaseline, localBaseline], { ignoreExitCode: true, waitForExit: false }));
task("diff").description = "Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable";
task("diff-rwc", () => exec(getDiffTool(), [refRwcBaseline, localRwcBaseline], { ignoreExitCode: true, waitForExit: false }));
task("diff-rwc").description = "Diffs the RWC baselines using the diff tool specified by the 'DIFF' environment variable";
/**
* @param {string} localBaseline Path to the local copy of the baselines
* @param {string} refBaseline Path to the reference copy of the baselines
*/
const baselineAccept = (localBaseline, refBaseline) => merge2(
src([`${localBaseline}/**`, `!${localBaseline}/**/*.delete`], { base: localBaseline })
.pipe(dest(refBaseline)),
src([`${localBaseline}/**/*.delete`], { base: localBaseline, read: false })
.pipe(rm())
.pipe(rename({ extname: "" }))
.pipe(rm(refBaseline)));
task("baseline-accept", () => baselineAccept(localBaseline, refBaseline));
task("baseline-accept").description = "Makes the most recent test results the new baseline, overwriting the old baseline";
task("baseline-accept-rwc", () => baselineAccept(localRwcBaseline, refRwcBaseline));
task("baseline-accept-rwc").description = "Makes the most recent rwc test results the new baseline, overwriting the old baseline";
const buildLoggedIO = async () => {
mkdirp.sync("built/local/temp");
await exec(process.execPath, ["lib/tsc", "--types", "--target", "es5", "--lib", "es5", "--outdir", "built/local/temp", "src/harness/loggedIO.ts"]);
fs.renameSync("built/local/temp/harness/loggedIO.js", "built/local/loggedIO.js");
await del("built/local/temp");
};
const cleanLoggedIO = () => del("built/local/temp/loggedIO.js");
cleanTasks.push(cleanLoggedIO);
const buildInstrumenter = () => buildProject("src/instrumenter");
const cleanInstrumenter = () => cleanProject("src/instrumenter");
cleanTasks.push(cleanInstrumenter);
const tscInstrumented = () => exec(process.execPath, ["built/local/instrumenter.js", "record", cmdLineOptions.tests || "iocapture", "built/local"]);
task("tsc-instrumented", series(lkgPreBuild, parallel(localize, buildTsc, buildLoggedIO, buildInstrumenter), tscInstrumented));
task("tsc-instrumented").description = "Builds an instrumented tsc.js";
task("tsc-instrumented").flags = {
"-t --tests=<testname>": "The test to run."
};
// TODO(rbuckton): Determine if we still need this task. Depending on a relative
// path here seems like a bad idea.
const updateSublime = () => src(["built/local/tsserver.js", "built/local/tsserver.js.map"])
.pipe(dest("../TypeScript-Sublime-Plugin/tsserver/"));
task("update-sublime", updateSublime);
task("update-sublime").description = "Updates the sublime plugin's tsserver";
const buildImportDefinitelyTypedTests = () => buildProject("scripts/importDefinitelyTypedTests");
const cleanImportDefinitelyTypedTests = () => cleanProject("scripts/importDefinitelyTypedTests");
cleanTasks.push(cleanImportDefinitelyTypedTests);
// TODO(rbuckton): Should the path to DefinitelyTyped be configurable via an environment variable?
const importDefinitelyTypedTests = () => exec(process.execPath, ["scripts/importDefinitelyTypedTests/importDefinitelyTypedTests.js", "./", "../DefinitelyTyped"]);
task("importDefinitelyTypedTests", series(buildImportDefinitelyTypedTests, importDefinitelyTypedTests));
task("importDefinitelyTypedTests").description = "Runs the importDefinitelyTypedTests script to copy DT's tests to the TS-internal RWC tests";
const buildReleaseTsc = () => buildProject("src/tsc/tsconfig.release.json");
const cleanReleaseTsc = () => cleanProject("src/tsc/tsconfig.release.json");
cleanTasks.push(cleanReleaseTsc);
const cleanBuilt = () => del("built");
task("LKG", series(lkgPreBuild, parallel(localize, buildTsc, buildOtherOutputs, buildReleaseTsc)));
task("LKG").description = "Makes a new LKG out of the built js files";
task("LKG").flags = {
" --built": "Compile using the built version of the compiler.",
};
task("lkg", series("LKG"));
const generateSpec = () => exec("cscript", ["//nologo", "scripts/word2md.js", path.resolve("doc/TypeScript Language Specification - ARCHIVED.docx"), path.resolve("doc/spec-ARCHIVED.md")]);
task("generate-spec", series(buildScripts, generateSpec));
task("generate-spec").description = "Generates a Markdown version of the Language Specification";
task("clean", series(parallel(cleanTasks), cleanBuilt));
task("clean").description = "Cleans build outputs";
const configureNightly = () => exec(process.execPath, ["scripts/configurePrerelease.js", "dev", "package.json", "src/compiler/corePublic.ts"]);
task("configure-nightly", series(buildScripts, configureNightly));
task("configure-nightly").description = "Runs scripts/configurePrerelease.ts to prepare a build for nightly publishing";
const configureInsiders = () => exec(process.execPath, ["scripts/configurePrerelease.js", "insiders", "package.json", "src/compiler/corePublic.ts"]);
task("configure-insiders", series(buildScripts, configureInsiders));
task("configure-insiders").description = "Runs scripts/configurePrerelease.ts to prepare a build for insiders publishing";
const configureExperimental = () => exec(process.execPath, ["scripts/configurePrerelease.js", "experimental", "package.json", "src/compiler/corePublic.ts"]);
task("configure-experimental", series(buildScripts, configureExperimental));
task("configure-experimental").description = "Runs scripts/configurePrerelease.ts to prepare a build for experimental publishing";
const createLanguageServicesBuild = () => exec(process.execPath, ["scripts/createLanguageServicesBuild.js"]);
task("create-language-services-build", series(buildScripts, createLanguageServicesBuild));
task("create-language-services-build").description = "Runs scripts/createLanguageServicesBuild.ts to prepare a build which only has the require('typescript') JS.";
const publishNightly = () => exec("npm", ["publish", "--tag", "next"]);
task("publish-nightly", series(task("clean"), task("LKG"), task("clean"), task("runtests-parallel"), publishNightly));
task("publish-nightly").description = "Runs `npm publish --tag next` to create a new nightly build on npm";
// TODO(rbuckton): The problem with watching in this way is that a change in compiler/ will result
// in cascading changes in other projects that may take differing amounts of times to complete. As
// a result, the watch may accidentally trigger early, so we have to set a significant delay. An
// alternative approach would be to leverage a builder API, or to have 'tsc -b' have an option to
// write some kind of trigger file that indicates build completion that we could listen for instead.
const watchRuntests = () => watch(["built/local/*.js", "tests/cases/**/*.ts", "tests/cases/**/tsconfig.json"], { delay: 5000 }, async () => {
if (cmdLineOptions.tests || cmdLineOptions.failed) {
await runConsoleTests("built/local/run.js", "mocha-fivemat-progress-reporter", /*runInParallel*/ false, /*watchMode*/ true);
}
else {
await runConsoleTests("built/local/run.js", "min", /*runInParallel*/ true, /*watchMode*/ true);
}
});
task("watch", series(preBuild, parallel(watchDiagnostics, watchRuntests)));
task("watch").description = "Watches for changes and rebuilds and runs tests in parallel.";
task("watch").flags = {
"-t --tests=<regex>": "Pattern for tests to run. Forces tests to be run in a single worker.",
" --failed": "Runs tests listed in '.failed-tests'. Forces tests to be run in a single worker.",
"-r --reporter=<reporter>": "The mocha reporter to use.",
" --keepFailed": "Keep tests in .failed-tests even if they pass",
" --light": "Run tests in light mode (fewer verifications, but tests run faster)",
" --dirty": "Run tests without first cleaning test output directories",
" --stackTraceLimit=<limit>": "Sets the maximum number of stack frames to display. Use 'full' to show all frames.",
" --no-color": "Disables color",
" --no-lint": "Disables lint",
" --timeout=<ms>": "Overrides the default test timeout.",
" --workers=<number>": "The number of parallel workers to use.",
" --built": "Compile using the built version of the compiler.",
};
task("default", series("local"));
task("default").description = "Runs 'local'";
task("help", () => exec("gulp", ["--tasks", "--depth", "1", "--sort-tasks"], { hidePrompt: true }));
task("help").description = "Prints the top-level tasks.";
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化