Do not suggest paths inside node_modules/.pnpm as module specifiers (#42095)

* Create symlink cache when a pnpm module is found

* Keep pnpm-internal symlinks out of the symlink cache

* Filter out  pnpm path from realpath module specifier too

* Use ignoredPaths instead of pnpm-specific path
This commit is contained in:
Andrew Branch 2021-01-12 14:04:03 -08:00 committed by GitHub
parent 2f5863754f
commit 33046e389a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 6 deletions

View File

@ -290,7 +290,9 @@ namespace ts.moduleSpecifiers {
const importedFileNames = [...(referenceRedirect ? [referenceRedirect] : emptyArray), importedFileName, ...redirects];
const targets = importedFileNames.map(f => getNormalizedAbsolutePath(f, cwd));
if (!preferSymlinks) {
const result = forEach(targets, p => cb(p, referenceRedirect === p));
// Symlinks inside ignored paths are already filtered out of the symlink cache,
// so we only need to remove them from the realpath filenames.
const result = forEach(targets, p => !containsIgnoredPath(p) && cb(p, referenceRedirect === p));
if (result) return result;
}
const links = host.getSymlinkCache
@ -318,8 +320,9 @@ namespace ts.moduleSpecifiers {
}
});
});
return result ||
(preferSymlinks ? forEach(targets, p => cb(p, p === referenceRedirect)) : undefined);
return result || (preferSymlinks
? forEach(targets, p => containsIgnoredPath(p) ? undefined : cb(p, p === referenceRedirect))
: undefined);
}
interface ModulePath {

View File

@ -3756,7 +3756,7 @@ namespace ts {
}
function handleDirectoryCouldBeSymlink(directory: string) {
if (!host.getResolvedProjectReferences()) return;
if (!host.getResolvedProjectReferences() || containsIgnoredPath(directory)) return;
// Because we already watch node_modules, handle symlinks in there
if (!originalRealpath || !stringContains(directory, nodeModulesPathPart)) return;

View File

@ -6092,7 +6092,14 @@ namespace ts {
getSymlinkedFiles: () => symlinkedFiles,
getSymlinkedDirectories: () => symlinkedDirectories,
setSymlinkedFile: (path, real) => (symlinkedFiles || (symlinkedFiles = new Map())).set(path, real),
setSymlinkedDirectory: (path, directory) => (symlinkedDirectories || (symlinkedDirectories = new Map())).set(path, directory),
setSymlinkedDirectory: (path, directory) => {
// Large, interconnected dependency graphs in pnpm will have a huge number of symlinks
// where both the realpath and the symlink path are inside node_modules/.pnpm. Since
// this path is never a candidate for a module specifier, we can ignore it entirely.
if (!containsIgnoredPath(path)) {
(symlinkedDirectories || (symlinkedDirectories = new Map())).set(path, directory);
}
}
};
}
@ -7066,4 +7073,8 @@ namespace ts {
return false;
}
}
export function containsIgnoredPath(path: string) {
return some(ignoredPaths, p => stringContains(path, p));
}
}

View File

@ -3022,7 +3022,7 @@ namespace FourSlash {
this.editScriptAndUpdateMarkers(fileName, span.start, span.start + insertedText.length, deletedText);
}
if (expectedTextArray.length !== actualTextArray.length) {
this.raiseError(`Expected ${expectedTextArray.length} import fixes, got ${actualTextArray.length}`);
this.raiseError(`Expected ${expectedTextArray.length} import fixes, got ${actualTextArray.length}:\n\n${actualTextArray.join("\n\n" + "-".repeat(20) + "\n\n")}`);
}
ts.zipWith(expectedTextArray, actualTextArray, (expected, actual, index) => {
if (expected !== actual) {

View File

@ -0,0 +1,24 @@
/// <reference path="fourslash.ts" />
// @Filename: /tsconfig.json
//// { "compilerOptions": { "module": "commonjs" } }
// @Filename: /node_modules/.pnpm/mobx@6.0.4/node_modules/mobx/package.json
//// { "types": "dist/mobx.d.ts" }
// @Filename: /node_modules/.pnpm/mobx@6.0.4/node_modules/mobx/dist/mobx.d.ts
//// export declare function autorun(): void;
// @Filename: /index.ts
//// autorun/**/
// @Filename: /utils.ts
//// import "mobx";
// @link: /node_modules/.pnpm/mobx@6.0.4/node_modules/mobx -> /node_modules/mobx
// @link: /node_modules/.pnpm/mobx@6.0.4/node_modules/mobx -> /node_modules/.pnpm/cool-mobx-dependent@1.2.3/node_modules/mobx
goTo.marker("");
verify.importFixAtPosition([`import { autorun } from "mobx";
autorun`]);