From 1f753d5c7e88b1613e8e5bea8e35a96d8092d5db Mon Sep 17 00:00:00 2001 From: ibutya Date: Sun, 20 Sep 2026 13:22:41 +0900 Subject: [PATCH] Fix tsgo import completion filtering --- .../importStatementCompletions_braces_test.go | 61 +++++++++++++++++++ tsc/internal/ls/completions.go | 4 +- 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tsc/internal/fourslash/tests/importStatementCompletions_braces_test.go diff --git a/tsc/internal/fourslash/tests/importStatementCompletions_braces_test.go b/tsc/internal/fourslash/tests/importStatementCompletions_braces_test.go new file mode 100644 index 0000000000000..239d7c6eb8239 --- /dev/null +++ b/tsc/internal/fourslash/tests/importStatementCompletions_braces_test.go @@ -0,0 +1,61 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/TypeScript/tsc/internal/fourslash" + . "github.com/microsoft/TypeScript/tsc/internal/fourslash/tests/util" + "github.com/microsoft/TypeScript/tsc/internal/lsp/lsproto" + "github.com/microsoft/TypeScript/tsc/internal/testutil" +) + +// verifyImportStatementFilterText checks the completions offered at `/**/` in the import statement `typed`. The edit +// range of an import statement completion covers the whole statement typed so far, and VS Code matches that text +// against the filter text, so the filter text must be the inserted statement rather than the bare export name. +func verifyImportStatementFilterText(t *testing.T, typed string) { + t.Helper() + content := "// @Filename: /mod.ts\nexport const foo = 0;\n// @Filename: /index.ts\n[|" + typed + "|]" + f, done := fourslash.NewFourslash(t, fourslash.GetDefaultCapabilitiesWithOptions(&fourslash.ClientCapabilitiesOptions{ + CompletionItem: &lsproto.ClientCompletionItemOptions{ + SnippetSupport: new(true), + }, + }), content) + defer done() + + const text = `import { foo$1 } from "./mod";` + f.VerifyCompletions(t, "", &fourslash.CompletionsExpectedList{ + IsIncomplete: false, + ItemDefaults: &fourslash.CompletionsExpectedItemDefaults{ + CommitCharacters: &[]string{}, + EditRange: Ignored, + }, + Items: &fourslash.CompletionsExpectedItems{ + Includes: []fourslash.CompletionsExpectedItem{ + &lsproto.CompletionItem{ + Label: "foo", + InsertText: new(text), + FilterText: new(text), + Data: &lsproto.CompletionItemData{ + AutoImport: &lsproto.AutoImportFix{ModuleSpecifier: "./mod"}, + }, + InsertTextFormat: new(lsproto.InsertTextFormatSnippet), + TextEdit: &lsproto.TextEditOrInsertReplaceEdit{ + TextEdit: &lsproto.TextEdit{NewText: text, Range: f.Ranges()[0].LSRange}, + }, + }, + }, + }, + }) +} + +func TestImportStatementCompletions_bareBrace(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + verifyImportStatementFilterText(t, "import {/**/") +} + +func TestImportStatementCompletions_bracePrefix(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + verifyImportStatementFilterText(t, "import { fo/**/") +} diff --git a/tsc/internal/ls/completions.go b/tsc/internal/ls/completions.go index 9e2f8ed3dc249..c704e4a17a892 100644 --- a/tsc/internal/ls/completions.go +++ b/tsc/internal/ls/completions.go @@ -2059,7 +2059,9 @@ func (l *LanguageService) getCompletionEntriesFromSymbols( preferences, isSnippet, ) - filterText = autoImport.Fix.Name + // The edit range covers the whole import statement typed so far, and clients match that text against the + // filter text, so it has to be the statement being inserted (as in Strada), not just the bare name. + filterText = insertText sortText = SortTextLocationPriority }