diff --git a/tsc/internal/module/cache.go b/tsc/internal/module/cache.go index 0de907f23212a..5b125abc0ada0 100644 --- a/tsc/internal/module/cache.go +++ b/tsc/internal/module/cache.go @@ -1,8 +1,6 @@ package module import ( - "sync" - "github.com/microsoft/TypeScript/tsc/internal/collections" "github.com/microsoft/TypeScript/tsc/internal/core" "github.com/microsoft/TypeScript/tsc/internal/packagejson" @@ -49,16 +47,28 @@ func (c *typeRefDirectiveResolutionCache) Set(key typeRefDirectiveResolutionCach c.cache.Store(key, value) } +type parsedPatternsCache struct { + cache collections.SyncMap[*collections.OrderedMap[string, []string], *ParsedPatterns] +} + +func (c *parsedPatternsCache) Get(pathMappings *collections.OrderedMap[string, []string]) *ParsedPatterns { + patterns, ok := c.cache.Load(pathMappings) + if !ok { + patterns, _ = c.cache.LoadOrStore(pathMappings, TryParsePatterns(pathMappings)) + } + return patterns +} + type caches struct { packageJsonInfoCache *packagejson.InfoCache moduleResolutionCache moduleResolutionCache typeRefDirectiveResolutionCache typeRefDirectiveResolutionCache - // Cached representation for `core.CompilerOptions.paths`. - // Doesn't handle other path patterns like in `typesVersions`. - parsedPatternsForPathsOnce sync.Once - parsedPatternsForPaths *ParsedPatterns + // Cached representations for `core.CompilerOptions.paths`, keyed by the + // path mappings themselves. This does not handle other path patterns such + // as `typesVersions`. + parsedPatternsForPaths parsedPatternsCache } func newCaches( diff --git a/tsc/internal/module/resolver.go b/tsc/internal/module/resolver.go index b408b7d4c027a..2363435bb2207 100644 --- a/tsc/internal/module/resolver.go +++ b/tsc/internal/module/resolver.go @@ -5,7 +5,6 @@ import ( "maps" "slices" "strings" - "sync" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -89,12 +88,6 @@ type resolutionState struct { candidateEndingIsFromConfig bool resolvedPackageDirectory bool diagnostics []*ast.Diagnostic - - // Similar to whats on resolver but only done if compilerOptions are for project reference redirect - // Cached representation for `core.CompilerOptions.paths`. - // Doesn't handle other path patterns like in `typesVersions`. - parsedPatternsForPathsOnce sync.Once - parsedPatternsForPaths *ParsedPatterns } func newResolutionState( @@ -1241,13 +1234,7 @@ func (r *resolutionState) tryLoadModuleUsingOptionalResolutionSettings() *resolv } func (r *resolutionState) getParsedPatternsForPaths() *ParsedPatterns { - if r.compilerOptions == r.resolver.compilerOptions { - return r.resolver.getParsedPatternsForPaths() - } - r.parsedPatternsForPathsOnce.Do(func() { - r.parsedPatternsForPaths = TryParsePatterns(r.compilerOptions.Paths) - }) - return r.parsedPatternsForPaths + return r.resolver.getParsedPatternsForPaths(r.compilerOptions) } func (r *resolutionState) tryLoadModuleUsingPathsIfEligible() *resolved { @@ -2001,23 +1988,24 @@ type ParsedPatterns struct { patterns []core.Pattern } -func (r *Resolver) getParsedPatternsForPaths() *ParsedPatterns { - r.parsedPatternsForPathsOnce.Do(func() { - r.parsedPatternsForPaths = TryParsePatterns(r.compilerOptions.Paths) - }) - return r.parsedPatternsForPaths +func (r *Resolver) getParsedPatternsForPaths(compilerOptions *core.CompilerOptions) *ParsedPatterns { + return r.parsedPatternsForPaths.Get(compilerOptions.Paths) } func TryParsePatterns(pathMappings *collections.OrderedMap[string, []string]) *ParsedPatterns { paths := pathMappings.Keys() numPatterns := 0 + numMatchables := 0 for path := range paths { - if pattern := core.TryParsePattern(path); pattern.IsValid() && pattern.StarIndex == -1 { - numPatterns++ + if pattern := core.TryParsePattern(path); pattern.IsValid() { + if pattern.StarIndex == -1 { + numMatchables++ + } else { + numPatterns++ + } } } - numMatchables := pathMappings.Size() - numPatterns var patterns []core.Pattern var matchableStringSet collections.Set[string]