Skip to content

Commit 1c82c69

Browse files
committed
chore(typescript) support node_modules lookup natively.
refs microsoft/TypeScript#3147 and microsoft/TypeScript#4154
1 parent 5fa52d0 commit 1c82c69

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed

dist/main/lang/core/languageServiceHost2.js

+53
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,63 @@ var LanguageServiceHost = (function () {
236236
return _this.config.projectFileDirectory;
237237
};
238238
this.getDefaultLibFileName = ts.getDefaultLibFileName;
239+
this.resolvedExternalModuleCache = {};
239240
if (!config.project.compilerOptions.noLib) {
240241
this.addScript(exports.getDefaultLibFilePath(config.project.compilerOptions));
241242
}
242243
}
244+
LanguageServiceHost.prototype.resolveModuleNames = function (moduleNames, containingFile) {
245+
var _this = this;
246+
return moduleNames.map(function (x) { return _this.resolveExternalModule(x, containingFile); });
247+
};
248+
LanguageServiceHost.prototype.resolveExternalModule = function (moduleName, containingFile) {
249+
var normalizePath = ts.normalizePath;
250+
var combinePaths = ts.combinePaths;
251+
var removeFileExtension = ts.removeFileExtension;
252+
var getDirectoryPath = ts.getDirectoryPath;
253+
var forEach = ts.forEach;
254+
var supportedExtensions = ts.supportedExtensions;
255+
var cacheLookupName = moduleName + containingFile;
256+
if (this.resolvedExternalModuleCache[cacheLookupName]) {
257+
return this.resolvedExternalModuleCache[cacheLookupName];
258+
}
259+
if (this.resolvedExternalModuleCache[cacheLookupName] === '') {
260+
return undefined;
261+
}
262+
function getNameIfExists(fileName) {
263+
if (fs.existsSync(fileName)) {
264+
return fileName;
265+
}
266+
}
267+
while (true) {
268+
var found = ts.forEach(ts.supportedExtensions, function (extension) { return getNameIfExists(ts.normalizePath(ts.combinePaths(containingFile, moduleName)) + extension); });
269+
if (!found) {
270+
found = ts.forEach(ts.supportedExtensions, function (extension) { return getNameIfExists(ts.normalizePath(ts.combinePaths(ts.combinePaths(containingFile, "node_modules"), moduleName)) + extension); });
271+
}
272+
if (!found) {
273+
var pkgJson = getNameIfExists(normalizePath(combinePaths(combinePaths(combinePaths(containingFile, "node_modules"), moduleName), "package.json")));
274+
if (pkgJson) {
275+
var pkgFile = JSON.parse(fs.readFileSync(pkgJson, 'utf8'));
276+
if (pkgFile.main) {
277+
var indexFileName = removeFileExtension(combinePaths(getDirectoryPath(pkgJson), pkgFile.main));
278+
found = forEach(supportedExtensions, function (extension) { return getNameIfExists(indexFileName + extension); });
279+
}
280+
}
281+
}
282+
if (!found) {
283+
found = forEach(supportedExtensions, function (extension) { return getNameIfExists(normalizePath(combinePaths(combinePaths(combinePaths(containingFile, "node_modules"), moduleName), "index")) + extension); });
284+
}
285+
if (found) {
286+
return this.resolvedExternalModuleCache[cacheLookupName] = found;
287+
}
288+
var parentPath = getDirectoryPath(containingFile);
289+
if (parentPath === containingFile) {
290+
this.resolvedExternalModuleCache[cacheLookupName] = '';
291+
return undefined;
292+
}
293+
containingFile = parentPath;
294+
}
295+
};
243296
return LanguageServiceHost;
244297
})();
245298
exports.LanguageServiceHost = LanguageServiceHost;

lib/main/lang/core/languageServiceHost2.ts

+70
Original file line numberDiff line numberDiff line change
@@ -360,4 +360,74 @@ export class LanguageServiceHost implements ts.LanguageServiceHost {
360360
return this.config.projectFileDirectory;
361361
}
362362
getDefaultLibFileName = ts.getDefaultLibFileName;
363+
364+
resolveModuleNames(moduleNames: string[], containingFile: string): string[] {
365+
return moduleNames.map(x=> this.resolveExternalModule(x, containingFile));
366+
}
367+
368+
/**
369+
* node_modules resolution logic
370+
* Code from https://github.com/Microsoft/TypeScript/pull/3147/files
371+
*/
372+
resolvedExternalModuleCache: ts.Map<string> = {};
373+
resolveExternalModule(moduleName: string, containingFile: string): string {
374+
let normalizePath = ts.normalizePath;
375+
let combinePaths = ts.combinePaths;
376+
let removeFileExtension = ts.removeFileExtension;
377+
let getDirectoryPath = ts.getDirectoryPath;
378+
let forEach = ts.forEach;
379+
let supportedExtensions = ts.supportedExtensions;
380+
381+
let cacheLookupName = moduleName + containingFile;
382+
if (this.resolvedExternalModuleCache[cacheLookupName]) {
383+
return this.resolvedExternalModuleCache[cacheLookupName];
384+
}
385+
if (this.resolvedExternalModuleCache[cacheLookupName] === '') {
386+
return undefined;
387+
}
388+
function getNameIfExists(fileName: string): string {
389+
if (fs.existsSync(fileName)) {
390+
return fileName;
391+
}
392+
}
393+
while (true) {
394+
// Look at files by all extensions
395+
let found = ts.forEach(ts.supportedExtensions,
396+
extension => getNameIfExists(ts.normalizePath(ts.combinePaths(containingFile, moduleName)) + extension));
397+
// Also look at all files by node_modules
398+
if (!found) {
399+
found = ts.forEach(ts.supportedExtensions,
400+
extension => getNameIfExists(ts.normalizePath(ts.combinePaths(ts.combinePaths(containingFile, "node_modules"), moduleName)) + extension));
401+
}
402+
// Also look at package.json's main in node_modules
403+
if (!found) {
404+
// If we found a package.json then look at its main field
405+
let pkgJson = getNameIfExists(normalizePath(combinePaths(combinePaths(combinePaths(containingFile, "node_modules"), moduleName), "package.json")));
406+
if (pkgJson) {
407+
let pkgFile = JSON.parse(fs.readFileSync(pkgJson,'utf8'));
408+
if (pkgFile.main) {
409+
var indexFileName = removeFileExtension(combinePaths(getDirectoryPath(pkgJson), pkgFile.main));
410+
found = forEach(supportedExtensions,
411+
extension => getNameIfExists(indexFileName + extension))
412+
}
413+
}
414+
}
415+
// look at node_modules index
416+
if (!found) {
417+
found = forEach(supportedExtensions,
418+
extension => getNameIfExists(normalizePath(combinePaths(combinePaths(combinePaths(containingFile, "node_modules"), moduleName), "index")) + extension));
419+
}
420+
421+
// Finally cache and return or continue up the directory tree
422+
if (found) {
423+
return this.resolvedExternalModuleCache[cacheLookupName] = found;
424+
}
425+
let parentPath = getDirectoryPath(containingFile);
426+
if (parentPath === containingFile) {
427+
this.resolvedExternalModuleCache[cacheLookupName] = '';
428+
return undefined;
429+
}
430+
containingFile = parentPath;
431+
}
432+
}
363433
}

0 commit comments

Comments
 (0)