UNPKG

33.4 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 makeResolversAndModuleResolutionHost(scriptRegex, loader, instance, fileExists, 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 readFile(filePath, encoding) {
39 return (instance.compiler.sys.readFile(filePath, encoding) ||
40 utils_1.fsReadFile(filePath, encoding));
41 }
42 function directoryExists(directoryName) {
43 return compiler.sys.directoryExists(directoryName);
44 }
45 function realpath(path) {
46 return compiler.sys.realpath(path);
47 }
48 function getDirectories(path) {
49 return compiler.sys.getDirectories(path);
50 }
51 function readDirectory(path, extensions, exclude, include, depth) {
52 return compiler.sys.readDirectory(path, extensions, exclude, include, depth);
53 }
54}
55/**
56 * Create the TypeScript language service
57 */
58function makeServicesHost(scriptRegex, loader, instance, projectReferences) {
59 const { compiler, compilerOptions, files, filePathKeyMapper } = instance;
60 const { moduleResolutionHost, resolveModuleNames, resolveTypeReferenceDirectives, } = makeResolversAndModuleResolutionHost(scriptRegex, loader, instance, filePathToCheck => compiler.sys.fileExists(filePathToCheck) ||
61 utils_1.fsReadFile(filePathToCheck) !== undefined, instance.loaderOptions.experimentalFileCaching);
62 const servicesHost = Object.assign(Object.assign({ getProjectVersion: () => `${instance.version}`, getProjectReferences: () => projectReferences, getScriptFileNames: () => [...files.values()]
63 .map(({ fileName }) => fileName)
64 .filter(filePath => filePath.match(scriptRegex)), getScriptVersion: (fileName) => {
65 var _a;
66 fileName = path.normalize(fileName);
67 const key = filePathKeyMapper(fileName);
68 const file = files.get(key);
69 if (file) {
70 return file.version.toString();
71 }
72 const outputFileAndKey = (_a = instance.solutionBuilderHost) === null || _a === void 0 ? void 0 : _a.getOutputFileAndKeyFromReferencedProject(fileName);
73 if (outputFileAndKey !== undefined) {
74 instance.solutionBuilderHost.outputAffectingInstanceVersion.set(outputFileAndKey.key, true);
75 }
76 return outputFileAndKey && outputFileAndKey.outputFile
77 ? outputFileAndKey.outputFile
78 : '';
79 }, getScriptSnapshot: (fileName) => {
80 // This is called any time TypeScript needs a file's text
81 // We either load from memory or from disk
82 fileName = path.normalize(fileName);
83 const key = filePathKeyMapper(fileName);
84 let file = files.get(key);
85 if (file === undefined) {
86 if (instance.solutionBuilderHost) {
87 const outputFileAndKey = instance.solutionBuilderHost.getOutputFileTextAndKeyFromReferencedProject(fileName);
88 if (outputFileAndKey !== undefined) {
89 instance.solutionBuilderHost.outputAffectingInstanceVersion.set(outputFileAndKey.key, true);
90 return outputFileAndKey && outputFileAndKey.text !== undefined
91 ? compiler.ScriptSnapshot.fromString(outputFileAndKey.text)
92 : undefined;
93 }
94 }
95 const text = moduleResolutionHost.readFile(fileName);
96 if (text === undefined) {
97 return undefined;
98 }
99 file = { fileName, version: 0, text };
100 files.set(key, file);
101 }
102 return compiler.ScriptSnapshot.fromString(file.text);
103 } }, moduleResolutionHost), { getCompilationSettings: () => compilerOptions, log: moduleResolutionHost.trace,
104 // used for (/// <reference types="...">) see https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/250#issuecomment-485061329
105 resolveTypeReferenceDirectives,
106 resolveModuleNames, getCustomTransformers: () => instance.transformers });
107 return servicesHost;
108}
109exports.makeServicesHost = makeServicesHost;
110function makeResolvers(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective, customResolveModuleName, resolveSync, appendTsTsxSuffixesIfRequired, scriptRegex, instance) {
111 const resolveTypeReferenceDirective = makeResolveTypeReferenceDirective(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective);
112 const resolveTypeReferenceDirectives = (typeDirectiveNames, containingFile, _redirectedReference) => typeDirectiveNames.map(directive => resolveTypeReferenceDirective(directive, containingFile, _redirectedReference).resolvedTypeReferenceDirective);
113 const resolveModuleName = makeResolveModuleName(compiler, compilerOptions, moduleResolutionHost, customResolveModuleName);
114 const resolveModuleNames = (moduleNames, containingFile, _reusedNames, _redirectedReference) => {
115 const resolvedModules = moduleNames.map(moduleName => resolveModule(resolveSync, resolveModuleName, appendTsTsxSuffixesIfRequired, scriptRegex, moduleName, containingFile));
116 utils_1.populateDependencyGraph(resolvedModules, instance, containingFile);
117 return resolvedModules;
118 };
119 return {
120 resolveTypeReferenceDirectives,
121 resolveModuleNames,
122 moduleResolutionHost,
123 };
124}
125function createWatchFactory(filePathKeyMapper, compiler) {
126 const watchedFiles = new Map();
127 const watchedDirectories = new Map();
128 const watchedDirectoriesRecursive = new Map();
129 return {
130 watchedFiles,
131 watchedDirectories,
132 watchedDirectoriesRecursive,
133 invokeFileWatcher,
134 watchFile,
135 watchDirectory,
136 };
137 function invokeWatcherCallbacks(map, key, fileName, eventKind) {
138 var _a;
139 const callbacks = (_a = map.get(filePathKeyMapper(key))) === null || _a === void 0 ? void 0 : _a.callbacks;
140 if (callbacks !== undefined && callbacks.length) {
141 // The array copy is made to ensure that even if one of the callback removes the callbacks,
142 // we dont miss any callbacks following it
143 const cbs = callbacks.slice();
144 for (const cb of cbs) {
145 cb(fileName, eventKind);
146 }
147 return true;
148 }
149 return false;
150 }
151 function invokeFileWatcher(fileName, eventKind) {
152 fileName = path.normalize(fileName);
153 let result = invokeWatcherCallbacks(watchedFiles, fileName, fileName, eventKind);
154 if (eventKind !== compiler.FileWatcherEventKind.Changed) {
155 const directory = path.dirname(fileName);
156 result =
157 invokeWatcherCallbacks(watchedDirectories, directory, fileName) ||
158 result;
159 result = invokeRecursiveDirectoryWatcher(directory, fileName) || result;
160 }
161 return result;
162 }
163 ``;
164 function invokeRecursiveDirectoryWatcher(directory, fileAddedOrRemoved) {
165 directory = path.normalize(directory);
166 let result = invokeWatcherCallbacks(watchedDirectoriesRecursive, directory, fileAddedOrRemoved);
167 const basePath = path.dirname(directory);
168 if (directory !== basePath) {
169 result =
170 invokeRecursiveDirectoryWatcher(basePath, fileAddedOrRemoved) || result;
171 }
172 return result;
173 }
174 function createWatcher(file, callbacks, callback) {
175 const key = filePathKeyMapper(file);
176 const existing = callbacks.get(key);
177 if (existing === undefined) {
178 callbacks.set(key, {
179 fileName: path.normalize(file),
180 callbacks: [callback],
181 });
182 }
183 else {
184 existing.callbacks.push(callback);
185 }
186 return {
187 close: () => {
188 const existing = callbacks.get(key);
189 if (existing !== undefined) {
190 utils_1.unorderedRemoveItem(existing.callbacks, callback);
191 if (!existing.callbacks.length) {
192 callbacks.delete(key);
193 }
194 }
195 },
196 };
197 }
198 function watchFile(fileName, callback, _pollingInterval) {
199 return createWatcher(fileName, watchedFiles, callback);
200 }
201 function watchDirectory(fileName, callback, recursive) {
202 return createWatcher(fileName, recursive === true ? watchedDirectoriesRecursive : watchedDirectories, callback);
203 }
204}
205function updateFileWithText(instance, key, filePath, text) {
206 const nFilePath = path.normalize(filePath);
207 const file = instance.files.get(key) || instance.otherFiles.get(key);
208 if (file !== undefined) {
209 const newText = text(nFilePath);
210 if (newText !== file.text) {
211 file.text = newText;
212 file.version++;
213 file.modifiedTime = new Date();
214 instance.version++;
215 if (!instance.modifiedFiles) {
216 instance.modifiedFiles = new Map();
217 }
218 instance.modifiedFiles.set(key, true);
219 if (instance.watchHost !== undefined) {
220 instance.watchHost.invokeFileWatcher(nFilePath, instance.compiler.FileWatcherEventKind.Changed);
221 }
222 }
223 }
224}
225exports.updateFileWithText = updateFileWithText;
226/**
227 * Create the TypeScript Watch host
228 */
229function makeWatchHost(scriptRegex, loader, instance, projectReferences) {
230 const { compiler, compilerOptions, files, otherFiles, filePathKeyMapper, } = instance;
231 const { watchFile, watchDirectory, invokeFileWatcher } = createWatchFactory(filePathKeyMapper, compiler);
232 const { moduleResolutionHost, resolveModuleNames, resolveTypeReferenceDirectives, } = makeResolversAndModuleResolutionHost(scriptRegex, loader, instance, fileName => files.has(filePathKeyMapper(fileName)) ||
233 compiler.sys.fileExists(fileName),
234 /*enabledCaching*/ false);
235 const watchHost = Object.assign(Object.assign({ rootFiles: getRootFileNames(), options: compilerOptions }, moduleResolutionHost), { readFile: readFileWithCachingText, watchFile: (fileName, callback, pollingInterval, options) => {
236 var _a;
237 const outputFileKey = (_a = instance.solutionBuilderHost) === null || _a === void 0 ? void 0 : _a.getOutputFileKeyFromReferencedProject(fileName);
238 if (!outputFileKey || outputFileKey === filePathKeyMapper(fileName)) {
239 return watchFile(fileName, callback, pollingInterval, options);
240 }
241 // Handle symlink to outputFile
242 const outputFileName = instance.solutionBuilderHost.realpath(fileName);
243 return watchFile(outputFileName, (_fileName, eventKind) => callback(fileName, eventKind), pollingInterval, options);
244 }, watchDirectory,
245 // used for (/// <reference types="...">) see https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/250#issuecomment-485061329
246 resolveTypeReferenceDirectives,
247 resolveModuleNames,
248 invokeFileWatcher, updateRootFileNames: () => {
249 instance.changedFilesList = false;
250 if (instance.watchOfFilesAndCompilerOptions !== undefined) {
251 instance.watchOfFilesAndCompilerOptions.updateRootFileNames(getRootFileNames());
252 }
253 }, createProgram: projectReferences === undefined
254 ? compiler.createEmitAndSemanticDiagnosticsBuilderProgram
255 : createBuilderProgramWithReferences, outputFiles: new Map() });
256 return watchHost;
257 function getRootFileNames() {
258 return [...files.values()]
259 .map(({ fileName }) => fileName)
260 .filter(filePath => filePath.match(scriptRegex));
261 }
262 function readFileWithCachingText(fileName, encoding) {
263 var _a;
264 fileName = path.normalize(fileName);
265 const key = filePathKeyMapper(fileName);
266 const file = files.get(key) || otherFiles.get(key);
267 if (file !== undefined) {
268 return file.text;
269 }
270 const text = moduleResolutionHost.readFile(fileName, encoding);
271 if (text === undefined) {
272 return undefined;
273 }
274 if (!((_a = instance.solutionBuilderHost) === null || _a === void 0 ? void 0 : _a.getOutputFileKeyFromReferencedProject(fileName))) {
275 otherFiles.set(key, { fileName, version: 0, text });
276 }
277 return text;
278 }
279 function createBuilderProgramWithReferences(rootNames, options, host, oldProgram, configFileParsingDiagnostics) {
280 const program = compiler.createProgram({
281 rootNames: rootNames,
282 options: options,
283 host,
284 oldProgram: oldProgram && oldProgram.getProgram(),
285 configFileParsingDiagnostics,
286 projectReferences,
287 });
288 const builderProgramHost = host;
289 return compiler.createEmitAndSemanticDiagnosticsBuilderProgram(program, builderProgramHost, oldProgram, configFileParsingDiagnostics);
290 }
291}
292exports.makeWatchHost = makeWatchHost;
293const missingFileModifiedTime = new Date(0);
294/**
295 * Create the TypeScript Watch host
296 */
297function makeSolutionBuilderHost(scriptRegex, loader, instance) {
298 const { compiler, loaderOptions: { transpileOnly }, filePathKeyMapper, } = instance;
299 // loader.context seems to work fine on Linux / Mac regardless causes problems for @types resolution on Windows for TypeScript < 2.3
300 const formatDiagnosticHost = {
301 getCurrentDirectory: compiler.sys.getCurrentDirectory,
302 getCanonicalFileName: utils_1.useCaseSensitiveFileNames(compiler, instance.loaderOptions)
303 ? s => s
304 : s => s.toLowerCase(),
305 getNewLine: () => compiler.sys.newLine,
306 };
307 const diagnostics = {
308 global: [],
309 perFile: new Map(),
310 transpileErrors: [],
311 };
312 const reportDiagnostic = (d) => {
313 if (transpileOnly) {
314 const filePath = d.file ? filePathKeyMapper(d.file.fileName) : undefined;
315 const last = diagnostics.transpileErrors[diagnostics.transpileErrors.length - 1];
316 if (diagnostics.transpileErrors.length && last[0] === filePath) {
317 last[1].push(d);
318 }
319 else {
320 diagnostics.transpileErrors.push([filePath, [d]]);
321 }
322 }
323 else if (d.file) {
324 const filePath = filePathKeyMapper(d.file.fileName);
325 const existing = diagnostics.perFile.get(filePath);
326 if (existing) {
327 existing.push(d);
328 }
329 else {
330 diagnostics.perFile.set(filePath, [d]);
331 }
332 }
333 else {
334 diagnostics.global.push(d);
335 }
336 instance.log.logInfo(compiler.formatDiagnostic(d, formatDiagnosticHost));
337 };
338 const reportSolutionBuilderStatus = (d) => instance.log.logInfo(compiler.formatDiagnostic(d, formatDiagnosticHost));
339 const reportWatchStatus = (d, newLine, _options) => instance.log.logInfo(`${compiler.flattenDiagnosticMessageText(d.messageText, compiler.sys.newLine)}${newLine + newLine}`);
340 const outputFiles = new Map();
341 const inputFiles = new Map();
342 const writtenFiles = [];
343 const outputAffectingInstanceVersion = new Map();
344 let timeoutId;
345 const { resolveModuleNames, resolveTypeReferenceDirectives, moduleResolutionHost, } = makeResolversAndModuleResolutionHost(scriptRegex, loader, instance, fileName => !!instance.files.has(filePathKeyMapper(fileName)) ||
346 !!instance.otherFiles.get(filePathKeyMapper(fileName)) ||
347 compiler.sys.fileExists(fileName),
348 /*enableFileCaching*/ true);
349 const configFileInfo = new Map();
350 const allWatches = [];
351 const sysHost = compiler.createSolutionBuilderWithWatchHost(compiler.sys, compiler.createEmitAndSemanticDiagnosticsBuilderProgram, reportDiagnostic, reportSolutionBuilderStatus, reportWatchStatus);
352 const solutionBuilderHost = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, sysHost), moduleResolutionHost), { resolveModuleNames,
353 resolveTypeReferenceDirectives,
354 diagnostics }), createWatchFactory(filePathKeyMapper, compiler)), {
355 // Overrides
356 writeFile: (name, text, writeByteOrderMark) => {
357 var _a;
358 const key = filePathKeyMapper(name);
359 updateFileWithText(instance, key, name, () => text);
360 const existing = ensureOutputFile(name);
361 const hash = hashOutputText(text);
362 outputFiles.set(key, hash);
363 writtenFiles.push({
364 name,
365 text,
366 writeByteOrderMark: !!writeByteOrderMark,
367 });
368 compiler.sys.writeFile(name, text, writeByteOrderMark);
369 (_a = moduleResolutionHost.fileExistsCache) === null || _a === void 0 ? void 0 : _a.delete(name);
370 if (outputAffectingInstanceVersion.has(key) &&
371 (!existing || existing !== hash)) {
372 instance.version++;
373 }
374 if (instance.watchHost &&
375 !instance.files.has(key) &&
376 !instance.otherFiles.has(key)) {
377 // If file wasnt updated in files or other files of instance, let watch host know of the change
378 if (!existing) {
379 instance.hasUnaccountedModifiedFiles =
380 instance.watchHost.invokeFileWatcher(name, compiler.FileWatcherEventKind.Created) || instance.hasUnaccountedModifiedFiles;
381 }
382 else if (existing !== hash) {
383 instance.hasUnaccountedModifiedFiles =
384 instance.watchHost.invokeFileWatcher(name, compiler.FileWatcherEventKind.Changed) || instance.hasUnaccountedModifiedFiles;
385 }
386 }
387 }, createDirectory: sysHost.createDirectory &&
388 (directory => {
389 var _a;
390 sysHost.createDirectory(directory);
391 (_a = moduleResolutionHost.directoryExistsCache) === null || _a === void 0 ? void 0 : _a.delete(directory);
392 }), afterProgramEmitAndDiagnostics: transpileOnly ? undefined : storeDtsFiles, setTimeout: (callback, _time, ...args) => {
393 timeoutId = [callback, args];
394 return timeoutId;
395 }, clearTimeout: _timeoutId => {
396 timeoutId = undefined;
397 }, getParsedCommandLine: file => {
398 const config = config_1.getParsedCommandLine(compiler, instance.loaderOptions, file);
399 configFileInfo.set(filePathKeyMapper(file), { config });
400 return config;
401 }, writtenFiles,
402 configFileInfo,
403 outputAffectingInstanceVersion,
404 getInputFileStamp,
405 updateSolutionBuilderInputFile,
406 getOutputFileKeyFromReferencedProject,
407 getOutputFileAndKeyFromReferencedProject,
408 getOutputFileTextAndKeyFromReferencedProject, getInputFileNameFromOutput: fileName => {
409 const result = getInputFileNameFromOutput(fileName);
410 return typeof result === 'string' ? result : undefined;
411 }, getOutputFilesFromReferencedProjectInput,
412 buildReferences,
413 ensureAllReferenceTimestamps,
414 clearCache,
415 close });
416 return solutionBuilderHost;
417 function close() {
418 allWatches.slice().forEach(w => w.close());
419 }
420 function clearCache() {
421 moduleResolutionHost.clearCache();
422 outputFiles.clear();
423 inputFiles.clear();
424 }
425 function buildReferences() {
426 if (!timeoutId) {
427 ensureAllReferenceTimestamps();
428 return;
429 }
430 diagnostics.global.length = 0;
431 diagnostics.perFile.clear();
432 diagnostics.transpileErrors.length = 0;
433 while (timeoutId) {
434 const [callback, args] = timeoutId;
435 timeoutId = undefined;
436 callback(...args);
437 }
438 ensureAllReferenceTimestamps();
439 }
440 function ensureAllReferenceTimestamps() {
441 if (inputFiles.size !== solutionBuilderHost.watchedFiles.size) {
442 for (const { fileName, } of instance.solutionBuilderHost.watchedFiles.values()) {
443 instance.solutionBuilderHost.getInputFileStamp(fileName);
444 }
445 }
446 }
447 function storeDtsFiles(builderProgram) {
448 const program = builderProgram.getProgram();
449 for (const configInfo of configFileInfo.values()) {
450 if (!configInfo.config ||
451 program.getRootFileNames() !== configInfo.config.fileNames ||
452 program.getCompilerOptions() !== configInfo.config.options ||
453 program.getProjectReferences() !== configInfo.config.projectReferences) {
454 continue;
455 }
456 configInfo.dtsFiles = program
457 .getSourceFiles()
458 .map(file => path.resolve(file.fileName))
459 .filter(fileName => fileName.match(constants.dtsDtsxOrDtsDtsxMapRegex));
460 return;
461 }
462 }
463 function getInputFileNameFromOutput(outputFileName) {
464 const resolvedFileName = filePathKeyMapper(outputFileName);
465 for (const configInfo of configFileInfo.values()) {
466 ensureInputOutputInfo(configInfo);
467 if (configInfo.outputFileNames) {
468 for (const { inputFileName, outputNames, } of configInfo.outputFileNames.values()) {
469 if (outputNames.some(outputName => resolvedFileName === filePathKeyMapper(outputName))) {
470 return inputFileName;
471 }
472 }
473 }
474 if (configInfo.tsbuildInfoFile &&
475 filePathKeyMapper(configInfo.tsbuildInfoFile) === resolvedFileName) {
476 return true;
477 }
478 }
479 const realPath = solutionBuilderHost.realpath(outputFileName);
480 return filePathKeyMapper(realPath) !== resolvedFileName
481 ? getInputFileNameFromOutput(realPath)
482 : undefined;
483 }
484 function ensureInputOutputInfo(configInfo) {
485 if (configInfo.outputFileNames || !configInfo.config) {
486 return;
487 }
488 configInfo.outputFileNames = new Map();
489 configInfo.config.fileNames.forEach(inputFile => configInfo.outputFileNames.set(filePathKeyMapper(inputFile), {
490 inputFileName: path.resolve(inputFile),
491 outputNames: instances_1.getOutputFileNames(instance, configInfo.config, inputFile),
492 }));
493 configInfo.tsbuildInfoFile = instance.compiler
494 .getTsBuildInfoEmitOutputFilePath
495 ? instance.compiler.getTsBuildInfoEmitOutputFilePath(configInfo.config.options)
496 : // before api
497 instance.compiler.getOutputPathForBuildInfo(configInfo.config.options);
498 }
499 function getOutputFileAndKeyFromReferencedProject(outputFileName) {
500 const outputFile = ensureOutputFile(outputFileName);
501 return outputFile !== undefined
502 ? {
503 key: getOutputFileKeyFromReferencedProject(outputFileName),
504 outputFile,
505 }
506 : undefined;
507 }
508 function getOutputFileTextAndKeyFromReferencedProject(outputFileName) {
509 const key = getOutputFileKeyFromReferencedProject(outputFileName);
510 if (!key) {
511 return undefined;
512 }
513 const file = writtenFiles.find(w => filePathKeyMapper(w.name) === key);
514 if (file) {
515 return { key, text: file.text };
516 }
517 const outputFile = outputFiles.get(key);
518 return {
519 key,
520 text: outputFile !== false
521 ? compiler.sys.readFile(outputFileName)
522 : undefined,
523 };
524 }
525 function getOutputFileKeyFromReferencedProject(outputFileName) {
526 const key = filePathKeyMapper(outputFileName);
527 if (outputFiles.has(key))
528 return key;
529 const realKey = filePathKeyMapper(solutionBuilderHost.realpath(outputFileName));
530 if (realKey !== key && outputFiles.has(realKey))
531 return realKey;
532 return getInputFileNameFromOutput(outputFileName) ? realKey : undefined;
533 }
534 function hashOutputText(text) {
535 return compiler.sys.createHash ? compiler.sys.createHash(text) : text;
536 }
537 function ensureOutputFile(outputFileName) {
538 const key = getOutputFileKeyFromReferencedProject(outputFileName);
539 if (!key) {
540 return undefined;
541 }
542 const outputFile = outputFiles.get(key);
543 if (outputFile !== undefined) {
544 return outputFile;
545 }
546 if (!getInputFileNameFromOutput(outputFileName)) {
547 return undefined;
548 }
549 const text = compiler.sys.readFile(outputFileName);
550 const hash = text === undefined ? false : hashOutputText(text);
551 outputFiles.set(key, hash);
552 return hash;
553 }
554 function getTypeScriptOutputFile(outputFileName) {
555 const key = filePathKeyMapper(outputFileName);
556 const writtenFile = writtenFiles.find(w => filePathKeyMapper(w.name) === key);
557 if (writtenFile)
558 return writtenFile;
559 // Read from sys
560 const text = compiler.sys.readFile(outputFileName);
561 return text !== undefined
562 ? {
563 name: outputFileName,
564 text,
565 writeByteOrderMark: false,
566 }
567 : undefined;
568 }
569 function getOutputFilesFromReferencedProjectInput(inputFileName) {
570 const resolvedFileName = filePathKeyMapper(inputFileName);
571 for (const configInfo of configFileInfo.values()) {
572 ensureInputOutputInfo(configInfo);
573 if (configInfo.outputFileNames) {
574 const result = configInfo.outputFileNames.get(resolvedFileName);
575 if (result) {
576 return result.outputNames
577 .map(getTypeScriptOutputFile)
578 .filter(output => !!output);
579 }
580 }
581 }
582 return [];
583 }
584 function getInputFileStamp(fileName) {
585 const key = filePathKeyMapper(fileName);
586 const existing = inputFiles.get(key);
587 if (existing !== undefined) {
588 return existing;
589 }
590 const time = compiler.sys.getModifiedTime(fileName) || missingFileModifiedTime;
591 inputFiles.set(key, time);
592 return time;
593 }
594 function updateSolutionBuilderInputFile(fileName) {
595 const key = filePathKeyMapper(fileName);
596 const existing = inputFiles.get(key) || missingFileModifiedTime;
597 const newTime = compiler.sys.getModifiedTime(fileName) || missingFileModifiedTime;
598 if (existing === newTime) {
599 return;
600 }
601 const eventKind = existing == missingFileModifiedTime
602 ? compiler.FileWatcherEventKind.Created
603 : newTime === missingFileModifiedTime
604 ? compiler.FileWatcherEventKind.Deleted
605 : compiler.FileWatcherEventKind.Changed;
606 solutionBuilderHost.invokeFileWatcher(fileName, eventKind);
607 }
608}
609exports.makeSolutionBuilderHost = makeSolutionBuilderHost;
610function getSolutionErrors(instance, context) {
611 const solutionErrors = [];
612 if (instance.solutionBuilderHost &&
613 instance.solutionBuilderHost.diagnostics.transpileErrors.length) {
614 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)));
615 }
616 return solutionErrors;
617}
618exports.getSolutionErrors = getSolutionErrors;
619function makeResolveTypeReferenceDirective(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective) {
620 if (customResolveTypeReferenceDirective === undefined) {
621 return (directive, containingFile, redirectedReference) => compiler.resolveTypeReferenceDirective(directive, containingFile, compilerOptions, moduleResolutionHost, redirectedReference);
622 }
623 return (directive, containingFile) => customResolveTypeReferenceDirective(directive, containingFile, compilerOptions, moduleResolutionHost, compiler.resolveTypeReferenceDirective);
624}
625function isJsImplementationOfTypings(resolvedModule, tsResolution) {
626 return (resolvedModule.resolvedFileName.endsWith('js') &&
627 /\.d\.ts$/.test(tsResolution.resolvedFileName));
628}
629function resolveModule(resolveSync, resolveModuleName, appendTsTsxSuffixesIfRequired, scriptRegex, moduleName, containingFile) {
630 let resolutionResult;
631 try {
632 const originalFileName = resolveSync(undefined, path.normalize(path.dirname(containingFile)), moduleName);
633 const resolvedFileName = appendTsTsxSuffixesIfRequired(originalFileName);
634 if (resolvedFileName.match(scriptRegex) !== null) {
635 resolutionResult = { resolvedFileName, originalFileName };
636 }
637 }
638 catch (e) { }
639 const tsResolution = resolveModuleName(moduleName, containingFile);
640 if (tsResolution.resolvedModule !== undefined) {
641 const resolvedFileName = path.normalize(tsResolution.resolvedModule.resolvedFileName);
642 const tsResolutionResult = {
643 originalFileName: resolvedFileName,
644 resolvedFileName,
645 isExternalLibraryImport: tsResolution.resolvedModule.isExternalLibraryImport,
646 };
647 return resolutionResult === undefined ||
648 resolutionResult.resolvedFileName ===
649 tsResolutionResult.resolvedFileName ||
650 isJsImplementationOfTypings(resolutionResult, tsResolutionResult)
651 ? tsResolutionResult
652 : resolutionResult;
653 }
654 return resolutionResult;
655}
656function makeResolveModuleName(compiler, compilerOptions, moduleResolutionHost, customResolveModuleName) {
657 if (customResolveModuleName === undefined) {
658 return (moduleName, containingFile) => compiler.resolveModuleName(moduleName, containingFile, compilerOptions, moduleResolutionHost);
659 }
660 return (moduleName, containingFile) => customResolveModuleName(moduleName, containingFile, compilerOptions, moduleResolutionHost, compiler.resolveModuleName);
661}
662function addCache(host) {
663 host.fileExists = createCache(host.fileExists, (host.fileExistsCache = new Map()));
664 host.directoryExists = createCache(host.directoryExists, (host.directoryExistsCache = new Map()));
665 host.realpath =
666 host.realpath &&
667 createCache(host.realpath, (host.realpathCache = new Map()));
668 host.clearCache = clearCache;
669 function createCache(originalFunction, cache) {
670 return function getCached(arg) {
671 let res = cache.get(arg);
672 if (res !== undefined) {
673 return res;
674 }
675 res = originalFunction(arg);
676 cache.set(arg, res);
677 return res;
678 };
679 }
680 function clearCache() {
681 var _a, _b, _c;
682 (_a = host.fileExistsCache) === null || _a === void 0 ? void 0 : _a.clear();
683 (_b = host.directoryExistsCache) === null || _b === void 0 ? void 0 : _b.clear();
684 (_c = host.realpathCache) === null || _c === void 0 ? void 0 : _c.clear();
685 }
686}
687//# sourceMappingURL=servicesHost.js.map
\No newline at end of file