Skip to content

Commit a44901d

Browse files
committed
Symlink cache changes
1 parent 5590cc8 commit a44901d

File tree

3 files changed

+53
-59
lines changed

3 files changed

+53
-59
lines changed

internal/compiler/fileloader.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/microsoft/typescript-go/internal/ast"
1111
"github.com/microsoft/typescript-go/internal/core"
1212
"github.com/microsoft/typescript-go/internal/module"
13+
"github.com/microsoft/typescript-go/internal/modulespecifiers"
1314
"github.com/microsoft/typescript-go/internal/tsoptions"
1415
"github.com/microsoft/typescript-go/internal/tspath"
1516
)
@@ -86,10 +87,9 @@ func processAllProgramFiles(
8687
loader.resolver = module.NewResolver(opts.Host, compilerOptions, opts.TypingsLocation, opts.ProjectName)
8788
} else {
8889
loader.resolver = module.NewResolver(&ProjectReferenceDtsFakingHost{
89-
host: opts.Host,
9090
projectReferenceFileMapper: loader.projectReferenceFileMapper,
9191
dtsDirectories: loader.dtsDirectories,
92-
symlinkCache: module.SymlinkCache{},
92+
symlinkCache: modulespecifiers.SymlinkCache{},
9393
}, compilerOptions, opts.TypingsLocation, opts.ProjectName)
9494
}
9595

internal/compiler/projectreferencedtsfakinghost.go

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import (
55

66
"github.com/microsoft/typescript-go/internal/core"
77
"github.com/microsoft/typescript-go/internal/module"
8+
"github.com/microsoft/typescript-go/internal/modulespecifiers"
89
"github.com/microsoft/typescript-go/internal/tspath"
910
"github.com/microsoft/typescript-go/internal/vfs"
1011
)
1112

1213
type ProjectReferenceDtsFakingHost struct {
13-
host CompilerHost
1414
projectReferenceFileMapper *ProjectReferenceFileMapper
1515
dtsDirectories core.Set[tspath.Path]
16-
symlinkCache module.SymlinkCache
16+
symlinkCache modulespecifiers.SymlinkCache
1717
}
1818

1919
var _ module.ResolutionHost = (*ProjectReferenceDtsFakingHost)(nil)
@@ -23,21 +23,21 @@ func (h *ProjectReferenceDtsFakingHost) FS() vfs.FS {
2323
}
2424

2525
func (h *ProjectReferenceDtsFakingHost) GetCurrentDirectory() string {
26-
return h.host.GetCurrentDirectory()
26+
return h.projectReferenceFileMapper.opts.Host.GetCurrentDirectory()
2727
}
2828

2929
func (h *ProjectReferenceDtsFakingHost) Trace(msg string) {
30-
h.host.Trace(msg)
30+
h.projectReferenceFileMapper.opts.Host.Trace(msg)
3131
}
3232

3333
// UseCaseSensitiveFileNames returns true if the file system is case-sensitive.
3434
func (h *ProjectReferenceDtsFakingHost) UseCaseSensitiveFileNames() bool {
35-
return h.host.FS().UseCaseSensitiveFileNames()
35+
return h.projectReferenceFileMapper.opts.Host.FS().UseCaseSensitiveFileNames()
3636
}
3737

3838
// FileExists returns true if the file exists.
3939
func (h *ProjectReferenceDtsFakingHost) FileExists(path string) bool {
40-
if h.host.FS().FileExists(path) {
40+
if h.projectReferenceFileMapper.opts.Host.FS().FileExists(path) {
4141
return true
4242
}
4343
if !tspath.IsDeclarationFileName(path) {
@@ -49,7 +49,7 @@ func (h *ProjectReferenceDtsFakingHost) FileExists(path string) bool {
4949

5050
func (h *ProjectReferenceDtsFakingHost) ReadFile(path string) (contents string, ok bool) {
5151
// Dont need to override as we cannot mimick read file
52-
return h.host.FS().ReadFile(path)
52+
return h.projectReferenceFileMapper.opts.Host.FS().ReadFile(path)
5353
}
5454

5555
func (h *ProjectReferenceDtsFakingHost) WriteFile(path string, data string, writeByteOrderMark bool) error {
@@ -63,7 +63,7 @@ func (h *ProjectReferenceDtsFakingHost) Remove(path string) error {
6363

6464
// DirectoryExists returns true if the path is a directory.
6565
func (h *ProjectReferenceDtsFakingHost) DirectoryExists(path string) bool {
66-
if h.host.FS().DirectoryExists(path) {
66+
if h.projectReferenceFileMapper.opts.Host.FS().DirectoryExists(path) {
6767
h.handleDirectoryCouldBeSymlink(path)
6868
return true
6969
}
@@ -89,11 +89,11 @@ func (h *ProjectReferenceDtsFakingHost) WalkDir(root string, walkFn vfs.WalkDirF
8989
// Realpath returns the "real path" of the specified path,
9090
// following symlinks and correcting filename casing.
9191
func (h *ProjectReferenceDtsFakingHost) Realpath(path string) string {
92-
result, ok := h.symlinkCache.SymlinkedFiles()[h.toPath(path)]
92+
result, ok := h.symlinkCache.SymlinkedFiles().Load(h.toPath(path))
9393
if ok {
9494
return result
9595
}
96-
return h.host.FS().Realpath(path)
96+
return h.projectReferenceFileMapper.opts.Host.FS().Realpath(path)
9797
}
9898

9999
func (h *ProjectReferenceDtsFakingHost) toPath(path string) tspath.Path {
@@ -110,27 +110,26 @@ func (h *ProjectReferenceDtsFakingHost) handleDirectoryCouldBeSymlink(directory
110110
return
111111
}
112112
directoryPath := tspath.Path(tspath.EnsureTrailingDirectorySeparator(string(h.toPath(directory))))
113-
if _, ok := h.symlinkCache.SymlinkedDirectories()[directoryPath]; ok {
113+
if _, ok := h.symlinkCache.SymlinkedDirectories().Load(directoryPath); ok {
114114
return
115115
}
116116

117-
realDirectory := h.host.FS().Realpath(directory)
117+
realDirectory := h.projectReferenceFileMapper.opts.Host.FS().Realpath(directory)
118118
var realPath tspath.Path
119+
var symlinkedDirectory *modulespecifiers.SymlinkedDirectory
119120
if realDirectory == directory {
120121
// not symlinked
121-
h.symlinkCache.SetSymlinkedDirectory(directory, directoryPath, nil)
122-
return
123-
}
124-
if realPath = tspath.Path(tspath.EnsureTrailingDirectorySeparator(string(h.toPath(realDirectory)))); realPath == directoryPath {
122+
symlinkedDirectory = nil
123+
} else if realPath = tspath.Path(tspath.EnsureTrailingDirectorySeparator(string(h.toPath(realDirectory)))); realPath == directoryPath {
125124
// not symlinked
126-
h.symlinkCache.SetSymlinkedDirectory(directory, directoryPath, nil)
127-
return
125+
symlinkedDirectory = nil
126+
} else {
127+
symlinkedDirectory = &modulespecifiers.SymlinkedDirectory{
128+
Real: tspath.EnsureTrailingDirectorySeparator(realDirectory),
129+
RealPath: realPath,
130+
}
128131
}
129-
130-
h.symlinkCache.SetSymlinkedDirectory(directory, directoryPath, &module.SymlinkedDirectory{
131-
Real: tspath.EnsureTrailingDirectorySeparator(realDirectory),
132-
RealPath: realPath,
133-
})
132+
h.symlinkCache.SetSymlinkedDirectory(directory, directoryPath, symlinkedDirectory)
134133
}
135134

136135
func (h *ProjectReferenceDtsFakingHost) fileOrDirectoryExistsUsingSource(fileOrDirectory string, isFile bool) bool {
@@ -141,33 +140,33 @@ func (h *ProjectReferenceDtsFakingHost) fileOrDirectoryExistsUsingSource(fileOrD
141140
return result == core.TSTrue
142141
}
143142

144-
// !!! sheetal this needs to be thread safe !!
145143
symlinkedDirectories := h.symlinkCache.SymlinkedDirectories()
146-
if symlinkedDirectories == nil {
144+
if symlinkedDirectories.Size() == 0 {
147145
return false
148146
}
149147
fileOrDirectoryPath := h.toPath(fileOrDirectory)
150148
if !strings.Contains(string(fileOrDirectoryPath), "/node_modules/") {
151149
return false
152150
}
153151
if isFile {
154-
_, ok := h.symlinkCache.SymlinkedFiles()[fileOrDirectoryPath]
152+
_, ok := h.symlinkCache.SymlinkedFiles().Load(fileOrDirectoryPath)
155153
if ok {
156154
return true
157155
}
158156
}
159157

160158
// If it contains node_modules check if its one of the symlinked path we know of
161-
for directoryPath, symlinkedDirectory := range symlinkedDirectories {
159+
var exists bool
160+
symlinkedDirectories.Range(func(directoryPath tspath.Path, symlinkedDirectory *modulespecifiers.SymlinkedDirectory) bool {
162161
if symlinkedDirectory == nil {
163-
continue
162+
return true
164163
}
165164

166165
relative, hasPrefix := strings.CutPrefix(string(fileOrDirectoryPath), string(directoryPath))
167166
if !hasPrefix {
168-
continue
167+
return true
169168
}
170-
if fileOrDirectoryExistsUsingSource(string(symlinkedDirectory.RealPath) + relative).IsTrue() {
169+
if exists = fileOrDirectoryExistsUsingSource(string(symlinkedDirectory.RealPath) + relative).IsTrue(); exists {
171170
if isFile {
172171
// Store the real path for the file
173172
absolutePath := tspath.GetNormalizedAbsolutePath(fileOrDirectory, h.GetCurrentDirectory())
@@ -176,16 +175,17 @@ func (h *ProjectReferenceDtsFakingHost) fileOrDirectoryExistsUsingSource(fileOrD
176175
symlinkedDirectory.Real+absolutePath[len(directoryPath):],
177176
)
178177
}
179-
return true
178+
return false
180179
}
181-
}
182-
return false
180+
return true
181+
})
182+
return exists
183183
}
184184

185185
func (h *ProjectReferenceDtsFakingHost) fileExistsIfProjectReferenceDts(file string) core.Tristate {
186186
source := h.projectReferenceFileMapper.getSourceAndProjectReference(h.toPath(file))
187187
if source != nil {
188-
return core.IfElse(h.host.FS().FileExists(source.Source), core.TSTrue, core.TSFalse)
188+
return core.IfElse(h.projectReferenceFileMapper.opts.Host.FS().FileExists(source.Source), core.TSTrue, core.TSFalse)
189189
}
190190
return core.TSUnknown
191191
}
Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
package module
1+
package modulespecifiers
22

33
import (
4-
"github.com/microsoft/typescript-go/internal/core"
4+
"github.com/microsoft/typescript-go/internal/collections"
55
"github.com/microsoft/typescript-go/internal/tspath"
66
)
77

@@ -19,41 +19,35 @@ type SymlinkedDirectory struct {
1919
}
2020

2121
type SymlinkCache struct {
22-
symlinkedDirectories map[tspath.Path]*SymlinkedDirectory
23-
symlinkedDirectoriesByRealpath core.MultiMap[tspath.Path, string]
24-
symlinkedFiles map[tspath.Path]string
22+
symlinkedDirectories collections.SyncMap[tspath.Path, *SymlinkedDirectory]
23+
symlinkedFiles collections.SyncMap[tspath.Path, string]
2524
}
2625

2726
/** Gets a map from symlink to realpath. Keys have trailing directory separators. */
28-
func (cache *SymlinkCache) SymlinkedDirectories() map[tspath.Path]*SymlinkedDirectory {
29-
return cache.symlinkedDirectories
27+
func (cache *SymlinkCache) SymlinkedDirectories() *collections.SyncMap[tspath.Path, *SymlinkedDirectory] {
28+
return &cache.symlinkedDirectories
3029
}
3130

3231
/** Gets a map from symlink to realpath */
33-
func (cache *SymlinkCache) SymlinkedFiles() map[tspath.Path]string {
34-
return cache.symlinkedFiles
32+
func (cache *SymlinkCache) SymlinkedFiles() *collections.SyncMap[tspath.Path, string] {
33+
return &cache.symlinkedFiles
3534
}
3635

36+
// all callers should check !containsIgnoredPath(symlinkPath)
3737
func (cache *SymlinkCache) SetSymlinkedDirectory(symlink string, symlinkPath tspath.Path, realDirectory *SymlinkedDirectory) {
3838
// Large, interconnected dependency graphs in pnpm will have a huge number of symlinks
3939
// where both the realpath and the symlink path are inside node_modules/.pnpm. Since
4040
// this path is never a candidate for a module specifier, we can ignore it entirely.
4141

42-
// !!! sheetal - all callers check this !containsIgnoredPath(symlinkPath) ?
43-
if realDirectory != nil {
44-
if _, ok := cache.symlinkedDirectories[symlinkPath]; !ok {
45-
cache.symlinkedDirectoriesByRealpath.Add(realDirectory.RealPath, symlink)
46-
}
47-
}
48-
if cache.symlinkedDirectories == nil {
49-
cache.symlinkedDirectories = make(map[tspath.Path]*SymlinkedDirectory)
50-
}
51-
cache.symlinkedDirectories[symlinkPath] = realDirectory
42+
// !!!
43+
// if realDirectory != nil {
44+
// if _, ok := cache.symlinkedDirectories.Load(symlinkPath); !ok {
45+
// cache.symlinkedDirectoriesByRealpath.Add(realDirectory.RealPath, symlink)
46+
// }
47+
// }
48+
cache.symlinkedDirectories.Store(symlinkPath, realDirectory)
5249
}
5350

5451
func (cache *SymlinkCache) SetSymlinkedFile(symlinkPath tspath.Path, realpath string) {
55-
if cache.symlinkedFiles == nil {
56-
cache.symlinkedFiles = make(map[tspath.Path]string)
57-
}
58-
cache.symlinkedFiles[symlinkPath] = realpath
52+
cache.symlinkedFiles.Store(symlinkPath, realpath)
5953
}

0 commit comments

Comments
 (0)