"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var bs_logger_1 = require("bs-logger"); var memoize = require("lodash.memoize"); var path_1 = require("path"); var messages_1 = require("../util/messages"); var hasOwn = Object.prototype.hasOwnProperty; exports.compileUsingLanguageService = function (configs, logger, memoryCache) { var _a; logger.debug('compileUsingLanguageService(): create typescript compiler'); var ts = configs.compilerModule, cwd = configs.cwd, options = configs.typescript.options, serviceHostTraceCtx = (_a = { namespace: 'ts:serviceHost', call: null }, _a[bs_logger_1.LogContexts.logLevel] = bs_logger_1.LogLevels.trace, _a); var projectVersion = 1; var updateMemoryCache = function (code, fileName) { var _a; logger.debug({ fileName: fileName }, "updateMemoryCache(): update memory cache for language service"); var fileVersion = (_a = memoryCache.versions[fileName]) !== null && _a !== void 0 ? _a : 0, isFileInCache = fileVersion !== 0; if (!isFileInCache) { memoryCache.versions[fileName] = 1; } if (memoryCache.contents[fileName] !== code) { memoryCache.contents[fileName] = code; memoryCache.versions[fileName] = fileVersion + 1; projectVersion++; } }; var serviceHost = { getProjectVersion: function () { return String(projectVersion); }, getScriptFileNames: function () { return Object.keys(memoryCache.versions); }, getScriptVersion: function (fileName) { var normalizedFileName = path_1.normalize(fileName), version = memoryCache.versions[normalizedFileName]; return version === undefined ? undefined : String(version); }, getScriptSnapshot: function (fileName) { var normalizedFileName = path_1.normalize(fileName), hit = hasOwn.call(memoryCache.contents, normalizedFileName); logger.trace({ normalizedFileName: normalizedFileName, cacheHit: hit }, "getScriptSnapshot():", 'cache', hit ? 'hit' : 'miss'); if (!hit) { memoryCache.contents[normalizedFileName] = ts.sys.readFile(normalizedFileName); } var contents = memoryCache.contents[normalizedFileName]; if (contents === undefined) { return; } return ts.ScriptSnapshot.fromString(contents); }, fileExists: memoize(ts.sys.fileExists), readFile: logger.wrap(serviceHostTraceCtx, 'readFile', memoize(ts.sys.readFile)), readDirectory: memoize(ts.sys.readDirectory), getDirectories: memoize(ts.sys.getDirectories), directoryExists: memoize(ts.sys.directoryExists), realpath: memoize(ts.sys.realpath), getNewLine: function () { return '\n'; }, getCurrentDirectory: function () { return cwd; }, getCompilationSettings: function () { return options; }, getDefaultLibFileName: function () { return ts.getDefaultLibFilePath(options); }, getCustomTransformers: function () { return configs.tsCustomTransformers; }, }; logger.debug('compileUsingLanguageService(): creating language service'); var service = ts.createLanguageService(serviceHost); return { compileFn: function (code, fileName) { var normalizedFileName = path_1.normalize(fileName); logger.debug({ normalizedFileName: normalizedFileName }, 'compileFn(): compiling using language service'); updateMemoryCache(code, normalizedFileName); var output = service.getEmitOutput(normalizedFileName); if (output.emitSkipped) { throw new TypeError(path_1.relative(cwd, normalizedFileName) + ": Emit skipped for language service"); } if (!output.outputFiles.length) { 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.outputFiles[1].text, output.outputFiles[0].text]; }, diagnoseFn: function (code, filePath) { var normalizedFileName = path_1.normalize(filePath); updateMemoryCache(code, normalizedFileName); if (configs.shouldReportDiagnostic(normalizedFileName)) { logger.debug({ normalizedFileName: normalizedFileName }, 'compileFn(): computing diagnostics for language service'); var diagnostics = service .getCompilerOptionsDiagnostics() .concat(service.getSyntacticDiagnostics(normalizedFileName)) .concat(service.getSemanticDiagnostics(normalizedFileName)); configs.raiseDiagnostics(diagnostics, normalizedFileName, logger); } }, program: service.getProgram(), }; };