alm
Version:
The best IDE for TypeScript
181 lines (180 loc) • 8.15 kB
JavaScript
;
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;