(host: PerformWatchHost)
| 130 | * The logic in this function is adapted from `tsc.ts` from TypeScript. |
| 131 | */ |
| 132 | export function performWatchCompilation(host: PerformWatchHost): { |
| 133 | close: () => void; |
| 134 | ready: (cb: () => void) => void; |
| 135 | firstCompileResult: ReadonlyArray<ts.Diagnostic>; |
| 136 | } { |
| 137 | let cachedProgram: api.Program | undefined; // Program cached from last compilation |
| 138 | let cachedCompilerHost: api.CompilerHost | undefined; // CompilerHost cached from last compilation |
| 139 | let cachedOptions: ParsedConfiguration | undefined; // CompilerOptions cached from last compilation |
| 140 | let timerHandleForRecompilation: QueuedCompilationInfo | undefined; // Handle for 0.25s wait timer to trigger recompilation |
| 141 | |
| 142 | const ignoreFilesForWatch = new Set<string>(); |
| 143 | const fileCache = new Map<string, CacheEntry>(); |
| 144 | |
| 145 | const firstCompileResult = doCompilation(); |
| 146 | |
| 147 | // Watch basePath, ignoring .dotfiles |
| 148 | let resolveReadyPromise: () => void; |
| 149 | const readyPromise = new Promise<void>((resolve) => (resolveReadyPromise = resolve)); |
| 150 | // Note: ! is ok as options are filled after the first compilation |
| 151 | // Note: ! is ok as resolvedReadyPromise is filled by the previous call |
| 152 | const fileWatcher = host.onFileChange( |
| 153 | cachedOptions!.options, |
| 154 | watchedFileChanged, |
| 155 | resolveReadyPromise!, |
| 156 | ); |
| 157 | |
| 158 | return {close, ready: (cb) => readyPromise.then(cb), firstCompileResult}; |
| 159 | |
| 160 | function cacheEntry(fileName: string): CacheEntry { |
| 161 | fileName = path.normalize(fileName); |
| 162 | let entry = fileCache.get(fileName); |
| 163 | if (!entry) { |
| 164 | entry = {}; |
| 165 | fileCache.set(fileName, entry); |
| 166 | } |
| 167 | return entry; |
| 168 | } |
| 169 | |
| 170 | function close() { |
| 171 | fileWatcher.close(); |
| 172 | if (timerHandleForRecompilation) { |
| 173 | host.clearTimeout(timerHandleForRecompilation.timerHandle); |
| 174 | timerHandleForRecompilation = undefined; |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | // Invoked to perform initial compilation or re-compilation in watch mode |
| 179 | function doCompilation(): ReadonlyArray<ts.Diagnostic> { |
| 180 | if (!cachedOptions) { |
| 181 | cachedOptions = host.readConfiguration(); |
| 182 | } |
| 183 | if (cachedOptions.errors && cachedOptions.errors.length) { |
| 184 | host.reportDiagnostics(cachedOptions.errors); |
| 185 | return cachedOptions.errors; |
| 186 | } |
| 187 | const startTime = Date.now(); |
| 188 | if (!cachedCompilerHost) { |
| 189 | cachedCompilerHost = host.createCompilerHost(cachedOptions.options); |
no test coverage detected
searching dependent graphs…