UNPKG

39.8 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.getSolutionErrors = exports.makeSolutionBuilderHost = exports.makeWatchHost = exports.updateFileWithText = exports.makeServicesHost = void 0;
4const path = require("path");
5const config_1 = require("./config");
6const constants = require("./constants");
7const instances_1 = require("./instances");
8const resolver_1 = require("./resolver");
9const utils_1 = require("./utils");
10function makeResolversHandlingProjectReferences(scriptRegex, loader, instance, originalFileExists, enableFileCaching) {
11 const { compiler, compilerOptions, appendTsTsxSuffixesIfRequired, loaderOptions: { resolveModuleName: customResolveModuleName, resolveTypeReferenceDirective: customResolveTypeReferenceDirective, }, } = instance;
12 const newLine = compilerOptions.newLine === constants.CarriageReturnLineFeedCode
13 ? constants.CarriageReturnLineFeed
14 : compilerOptions.newLine === constants.LineFeedCode
15 ? constants.LineFeed
16 : constants.EOL;
17 // loader.context seems to work fine on Linux / Mac regardless causes problems for @types resolution on Windows for TypeScript < 2.3
18 const getCurrentDirectory = () => loader.context;
19 // make a (sync) resolver that follows webpack's rules
20 const resolveSync = resolver_1.makeResolver(loader._compiler.options);
21 const moduleResolutionHost = {
22 trace: logData => instance.log.log(logData),
23 fileExists,
24 readFile,
25 realpath: compiler.sys.realpath && realpath,
26 directoryExists,
27 getCurrentDirectory,
28 getDirectories,
29 readDirectory,
30 useCaseSensitiveFileNames: () => utils_1.useCaseSensitiveFileNames(compiler, instance.loaderOptions),
31 getNewLine: () => newLine,
32 getDefaultLibFileName: options => compiler.getDefaultLibFilePath(options),
33 };
34 if (enableFileCaching) {
35 addCache(moduleResolutionHost);
36 }
37 return makeResolvers(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective, customResolveModuleName, resolveSync, appendTsTsxSuffixesIfRequired, scriptRegex, instance);
38 function fileExists(filePathToCheck) {
39 var _a;
40 const outputFile = (_a = instance.solutionBuilderHost) === null || _a === void 0 ? void 0 : _a.getOutputFileFromReferencedProject(filePathToCheck);
41 if (outputFile !== undefined) {
42 return !!outputFile;
43 }
44 return originalFileExists(filePathToCheck);
45 }
46 function readFile(filePath, encoding) {
47 var _a;
48 const outputFile = (_a = instance.solutionBuilderHost) === null || _a === void 0 ? void 0 : _a.getOutputFileFromReferencedProject(filePath);
49 if (outputFile !== undefined) {
50 return outputFile ? outputFile.text : undefined;
51 }
52 return (instance.compiler.sys.readFile(filePath, encoding) ||
53 utils_1.fsReadFile(filePath, encoding));
54 }
55 function directoryExists(directoryName) {
56 return instance.solutionBuilderHost
57 ? instance.solutionBuilderHost.directoryExists(directoryName)
58 : compiler.sys.directoryExists(directoryName);
59 }
60 function realpath(path) {
61 return instance.solutionBuilderHost
62 ? instance.solutionBuilderHost.realpath(path)
63 : compiler.sys.realpath(path);
64 }
65 function getDirectories(path) {
66 return instance.solutionBuilderHost
67 ? instance.solutionBuilderHost.getDirectories(path)
68 : compiler.sys.getDirectories(path);
69 }
70 function readDirectory(path, extensions, exclude, include, depth) {
71 return instance.solutionBuilderHost
72 ? instance.solutionBuilderHost.readDirectory(path, extensions, exclude, include, depth)
73 : compiler.sys.readDirectory(path, extensions, exclude, include, depth);
74 }
75}
76/**
77 * Create the TypeScript language service
78 */
79function makeServicesHost(scriptRegex, loader, instance, projectReferences) {
80 const { compiler, compilerOptions, files, filePathKeyMapper } = instance;
81 const { moduleResolutionHost: { fileExists, readFile, trace, directoryExists, realpath, getCurrentDirectory, getDirectories, clearCache, useCaseSensitiveFileNames, getNewLine, getDefaultLibFileName, readDirectory, }, resolveModuleNames, resolveTypeReferenceDirectives, } = makeResolversHandlingProjectReferences(scriptRegex, loader, instance, filePathToCheck => compiler.sys.fileExists(filePathToCheck) ||
82 utils_1.fsReadFile(filePathToCheck) !== undefined, instance.loaderOptions.experimentalFileCaching);
83 const servicesHost = {
84 getProjectVersion: () => `${instance.version}`,
85 getProjectReferences: () => projectReferences,
86 getScriptFileNames: () => [...files.values()]
87 .map(({ fileName }) => fileName)
88 .filter(filePath => filePath.match(scriptRegex)),
89 getScriptVersion: (fileName) => {
90 fileName = path.normalize(fileName);
91 const key = filePathKeyMapper(fileName);
92 const file = files.get(key);
93 if (file) {
94 return file.version.toString();
95 }
96 const outputFileAndKey = instance.solutionBuilderHost &&
97 instance.solutionBuilderHost.getOutputFileAndKeyFromReferencedProject(fileName);
98 if (outputFileAndKey !== undefined) {
99 instance.solutionBuilderHost.outputAffectingInstanceVersion.set(outputFileAndKey.key, true);
100 }
101 return outputFileAndKey && outputFileAndKey.outputFile
102 ? outputFileAndKey.outputFile.version.toString()
103 : '';
104 },
105 getScriptSnapshot: (fileName) => {
106 // This is called any time TypeScript needs a file's text
107 // We either load from memory or from disk
108 fileName = path.normalize(fileName);
109 const key = filePathKeyMapper(fileName);
110 let file = files.get(key);
111 if (file === undefined) {
112 if (instance.solutionBuilderHost) {
113 const outputFileAndKey = instance.solutionBuilderHost.getOutputFileAndKeyFromReferencedProject(fileName);
114 if (outputFileAndKey !== undefined) {
115 instance.solutionBuilderHost.outputAffectingInstanceVersion.set(outputFileAndKey.key, true);
116 return outputFileAndKey && outputFileAndKey.outputFile
117 ? compiler.ScriptSnapshot.fromString(outputFileAndKey.outputFile.text)
118 : undefined;
119 }
120 }
121 const text = readFile(fileName);
122 if (text === undefined) {
123 return undefined;
124 }
125 file = { fileName, version: 0, text };
126 files.set(key, file);
127 }
128 return compiler.ScriptSnapshot.fromString(file.text);
129 },
130 /**
131 * getDirectories is also required for full import and type reference completions.
132 * Without it defined, certain completions will not be provided
133 */
134 getDirectories,
135 /**
136 * For @types expansion, these two functions are needed.
137 */
138 directoryExists,
139 useCaseSensitiveFileNames,
140 realpath,
141 // The following three methods are necessary for @types resolution from TS 2.4.1 onwards see: https://github.com/Microsoft/TypeScript/issues/16772
142 fileExists,
143 readFile,
144 readDirectory,
145 getCurrentDirectory,
146 getCompilationSettings: () => compilerOptions,
147 getDefaultLibFileName,
148 getNewLine,
149 trace,
150 log: trace,
151 // used for (/// <reference types="...">) see https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/250#issuecomment-485061329
152 resolveTypeReferenceDirectives,
153 resolveModuleNames,
154 getCustomTransformers: () => instance.transformers,
155 clearCache,
156 };
157 return servicesHost;
158}
159exports.makeServicesHost = makeServicesHost;
160function makeResolvers(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective, customResolveModuleName, resolveSync, appendTsTsxSuffixesIfRequired, scriptRegex, instance) {
161 const resolveTypeReferenceDirective = makeResolveTypeReferenceDirective(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective);
162 const resolveTypeReferenceDirectives = (typeDirectiveNames, containingFile, _redirectedReference) => typeDirectiveNames.map(directive => resolveTypeReferenceDirective(directive, containingFile, _redirectedReference).resolvedTypeReferenceDirective);
163 const resolveModuleName = makeResolveModuleName(compiler, compilerOptions, moduleResolutionHost, customResolveModuleName);
164 const resolveModuleNames = (moduleNames, containingFile, _reusedNames, _redirectedReference) => {
165 const resolvedModules = moduleNames.map(moduleName => resolveModule(resolveSync, resolveModuleName, appendTsTsxSuffixesIfRequired, scriptRegex, moduleName, containingFile));
166 utils_1.populateDependencyGraph(resolvedModules, instance, containingFile);
167 return resolvedModules;
168 };
169 return {
170 resolveTypeReferenceDirectives,
171 resolveModuleNames,
172 moduleResolutionHost,
173 };
174}
175function createWatchFactory(filePathKeyMapper, compiler) {
176 const watchedFiles = new Map();
177 const watchedDirectories = new Map();
178 const watchedDirectoriesRecursive = new Map();
179 return {
180 watchedFiles,
181 watchedDirectories,
182 watchedDirectoriesRecursive,
183 invokeFileWatcher,
184 watchFile,
185 watchDirectory,
186 };
187 function invokeWatcherCallbacks(map, key, fileName, eventKind) {
188 var _a;
189 const callbacks = (_a = map.get(filePathKeyMapper(key))) === null || _a === void 0 ? void 0 : _a.callbacks;
190 if (callbacks !== undefined && callbacks.length) {
191 // The array copy is made to ensure that even if one of the callback removes the callbacks,
192 // we dont miss any callbacks following it
193 const cbs = callbacks.slice();
194 for (const cb of cbs) {
195 cb(fileName, eventKind);
196 }
197 return true;
198 }
199 return false;
200 }
201 function invokeFileWatcher(fileName, eventKind) {
202 fileName = path.normalize(fileName);
203 let result = invokeWatcherCallbacks(watchedFiles, fileName, fileName, eventKind);
204 if (eventKind !== compiler.FileWatcherEventKind.Changed) {
205 const directory = path.dirname(fileName);
206 result =
207 invokeWatcherCallbacks(watchedDirectories, directory, fileName) ||
208 result;
209 result = invokeRecursiveDirectoryWatcher(directory, fileName) || result;
210 }
211 return result;
212 }
213 ``;
214 function invokeRecursiveDirectoryWatcher(directory, fileAddedOrRemoved) {
215 directory = path.normalize(directory);
216 let result = invokeWatcherCallbacks(watchedDirectoriesRecursive, directory, fileAddedOrRemoved);
217 const basePath = path.dirname(directory);
218 if (directory !== basePath) {
219 result =
220 invokeRecursiveDirectoryWatcher(basePath, fileAddedOrRemoved) || result;
221 }
222 return result;
223 }
224 function createWatcher(file, callbacks, callback) {
225 const key = filePathKeyMapper(file);
226 const existing = callbacks.get(key);
227 if (existing === undefined) {
228 callbacks.set(key, {
229 fileName: path.normalize(file),
230 callbacks: [callback],
231 });
232 }
233 else {
234 existing.callbacks.push(callback);
235 }
236 return {
237 close: () => {
238 const existing = callbacks.get(key);
239 if (existing !== undefined) {
240 utils_1.unorderedRemoveItem(existing.callbacks, callback);
241 if (!existing.callbacks.length) {
242 callbacks.delete(key);
243 }
244 }
245 },
246 };
247 }
248 function watchFile(fileName, callback, _pollingInterval) {
249 return createWatcher(fileName, watchedFiles, callback);
250 }
251 function watchDirectory(fileName, callback, recursive) {
252 return createWatcher(fileName, recursive === true ? watchedDirectoriesRecursive : watchedDirectories, callback);
253 }
254}
255function updateFileWithText(instance, key, filePath, text) {
256 const nFilePath = path.normalize(filePath);
257 const file = instance.files.get(key) || instance.otherFiles.get(key);
258 if (file !== undefined) {
259 const newText = text(nFilePath);
260 if (newText !== file.text) {
261 file.text = newText;
262 file.version++;
263 file.modifiedTime = new Date();
264 instance.version++;
265 if (!instance.modifiedFiles) {
266 instance.modifiedFiles = new Map();
267 }
268 instance.modifiedFiles.set(key, true);
269 if (instance.watchHost !== undefined) {
270 instance.watchHost.invokeFileWatcher(nFilePath, instance.compiler.FileWatcherEventKind.Changed);
271 }
272 if (instance.solutionBuilderHost !== undefined) {
273 instance.solutionBuilderHost.invokeFileWatcher(nFilePath, instance.compiler.FileWatcherEventKind.Changed);
274 }
275 }
276 }
277}
278exports.updateFileWithText = updateFileWithText;
279/**
280 * Create the TypeScript Watch host
281 */
282function makeWatchHost(scriptRegex, loader, instance, projectReferences) {
283 const { compiler, compilerOptions, files, otherFiles, filePathKeyMapper, } = instance;
284 const { watchFile, watchDirectory, invokeFileWatcher } = createWatchFactory(filePathKeyMapper, compiler);
285 const { moduleResolutionHost: { fileExists, readFile, trace, directoryExists, realpath, getCurrentDirectory, getDirectories, useCaseSensitiveFileNames, getNewLine, getDefaultLibFileName, readDirectory, }, resolveModuleNames, resolveTypeReferenceDirectives, } = makeResolversHandlingProjectReferences(scriptRegex, loader, instance, (fileName) => {
286 const filePath = filePathKeyMapper(fileName);
287 return files.has(filePath) || compiler.sys.fileExists(filePath);
288 },
289 /*enabledCaching*/ false);
290 const watchHost = {
291 rootFiles: getRootFileNames(),
292 options: compilerOptions,
293 useCaseSensitiveFileNames,
294 getNewLine,
295 getCurrentDirectory,
296 getDefaultLibFileName,
297 fileExists,
298 readFile: readFileWithCachingText,
299 directoryExists,
300 getDirectories,
301 readDirectory,
302 realpath,
303 trace,
304 watchFile: (fileName, callback, pollingInterval, options) => {
305 var _a;
306 const outputFileAndKey = (_a = instance.solutionBuilderHost) === null || _a === void 0 ? void 0 : _a.getOutputFileAndKeyFromReferencedProject(fileName);
307 if (!outputFileAndKey ||
308 outputFileAndKey.key === filePathKeyMapper(fileName)) {
309 return watchFile(fileName, callback, pollingInterval, options);
310 }
311 // Handle symlink to outputFile
312 const outputFileName = instance.solutionBuilderHost.realpath(fileName);
313 const watcher = watchFile(outputFileName, (_fileName, eventKind) => callback(fileName, eventKind), pollingInterval, options);
314 return { close: () => watcher.close() };
315 },
316 watchDirectory,
317 // used for (/// <reference types="...">) see https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/250#issuecomment-485061329
318 resolveTypeReferenceDirectives,
319 resolveModuleNames,
320 invokeFileWatcher,
321 updateRootFileNames: () => {
322 instance.changedFilesList = false;
323 if (instance.watchOfFilesAndCompilerOptions !== undefined) {
324 instance.watchOfFilesAndCompilerOptions.updateRootFileNames(getRootFileNames());
325 }
326 },
327 createProgram: projectReferences === undefined
328 ? compiler.createEmitAndSemanticDiagnosticsBuilderProgram
329 : createBuilderProgramWithReferences,
330 outputFiles: new Map(),
331 };
332 return watchHost;
333 function getRootFileNames() {
334 return [...files.values()]
335 .map(({ fileName }) => fileName)
336 .filter(filePath => filePath.match(scriptRegex));
337 }
338 function readFileWithCachingText(fileName, encoding) {
339 var _a;
340 fileName = path.normalize(fileName);
341 const key = filePathKeyMapper(fileName);
342 const file = files.get(key) || otherFiles.get(key);
343 if (file !== undefined) {
344 return file.text;
345 }
346 const text = readFile(fileName, encoding);
347 if (text === undefined) {
348 return undefined;
349 }
350 if (!((_a = instance.solutionBuilderHost) === null || _a === void 0 ? void 0 : _a.getOutputFileKeyFromReferencedProject(fileName))) {
351 otherFiles.set(key, { fileName, version: 0, text });
352 }
353 return text;
354 }
355 function createBuilderProgramWithReferences(rootNames, options, host, oldProgram, configFileParsingDiagnostics) {
356 const program = compiler.createProgram({
357 rootNames: rootNames,
358 options: options,
359 host,
360 oldProgram: oldProgram && oldProgram.getProgram(),
361 configFileParsingDiagnostics,
362 projectReferences,
363 });
364 const builderProgramHost = host;
365 return compiler.createEmitAndSemanticDiagnosticsBuilderProgram(program, builderProgramHost, oldProgram, configFileParsingDiagnostics);
366 }
367}
368exports.makeWatchHost = makeWatchHost;
369function normalizeSlashes(file) {
370 return file.replace(/\\/g, '/');
371}
372/**
373 * Create the TypeScript Watch host
374 */
375function makeSolutionBuilderHost(scriptRegex, loader, instance) {
376 const { compiler, compilerOptions, appendTsTsxSuffixesIfRequired, loaderOptions: { resolveModuleName: customResolveModuleName, resolveTypeReferenceDirective: customResolveTypeReferenceDirective, transpileOnly, }, filePathKeyMapper, } = instance;
377 // loader.context seems to work fine on Linux / Mac regardless causes problems for @types resolution on Windows for TypeScript < 2.3
378 const getCurrentDirectory = () => loader.context;
379 const formatDiagnosticHost = {
380 getCurrentDirectory: compiler.sys.getCurrentDirectory,
381 getCanonicalFileName: utils_1.useCaseSensitiveFileNames(compiler, instance.loaderOptions)
382 ? s => s
383 : s => s.toLowerCase(),
384 getNewLine: () => compiler.sys.newLine,
385 };
386 const diagnostics = {
387 global: [],
388 perFile: new Map(),
389 transpileErrors: [],
390 };
391 const reportDiagnostic = (d) => {
392 if (transpileOnly) {
393 const filePath = d.file ? filePathKeyMapper(d.file.fileName) : undefined;
394 const last = diagnostics.transpileErrors[diagnostics.transpileErrors.length - 1];
395 if (diagnostics.transpileErrors.length && last[0] === filePath) {
396 last[1].push(d);
397 }
398 else {
399 diagnostics.transpileErrors.push([filePath, [d]]);
400 }
401 }
402 else if (d.file) {
403 const filePath = filePathKeyMapper(d.file.fileName);
404 const existing = diagnostics.perFile.get(filePath);
405 if (existing) {
406 existing.push(d);
407 }
408 else {
409 diagnostics.perFile.set(filePath, [d]);
410 }
411 }
412 else {
413 diagnostics.global.push(d);
414 }
415 instance.log.logInfo(compiler.formatDiagnostic(d, formatDiagnosticHost));
416 };
417 const reportSolutionBuilderStatus = (d) => instance.log.logInfo(compiler.formatDiagnostic(d, formatDiagnosticHost));
418 const reportWatchStatus = (d, newLine, _options) => instance.log.logInfo(`${compiler.flattenDiagnosticMessageText(d.messageText, compiler.sys.newLine)}${newLine + newLine}`);
419 const outputFiles = new Map();
420 const writtenFiles = [];
421 const outputAffectingInstanceVersion = new Map();
422 let timeoutId;
423 const symlinkedDirectories = new Map();
424 const symlinkedFiles = new Map();
425 const cachedSys = {
426 fileExists: fileName => compiler.sys.fileExists(fileName),
427 directoryExists: directory => compiler.sys.directoryExists(directory),
428 realpath: compiler.sys.realpath && (path => compiler.sys.realpath(path)),
429 };
430 addCache(cachedSys);
431 const configFileInfo = new Map();
432 const solutionBuilderHost = Object.assign(Object.assign(Object.assign(Object.assign({}, compiler.createSolutionBuilderWithWatchHost(compiler.sys, compiler.createEmitAndSemanticDiagnosticsBuilderProgram, reportDiagnostic, reportSolutionBuilderStatus, reportWatchStatus)), { useCaseSensitiveFileNames: () => utils_1.useCaseSensitiveFileNames(compiler, instance.loaderOptions), diagnostics }), createWatchFactory(filePathKeyMapper, compiler)), {
433 // Overrides
434 getCurrentDirectory,
435 // behave as if there is no tsbuild info on disk since we want to generate all outputs in memory and only use those
436 readFile: (fileName, encoding) => {
437 const outputFile = ensureOutputFile(fileName);
438 return outputFile !== undefined
439 ? outputFile
440 ? outputFile.text
441 : undefined
442 : readInputFile(fileName, encoding).text;
443 }, writeFile: (name, text, writeByteOrderMark) => {
444 const key = filePathKeyMapper(name);
445 updateFileWithText(instance, key, name, () => text);
446 const existing = outputFiles.get(key);
447 const newOutputFile = {
448 name,
449 text,
450 writeByteOrderMark: !!writeByteOrderMark,
451 time: new Date(),
452 version: existing
453 ? existing.text !== text
454 ? existing.version + 1
455 : existing.version
456 : 0,
457 };
458 outputFiles.set(key, newOutputFile);
459 writtenFiles.push(newOutputFile);
460 if (outputAffectingInstanceVersion.has(key) &&
461 (!existing || existing.text !== text)) {
462 instance.version++;
463 }
464 if (instance.watchHost &&
465 !instance.files.has(key) &&
466 !instance.otherFiles.has(key)) {
467 // If file wasnt updated in files or other files of instance, let watch host know of the change
468 if (!existing) {
469 instance.hasUnaccountedModifiedFiles =
470 instance.watchHost.invokeFileWatcher(name, compiler.FileWatcherEventKind.Created) || instance.hasUnaccountedModifiedFiles;
471 }
472 else if (existing.version !== newOutputFile.version) {
473 instance.hasUnaccountedModifiedFiles =
474 instance.watchHost.invokeFileWatcher(name, compiler.FileWatcherEventKind.Changed) || instance.hasUnaccountedModifiedFiles;
475 }
476 }
477 compiler.sys.writeFile(name, text, writeByteOrderMark);
478 }, getModifiedTime: fileName => {
479 const outputFile = ensureOutputFile(fileName);
480 if (outputFile !== undefined) {
481 return outputFile ? outputFile.time : undefined;
482 }
483 const key = filePathKeyMapper(fileName);
484 const existing = instance.files.get(key) || instance.otherFiles.get(key);
485 return existing
486 ? existing.modifiedTime
487 : compiler.sys.getModifiedTime(fileName);
488 }, setModifiedTime: (fileName, time) => {
489 const outputFile = ensureOutputFile(fileName);
490 if (outputFile !== undefined) {
491 if (outputFile) {
492 outputFile.time = time;
493 }
494 }
495 compiler.sys.setModifiedTime(fileName, time);
496 const key = filePathKeyMapper(fileName);
497 const existing = instance.files.get(key) || instance.otherFiles.get(key);
498 if (existing) {
499 existing.modifiedTime = time;
500 }
501 }, fileExists: fileName => {
502 const outputFile = ensureOutputFile(fileName);
503 if (outputFile !== undefined) {
504 return !!outputFile;
505 }
506 const key = filePathKeyMapper(fileName);
507 const existing = instance.files.get(key) || instance.otherFiles.get(key);
508 return existing
509 ? existing.text !== undefined
510 : cachedSys.fileExists(fileName);
511 }, directoryExists: directory => {
512 if (cachedSys.directoryExists(directory)) {
513 return true;
514 }
515 const resolvedDirectory = trailingDirectorySeparatorPathKey(directory);
516 for (const outputFile of outputFiles.keys()) {
517 if (normalizeSlashes(outputFile).startsWith(resolvedDirectory)) {
518 return true;
519 }
520 }
521 // see if this is symlink to in memory files's directory
522 const ancestor = findExistingAncestor(directory);
523 const ancestorRealpath = getRealpathOfExistingDirectory(ancestor);
524 return ancestorRealpath
525 ? solutionBuilderHost.directoryExists(path.resolve(ancestorRealpath, path.relative(ancestor, directory)))
526 : false;
527 }, getDirectories: directory => cachedSys.directoryExists(directory)
528 ? compiler.sys.getDirectories(directory)
529 : [], readDirectory: (path, extensions, exclude, include, depth) => cachedSys.directoryExists(path)
530 ? compiler.sys.readDirectory(path, extensions, exclude, include, depth)
531 : [], realpath: cachedSys.realpath && (file => getRealpathOfFile(file) || file), afterProgramEmitAndDiagnostics: transpileOnly ? undefined : storeDtsFiles, setTimeout: (callback, _time, ...args) => {
532 timeoutId = [callback, args];
533 return timeoutId;
534 }, clearTimeout: _timeoutId => {
535 timeoutId = undefined;
536 }, writtenFiles,
537 configFileInfo,
538 outputAffectingInstanceVersion,
539 getOutputFileKeyFromReferencedProject,
540 getOutputFileFromReferencedProject,
541 getOutputFileAndKeyFromReferencedProject, getInputFileNameFromOutput: fileName => {
542 const result = getInputFileNameFromOutput(fileName);
543 return typeof result === 'string' ? result : undefined;
544 }, getOutputFilesFromReferencedProjectInput,
545 buildReferences,
546 clearCache });
547 solutionBuilderHost.trace = logData => instance.log.logInfo(logData);
548 solutionBuilderHost.getParsedCommandLine = file => {
549 const config = config_1.getParsedCommandLine(compiler, instance.loaderOptions, file);
550 configFileInfo.set(filePathKeyMapper(file), { config });
551 return config;
552 };
553 // make a (sync) resolver that follows webpack's rules
554 const resolveSync = resolver_1.makeResolver(loader._compiler.options);
555 const resolvers = makeResolvers(compiler, compilerOptions, solutionBuilderHost, customResolveTypeReferenceDirective, customResolveModuleName, resolveSync, appendTsTsxSuffixesIfRequired, scriptRegex, instance);
556 // used for (/// <reference types="...">) see https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/250#issuecomment-485061329
557 solutionBuilderHost.resolveTypeReferenceDirectives =
558 resolvers.resolveTypeReferenceDirectives;
559 solutionBuilderHost.resolveModuleNames = resolvers.resolveModuleNames;
560 return solutionBuilderHost;
561 function trailingDirectorySeparatorPathKey(directory) {
562 return utils_1.ensureTrailingDirectorySeparator(normalizeSlashes(filePathKeyMapper(directory)));
563 }
564 function clearCache() {
565 cachedSys.clearCache();
566 symlinkedDirectories.clear();
567 symlinkedFiles.clear();
568 }
569 function findExistingAncestor(fileOrDirectory) {
570 let ancestor = path.dirname(fileOrDirectory);
571 while (ancestor !== path.dirname(ancestor)) {
572 if (cachedSys.directoryExists(ancestor))
573 return ancestor;
574 ancestor = path.dirname(ancestor);
575 }
576 // Root should always be present
577 return ancestor;
578 }
579 function getRealpathOfExistingDirectory(directory) {
580 return getRealpath(directory, symlinkedDirectories, () => cachedSys.realpath(directory));
581 }
582 function getRealpathOfFile(file) {
583 return getRealpath(file, symlinkedFiles, () => {
584 if (cachedSys.fileExists(file))
585 return cachedSys.realpath(file);
586 // see if this is symlink to in memory file
587 const ancestor = findExistingAncestor(file);
588 const ancestorRealpath = getRealpathOfExistingDirectory(ancestor);
589 if (!ancestorRealpath)
590 return file;
591 const newFile = path.resolve(ancestorRealpath, path.relative(ancestor, file));
592 return getRealpathOfFile(newFile) || newFile;
593 });
594 }
595 function getRealpath(fileOrDirectory, symlinked, realpath) {
596 if (!cachedSys.realpath)
597 return undefined;
598 const fileOrDirectoryKey = filePathKeyMapper(fileOrDirectory);
599 const existing = symlinked.get(fileOrDirectoryKey);
600 if (existing !== undefined)
601 return existing || undefined;
602 const real = realpath();
603 if (real === fileOrDirectory ||
604 filePathKeyMapper(real) === fileOrDirectoryKey) {
605 // not symlinked
606 symlinked.set(fileOrDirectoryKey, false);
607 return undefined;
608 }
609 symlinked.set(fileOrDirectoryKey, real);
610 return real;
611 }
612 function buildReferences() {
613 if (!timeoutId) {
614 return;
615 }
616 diagnostics.global.length = 0;
617 diagnostics.perFile.clear();
618 diagnostics.transpileErrors.length = 0;
619 while (timeoutId) {
620 const [callback, args] = timeoutId;
621 timeoutId = undefined;
622 callback(...args);
623 }
624 }
625 function storeDtsFiles(builderProgram) {
626 const program = builderProgram.getProgram();
627 for (const configInfo of configFileInfo.values()) {
628 if (!configInfo.config ||
629 program.getRootFileNames() !== configInfo.config.fileNames ||
630 program.getCompilerOptions() !== configInfo.config.options ||
631 program.getProjectReferences() !== configInfo.config.projectReferences) {
632 continue;
633 }
634 configInfo.dtsFiles = program
635 .getSourceFiles()
636 .map(file => path.resolve(file.fileName))
637 .filter(fileName => fileName.match(constants.dtsDtsxOrDtsDtsxMapRegex));
638 return;
639 }
640 }
641 function getInputFileNameFromOutput(outputFileName) {
642 const resolvedFileName = filePathKeyMapper(outputFileName);
643 for (const configInfo of configFileInfo.values()) {
644 ensureInputOutputInfo(configInfo);
645 if (configInfo.outputFileNames) {
646 for (const { inputFileName, outputNames, } of configInfo.outputFileNames.values()) {
647 if (outputNames.indexOf(resolvedFileName) !== -1) {
648 return inputFileName;
649 }
650 }
651 }
652 if (configInfo.tsbuildInfoFile &&
653 filePathKeyMapper(configInfo.tsbuildInfoFile) === resolvedFileName) {
654 return true;
655 }
656 }
657 const symlinkedOutputFileName = getRealpathOfFile(outputFileName);
658 return symlinkedOutputFileName
659 ? getInputFileNameFromOutput(symlinkedOutputFileName)
660 : undefined;
661 }
662 function ensureInputOutputInfo(configInfo) {
663 if (configInfo.outputFileNames || !configInfo.config) {
664 return;
665 }
666 configInfo.outputFileNames = new Map();
667 configInfo.config.fileNames.forEach(inputFile => configInfo.outputFileNames.set(filePathKeyMapper(inputFile), {
668 inputFileName: path.resolve(inputFile),
669 outputNames: instances_1.getOutputFileNames(instance, configInfo.config, inputFile).map(filePathKeyMapper),
670 }));
671 configInfo.tsbuildInfoFile = instance.compiler
672 .getTsBuildInfoEmitOutputFilePath
673 ? instance.compiler.getTsBuildInfoEmitOutputFilePath(configInfo.config.options)
674 : // before api
675 instance.compiler.getOutputPathForBuildInfo(configInfo.config.options);
676 }
677 function getOutputFileAndKeyFromReferencedProject(outputFileName) {
678 const key = getOutputFileKeyFromReferencedProject(outputFileName);
679 return key && { key, outputFile: outputFiles.get(key) };
680 }
681 function getOutputFileFromReferencedProject(outputFileName) {
682 const key = getOutputFileKeyFromReferencedProject(outputFileName);
683 return key && outputFiles.get(key);
684 }
685 function getOutputFileKeyFromReferencedProject(outputFileName) {
686 const key = filePathKeyMapper(outputFileName);
687 const result = outputFiles.has(key);
688 if (result)
689 return key;
690 const symlinkedOutputFileName = getRealpathOfFile(outputFileName);
691 return symlinkedOutputFileName
692 ? getOutputFileKeyFromReferencedProject(symlinkedOutputFileName)
693 : undefined;
694 }
695 function ensureOutputFile(outputFileName, encoding) {
696 const outputFile = getOutputFileFromReferencedProject(outputFileName);
697 if (outputFile !== undefined) {
698 return outputFile;
699 }
700 if (!getInputFileNameFromOutput(outputFileName)) {
701 return undefined;
702 }
703 outputFileName = getRealpathOfFile(outputFileName) || outputFileName;
704 const key = filePathKeyMapper(outputFileName);
705 const text = compiler.sys.readFile(outputFileName, encoding);
706 if (text === undefined) {
707 outputFiles.set(key, false);
708 return false;
709 }
710 const newOutputFile = {
711 name: outputFileName,
712 text,
713 writeByteOrderMark: false,
714 time: compiler.sys.getModifiedTime(outputFileName),
715 version: 0,
716 };
717 outputFiles.set(key, newOutputFile);
718 return newOutputFile;
719 }
720 function getOutputFilesFromReferencedProjectInput(inputFileName) {
721 const resolvedFileName = filePathKeyMapper(inputFileName);
722 for (const configInfo of configFileInfo.values()) {
723 ensureInputOutputInfo(configInfo);
724 if (configInfo.outputFileNames) {
725 const result = configInfo.outputFileNames.get(resolvedFileName);
726 if (result) {
727 return result.outputNames
728 .map(outputFile => outputFiles.get(outputFile))
729 .filter(output => !!output);
730 }
731 }
732 }
733 return [];
734 }
735 function readInputFile(inputFileName, encoding) {
736 const resolvedFileName = filePathKeyMapper(inputFileName);
737 const existing = instance.otherFiles.get(resolvedFileName);
738 if (existing) {
739 return existing;
740 }
741 inputFileName = path.resolve(inputFileName);
742 const tsFile = {
743 fileName: inputFileName,
744 version: 1,
745 text: compiler.sys.readFile(inputFileName, encoding),
746 modifiedTime: compiler.sys.getModifiedTime(inputFileName),
747 };
748 instance.otherFiles.set(resolvedFileName, tsFile);
749 return tsFile;
750 }
751}
752exports.makeSolutionBuilderHost = makeSolutionBuilderHost;
753function getSolutionErrors(instance, context) {
754 const solutionErrors = [];
755 if (instance.solutionBuilderHost &&
756 instance.solutionBuilderHost.diagnostics.transpileErrors.length) {
757 instance.solutionBuilderHost.diagnostics.transpileErrors.forEach(([filePath, errors]) => solutionErrors.push(...utils_1.formatErrors(errors, instance.loaderOptions, instance.colors, instance.compiler, { file: filePath ? undefined : 'tsconfig.json' }, context)));
758 }
759 return solutionErrors;
760}
761exports.getSolutionErrors = getSolutionErrors;
762function makeResolveTypeReferenceDirective(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective) {
763 if (customResolveTypeReferenceDirective === undefined) {
764 return (directive, containingFile, redirectedReference) => compiler.resolveTypeReferenceDirective(directive, containingFile, compilerOptions, moduleResolutionHost, redirectedReference);
765 }
766 return (directive, containingFile) => customResolveTypeReferenceDirective(directive, containingFile, compilerOptions, moduleResolutionHost, compiler.resolveTypeReferenceDirective);
767}
768function isJsImplementationOfTypings(resolvedModule, tsResolution) {
769 return (resolvedModule.resolvedFileName.endsWith('js') &&
770 /\.d\.ts$/.test(tsResolution.resolvedFileName));
771}
772function resolveModule(resolveSync, resolveModuleName, appendTsTsxSuffixesIfRequired, scriptRegex, moduleName, containingFile) {
773 let resolutionResult;
774 try {
775 const originalFileName = resolveSync(undefined, path.normalize(path.dirname(containingFile)), moduleName);
776 const resolvedFileName = appendTsTsxSuffixesIfRequired(originalFileName);
777 if (resolvedFileName.match(scriptRegex) !== null) {
778 resolutionResult = { resolvedFileName, originalFileName };
779 }
780 }
781 catch (e) { }
782 const tsResolution = resolveModuleName(moduleName, containingFile);
783 if (tsResolution.resolvedModule !== undefined) {
784 const resolvedFileName = path.normalize(tsResolution.resolvedModule.resolvedFileName);
785 const tsResolutionResult = {
786 originalFileName: resolvedFileName,
787 resolvedFileName,
788 isExternalLibraryImport: tsResolution.resolvedModule.isExternalLibraryImport,
789 };
790 return resolutionResult === undefined ||
791 resolutionResult.resolvedFileName ===
792 tsResolutionResult.resolvedFileName ||
793 isJsImplementationOfTypings(resolutionResult, tsResolutionResult)
794 ? tsResolutionResult
795 : resolutionResult;
796 }
797 return resolutionResult;
798}
799function makeResolveModuleName(compiler, compilerOptions, moduleResolutionHost, customResolveModuleName) {
800 if (customResolveModuleName === undefined) {
801 return (moduleName, containingFile) => compiler.resolveModuleName(moduleName, containingFile, compilerOptions, moduleResolutionHost);
802 }
803 return (moduleName, containingFile) => customResolveModuleName(moduleName, containingFile, compilerOptions, moduleResolutionHost, compiler.resolveModuleName);
804}
805function addCache(host) {
806 const clearCacheFunctions = [];
807 host.fileExists = createCache(host.fileExists);
808 host.directoryExists = createCache(host.directoryExists);
809 host.realpath = host.realpath && createCache(host.realpath);
810 host.clearCache = () => clearCacheFunctions.forEach(clear => clear());
811 function createCache(originalFunction) {
812 const cache = new Map();
813 clearCacheFunctions.push(() => cache.clear());
814 return function getCached(arg) {
815 let res = cache.get(arg);
816 if (res !== undefined) {
817 return res;
818 }
819 res = originalFunction(arg);
820 cache.set(arg, res);
821 return res;
822 };
823 }
824}
825//# sourceMappingURL=servicesHost.js.map
\No newline at end of file