mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 21:36:50 -05:00
Merge pull request #16684 from amcasey/Vsts434619
Watch for the creation of missing files
This commit is contained in:
@@ -210,8 +210,11 @@ namespace ts.server {
|
||||
return this.host.resolvePath(path);
|
||||
}
|
||||
|
||||
fileExists(path: string): boolean {
|
||||
return this.host.fileExists(path);
|
||||
fileExists(file: string): boolean {
|
||||
// As an optimization, don't hit the disks for files we already know don't exist
|
||||
// (because we're watching for their creation).
|
||||
const path = toPath(file, this.host.getCurrentDirectory(), this.getCanonicalFileName);
|
||||
return !this.project.isWatchedMissingFile(path) && this.host.fileExists(file);
|
||||
}
|
||||
|
||||
readFile(fileName: string): string {
|
||||
|
||||
@@ -107,6 +107,7 @@ namespace ts.server {
|
||||
private rootFilesMap: Map<ScriptInfo> = createMap<ScriptInfo>();
|
||||
private program: ts.Program;
|
||||
private externalFiles: SortedReadonlyArray<string>;
|
||||
private missingFilesMap: Map<FileWatcher> = createMap<FileWatcher>();
|
||||
|
||||
private cachedUnresolvedImportsPerFile = new UnresolvedImportsMap();
|
||||
private lastCachedUnresolvedImportsList: SortedReadonlyArray<string>;
|
||||
@@ -310,6 +311,10 @@ namespace ts.server {
|
||||
this.lsHost.dispose();
|
||||
this.lsHost = undefined;
|
||||
|
||||
// Clean up file watchers waiting for missing files
|
||||
this.missingFilesMap.forEach(fileWatcher => fileWatcher.close());
|
||||
this.missingFilesMap = undefined;
|
||||
|
||||
// signal language service to release source files acquired from document registry
|
||||
this.languageService.dispose();
|
||||
this.languageService = undefined;
|
||||
@@ -586,12 +591,12 @@ namespace ts.server {
|
||||
const oldProgram = this.program;
|
||||
this.program = this.languageService.getProgram();
|
||||
|
||||
let hasChanges = false;
|
||||
// bump up the version if
|
||||
// - oldProgram is not set - this is a first time updateGraph is called
|
||||
// - newProgram is different from the old program and structure of the old program was not reused.
|
||||
if (!oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused & StructureIsReused.Completely))) {
|
||||
hasChanges = true;
|
||||
const hasChanges = !oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused & StructureIsReused.Completely));
|
||||
|
||||
if (hasChanges) {
|
||||
if (oldProgram) {
|
||||
for (const f of oldProgram.getSourceFiles()) {
|
||||
if (this.program.getSourceFileByPath(f.path)) {
|
||||
@@ -604,6 +609,35 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const missingFilePaths = this.program.getMissingFilePaths();
|
||||
const missingFilePathsSet = arrayToSet(missingFilePaths, p => p);
|
||||
|
||||
// Files that are no longer missing (e.g. because they are no longer required)
|
||||
// should no longer be watched.
|
||||
this.missingFilesMap.forEach((fileWatcher, missingFilePath) => {
|
||||
if (!missingFilePathsSet.has(missingFilePath)) {
|
||||
this.missingFilesMap.delete(missingFilePath);
|
||||
fileWatcher.close();
|
||||
}
|
||||
});
|
||||
|
||||
// Missing files that are not yet watched should be added to the map.
|
||||
for (const missingFilePath of missingFilePaths) {
|
||||
if (!this.missingFilesMap.has(missingFilePath)) {
|
||||
const fileWatcher = this.projectService.host.watchFile(missingFilePath, (_filename: string, eventKind: FileWatcherEventKind) => {
|
||||
if (eventKind === FileWatcherEventKind.Created && this.missingFilesMap.has(missingFilePath)) {
|
||||
fileWatcher.close();
|
||||
this.missingFilesMap.delete(missingFilePath);
|
||||
|
||||
// When a missing file is created, we should update the graph.
|
||||
this.markAsDirty();
|
||||
this.updateGraph();
|
||||
}
|
||||
});
|
||||
this.missingFilesMap.set(missingFilePath, fileWatcher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const oldExternalFiles = this.externalFiles || emptyArray as SortedReadonlyArray<string>;
|
||||
@@ -626,6 +660,10 @@ namespace ts.server {
|
||||
return hasChanges;
|
||||
}
|
||||
|
||||
isWatchedMissingFile(path: Path) {
|
||||
return this.missingFilesMap.has(path);
|
||||
}
|
||||
|
||||
getScriptInfoLSHost(fileName: string) {
|
||||
const scriptInfo = this.projectService.getOrCreateScriptInfo(fileName, /*openedByClient*/ false);
|
||||
if (scriptInfo) {
|
||||
|
||||
@@ -523,11 +523,14 @@ namespace ts.server {
|
||||
|
||||
fs.stat(watchedFile.fileName, (err: any, stats: any) => {
|
||||
if (err) {
|
||||
watchedFile.callback(watchedFile.fileName);
|
||||
watchedFile.callback(watchedFile.fileName, FileWatcherEventKind.Changed);
|
||||
}
|
||||
else if (watchedFile.mtime.getTime() !== stats.mtime.getTime()) {
|
||||
watchedFile.mtime = stats.mtime;
|
||||
watchedFile.callback(watchedFile.fileName, watchedFile.mtime.getTime() === 0);
|
||||
const eventKind = watchedFile.mtime.getTime() === 0
|
||||
? FileWatcherEventKind.Deleted
|
||||
: FileWatcherEventKind.Changed;
|
||||
watchedFile.callback(watchedFile.fileName, eventKind);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -559,7 +562,9 @@ namespace ts.server {
|
||||
const file: WatchedFile = {
|
||||
fileName,
|
||||
callback,
|
||||
mtime: getModifiedTime(fileName)
|
||||
mtime: sys.fileExists(fileName)
|
||||
? getModifiedTime(fileName)
|
||||
: new Date(0) // Any subsequent modification will occur after this time
|
||||
};
|
||||
|
||||
watchedFiles.push(file);
|
||||
|
||||
Reference in New Issue
Block a user