UNPKG

alm

Version:

The best IDE for TypeScript

181 lines (180 loc) 8.15 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var utils_1 = require("../../../../common/utils"); var fmc = require("../../../disk/fileModelCache"); var path = require("path"); var fsu = require("../../../utils/fsu"); /** * The files that you provide in a tsconfig.json might not be the *complete* set of files * We preprocess these files to add additional files based on the contents of these files */ function increaseCompilationContext(files, allowJs) { var filesMap = utils_1.createMap(files); var willNeedMoreAnalysis = function (file) { if (!filesMap[file]) { filesMap[file] = true; files.push(file); return true; } else { return false; } }; var getReferencedOrImportedFiles = function (files) { var referenced = []; files.forEach(function (file) { try { var content = fmc.getOrCreateOpenFile(file).getContents(); } catch (ex) { // if we cannot read a file for whatever reason just quit return; } var preProcessedFileInfo = ts.preProcessFile(content, true), dir = path.dirname(file); var extensions = ['.ts', '.d.ts', '.tsx']; if (allowJs) { extensions.push('.js'); extensions.push('.jsx'); } function getIfExists(filePathNoExt) { for (var _i = 0, extensions_1 = extensions; _i < extensions_1.length; _i++) { var ext = extensions_1[_i]; if (fsu.existsSync(filePathNoExt + ext)) { return filePathNoExt + ext; } } } referenced.push(preProcessedFileInfo.referencedFiles.map(function (fileReference) { // We assume reference paths are always relative var file = path.resolve(dir, fsu.consistentPath(fileReference.fileName)); // Try by itself then with extensions if (fsu.existsSync(file)) { return file; } return getIfExists(file); }).filter(function (file) { return !!file; }) .concat(preProcessedFileInfo.importedFiles .filter(function (fileReference) { return fsu.isRelative(fileReference.fileName); }) .map(function (fileReference) { var fileNoExt = path.resolve(dir, fileReference.fileName); var file = getIfExists(fileNoExt); if (!file) { file = getIfExists(file + "/index"); } return file; }).filter(function (file) { return !!file; }))); }); return utils_1.selectMany(referenced); }; var more = getReferencedOrImportedFiles(files) .filter(willNeedMoreAnalysis); while (more.length) { more = getReferencedOrImportedFiles(files) .filter(willNeedMoreAnalysis); } return files; } exports.increaseCompilationContext = increaseCompilationContext; /** * Spec * We will expand on files making sure that we don't have a `typing` with the same name * Also if two node_modules reference a similar sub project (and also recursively) then the one with latest `version` field wins */ function getDefinitionsForNodeModules(projectDir, files) { var packagejson = []; /** TODO use later when we care about versions */ function versionStringToNumber(version) { var _a = version.split('.'), maj = _a[0], min = _a[1], patch = _a[2]; return parseInt(maj) * 1000000 + parseInt(min); } var typings = {}; // Find our `typings` (anything in a typings folder with extension `.d.ts` is considered a typing) // These are INF powerful var ourTypings = files .filter(function (f) { return path.basename(path.dirname(f)) == 'typings' && f.endsWith('.d.ts') || path.basename(path.dirname(path.dirname(f))) == 'typings' && f.endsWith('.d.ts'); }); ourTypings.forEach(function (f) { return typings[path.basename(f)] = { filePath: f, version: Infinity }; }); var existing = utils_1.createMap(files.map(fsu.consistentPath)); function addAllReferencedFilesWithMaxVersion(file) { var dir = path.dirname(file); try { var content = fmc.getOrCreateOpenFile(file).getContents(); } catch (ex) { // if we cannot read a file for whatever reason just quit return; } var preProcessedFileInfo = ts.preProcessFile(content, true); var files = preProcessedFileInfo.referencedFiles.map(function (fileReference) { // We assume reference paths are always relative var file = path.resolve(dir, fileReference.fileName); // Try by itself, .d.ts if (fsu.existsSync(file)) { return file; } if (fsu.existsSync(file + '.tsx')) { return file + '.tsx'; } if (fsu.existsSync(file + '.d.ts')) { return file + '.d.ts'; } }).filter(function (f) { return !!f; }); // Only ones we don't have by name yet // TODO: replace INF with an actual version files = files .filter(function (f) { return !typings[path.basename(f)] || typings[path.basename(f)].version > Infinity; }); // Add these files.forEach(function (f) { return typings[path.basename(f)] = { filePath: f, version: Infinity }; }); // Keep expanding files.forEach(function (f) { return addAllReferencedFilesWithMaxVersion(f); }); } // Keep going up till we find node_modules // at that point read the `package.json` for each file in node_modules // And then if that package.json has `typescript.definition` we import that file try { var node_modules = fsu.travelUpTheDirectoryTreeTillYouFind(projectDir, 'node_modules', true); // For each sub directory of node_modules look at package.json and then `typescript.definition` var moduleDirs = fsu.getDirs(node_modules); for (var _i = 0, moduleDirs_1 = moduleDirs; _i < moduleDirs_1.length; _i++) { var moduleDir = moduleDirs_1[_i]; try { var package_json = JSON.parse(fmc.getOrCreateOpenFile(moduleDir + "/package.json").getContents()); packagejson.push(moduleDir + "/package.json"); } catch (ex) { // Can't read package.json ... no worries ... move on to other modules continue; } if (package_json.typescript && package_json.typescript.definition) { var file = path.resolve(moduleDir, './', package_json.typescript.definition); /** If the file configuration points to a valid file */ if (fsu.existsSync(file)) { typings[path.basename(file)] = { filePath: file, version: Infinity }; // Also add any files that this `.d.ts` references as long as they don't conflict with what we have addAllReferencedFilesWithMaxVersion(file); } } } } catch (ex) { if (ex.message == "not found") { // Sure we didn't find node_modules // Thats cool } else { console.error('Failed to read package.json from node_modules due to error:', ex, ex.stack); } } var all = Object.keys(typings) .map(function (typing) { return typings[typing].filePath; }) .map(function (x) { return fsu.consistentPath(x); }); var implicit = all .filter(function (x) { return !existing[x]; }); var ours = all .filter(function (x) { return existing[x]; }); return { implicit: implicit, ours: ours, packagejson: packagejson }; } exports.getDefinitionsForNodeModules = getDefinitionsForNodeModules;