@@ -44,7 +44,7 @@ namespace ts {
44
44
return undefined ;
45
45
}
46
46
47
- const cachedReadDirectoryResult = new Map < string , MutableFileSystemEntries > ( ) ;
47
+ const cachedReadDirectoryResult = new Map < string , MutableFileSystemEntries | false > ( ) ;
48
48
const getCanonicalFileName = createGetCanonicalFileName ( useCaseSensitiveFileNames ) ;
49
49
return {
50
50
useCaseSensitiveFileNames,
@@ -65,11 +65,11 @@ namespace ts {
65
65
return ts . toPath ( fileName , currentDirectory , getCanonicalFileName ) ;
66
66
}
67
67
68
- function getCachedFileSystemEntries ( rootDirPath : Path ) : MutableFileSystemEntries | undefined {
68
+ function getCachedFileSystemEntries ( rootDirPath : Path ) {
69
69
return cachedReadDirectoryResult . get ( ensureTrailingDirectorySeparator ( rootDirPath ) ) ;
70
70
}
71
71
72
- function getCachedFileSystemEntriesForBaseDir ( path : Path ) : MutableFileSystemEntries | undefined {
72
+ function getCachedFileSystemEntriesForBaseDir ( path : Path ) {
73
73
return getCachedFileSystemEntries ( getDirectoryPath ( path ) ) ;
74
74
}
75
75
@@ -78,21 +78,32 @@ namespace ts {
78
78
}
79
79
80
80
function createCachedFileSystemEntries ( rootDir : string , rootDirPath : Path ) {
81
- const resultFromHost : MutableFileSystemEntries = {
82
- files : map ( host . readDirectory ! ( rootDir , /*extensions*/ undefined , /*exclude*/ undefined , /*include*/ [ "*.*" ] ) , getBaseNameOfFileName ) || [ ] ,
83
- directories : host . getDirectories ! ( rootDir ) || [ ]
84
- } ;
81
+ if ( ! host . realpath || ensureTrailingDirectorySeparator ( toPath ( host . realpath ( rootDir ) ) ) === rootDirPath ) {
82
+ const resultFromHost : MutableFileSystemEntries = {
83
+ files : map ( host . readDirectory ! ( rootDir , /*extensions*/ undefined , /*exclude*/ undefined , /*include*/ [ "*.*" ] ) , getBaseNameOfFileName ) || [ ] ,
84
+ directories : host . getDirectories ! ( rootDir ) || [ ]
85
+ } ;
86
+
87
+ cachedReadDirectoryResult . set ( ensureTrailingDirectorySeparator ( rootDirPath ) , resultFromHost ) ;
88
+ return resultFromHost ;
89
+ }
85
90
86
- cachedReadDirectoryResult . set ( ensureTrailingDirectorySeparator ( rootDirPath ) , resultFromHost ) ;
87
- return resultFromHost ;
91
+ // If the directory is symlink do not cache the result
92
+ if ( host . directoryExists ?.( rootDir ) ) {
93
+ cachedReadDirectoryResult . set ( rootDirPath , false ) ;
94
+ return false ;
95
+ }
96
+
97
+ // Non existing directory
98
+ return undefined ;
88
99
}
89
100
90
101
/**
91
102
* If the readDirectory result was already cached, it returns that
92
103
* Otherwise gets result from host and caches it.
93
104
* The host request is done under try catch block to avoid caching incorrect result
94
105
*/
95
- function tryReadDirectory ( rootDir : string , rootDirPath : Path ) : MutableFileSystemEntries | undefined {
106
+ function tryReadDirectory ( rootDir : string , rootDirPath : Path ) {
96
107
rootDirPath = ensureTrailingDirectorySeparator ( rootDirPath ) ;
97
108
const cachedResult = getCachedFileSystemEntries ( rootDirPath ) ;
98
109
if ( cachedResult ) {
@@ -170,18 +181,32 @@ namespace ts {
170
181
171
182
function readDirectory ( rootDir : string , extensions ?: readonly string [ ] , excludes ?: readonly string [ ] , includes ?: readonly string [ ] , depth ?: number ) : string [ ] {
172
183
const rootDirPath = toPath ( rootDir ) ;
173
- const result = tryReadDirectory ( rootDir , rootDirPath ) ;
174
- if ( result ) {
184
+ const rootResult = tryReadDirectory ( rootDir , rootDirPath ) ;
185
+ let rootSymLinkResult : FileSystemEntries | undefined ;
186
+ if ( rootResult !== undefined ) {
175
187
return matchFiles ( rootDir , extensions , excludes , includes , useCaseSensitiveFileNames , currentDirectory , depth , getFileSystemEntries , realpath ) ;
176
188
}
177
189
return host . readDirectory ! ( rootDir , extensions , excludes , includes , depth ) ;
178
190
179
191
function getFileSystemEntries ( dir : string ) : FileSystemEntries {
180
192
const path = toPath ( dir ) ;
181
193
if ( path === rootDirPath ) {
182
- return result ! ;
194
+ return rootResult || getFileSystemEntriesFromHost ( dir , path ) ;
183
195
}
184
- return tryReadDirectory ( dir , path ) || emptyFileSystemEntries ;
196
+ const result = tryReadDirectory ( dir , path ) ;
197
+ return result !== undefined ?
198
+ result || getFileSystemEntriesFromHost ( dir , path ) :
199
+ emptyFileSystemEntries ;
200
+ }
201
+
202
+ function getFileSystemEntriesFromHost ( dir : string , path : Path ) : FileSystemEntries {
203
+ if ( rootSymLinkResult && path === rootDirPath ) return rootSymLinkResult ;
204
+ const result : FileSystemEntries = {
205
+ files : map ( host . readDirectory ! ( dir , /*extensions*/ undefined , /*exclude*/ undefined , /*include*/ [ "*.*" ] ) , getBaseNameOfFileName ) || emptyArray ,
206
+ directories : host . getDirectories ! ( dir ) || emptyArray
207
+ } ;
208
+ if ( path === rootDirPath ) rootSymLinkResult = result ;
209
+ return result ;
185
210
}
186
211
}
187
212
@@ -191,7 +216,7 @@ namespace ts {
191
216
192
217
function addOrDeleteFileOrDirectory ( fileOrDirectory : string , fileOrDirectoryPath : Path ) {
193
218
const existingResult = getCachedFileSystemEntries ( fileOrDirectoryPath ) ;
194
- if ( existingResult ) {
219
+ if ( existingResult !== undefined ) {
195
220
// Just clear the cache for now
196
221
// For now just clear the cache, since this could mean that multiple level entries might need to be re-evaluated
197
222
clearCache ( ) ;
0 commit comments