From b8de0a6efa0b186e0ab9b4ecf5326ca3dd44f7d5 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 13 Aug 2025 17:30:40 -0700 Subject: [PATCH 1/2] Pool collators in LS --- internal/ls/completions.go | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/internal/ls/completions.go b/internal/ls/completions.go index f72de5f5c3..742543d3d7 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -24,6 +24,7 @@ import ( "github.com/microsoft/typescript-go/internal/scanner" "github.com/microsoft/typescript-go/internal/stringutil" "golang.org/x/text/collate" + "golang.org/x/text/language" ) func (l *LanguageService) ProvideCompletion( @@ -2980,6 +2981,26 @@ func getCompletionsSymbolKind(kind ScriptElementKind) lsproto.CompletionItemKind } } +var collatorCache collections.SyncMap[language.Tag, *sync.Pool] + +func getCollator(tag language.Tag) *collate.Collator { + pool, ok := collatorCache.Load(tag) + if !ok { + pool, _ = collatorCache.LoadOrStore(tag, &sync.Pool{ + New: func() any { + return collate.New(tag) + }, + }) + } + return pool.Get().(*collate.Collator) +} + +func putCollator(tag language.Tag, collator *collate.Collator) { + pool, _ := collatorCache.Load(tag) + pool.Put(collator) +} + + // Editors will use the `sortText` and then fall back to `name` for sorting, but leave ties in response order. // So, it's important that we sort those ties in the order we want them displayed if it matters. We don't // strictly need to sort by name or SortText here since clients are going to do it anyway, but we have to @@ -2989,7 +3010,10 @@ func getCompletionsSymbolKind(kind ScriptElementKind) lsproto.CompletionItemKind // this made tests really weird, since most fourslash tests don't use the server. func getCompareCompletionEntries(ctx context.Context) func(entryInSlice *lsproto.CompletionItem, entryToInsert *lsproto.CompletionItem) int { return func(entryInSlice *lsproto.CompletionItem, entryToInsert *lsproto.CompletionItem) int { - compareStrings := collate.New(core.GetLocale(ctx)).CompareString + locale := core.GetLocale(ctx) + collator := getCollator(locale) + defer putCollator(locale, collator) + compareStrings := collator.CompareString result := compareStrings(*entryInSlice.SortText, *entryToInsert.SortText) if result == stringutil.ComparisonEqual { result = compareStrings(entryInSlice.Label, entryToInsert.Label) From 9bd5e977d00435ee10650fe010ad026920c023aa Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 13 Aug 2025 17:43:28 -0700 Subject: [PATCH 2/2] fmt --- internal/ls/completions.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/ls/completions.go b/internal/ls/completions.go index 742543d3d7..411288ab32 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -3000,7 +3000,6 @@ func putCollator(tag language.Tag, collator *collate.Collator) { pool.Put(collator) } - // Editors will use the `sortText` and then fall back to `name` for sorting, but leave ties in response order. // So, it's important that we sort those ties in the order we want them displayed if it matters. We don't // strictly need to sort by name or SortText here since clients are going to do it anyway, but we have to