diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 1f36f09393b..974edd6c60c 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -332,6 +332,7 @@ namespace ts { if (sourceFile === undefined) { return undefined; } + const parsed = parseJsonSourceFileConfigFileContent(sourceFile, configParseHost, getDirectoryPath(configFilePath)); parsed.options.configFilePath = configFilePath; cache.setValue(configFilePath, parsed); @@ -410,7 +411,7 @@ namespace ts { } ]; - export function performBuild(host: CompilerHost, reportDiagnostic: DiagnosticReporter, args: string[]) { + export function performBuild(host: CompilerHost, reportDiagnostic: DiagnosticReporter, args: string[], system?: System) { let verbose = false; let dry = false; let force = false; @@ -472,7 +473,7 @@ namespace ts { addProject("."); } - const builder = createSolutionBuilder(host, projects, reportDiagnostic, { verbose, dry, force }); + const builder = createSolutionBuilder(host, projects, reportDiagnostic, { verbose, dry, force }, system); if (clean) { builder.cleanAllProjects(); } @@ -480,6 +481,10 @@ namespace ts { builder.buildAllProjects(); } + if (watch) { + return builder.startWatching(); + } + function addProject(projectSpecification: string) { const fileName = resolvePath(host.getCurrentDirectory(), projectSpecification); const refPath = resolveProjectReferencePath(host, { path: fileName }); @@ -500,7 +505,7 @@ namespace ts { * A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but * can dynamically add/remove other projects based on changes on the rootNames' references */ - export function createSolutionBuilder(host: CompilerHost, rootNames: ReadonlyArray, reportDiagnostic: DiagnosticReporter, defaultOptions: BuildOptions) { + export function createSolutionBuilder(host: CompilerHost, rootNames: ReadonlyArray, reportDiagnostic: DiagnosticReporter, defaultOptions: BuildOptions, system?: System) { if (!host.getModifiedTime || !host.setModifiedTime) { throw new Error("Host must support timestamp APIs"); } @@ -520,9 +525,30 @@ namespace ts { buildInvalidatedProjects, buildDependentInvalidatedProjects, - resolveProjectName + resolveProjectName, + + startWatching }; + function startWatching() { + if (!system) throw new Error("System host must be provided if using --watch"); + if (!system.watchFile || !system.watchDirectory || !system.setTimeout) throw new Error("System host must support watchFile / watchDirectory / setTimeout if using --watch"); + + const graph = getGlobalDependencyGraph()!; + for (const resolved of graph.buildQueue) { + const cfg = configFileCache.parseConfigFile(resolved); + if (cfg) { + for (const input of cfg.fileNames) { + system.watchFile(input, () => { + invalidateProject(resolved); + system.setTimeout!(buildInvalidatedProjects, 100); + system.setTimeout!(buildDependentInvalidatedProjects, 3000); + }); + } + } + } + } + function resetBuildContext(opts = defaultOptions) { context = createBuildContext(opts, reportDiagnostic); } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 9800d2e768a..744379aa696 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -50,7 +50,7 @@ namespace ts { export function executeCommandLine(args: string[]): void { if ((args[0].toLowerCase() === "--build") || (args[0].toLowerCase() === "-b")) { - return performBuild(createCompilerHost({}), createDiagnosticReporter(sys), args.slice(1)); + return performBuild(createCompilerHost({}), createDiagnosticReporter(sys), args.slice(1), sys); } const commandLine = parseCommandLine(args);