forked from microsoft/TypeScript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwatchUtilities.ts
More file actions
161 lines (142 loc) · 7.92 KB
/
watchUtilities.ts
File metadata and controls
161 lines (142 loc) · 7.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/// <reference path="core.ts" />
/* @internal */
namespace ts {
export enum ConfigFileProgramReloadLevel {
None,
/** Update the file name list from the disk */
Partial,
/** Reload completely by re-reading contents of config file from disk and updating program */
Full
}
/**
* Updates the existing missing file watches with the new set of missing files after new program is created
*/
export function updateMissingFilePathsWatch(
program: Program,
missingFileWatches: Map<FileWatcher>,
createMissingFileWatch: (missingFilePath: Path) => FileWatcher,
) {
const missingFilePaths = program.getMissingFilePaths();
const newMissingFilePathMap = arrayToSet(missingFilePaths);
// Update the missing file paths watcher
mutateMap(
missingFileWatches,
newMissingFilePathMap,
{
// Watch the missing files
createNewValue: createMissingFileWatch,
// Files that are no longer missing (e.g. because they are no longer required)
// should no longer be watched.
onDeleteValue: closeFileWatcher
}
);
}
export interface WildcardDirectoryWatcher {
watcher: FileWatcher;
flags: WatchDirectoryFlags;
}
/**
* Updates the existing wild card directory watches with the new set of wild card directories from the config file
* after new program is created because the config file was reloaded or program was created first time from the config file
* Note that there is no need to call this function when the program is updated with additional files without reloading config files,
* as wildcard directories wont change unless reloading config file
*/
export function updateWatchingWildcardDirectories(
existingWatchedForWildcards: Map<WildcardDirectoryWatcher>,
wildcardDirectories: Map<WatchDirectoryFlags>,
watchDirectory: (directory: string, flags: WatchDirectoryFlags) => FileWatcher
) {
mutateMap(
existingWatchedForWildcards,
wildcardDirectories,
{
// Create new watch and recursive info
createNewValue: createWildcardDirectoryWatcher,
// Close existing watch thats not needed any more
onDeleteValue: closeFileWatcherOf,
// Close existing watch that doesnt match in the flags
onExistingValue: updateWildcardDirectoryWatcher
}
);
function createWildcardDirectoryWatcher(directory: string, flags: WatchDirectoryFlags): WildcardDirectoryWatcher {
// Create new watch and recursive info
return {
watcher: watchDirectory(directory, flags),
flags
};
}
function updateWildcardDirectoryWatcher(existingWatcher: WildcardDirectoryWatcher, flags: WatchDirectoryFlags, directory: string) {
// Watcher needs to be updated if the recursive flags dont match
if (existingWatcher.flags === flags) {
return;
}
existingWatcher.watcher.close();
existingWatchedForWildcards.set(directory, createWildcardDirectoryWatcher(directory, flags));
}
}
export function addFileWatcher(host: System, file: string, cb: FileWatcherCallback): FileWatcher {
return host.watchFile(file, cb);
}
export function addFileWatcherWithLogging(host: System, file: string, cb: FileWatcherCallback, log: (s: string) => void): FileWatcher {
const watcherCaption = `FileWatcher:: `;
return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ false, host, file, cb);
}
export function addFileWatcherWithOnlyTriggerLogging(host: System, file: string, cb: FileWatcherCallback, log: (s: string) => void): FileWatcher {
const watcherCaption = `FileWatcher:: `;
return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ true, host, file, cb);
}
export type FilePathWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind, filePath: Path) => void;
export function addFilePathWatcher(host: System, file: string, cb: FilePathWatcherCallback, path: Path): FileWatcher {
return host.watchFile(file, (fileName, eventKind) => cb(fileName, eventKind, path));
}
export function addFilePathWatcherWithLogging(host: System, file: string, cb: FilePathWatcherCallback, path: Path, log: (s: string) => void): FileWatcher {
const watcherCaption = `FileWatcher:: `;
return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ false, host, file, cb, path);
}
export function addFilePathWatcherWithOnlyTriggerLogging(host: System, file: string, cb: FilePathWatcherCallback, path: Path, log: (s: string) => void): FileWatcher {
const watcherCaption = `FileWatcher:: `;
return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ true, host, file, cb, path);
}
export function addDirectoryWatcher(host: System, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher {
const recursive = (flags & WatchDirectoryFlags.Recursive) !== 0;
return host.watchDirectory(directory, cb, recursive);
}
export function addDirectoryWatcherWithLogging(host: System, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags, log: (s: string) => void): FileWatcher {
const watcherCaption = `DirectoryWatcher ${(flags & WatchDirectoryFlags.Recursive) !== 0 ? "recursive" : ""}:: `;
return createWatcherWithLogging(addDirectoryWatcher, watcherCaption, log, /*logOnlyTrigger*/ false, host, directory, cb, flags);
}
export function addDirectoryWatcherWithOnlyTriggerLogging(host: System, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags, log: (s: string) => void): FileWatcher {
const watcherCaption = `DirectoryWatcher ${(flags & WatchDirectoryFlags.Recursive) !== 0 ? "recursive" : ""}:: `;
return createWatcherWithLogging(addDirectoryWatcher, watcherCaption, log, /*logOnlyTrigger*/ true, host, directory, cb, flags);
}
type WatchCallback<T, U> = (fileName: string, cbOptional1?: T, optional?: U) => void;
type AddWatch<T, U> = (host: System, file: string, cb: WatchCallback<T, U>, optional?: U) => FileWatcher;
function createWatcherWithLogging<T, U>(addWatch: AddWatch<T, U>, watcherCaption: string, log: (s: string) => void, logOnlyTrigger: boolean, host: System, file: string, cb: WatchCallback<T, U>, optional?: U): FileWatcher {
const info = `PathInfo: ${file}`;
if (!logOnlyTrigger) {
log(`${watcherCaption}Added: ${info}`);
}
const watcher = addWatch(host, file, (fileName, cbOptional1?) => {
const optionalInfo = cbOptional1 !== undefined ? ` ${cbOptional1}` : "";
log(`${watcherCaption}Trigger: ${fileName}${optionalInfo} ${info}`);
const start = timestamp();
cb(fileName, cbOptional1, optional);
const elapsed = timestamp() - start;
log(`${watcherCaption}Elapsed: ${elapsed}ms Trigger: ${fileName}${optionalInfo} ${info}`);
}, optional);
return {
close: () => {
if (!logOnlyTrigger) {
log(`${watcherCaption}Close: ${info}`);
}
watcher.close();
}
};
}
export function closeFileWatcher(watcher: FileWatcher) {
watcher.close();
}
export function closeFileWatcherOf<T extends { watcher: FileWatcher; }>(objWithWatcher: T) {
objWithWatcher.watcher.close();
}
}