"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); var bs_logger_1 = require("bs-logger"); var memoize = require("lodash.memoize"); var path_1 = require("path"); var constants_1 = require("../constants"); var messages_1 = require("../util/messages"); var compiler_utils_1 = require("./compiler-utils"); function doTypeChecking(configs, fileName, program, logger) { if (configs.shouldReportDiagnostic(fileName)) { var sourceFile = program.getSourceFile(fileName); var diagnostics = program.getSemanticDiagnostics(sourceFile).concat(program.getSyntacticDiagnostics(sourceFile)); configs.raiseDiagnostics(diagnostics, fileName, logger); } } exports.compileUsingProgram = function (configs, logger, memoryCache) { var _a; logger.debug('compileUsingProgram(): create typescript compiler'); var ts = configs.compilerModule; var cwd = configs.cwd; var _b = configs.typescript, options = _b.options, projectReferences = _b.projectReferences, errors = _b.errors; var incremental = configs.tsJest.incremental; var programDebugText = "" + (incremental ? 'incremental program' : 'program'); var cacheDir = configs.tsCacheDir; var compilerHostTraceCtx = (_a = { namespace: 'ts:compilerHost', call: null }, _a[bs_logger_1.LogContexts.logLevel] = bs_logger_1.LogLevels.trace, _a); var sys = __assign(__assign({}, ts.sys), { readFile: logger.wrap(compilerHostTraceCtx, 'readFile', memoize(ts.sys.readFile)), readDirectory: memoize(ts.sys.readDirectory), getDirectories: memoize(ts.sys.getDirectories), fileExists: memoize(ts.sys.fileExists), directoryExists: memoize(ts.sys.directoryExists), resolvePath: memoize(ts.sys.resolvePath), realpath: memoize(ts.sys.realpath), getCurrentDirectory: function () { return cwd; }, getNewLine: function () { return constants_1.LINE_FEED; }, getCanonicalFileName: function (fileName) { return (ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase()); } }); var builderProgram; var program; var host; if (incremental) { host = ts.createIncrementalCompilerHost(options, sys); builderProgram = ts.createIncrementalProgram({ rootNames: Object.keys(memoryCache.versions), options: options, host: host, configFileParsingDiagnostics: errors, projectReferences: projectReferences, }); program = builderProgram.getProgram(); } else { host = __assign(__assign({}, sys), { getSourceFile: function (fileName, languageVersion) { var contents = ts.sys.readFile(fileName); if (contents === undefined) return; return ts.createSourceFile(fileName, contents, languageVersion); }, getDefaultLibFileName: function () { return ts.getDefaultLibFilePath(options); }, useCaseSensitiveFileNames: function () { return sys.useCaseSensitiveFileNames; } }); program = ts.createProgram({ rootNames: Object.keys(memoryCache.versions), options: options, host: host, configFileParsingDiagnostics: errors, projectReferences: projectReferences, }); } var customTransformers = configs.tsCustomTransformers; var updateMemoryCache = function (contents, fileName) { var _a; logger.debug({ fileName: fileName }, "updateMemoryCache(): update memory cache for " + programDebugText); var sourceFile = incremental ? builderProgram.getSourceFile(fileName) : program.getSourceFile(fileName); var fileVersion = (_a = memoryCache.versions[fileName]) !== null && _a !== void 0 ? _a : 0; var isFileInCache = fileVersion !== 0; if (!isFileInCache) { memoryCache.versions[fileName] = 1; } var previousContents = memoryCache.contents[fileName]; if (previousContents !== contents) { memoryCache.versions[fileName] = fileVersion + 1; memoryCache.contents[fileName] = contents; } if (sourceFile === undefined || sourceFile.text !== contents || program.isSourceFileFromExternalLibrary(sourceFile)) { var programOptions = { rootNames: Object.keys(memoryCache.versions), options: options, host: host, configFileParsingDiagnostics: errors, projectReferences: projectReferences, }; if (incremental) { builderProgram = ts.createIncrementalProgram(programOptions); program = builderProgram.getProgram(); } else { program = ts.createProgram(__assign(__assign({}, programOptions), { oldProgram: program })); } } }; return { compileFn: function (code, fileName) { var normalizedFileName = path_1.normalize(fileName); var output = ['', '']; updateMemoryCache(code, normalizedFileName); var sourceFile = incremental ? builderProgram.getSourceFile(normalizedFileName) : program.getSourceFile(normalizedFileName); if (!sourceFile) throw new TypeError("Unable to read file: " + fileName); logger.debug({ normalizedFileName: normalizedFileName }, "compileFn(): compiling using " + programDebugText); var result = incremental ? builderProgram.emit(sourceFile, function (path, file, _writeByteOrderMark) { output[path.endsWith('.map') ? 1 : 0] = file; }, undefined, undefined, customTransformers) : program.emit(sourceFile, function (path, file, _writeByteOrderMark) { output[path.endsWith('.map') ? 1 : 0] = file; }, undefined, undefined, customTransformers); logger.debug("diagnoseFn(): computing diagnostics for " + normalizedFileName + " using " + programDebugText); doTypeChecking(configs, normalizedFileName, program, logger); if (cacheDir) { if (compiler_utils_1.isTestFile(configs.testMatchPatterns, normalizedFileName)) { compiler_utils_1.cacheResolvedModules(normalizedFileName, code, memoryCache, program, cacheDir, logger); } else { Object.entries(memoryCache.resolvedModules) .filter(function (entry) { return (entry[1].modulePaths.find(function (modulePath) { return modulePath === normalizedFileName; }) && !compiler_utils_1.hasOwn.call(memoryCache.outputs, entry[0])); }) .forEach(function (entry) { logger.debug("diagnoseFn(): computing diagnostics for test file that imports " + normalizedFileName + " using " + programDebugText); doTypeChecking(configs, entry[0], program, logger); }); } } if (result.emitSkipped) { throw new TypeError(path_1.relative(cwd, fileName) + ": Emit skipped"); } if (output[0] === '') { throw new TypeError(messages_1.interpolate("Unable to require `.d.ts` file for file: {{file}}.\nThis is usually the result of a faulty configuration or import. Make sure there is a `.js`, `.json` or another executable extension available alongside `{{file}}`.", { file: path_1.basename(normalizedFileName), })); } return output; }, program: program, }; };