From 9db53f23cfffd88067ce241f0dc4841359c0a760 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Mon, 5 Oct 2015 13:12:13 -0700 Subject: [PATCH] Add directory watcher to tsc --- src/compiler/sys.ts | 2 +- src/compiler/tsc.ts | 57 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 02728dffaf4..840e8de8271 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -423,7 +423,7 @@ namespace ts { (eventName: string, relativeFileName: string) => { if (eventName == "rename") { // when deleting a file, the passed baseFileName is null - callback(relativeFileName == null ? null : ts.combinePaths(path, ts.normalizeSlashes(relativeFileName))) + callback(relativeFileName == null ? null : normalizePath(ts.combinePaths(path, relativeFileName))) }; } ); diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 02b8e636772..d5682d8860e 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -149,6 +149,7 @@ namespace ts { let commandLine = parseCommandLine(args); let configFileName: string; // Configuration file name (if any) let configFileWatcher: FileWatcher; // Configuration file watcher + let directoryWatcher: FileWatcher; // Directory watcher to monitor source file addition/removal let cachedProgram: Program; // Program cached from last compilation let rootFileNames: string[]; // Root fileNames for compilation let compilerOptions: CompilerOptions; // Compiler options for compilation @@ -218,28 +219,43 @@ namespace ts { if (configFileName) { configFileWatcher = sys.watchFile(configFileName, configFileChanged); } + if (sys.watchDirectory && configFileName) { + let directory = ts.getDirectoryPath(configFileName); + directoryWatcher = sys.watchDirectory( + // When the configFileName is just "tsconfig.json", the watched directory should be + // the current direcotry; if there is a given "project" parameter, then the configFileName + // is an absolute file name. + directory == "" ? "." : directory, + watchedDirectoryChanged, /*recursive*/ true); + } } performCompilation(); + function configFileToParsedCommandLine(configFilename: string): ParsedCommandLine { + let result = readConfigFile(configFileName, sys.readFile); + if (result.error) { + reportWatchDiagnostic(result.error); + sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; + } + + let configObject = result.config; + let configParseResult = parseConfigFile(configObject, sys, getDirectoryPath(configFileName)); + if (configParseResult.errors.length > 0) { + reportDiagnostics(configParseResult.errors); + sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; + } + return configParseResult; + } + // Invoked to perform initial compilation or re-compilation in watch mode function performCompilation() { if (!cachedProgram) { if (configFileName) { - - let result = readConfigFile(configFileName, sys.readFile); - if (result.error) { - reportWatchDiagnostic(result.error); - return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); - } - - let configObject = result.config; - let configParseResult = parseConfigFile(configObject, sys, getDirectoryPath(configFileName)); - if (configParseResult.errors.length > 0) { - reportDiagnostics(configParseResult.errors); - return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); - } + let configParseResult = configFileToParsedCommandLine(configFileName); rootFileNames = configParseResult.fileNames; compilerOptions = extend(commandLine.options, configParseResult.options); } @@ -309,6 +325,21 @@ namespace ts { startTimer(); } + function watchedDirectoryChanged(fileName: string) { + if (fileName && !ts.isSupportedSourceFileName(fileName)) { + return; + } + + let parsedCommandLine = configFileToParsedCommandLine(configFileName); + let newFileNames = parsedCommandLine.fileNames.map(compilerHost.getCanonicalFileName); + let canonicalRootFileNames = rootFileNames.map(compilerHost.getCanonicalFileName); + + if (!doTwoArraysHaveTheSameElements(newFileNames, canonicalRootFileNames)) { + setCachedProgram(undefined); + startTimer(); + } + } + // Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch // operations (such as saving all modified files in an editor) a chance to complete before we kick // off a new compilation.