@@ -6083,49 +6083,60 @@ namespace ts {
6083
6083
}
6084
6084
6085
6085
export interface SymlinkCache {
6086
+ /** Gets a map from symlink to realpath. Keys have trailing directory separators. */
6086
6087
getSymlinkedDirectories ( ) : ReadonlyESMap < Path , SymlinkedDirectory | false > | undefined ;
6088
+ /** Gets a map from realpath to symlinks. Keys have trailing directory separators. */
6089
+ getSymlinkedDirectoriesByRealpath ( ) : MultiMap < Path , string > | undefined ;
6090
+ /** Gets a map from symlink to realpath */
6087
6091
getSymlinkedFiles ( ) : ReadonlyESMap < Path , string > | undefined ;
6088
- setSymlinkedDirectory ( path : Path , directory : SymlinkedDirectory | false ) : void ;
6089
- setSymlinkedFile ( path : Path , real : string ) : void ;
6092
+ setSymlinkedDirectory ( symlink : string , real : SymlinkedDirectory | false ) : void ;
6093
+ setSymlinkedFile ( symlinkPath : Path , real : string ) : void ;
6090
6094
}
6091
6095
6092
- export function createSymlinkCache ( ) : SymlinkCache {
6096
+ export function createSymlinkCache ( cwd : string , getCanonicalFileName : GetCanonicalFileName ) : SymlinkCache {
6093
6097
let symlinkedDirectories : ESMap < Path , SymlinkedDirectory | false > | undefined ;
6098
+ let symlinkedDirectoriesByRealpath : MultiMap < Path , string > | undefined ;
6094
6099
let symlinkedFiles : ESMap < Path , string > | undefined ;
6095
6100
return {
6096
6101
getSymlinkedFiles : ( ) => symlinkedFiles ,
6097
6102
getSymlinkedDirectories : ( ) => symlinkedDirectories ,
6103
+ getSymlinkedDirectoriesByRealpath : ( ) => symlinkedDirectoriesByRealpath ,
6098
6104
setSymlinkedFile : ( path , real ) => ( symlinkedFiles || ( symlinkedFiles = new Map ( ) ) ) . set ( path , real ) ,
6099
- setSymlinkedDirectory : ( path , directory ) => {
6105
+ setSymlinkedDirectory : ( symlink , real ) => {
6100
6106
// Large, interconnected dependency graphs in pnpm will have a huge number of symlinks
6101
6107
// where both the realpath and the symlink path are inside node_modules/.pnpm. Since
6102
6108
// this path is never a candidate for a module specifier, we can ignore it entirely.
6103
- if ( ! containsIgnoredPath ( path ) ) {
6104
- ( symlinkedDirectories || ( symlinkedDirectories = new Map ( ) ) ) . set ( path , directory ) ;
6109
+ let symlinkPath = toPath ( symlink , cwd , getCanonicalFileName ) ;
6110
+ if ( ! containsIgnoredPath ( symlinkPath ) ) {
6111
+ symlinkPath = ensureTrailingDirectorySeparator ( symlinkPath ) ;
6112
+ if ( real !== false && ! symlinkedDirectories ?. has ( symlinkPath ) ) {
6113
+ ( symlinkedDirectoriesByRealpath ||= createMultiMap ( ) ) . add ( ensureTrailingDirectorySeparator ( real . realPath ) , symlink ) ;
6114
+ }
6115
+ ( symlinkedDirectories || ( symlinkedDirectories = new Map ( ) ) ) . set ( symlinkPath , real ) ;
6105
6116
}
6106
6117
}
6107
6118
} ;
6108
6119
}
6109
6120
6110
6121
export function discoverProbableSymlinks ( files : readonly SourceFile [ ] , getCanonicalFileName : GetCanonicalFileName , cwd : string ) : SymlinkCache {
6111
- const cache = createSymlinkCache ( ) ;
6122
+ const cache = createSymlinkCache ( cwd , getCanonicalFileName ) ;
6112
6123
const symlinks = flatten < readonly [ string , string ] > ( mapDefined ( files , sf =>
6113
6124
sf . resolvedModules && compact ( arrayFrom ( mapIterator ( sf . resolvedModules . values ( ) , res =>
6114
6125
res && res . originalPath && res . resolvedFileName !== res . originalPath ? [ res . resolvedFileName , res . originalPath ] as const : undefined ) ) ) ) ) ;
6115
6126
for ( const [ resolvedPath , originalPath ] of symlinks ) {
6116
6127
const [ commonResolved , commonOriginal ] = guessDirectorySymlink ( resolvedPath , originalPath , cwd , getCanonicalFileName ) || emptyArray ;
6117
6128
if ( commonResolved && commonOriginal ) {
6118
6129
cache . setSymlinkedDirectory (
6119
- toPath ( commonOriginal , cwd , getCanonicalFileName ) ,
6130
+ commonOriginal ,
6120
6131
{ real : commonResolved , realPath : toPath ( commonResolved , cwd , getCanonicalFileName ) } ) ;
6121
6132
}
6122
6133
}
6123
6134
return cache ;
6124
6135
}
6125
6136
6126
6137
function guessDirectorySymlink ( a : string , b : string , cwd : string , getCanonicalFileName : GetCanonicalFileName ) : [ string , string ] | undefined {
6127
- const aParts = getPathComponents ( toPath ( a , cwd , getCanonicalFileName ) ) ;
6128
- const bParts = getPathComponents ( toPath ( b , cwd , getCanonicalFileName ) ) ;
6138
+ const aParts = getPathComponents ( getNormalizedAbsolutePath ( a , cwd ) ) ;
6139
+ const bParts = getPathComponents ( getNormalizedAbsolutePath ( b , cwd ) ) ;
6129
6140
let isDirectory = false ;
6130
6141
while ( ! isNodeModulesOrScopedPackageDirectory ( aParts [ aParts . length - 2 ] , getCanonicalFileName ) &&
6131
6142
! isNodeModulesOrScopedPackageDirectory ( bParts [ bParts . length - 2 ] , getCanonicalFileName ) &&
0 commit comments