Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions internal/collections/syncmap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package collections
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is here in core so that leaf packages like cachedvfs don't need to import core.


import "sync"

type SyncMap[K comparable, V any] struct {
m sync.Map
}

func (s *SyncMap[K, V]) Load(key K) (value V, ok bool) {
val, ok := s.m.Load(key)
if !ok {
return
}
return val.(V), true
}

func (s *SyncMap[K, V]) Store(key K, value V) {
s.m.Store(key, value)
}

func (s *SyncMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) {
actualAny, loaded := s.m.LoadOrStore(key, value)
return actualAny.(V), loaded
}

func (s *SyncMap[K, V]) Delete(key K) {
s.m.Delete(key)
}

func (s *SyncMap[K, V]) Clear() {
s.m.Clear()
}

func (s *SyncMap[K, V]) Range(f func(key K, value V) bool) {
s.m.Range(func(key, value any) bool {
return f(key.(K), value.(V))
})
}

// Size returns the approximate number of items in the map.
// Note that this is not a precise count, as the map may be modified
// concurrently while this method is running.
func (s *SyncMap[K, V]) Size() int {
count := 0
s.m.Range(func(_, _ any) bool {
count++
return true
})
return count
}

func (s *SyncMap[K, V]) ToMap() map[K]V {
m := make(map[K]V, s.Size())
s.m.Range(func(key, value any) bool {
m[key.(K)] = value.(V)
return true
})
return m
}
19 changes: 6 additions & 13 deletions internal/project/documentregistry.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"sync"

"github.com/microsoft/typescript-go/internal/ast"
"github.com/microsoft/typescript-go/internal/collections"
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/parser"
"github.com/microsoft/typescript-go/internal/scanner"
Expand Down Expand Up @@ -34,7 +35,7 @@ type registryEntry struct {
// multiple LanguageService instances.
type documentRegistry struct {
options tspath.ComparePathsOptions
documents sync.Map
documents collections.SyncMap[registryKey, *registryEntry]
}

func newDocumentRegistry(options tspath.ComparePathsOptions) *documentRegistry {
Expand Down Expand Up @@ -70,8 +71,7 @@ func (r *documentRegistry) releaseDocument(file *ast.SourceFile, compilerOptions
}

func (r *documentRegistry) releaseDocumentWithKey(key registryKey) {
if entryAny, ok := r.documents.Load(key); ok {
entry := entryAny.(*registryEntry)
if entry, ok := r.documents.Load(key); ok {
entry.mu.Lock()
defer entry.mu.Unlock()
entry.refCount--
Expand All @@ -87,10 +87,9 @@ func (r *documentRegistry) getDocumentWorker(
key registryKey,
) *ast.SourceFile {
scriptTarget := core.IfElse(scriptInfo.scriptKind == core.ScriptKindJSON, core.ScriptTargetJSON, compilerOptions.GetEmitScriptTarget())
if entryAny, ok := r.documents.Load(key); ok {
if entry, ok := r.documents.Load(key); ok {
// We have an entry for this file. However, it may be for a different version of
// the script snapshot. If so, update it appropriately.
entry := entryAny.(*registryEntry)
if entry.sourceFile.Version != scriptInfo.version {
sourceFile := parser.ParseSourceFile(scriptInfo.fileName, scriptInfo.path, scriptInfo.text, scriptTarget, scanner.JSDocParsingModeParseAll)
sourceFile.Version = scriptInfo.version
Expand All @@ -104,11 +103,10 @@ func (r *documentRegistry) getDocumentWorker(
// Have never seen this file with these settings. Create a new source file for it.
sourceFile := parser.ParseSourceFile(scriptInfo.fileName, scriptInfo.path, scriptInfo.text, scriptTarget, scanner.JSDocParsingModeParseAll)
sourceFile.Version = scriptInfo.version
entryAny, _ := r.documents.LoadOrStore(key, &registryEntry{
entry, _ := r.documents.LoadOrStore(key, &registryEntry{
sourceFile: sourceFile,
refCount: 0,
})
entry := entryAny.(*registryEntry)
entry.mu.Lock()
defer entry.mu.Unlock()
entry.refCount++
Expand All @@ -118,10 +116,5 @@ func (r *documentRegistry) getDocumentWorker(

// size should only be used for testing.
func (r *documentRegistry) size() int {
count := 0
r.documents.Range(func(_, _ any) bool {
count++
return true
})
return count
return r.documents.Size()
}
22 changes: 11 additions & 11 deletions internal/testutil/harnessutil/harnessutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,19 +429,19 @@ type cachedCompilerHost struct {
options *core.CompilerOptions
}

var sourceFileCache sync.Map
var sourceFileCache collections.SyncMap[sourceFileCacheKey, *ast.SourceFile]

type sourceFileCacheKey struct {
core.SourceFileAffectingCompilerOptions
fileName string
path tspath.Path
languageVersion core.ScriptTarget
text string
}

func (h *cachedCompilerHost) GetSourceFile(fileName string, path tspath.Path, languageVersion core.ScriptTarget) *ast.SourceFile {
text, _ := h.FS().ReadFile(fileName)

type sourceFileCacheKey struct {
core.SourceFileAffectingCompilerOptions
fileName string
path tspath.Path
languageVersion core.ScriptTarget
text string
}

key := sourceFileCacheKey{
SourceFileAffectingCompilerOptions: h.options.SourceFileAffecting(),
fileName: fileName,
Expand All @@ -451,7 +451,7 @@ func (h *cachedCompilerHost) GetSourceFile(fileName string, path tspath.Path, la
}

if cached, ok := sourceFileCache.Load(key); ok {
return cached.(*ast.SourceFile)
return cached
}

// !!! dedupe with compiler.compilerHost
Expand All @@ -464,7 +464,7 @@ func (h *cachedCompilerHost) GetSourceFile(fileName string, path tspath.Path, la
}

result, _ := sourceFileCache.LoadOrStore(key, sourceFile)
return result.(*ast.SourceFile)
return result
}

func createCompilerHost(fs vfs.FS, defaultLibraryPath string, options *core.CompilerOptions, currentDirectory string) compiler.CompilerHost {
Expand Down
21 changes: 10 additions & 11 deletions internal/vfs/cachedvfs/cachedvfs.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package cachedvfs

import (
"sync"

"github.com/microsoft/typescript-go/internal/collections"
"github.com/microsoft/typescript-go/internal/vfs"
)

type FS struct {
fs vfs.FS

directoryExistsCache sync.Map // map[string]bool
fileExistsCache sync.Map // map[string]bool
getAccessibleEntriesCache sync.Map // map[string]vfs.Entries
realpathCache sync.Map // map[string]string
statCache sync.Map // map[string]vfs.FileInfo
directoryExistsCache collections.SyncMap[string, bool]
fileExistsCache collections.SyncMap[string, bool]
getAccessibleEntriesCache collections.SyncMap[string, vfs.Entries]
realpathCache collections.SyncMap[string, string]
statCache collections.SyncMap[string, vfs.FileInfo]
}

var _ vfs.FS = (*FS)(nil)
Expand All @@ -32,7 +31,7 @@ func (fsys *FS) ClearCache() {

func (fsys *FS) DirectoryExists(path string) bool {
if ret, ok := fsys.directoryExistsCache.Load(path); ok {
return ret.(bool)
return ret
}
ret := fsys.fs.DirectoryExists(path)
fsys.directoryExistsCache.Store(path, ret)
Expand All @@ -41,7 +40,7 @@ func (fsys *FS) DirectoryExists(path string) bool {

func (fsys *FS) FileExists(path string) bool {
if ret, ok := fsys.fileExistsCache.Load(path); ok {
return ret.(bool)
return ret
}
ret := fsys.fs.FileExists(path)
fsys.fileExistsCache.Store(path, ret)
Expand All @@ -50,7 +49,7 @@ func (fsys *FS) FileExists(path string) bool {

func (fsys *FS) GetAccessibleEntries(path string) vfs.Entries {
if ret, ok := fsys.getAccessibleEntriesCache.Load(path); ok {
return ret.(vfs.Entries)
return ret
}
ret := fsys.fs.GetAccessibleEntries(path)
fsys.getAccessibleEntriesCache.Store(path, ret)
Expand All @@ -63,7 +62,7 @@ func (fsys *FS) ReadFile(path string) (contents string, ok bool) {

func (fsys *FS) Realpath(path string) string {
if ret, ok := fsys.realpathCache.Load(path); ok {
return ret.(string)
return ret
}
ret := fsys.fs.Realpath(path)
fsys.realpathCache.Store(path, ret)
Expand Down