diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 909dd0feede..aee8c98db0d 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -18,8 +18,8 @@ namespace ts { * If an array, the full list of source files to emit. * Else, calls `getSourceFilesToEmit` with the (optional) target source file to determine the list of source files to emit. */ - export function forEachEmittedFile( - host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle, emitOnlyDtsFiles: boolean) => void, + export function forEachEmittedFile( + host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle, emitOnlyDtsFiles: boolean) => T, sourceFilesOrTargetSourceFile?: SourceFile[] | SourceFile, emitOnlyDtsFiles?: boolean) { @@ -30,7 +30,10 @@ namespace ts { const jsFilePath = options.outFile || options.out; const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + Extension.Dts : ""; - action({ jsFilePath, sourceMapFilePath, declarationFilePath }, createBundle(sourceFiles), emitOnlyDtsFiles); + const result = action({ jsFilePath, sourceMapFilePath, declarationFilePath }, createBundle(sourceFiles), emitOnlyDtsFiles); + if (result) { + return result; + } } } else { @@ -38,7 +41,10 @@ namespace ts { const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, getOutputExtension(sourceFile, options)); const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); const declarationFilePath = !isSourceFileJavaScript(sourceFile) && (emitOnlyDtsFiles || options.declaration) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined; - action({ jsFilePath, sourceMapFilePath, declarationFilePath }, sourceFile, emitOnlyDtsFiles); + const result = action({ jsFilePath, sourceMapFilePath, declarationFilePath }, sourceFile, emitOnlyDtsFiles); + if (result) { + return result; + } } } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 88a2f5ee8f1..0d1bbf233a3 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -667,7 +667,8 @@ namespace ts { dropDiagnosticsProducingTypeChecker, getSourceFileFromReference, sourceFileToPackageName, - redirectTargetsSet + redirectTargetsSet, + isEmittedFile }; verifyCompilerOptions(); @@ -2343,6 +2344,20 @@ namespace ts { hasEmitBlockingDiagnostics.set(toPath(emitFileName), true); programDiagnostics.add(diag); } + + function isEmittedFile(file: string) { + if (options.noEmit) { + return false; + } + + return forEachEmittedFile(getEmitHost(), ({ jsFilePath, declarationFilePath }) => + isSameFile(jsFilePath, file) || + (declarationFilePath && isSameFile(declarationFilePath, file))); + } + + function isSameFile(file1: string, file2: string) { + return comparePaths(file1, file2, currentDirectory, !host.useCaseSensitiveFileNames()) === Comparison.EqualTo; + } } /* @internal */ diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index e21e81a2e88..aac25c5d596 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -52,6 +52,7 @@ namespace ts { getGlobalCache?(): string | undefined; writeLog(s: string): void; maxNumberOfFilesToIterateForInvalidation?: number; + getCurrentProgram(): Program; } interface DirectoryWatchesOfFailedLookup { @@ -472,6 +473,11 @@ namespace ts { resolutionHost.getCachedDirectoryStructureHost().addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } + // Ignore emits from the program + if (isEmittedFileOfProgram(resolutionHost.getCurrentProgram(), fileOrDirectory)) { + return; + } + // If the files are added to project root or node_modules directory, always run through the invalidation process // Otherwise run through invalidation only if adding to the immediate directory if (!allFilesHaveInvalidatedResolution && diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 23798635671..e4ada136730 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2659,6 +2659,8 @@ namespace ts { /* @internal */ sourceFileToPackageName: Map; /** Set of all source files that some other source file redirects to. */ /* @internal */ redirectTargetsSet: Map; + /** Is the file emitted file */ + /* @internal */ isEmittedFile(file: string): boolean; } /* @internal */ diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index ccbf169c3a2..79e26f5986c 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -305,6 +305,7 @@ namespace ts { scheduleProgramUpdate(); }, maxNumberOfFilesToIterateForInvalidation: watchingHost.maxNumberOfFilesToIterateForInvalidation, + getCurrentProgram, writeLog }; // Cache for the module resolution @@ -322,7 +323,11 @@ namespace ts { // Update the wild card directory watch watchConfigFileWildCardDirectories(); - return () => program; + return getCurrentProgram; + + function getCurrentProgram() { + return program; + } function synchronizeProgram() { writeLog(`Synchronizing program`); diff --git a/src/compiler/watchUtilities.ts b/src/compiler/watchUtilities.ts index 0cf38f372d9..0bc6920479b 100644 --- a/src/compiler/watchUtilities.ts +++ b/src/compiler/watchUtilities.ts @@ -82,6 +82,14 @@ namespace ts { } } + export function isEmittedFileOfProgram(program: Program | undefined, file: string) { + if (!program) { + return false; + } + + return program.isEmittedFile(file); + } + export function addFileWatcher(host: System, file: string, cb: FileWatcherCallback): FileWatcher { return host.watchFile(file, cb); } diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index 096778300e1..9e01021155c 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -1096,7 +1096,7 @@ namespace ts.tscWatch { assert.isTrue(host.fileExists("build/src/file2.js")); // This should be 0 - host.checkTimeoutQueueLengthAndRun(1); + host.checkTimeoutQueueLengthAndRun(0); }); }); diff --git a/src/server/project.ts b/src/server/project.ts index ebc93ae3e1e..a25e6870bda 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -830,7 +830,10 @@ namespace ts.server { return !hasChanges; } - + /* @internal */ + getCurrentProgram() { + return this.program; + } protected removeExistingTypings(include: string[]): string[] { const existing = ts.getAutomaticTypeDirectiveNames(this.getCompilerOptions(), this.directoryStructureHost);