@@ -6083,49 +6083,60 @@ namespace ts {
60836083 }
60846084
60856085 export interface SymlinkCache {
6086+ /** Gets a map from symlink to realpath. Keys have trailing directory separators. */
60866087 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 */
60876091 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 ;
60906094 }
60916095
6092- export function createSymlinkCache ( ) : SymlinkCache {
6096+ export function createSymlinkCache ( cwd : string , getCanonicalFileName : GetCanonicalFileName ) : SymlinkCache {
60936097 let symlinkedDirectories : ESMap < Path , SymlinkedDirectory | false > | undefined ;
6098+ let symlinkedDirectoriesByRealpath : MultiMap < Path , string > | undefined ;
60946099 let symlinkedFiles : ESMap < Path , string > | undefined ;
60956100 return {
60966101 getSymlinkedFiles : ( ) => symlinkedFiles ,
60976102 getSymlinkedDirectories : ( ) => symlinkedDirectories ,
6103+ getSymlinkedDirectoriesByRealpath : ( ) => symlinkedDirectoriesByRealpath ,
60986104 setSymlinkedFile : ( path , real ) => ( symlinkedFiles || ( symlinkedFiles = new Map ( ) ) ) . set ( path , real ) ,
6099- setSymlinkedDirectory : ( path , directory ) => {
6105+ setSymlinkedDirectory : ( symlink , real ) => {
61006106 // Large, interconnected dependency graphs in pnpm will have a huge number of symlinks
61016107 // where both the realpath and the symlink path are inside node_modules/.pnpm. Since
61026108 // 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 ) ;
61056116 }
61066117 }
61076118 } ;
61086119 }
61096120
61106121 export function discoverProbableSymlinks ( files : readonly SourceFile [ ] , getCanonicalFileName : GetCanonicalFileName , cwd : string ) : SymlinkCache {
6111- const cache = createSymlinkCache ( ) ;
6122+ const cache = createSymlinkCache ( cwd , getCanonicalFileName ) ;
61126123 const symlinks = flatten < readonly [ string , string ] > ( mapDefined ( files , sf =>
61136124 sf . resolvedModules && compact ( arrayFrom ( mapIterator ( sf . resolvedModules . values ( ) , res =>
61146125 res && res . originalPath && res . resolvedFileName !== res . originalPath ? [ res . resolvedFileName , res . originalPath ] as const : undefined ) ) ) ) ) ;
61156126 for ( const [ resolvedPath , originalPath ] of symlinks ) {
61166127 const [ commonResolved , commonOriginal ] = guessDirectorySymlink ( resolvedPath , originalPath , cwd , getCanonicalFileName ) || emptyArray ;
61176128 if ( commonResolved && commonOriginal ) {
61186129 cache . setSymlinkedDirectory (
6119- toPath ( commonOriginal , cwd , getCanonicalFileName ) ,
6130+ commonOriginal ,
61206131 { real : commonResolved , realPath : toPath ( commonResolved , cwd , getCanonicalFileName ) } ) ;
61216132 }
61226133 }
61236134 return cache ;
61246135 }
61256136
61266137 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 ) ) ;
61296140 let isDirectory = false ;
61306141 while ( ! isNodeModulesOrScopedPackageDirectory ( aParts [ aParts . length - 2 ] , getCanonicalFileName ) &&
61316142 ! isNodeModulesOrScopedPackageDirectory ( bParts [ bParts . length - 2 ] , getCanonicalFileName ) &&
0 commit comments