Skip to content

feat: completion snippets#3949

Open
a-tarasyuk wants to merge 33 commits into
microsoft:mainfrom
a-tarasyuk:feat/completion-snippets
Open

feat: completion snippets#3949
a-tarasyuk wants to merge 33 commits into
microsoft:mainfrom
a-tarasyuk:feat/completion-snippets

Conversation

@a-tarasyuk

@a-tarasyuk a-tarasyuk commented May 18, 2026

Copy link
Copy Markdown
Contributor

Fixes #2279

@a-tarasyuk a-tarasyuk force-pushed the feat/completion-snippets branch from f981cd0 to 07b3ca6 Compare May 18, 2026 13:33
@a-tarasyuk a-tarasyuk marked this pull request as ready for review May 18, 2026 20:35
Copilot AI review requested due to automatic review settings May 18, 2026 20:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds snippet-aware completion behavior to the Go-based TypeScript language service port (tsgo), including new user preference flags, richer completion items (snippets/label details/additional edits), and updated fourslash conversion + generated tests to validate the new completion shapes.

Changes:

  • Implement snippet-based completion entries for class member stubs, object-literal method stubs, and import-statement completions (including label details and additional text edits where applicable).
  • Add new UserPreferences flags controlling snippet text and label-details behavior, and thread them through completion generation.
  • Update fourslash harness + conversion scripts and regenerate/add tests to cover the new completion item shapes and preferences.

Reviewed changes

Copilot reviewed 60 out of 84 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
internal/ls/utilities.go Fix single-quote quote() output to include surrounding quotes (used by snippet generation).
internal/ls/string_completions.go Update completion item construction for new additionalTextEdits parameter.
internal/ls/lsutil/userpreferences.go Add snippet/label-details completion preference flags and clean up struct tags/comments.
internal/ls/completions.go Main implementation of snippet completions (class member stubs, object-literal method stubs, import statement completions), plus new sort text helpers and completion item plumbing.
internal/ls/codeactions_missingmemberfixer.go Extend missing-member fixer to support abstract context and safer auto-import symbol handling.
internal/ls/codeactions_fixclassincorrectlyimplementsinterface.go Update call site for new missing-member fixer signature.
internal/ls/change/trackerimpl.go Export GetFormatCodeSettingsForWriting for reuse by snippet formatting paths.
internal/ls/autoimport/view.go Add a nil-safe/availability-checked export lookup helper for auto-import views.
internal/ls/autoimport/import_adder.go Make auto-import export lookup resilient when the view index isn’t available by falling back to the direct export.
internal/ls/autoimport/extract.go Exclude pattern ambient modules from ambient module export extraction.
internal/fourslash/tests/completionClassMembersAfterConstAssertionInitializer_test.go Update expected completion to include inserted text for a class member.
internal/fourslash/fourslash.go Improve preference override handling during tests; adjust strictness/normalization in completion comparisons; set CRLF for Strada server tests.
internal/fourslash/_scripts/unparsedTests.txt Update parsing error messages to reflect improved conversion handling for sources/sortText.
internal/fourslash/_scripts/failingTests.txt Remove several tests from failing list as conversions/expectations are now supported.
internal/fourslash/_scripts/convertFourslash.mts Extend converter to handle format options, completion sources, labelDetails, preferences, and object-literal sortText helpers.
internal/checker/nodecopy.go Preserve qualifier symbol links when copying import() type nodes.
internal/fourslash/tests/gen/jsxTagNameCompletionWithExistingJsxInitializer_test.go Regenerated: pass snippet-enabled user preferences for JSX attribute snippet behavior.
internal/fourslash/tests/gen/jsxTagNameCompletionUnderElementUnclosed_test.go Regenerated: pass snippet-enabled user preferences for JSX attribute snippet behavior.
internal/fourslash/tests/gen/jsxTagNameCompletionUnderElementClosed_test.go Regenerated: pass snippet-enabled user preferences for JSX attribute snippet behavior.
internal/fourslash/tests/gen/jsxTagNameCompletionUnclosed_test.go Regenerated: pass snippet-enabled user preferences for JSX attribute snippet behavior.
internal/fourslash/tests/gen/jsxTagNameCompletionClosed_test.go Regenerated: pass snippet-enabled user preferences for JSX attribute snippet behavior.
internal/fourslash/tests/gen/jsxAttributeSnippetCompletionUnclosed_test.go Regenerated: pass snippet-enabled user preferences for JSX attribute snippet behavior.
internal/fourslash/tests/gen/jsxAttributeSnippetCompletionClosed_test.go Regenerated: pass snippet-enabled user preferences for JSX attribute snippet behavior.
internal/fourslash/tests/gen/jsxAttributeSnippetCompletionAfterTypeArgs_test.go Regenerated: pass snippet-enabled user preferences for JSX attribute snippet behavior.
internal/fourslash/tests/gen/jsxAttributeCompletionStyleNoSnippet_test.go Regenerated: set preferences to explicitly disable snippet text.
internal/fourslash/tests/gen/jsxAttributeCompletionStyleNone_test.go Regenerated: include snippet-text preference alongside none style.
internal/fourslash/tests/gen/jsxAttributeCompletionStyleDefault_test.go Regenerated: include snippet-text preference.
internal/fourslash/tests/gen/jsxAttributeCompletionStyleBraces_test.go Regenerated: include snippet-text preference and braces style.
internal/fourslash/tests/gen/jsxAttributeCompletionStyleAuto_test.go Regenerated: include snippet-text preference and auto style.
internal/fourslash/tests/gen/importStatementCompletions_semicolons_test.go New/regenerated: verify snippet import statement completions respect semicolon preference.
internal/fourslash/tests/gen/importStatementCompletions_quotes_test.go New/regenerated: verify snippet import statement completions respect quote preference.
internal/fourslash/tests/gen/importStatementCompletions_pnpmTransitive_test.go New/regenerated: verify import statement completions with pnpm transitive layout.
internal/fourslash/tests/gen/importStatementCompletions_pnpm1_test.go New/regenerated: verify import statement completions with pnpm layout.
internal/fourslash/tests/gen/importStatementCompletions_noSnippet_test.go New/regenerated: verify non-snippet import statement completion shape.
internal/fourslash/tests/gen/importStatementCompletions_noPatternAmbient_test.go New/regenerated: verify pattern ambient modules are excluded from import statement completions.
internal/fourslash/tests/gen/importStatementCompletions_js2_test.go New/regenerated: verify import statement completions in JS (variant).
internal/fourslash/tests/gen/importStatementCompletions_js_test.go New/regenerated: verify import statement completions in JS.
internal/fourslash/tests/gen/importStatementCompletions_esModuleInterop2_test.go New/regenerated: verify import statement completions with esModuleInterop (variant).
internal/fourslash/tests/gen/importStatementCompletions_esModuleInterop1_test.go New/regenerated: verify import statement completions with esModuleInterop.
internal/fourslash/tests/gen/completionsOverridingProperties3_test.go Regenerated: set snippet preferences for class member snippet completion behavior.
internal/fourslash/tests/gen/completionsOverridingProperties2_test.go Regenerated: set snippet preferences for class member snippet completion behavior.
internal/fourslash/tests/gen/completionsOverridingProperties1_test.go Regenerated: set snippet preferences for class member snippet completion behavior.
internal/fourslash/tests/gen/completionsOverridingMethodDefaultExported_test.go New/regenerated: validate class member stub completion with default-exported return types and import edits.
internal/fourslash/tests/gen/completionsOverridingMethodCrash2_test.go New/regenerated: regression coverage for previous crash scenario with snippet class member completions.
internal/fourslash/tests/gen/completionsOverridingMethodCrash1_test.go Regenerated: set snippet preferences for class member snippet completion behavior.
internal/fourslash/tests/gen/completionsOverridingMethod9_test.go Regenerated: set snippet preferences for class member snippet completion behavior.
internal/fourslash/tests/gen/completionsOverridingMethod8_test.go New/regenerated: validate class member snippet completion + apply code action updates.
internal/fourslash/tests/gen/completionsOverridingMethod7_test.go New/regenerated: validate abstract overload completion behavior.
internal/fourslash/tests/gen/completionsOverridingMethod6_test.go New/regenerated: validate modifier handling and excludes/includes across scenarios.
internal/fourslash/tests/gen/completionsOverridingMethod5_test.go New/regenerated: validate abstract vs non-abstract stub generation.
internal/fourslash/tests/gen/completionsOverridingMethod4_test.go Regenerated: set snippet preferences for class member snippet completion behavior.
internal/fourslash/tests/gen/completionsOverridingMethod3_test.go Regenerated: set snippet preferences for class member snippet completion behavior.
internal/fourslash/tests/gen/completionsOverridingMethod22_test.go New/regenerated: validate $-prefixed member completion with import edits.
internal/fourslash/tests/gen/completionsOverridingMethod21_test.go New/regenerated: validate async modifier handling in overrides.
internal/fourslash/tests/gen/completionsOverridingMethod20_test.go New/regenerated: validate completion when typing partial identifier with async modifier.
internal/fourslash/tests/gen/completionsOverridingMethod2_test.go Regenerated: set snippet preferences for class member snippet completion behavior.
internal/fourslash/tests/gen/completionsOverridingMethod19_test.go New/regenerated: validate robustness when non-modifier identifiers are present in modifier positions.
internal/fourslash/tests/gen/completionsOverridingMethod18_test.go New/regenerated: validate decorator preservation in generated member stubs.
internal/fourslash/tests/gen/completionsOverridingMethod17_test.go Regenerated: set snippet preferences for class member snippet completion behavior.
internal/fourslash/tests/gen/completionsOverridingMethod14_test.go Regenerated: set snippet preferences for class member snippet completion behavior.
internal/fourslash/tests/gen/completionsOverridingMethod12_test.go New/regenerated: validate accessor override stub completion for abstract/override scenarios.
internal/fourslash/tests/gen/completionsOverridingMethod11_test.go Regenerated: set snippet preferences for class member snippet completion behavior.
internal/fourslash/tests/gen/completionsOverridingMethod10_test.go Regenerated: set snippet preferences for class member snippet completion behavior.
internal/fourslash/tests/gen/completionsOverridingMethod1_test.go Regenerated: set snippet preferences for class member snippet completion behavior.
internal/fourslash/tests/gen/completionsOverridingMethod0_test.go New/regenerated: broad baseline coverage for override stub completions.
internal/fourslash/tests/gen/completionsObjectLiteralMethod5_test.go New/regenerated: validate object-literal method snippet insertion + sortText ordering.
internal/fourslash/tests/gen/completionsObjectLiteralMethod4_test.go New/regenerated: validate this parameter handling in object-literal method snippets.
internal/fourslash/tests/gen/completionsObjectLiteralMethod3_test.go New/regenerated: validate union/intersection and optional member behavior for object-literal method snippets.
internal/fourslash/tests/gen/completionsObjectLiteralMethod2_test.go New/regenerated: validate cross-file type references for object-literal method snippets.
internal/fourslash/tests/gen/completionsObjectLiteralMethod1_test.go New/regenerated: validate overload/quoted names and labelDetails behavior for object-literal method snippets.
internal/fourslash/tests/gen/completionsJsxExpression_test.go Regenerated: set snippet-text preference for JSX expression completions.
internal/fourslash/tests/gen/completionsClassMemberImportTypeNodeParameter4_test.go Regenerated: set class member snippet preference for import-type-node cases.
internal/fourslash/tests/gen/completionsClassMemberImportTypeNodeParameter3_test.go Regenerated: set class member snippet preference for import-type-node cases.
internal/fourslash/tests/gen/completionsClassMemberImportTypeNodeParameter2_test.go Regenerated: set class member snippet preference for import-type-node cases.
internal/fourslash/tests/gen/completionsClassMemberImportTypeNodeParameter1_test.go Regenerated: set class member snippet preference for import-type-node cases.
internal/fourslash/tests/gen/completionEntryClassMembersWithInferredFunctionReturnType1_test.go Regenerated: set class member snippet preference for inferred return types.
internal/fourslash/tests/gen/completionCloneQuestionToken_test.go Regenerated: set class member snippet preference for optional members.
internal/fourslash/tests/gen/completionClassMemberSnippetCrossFileNodeReuse1_test.go New/regenerated: validate snippet generation without cross-file node reuse issues.
internal/fourslash/tests/gen/autoImportCompletionExportListAugmentation4_test.go Regenerated: set class member snippet preference in auto-import augmentation scenarios.
internal/fourslash/tests/gen/autoImportCompletionExportListAugmentation3_test.go Regenerated: set class member snippet preference in auto-import augmentation scenarios.
internal/fourslash/tests/gen/autoImportCompletionExportListAugmentation2_test.go Regenerated: set class member snippet preference in auto-import augmentation scenarios.
internal/fourslash/tests/gen/autoImportCompletionExportListAugmentation1_test.go Regenerated: set class member snippet preference in auto-import augmentation scenarios.
internal/fourslash/tests/gen/autoImportCompletionExportEqualsWithDefault1_test.go Regenerated: set class member snippet preference for export-equals-with-default scenarios.
internal/fourslash/tests/gen/autoImportCompletionAmbientMergedModule1_test.go Regenerated: set class member snippet preference for ambient merged module scenarios.
Files not reviewed (24)
  • internal/fourslash/tests/gen/autoImportCompletionAmbientMergedModule1_test.go: Language not supported
  • internal/fourslash/tests/gen/autoImportCompletionExportEqualsWithDefault1_test.go: Language not supported
  • internal/fourslash/tests/gen/autoImportCompletionExportListAugmentation1_test.go: Language not supported
  • internal/fourslash/tests/gen/autoImportCompletionExportListAugmentation2_test.go: Language not supported
  • internal/fourslash/tests/gen/autoImportCompletionExportListAugmentation3_test.go: Language not supported
  • internal/fourslash/tests/gen/autoImportCompletionExportListAugmentation4_test.go: Language not supported
  • internal/fourslash/tests/gen/completionClassMemberSnippetCrossFileNodeReuse1_test.go: Language not supported
  • internal/fourslash/tests/gen/completionCloneQuestionToken_test.go: Language not supported
  • internal/fourslash/tests/gen/completionEntryClassMembersWithInferredFunctionReturnType1_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsClassMemberImportTypeNodeParameter1_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsClassMemberImportTypeNodeParameter2_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsClassMemberImportTypeNodeParameter3_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsClassMemberImportTypeNodeParameter4_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsJsxExpression_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsObjectLiteralMethod1_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsObjectLiteralMethod2_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsObjectLiteralMethod3_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsObjectLiteralMethod4_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsObjectLiteralMethod5_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsOverridingMethod0_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsOverridingMethod10_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsOverridingMethod11_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsOverridingMethod12_test.go: Language not supported
  • internal/fourslash/tests/gen/completionsOverridingMethod14_test.go: Language not supported

Comment thread internal/ls/completions.go

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@a-tarasyuk a-tarasyuk closed this May 21, 2026
@a-tarasyuk a-tarasyuk reopened this Jun 9, 2026
Comment thread internal/checker/nodecopy.go Outdated
Comment thread internal/ls/lsutil/userpreferences.go Outdated
Comment thread internal/ls/codeactions_missingmemberfixer.go Outdated
Comment thread internal/ls/codeactions_missingmemberfixer.go Outdated
Comment thread internal/ls/codeactions_missingmemberfixer.go Outdated

func (f *missingMemberFixer) shouldAddOverrideKeyword(declaration *ast.Node) bool {
return declaration != nil && f.program.Options().NoImplicitOverride.IsTrue() && ast.HasAbstractModifier(declaration)
return declaration != nil && f.program.Options().NoImplicitOverride.IsTrue() && ast.IsClassElement(declaration)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do we need this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmm, yeah, the original code seems wrong, but shouldn't we be checking that the declaration comes from a class? Since it could also come from an interface. I don't think IsClassElement does that, despite the name.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've changed to check the parent class context

Comment thread internal/ls/codeactions_missingmemberfixer.go Outdated
@RyanCavanaugh RyanCavanaugh added this to the Post-7.0 milestone Jun 9, 2026
@a-tarasyuk a-tarasyuk requested a review from gabritto June 9, 2026 23:31
@a-tarasyuk a-tarasyuk force-pushed the feat/completion-snippets branch from effa665 to b686dd4 Compare June 10, 2026 10:01
Comment thread internal/ls/completions.go Outdated
originalSortText := core.OrElse(symbolToSortTextMap[symbolId], SortTextLocationPriority)
symbolToSortTextMap[symbolId] = ObjectLiteralPropertySortText(originalSortText, displayName)
}
entry := l.getEntryForObjectLiteralMethodCompletion(ctx, typeChecker, member, objectLikeContainer, file)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shouldn't we opt out if we're in a JS file?

Comment thread internal/ls/completions.go Outdated
NewLine: core.GetNewLineKind(l.FormatOptions().NewLineCharacter),
Target: l.GetProgram().Options().GetEmitScriptTarget(),
}, printer.PrintHandlers{}, nil /*emitContext*/)
return strings.TrimSuffix(signaturePrinter.Emit(methodSignature, file), ";")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you add a comment for a todo here? like // !!! OmitTrailingSemicolon printer option so we know this is a temporary thing because we don't have that option yet.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I added support for OmitTrailingSemicolon. Not sure if that’s appropriate for this PR, though.

Comment thread internal/ls/completions.go Outdated
}

func (l *LanguageService) getEntryForObjectLiteralMethodCompletion(ctx context.Context, typeChecker *checker.Checker, symbol *ast.Symbol, enclosingDeclaration *ast.Node, file *ast.SourceFile) *symbolOriginInfoObjectLiteralMethod {
method := l.createObjectLiteralMethod(typeChecker, symbol, enclosingDeclaration, file)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think related to my comment on skipping for JS files, we seem to be missing stuff that is in collectObjectLiteralMethodSymbols in Strada, like the isObjectLiteralMethodSymbol check.

Comment thread internal/ls/completions.go Outdated
return factory.NewModifierList(nodes)
}

func addClassMemberSnippet(text string, newLine string) string {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't know that I like this. I may need to think about how we should do snippets in Corsa.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I added support for snippet elements and removed the string-based snippet normalization.

Comment thread internal/ls/completions.go Outdated
}
view, err := l.getPreparedAutoImportView(file)
if err != nil {
view = l.getCurrentAutoImportView(file)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this needs to return an error, like we do for exhaustive case completions, so that we then redo the completion requests with the autoimport view.

@a-tarasyuk a-tarasyuk requested a review from gabritto June 10, 2026 21:32
@a-tarasyuk a-tarasyuk force-pushed the feat/completion-snippets branch 4 times, most recently from c1bed17 to 1871214 Compare July 3, 2026 18:17
@a-tarasyuk a-tarasyuk force-pushed the feat/completion-snippets branch from 1871214 to cb13b5f Compare July 4, 2026 06:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add snippet completions for methods

4 participants