// Package trackingvfs provides a VFS wrapper that records every file path // accessed during compilation. This allows watch mode to know exactly which // files and directories the compiler depended on, including non-existent // paths from failed module resolution. package trackingvfs import ( "time" "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/vfs" ) // FS wraps a vfs.FS and records every path accessed via read-like operations. // Write operations (WriteFile, Remove, Chtimes) are not tracked since they // represent outputs, not dependencies. type FS struct { Inner vfs.FS SeenFiles collections.SyncSet[string] } var _ vfs.FS = (*FS)(nil) func (fs *FS) ReadFile(path string) (string, bool) { fs.SeenFiles.Add(path) return fs.Inner.ReadFile(path) } func (fs *FS) FileExists(path string) bool { fs.SeenFiles.Add(path) return fs.Inner.FileExists(path) } func (fs *FS) UseCaseSensitiveFileNames() bool { return fs.Inner.UseCaseSensitiveFileNames() } func (fs *FS) WriteFile(path string, data string) error { return fs.Inner.WriteFile(path, data) } func (fs *FS) AppendFile(path string, data string) error { return fs.Inner.AppendFile(path, data) } func (fs *FS) Remove(path string) error { return fs.Inner.Remove(path) } func (fs *FS) Chtimes(path string, aTime time.Time, mTime time.Time) error { return fs.Inner.Chtimes(path, aTime, mTime) } func (fs *FS) DirectoryExists(path string) bool { fs.SeenFiles.Add(path) return fs.Inner.DirectoryExists(path) } func (fs *FS) GetAccessibleEntries(path string) vfs.Entries { fs.SeenFiles.Add(path) return fs.Inner.GetAccessibleEntries(path) } func (fs *FS) Stat(path string) vfs.FileInfo { fs.SeenFiles.Add(path) return fs.Inner.Stat(path) } func (fs *FS) WalkDir(root string, walkFn vfs.WalkDirFunc) error { fs.SeenFiles.Add(root) return fs.Inner.WalkDir(root, func(path string, d vfs.DirEntry, err error) error { fs.SeenFiles.Add(path) return walkFn(path, d, err) }) } func (fs *FS) Realpath(path string) string { fs.SeenFiles.Add(path) return fs.Inner.Realpath(path) }