mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-18 16:34:36 -05:00
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:
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user