Skip to content

Commit 8c25128

Browse files
committed
Merge branch 'main' into bug/module-resolution-refactor
2 parents 22a4987 + 9f64a3a commit 8c25128

File tree

290 files changed

+9737
-9730
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

290 files changed

+9737
-9730
lines changed

.eslintrc.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"es6": true
1111
},
1212
"plugins": [
13-
"@typescript-eslint", "jsdoc", "no-null", "import", "eslint-plugin-local"
13+
"@typescript-eslint", "no-null", "import", "eslint-plugin-local"
1414
],
1515
"rules": {
1616
"@typescript-eslint/adjacent-overload-signatures": "error",
@@ -95,9 +95,6 @@
9595
// eslint-plugin-no-null
9696
"no-null/no-null": "error",
9797

98-
// eslint-plugin-jsdoc
99-
"jsdoc/check-alignment": "error",
100-
10198
// eslint
10299
"constructor-super": "error",
103100
"curly": ["error", "multi-line"],

Herebyfile.mjs

Lines changed: 145 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@ import { task } from "hereby";
66
import _glob from "glob";
77
import util from "util";
88
import chalk from "chalk";
9-
import { exec, readJson, getDiffTool, getDirSize, memoize, needsUpdate } from "./scripts/build/utils.mjs";
10-
import { runConsoleTests, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline } from "./scripts/build/tests.mjs";
9+
import { exec, readJson, getDiffTool, getDirSize, memoize, needsUpdate, Debouncer, Deferred } from "./scripts/build/utils.mjs";
10+
import { runConsoleTests, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline, cleanTestDirs } from "./scripts/build/tests.mjs";
1111
import { buildProject as realBuildProject, cleanProject, watchProject } from "./scripts/build/projects.mjs";
1212
import { localizationDirectories } from "./scripts/build/localization.mjs";
1313
import cmdLineOptions from "./scripts/build/options.mjs";
1414
import esbuild from "esbuild";
15+
import chokidar from "chokidar";
16+
import { EventEmitter } from "events";
17+
import { CancelToken } from "@esfx/canceltoken";
1518

1619
const glob = util.promisify(_glob);
1720

@@ -141,7 +144,7 @@ const localize = task({
141144
dependencies: [generateDiagnostics],
142145
run: async () => {
143146
if (needsUpdate(diagnosticMessagesGeneratedJson, generatedLCGFile)) {
144-
return exec(process.execPath, ["scripts/generateLocalizedDiagnosticMessages.mjs", "src/loc/lcl", "built/local", diagnosticMessagesGeneratedJson], { ignoreExitCode: true });
147+
await exec(process.execPath, ["scripts/generateLocalizedDiagnosticMessages.mjs", "src/loc/lcl", "built/local", diagnosticMessagesGeneratedJson], { ignoreExitCode: true });
145148
}
146149
}
147150
});
@@ -191,6 +194,7 @@ async function runDtsBundler(entrypoint, output) {
191194
* @property {string[]} [external]
192195
* @property {boolean} [exportIsTsObject]
193196
* @property {boolean} [treeShaking]
197+
* @property {esbuild.WatchMode} [watchMode]
194198
*/
195199
function createBundler(entrypoint, outfile, taskOptions = {}) {
196200
const getOptions = memoize(async () => {
@@ -269,7 +273,7 @@ function createBundler(entrypoint, outfile, taskOptions = {}) {
269273

270274
return {
271275
build: async () => esbuild.build(await getOptions()),
272-
watch: async () => esbuild.build({ ...await getOptions(), watch: true, logLevel: "info" }),
276+
watch: async () => esbuild.build({ ...await getOptions(), watch: taskOptions.watchMode ?? true, logLevel: "info" }),
273277
};
274278
}
275279

@@ -320,7 +324,7 @@ function entrypointBuildTask(options) {
320324
const outDir = path.dirname(options.output);
321325
await fs.promises.mkdir(outDir, { recursive: true });
322326
const moduleSpecifier = path.relative(outDir, options.builtEntrypoint);
323-
await fs.promises.writeFile(options.output, `module.exports = require("./${moduleSpecifier}")`);
327+
await fs.promises.writeFile(options.output, `module.exports = require("./${moduleSpecifier.replace(/[\\/]/g, "/")}")`);
324328
},
325329
});
326330

@@ -354,7 +358,7 @@ function entrypointBuildTask(options) {
354358
}
355359

356360

357-
const { main: tsc, watch: watchTsc } = entrypointBuildTask({
361+
const { main: tsc, build: buildTsc, watch: watchTsc } = entrypointBuildTask({
358362
name: "tsc",
359363
description: "Builds the command-line compiler",
360364
buildDeps: [generateDiagnostics],
@@ -386,13 +390,13 @@ export const dtsServices = task({
386390
dependencies: [buildServices],
387391
run: async () => {
388392
if (needsUpdate("./built/local/typescript/tsconfig.tsbuildinfo", ["./built/local/typescript.d.ts", "./built/local/typescript.internal.d.ts"])) {
389-
runDtsBundler("./built/local/typescript/typescript.d.ts", "./built/local/typescript.d.ts");
393+
await runDtsBundler("./built/local/typescript/typescript.d.ts", "./built/local/typescript.d.ts");
390394
}
391395
},
392396
});
393397

394398

395-
const { main: tsserver, watch: watchTsserver } = entrypointBuildTask({
399+
const { main: tsserver, build: buildTsserver, watch: watchTsserver } = entrypointBuildTask({
396400
name: "tsserver",
397401
description: "Builds the language server",
398402
buildDeps: [generateDiagnostics],
@@ -410,10 +414,15 @@ const { main: tsserver, watch: watchTsserver } = entrypointBuildTask({
410414
export { tsserver, watchTsserver };
411415

412416

417+
const buildMin = task({
418+
name: "build-min",
419+
dependencies: [buildTsc, buildTsserver],
420+
});
421+
413422
export const min = task({
414423
name: "min",
415424
description: "Builds only tsc and tsserver",
416-
dependencies: [tsc, tsserver],
425+
dependencies: [tsc, tsserver].concat(cmdLineOptions.typecheck ? [buildMin] : []),
417426
});
418427

419428
export const watchMin = task({
@@ -456,7 +465,7 @@ export const dts = task({
456465

457466

458467
const testRunner = "./built/local/run.js";
459-
468+
const watchTestsEmitter = new EventEmitter();
460469
const { main: tests, watch: watchTests } = entrypointBuildTask({
461470
name: "tests",
462471
description: "Builds the test infrastructure",
@@ -477,6 +486,11 @@ const { main: tests, watch: watchTests } = entrypointBuildTask({
477486
"mocha",
478487
"ms",
479488
],
489+
watchMode: {
490+
onRebuild() {
491+
watchTestsEmitter.emit("rebuild");
492+
}
493+
}
480494
},
481495
});
482496
export { tests, watchTests };
@@ -577,10 +591,15 @@ export const watchOtherOutputs = task({
577591
dependencies: [watchCancellationToken, watchTypingsInstaller, watchWatchGuard, generateTypesMap, copyBuiltLocalDiagnosticMessages],
578592
});
579593

594+
const buildLocal = task({
595+
name: "build-local",
596+
dependencies: [buildTsc, buildTsserver, buildServices, buildLssl]
597+
});
598+
580599
export const local = task({
581600
name: "local",
582601
description: "Builds the full compiler and services",
583-
dependencies: [localize, tsc, tsserver, services, lssl, otherOutputs, dts, buildSrc],
602+
dependencies: [localize, tsc, tsserver, services, lssl, otherOutputs, dts].concat(cmdLineOptions.typecheck ? [buildLocal] : []),
584603
});
585604
export default local;
586605

@@ -591,11 +610,12 @@ export const watchLocal = task({
591610
dependencies: [localize, watchTsc, watchTsserver, watchServices, watchLssl, watchOtherOutputs, dts, watchSrc],
592611
});
593612

613+
const runtestsDeps = [tests, generateLibs].concat(cmdLineOptions.typecheck ? [dts, buildSrc] : []);
594614

595615
export const runTests = task({
596616
name: "runtests",
597617
description: "Runs the tests using the built run.js file.",
598-
dependencies: [tests, generateLibs, dts, buildSrc],
618+
dependencies: runtestsDeps,
599619
run: () => runConsoleTests(testRunner, "mocha-fivemat-progress-reporter", /*runInParallel*/ false),
600620
});
601621
// task("runtests").flags = {
@@ -614,10 +634,121 @@ export const runTests = task({
614634
// " --shardId": "1-based ID of this shard (default: 1)",
615635
// };
616636

637+
export const runTestsAndWatch = task({
638+
name: "runtests-watch",
639+
dependencies: [watchTests],
640+
run: async () => {
641+
if (!cmdLineOptions.tests && !cmdLineOptions.failed) {
642+
console.log(chalk.redBright(`You must specifiy either --tests/-t or --failed to use 'runtests-watch'.`));
643+
return;
644+
}
645+
646+
let watching = true;
647+
let running = true;
648+
let lastTestChangeTimeMs = Date.now();
649+
let testsChangedDeferred = /** @type {Deferred<void>} */(new Deferred());
650+
let testsChangedCancelSource = CancelToken.source();
651+
652+
const testsChangedDebouncer = new Debouncer(1_000, endRunTests);
653+
const testCaseWatcher = chokidar.watch([
654+
"tests/cases/**/*.*",
655+
"tests/lib/**/*.*",
656+
"tests/projects/**/*.*",
657+
], {
658+
ignorePermissionErrors: true,
659+
alwaysStat: true
660+
});
661+
662+
process.on("SIGINT", endWatchMode);
663+
process.on("SIGKILL", endWatchMode);
664+
process.on("beforeExit", endWatchMode);
665+
watchTestsEmitter.on("rebuild", onRebuild);
666+
testCaseWatcher.on("all", onChange);
667+
668+
while (watching) {
669+
const promise = testsChangedDeferred.promise;
670+
const token = testsChangedCancelSource.token;
671+
if (!token.signaled) {
672+
running = true;
673+
try {
674+
await runConsoleTests(testRunner, "mocha-fivemat-progress-reporter", /*runInParallel*/ false, { token, watching: true });
675+
}
676+
catch {
677+
// ignore
678+
}
679+
running = false;
680+
}
681+
if (watching) {
682+
console.log(chalk.yellowBright(`[watch] test run complete, waiting for changes...`));
683+
await promise;
684+
}
685+
}
686+
687+
function onRebuild() {
688+
beginRunTests(testRunner);
689+
}
690+
691+
/**
692+
* @param {'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir'} eventName
693+
* @param {string} path
694+
* @param {fs.Stats | undefined} stats
695+
*/
696+
function onChange(eventName, path, stats) {
697+
switch (eventName) {
698+
case "change":
699+
case "unlink":
700+
case "unlinkDir":
701+
break;
702+
case "add":
703+
case "addDir":
704+
// skip files that are detected as 'add' but haven't actually changed since the last time tests were
705+
// run.
706+
if (stats && stats.mtimeMs <= lastTestChangeTimeMs) {
707+
return;
708+
}
709+
break;
710+
}
711+
beginRunTests(path);
712+
}
713+
714+
/**
715+
* @param {string} path
716+
*/
717+
function beginRunTests(path) {
718+
if (testsChangedDebouncer.empty) {
719+
console.log(chalk.yellowBright(`[watch] tests changed due to '${path}', restarting...`));
720+
if (running) {
721+
console.log(chalk.yellowBright("[watch] aborting in-progress test run..."));
722+
}
723+
testsChangedCancelSource.cancel();
724+
testsChangedCancelSource = CancelToken.source();
725+
}
726+
727+
testsChangedDebouncer.enqueue();
728+
}
729+
730+
function endRunTests() {
731+
lastTestChangeTimeMs = Date.now();
732+
testsChangedDeferred.resolve();
733+
testsChangedDeferred = /** @type {Deferred<void>} */(new Deferred());
734+
}
735+
736+
function endWatchMode() {
737+
if (watching) {
738+
watching = false;
739+
console.log(chalk.yellowBright("[watch] exiting watch mode..."));
740+
testsChangedCancelSource.cancel();
741+
testCaseWatcher.close();
742+
watchTestsEmitter.off("rebuild", onRebuild);
743+
}
744+
}
745+
},
746+
});
747+
617748
export const runTestsParallel = task({
618749
name: "runtests-parallel",
619750
description: "Runs all the tests in parallel using the built run.js file.",
620-
dependencies: [tests, generateLibs, dts, buildSrc],
751+
dependencies: runtestsDeps,
621752
run: () => runConsoleTests(testRunner, "min", /*runInParallel*/ cmdLineOptions.workers > 1),
622753
});
623754
// task("runtests-parallel").flags = {
@@ -715,7 +846,7 @@ export const importDefinitelyTypedTests = task({
715846
export const produceLKG = task({
716847
name: "LKG",
717848
description: "Makes a new LKG out of the built js files",
718-
dependencies: [localize, tsc, tsserver, services, lssl, otherOutputs, dts],
849+
dependencies: [local],
719850
run: async () => {
720851
if (!cmdLineOptions.bundle) {
721852
throw new Error("LKG cannot be created when --bundle=false");

0 commit comments

Comments
 (0)