Skip to content

Add "Sort Imports" & "Remove Unused Imports" commands to VS Code extension#3305

Open
Copilot wants to merge 7 commits intomainfrom
copilot/add-sort-and-remove-unused-imports
Open

Add "Sort Imports" & "Remove Unused Imports" commands to VS Code extension#3305
Copilot wants to merge 7 commits intomainfrom
copilot/add-sort-and-remove-unused-imports

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 31, 2026

The LSP server already supports source.sortImports and source.removeUnusedImports code action kinds, but the extension never registered corresponding command handlers.

  • _extension/src/session.ts: Register runtime command handlers for the main TypeScript extension's command IDs (typescript.sortImports, javascript.sortImports, typescript.removeUnusedImports, javascript.removeUnusedImports) that delegate to VS Code's built-in editor.action.sourceAction
  • _extension/src/session.ts: Reorder Session.dispose() to unregister commands before yielding to the event loop, preventing "command already exists" race conditions when the built-in TypeScript extension reactivates

The commands are registered only at runtime (not declared in package.json) to avoid "command already exists" conflicts when useTsgo is off and the main TypeScript extension is also loaded. By reusing the main extension's command IDs, the native preview extension seamlessly takes over those commands when tsgo is active. Disposal is ordered so that command registrations are synchronously removed before any await yields control, ensuring the built-in extension can cleanly re-register them when the native preview extension is disabled. The existing "Organize Imports" command is already wired up through the language client and does not need a separate entry.

…s to VS Code extension

Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/045863e2-6044-4847-8156-7e044e313d98

Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
Copilot AI changed the title [WIP] Add commands for sorting and removing unused imports Add "Sort Imports" & "Remove Unused Imports" commands to VS Code extension Mar 31, 2026
Copilot AI requested a review from DanielRosenwasser March 31, 2026 23:20
Comment thread _extension/src/session.ts Outdated

this.disposables.push(vscode.commands.registerCommand("typescript.native-preview.organizeImports", async () => {
await vscode.commands.executeCommand("editor.action.organizeImports");
}));
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.

We don't need this, it's already wired up to the language client.

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.

@copilot fix

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.

Removed in 0545e93.

…uage client

Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/413800a1-0e85-4c97-bf25-4df34fdfea1c

Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds explicit command palette entries in the VS Code “TypeScript (Native Preview)” extension for actions the LSP server already supports (source.sortImports and source.removeUnusedImports), by delegating to VS Code’s built-in editor.action.sourceAction.

Changes:

  • Contribute two new commands (typescript.native-preview.sortImports, typescript.native-preview.removeUnusedImports) gated on typescript.native-preview.serverRunning.
  • Register command handlers that invoke editor.action.sourceAction with the corresponding kind (source.sortImports / source.removeUnusedImports).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
_extension/src/session.ts Registers two new commands and delegates execution to VS Code source actions for sort/remove-unused-imports.
_extension/package.json Declares the two new commands with enablement tied to the native preview server running.

Comment thread _extension/package.json Outdated
Comment on lines 158 to 168
"command": "typescript.native-preview.sortImports",
"title": "Sort Imports",
"enablement": "typescript.native-preview.serverRunning",
"category": "TypeScript Native Preview"
},
{
"command": "typescript.native-preview.removeUnusedImports",
"title": "Remove Unused Imports",
"enablement": "typescript.native-preview.serverRunning",
"category": "TypeScript Native Preview"
}
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.

This is going to be awkward because even though tsgo is enabled, the main package's is still declared:

Image

Could we just register the command that the main extension is expecting? They shouldn't load when we are loaded and so on, so I think it might be possible.

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.

@copilot give it a try. Also format when you're done.

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.

Updated in 4c4a395 to register the same command IDs as the main extension: typescript.sortImports, javascript.sortImports, typescript.removeUnusedImports, and javascript.removeUnusedImports. Also matched apply: 'first' to be consistent with the main extension's behavior, and ran formatting.

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.

Just tested it. If you do that while useTsgo is off, you weirdly get

Activating extension 'TypeScriptTeam.native-preview' failed: command 'typescript.sortImports' already exists.

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 the main extension should just be updated.

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.

Do that @copilot

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.

Removed the command declarations from package.json in 67ea746. The commands are now only registered at runtime in session.ts, so there's no conflict with the main extension's declarations when useTsgo is off.

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.

If you disable this extension, the built-in extension will have issues:

rejected promise not handled within 1 second: Error: command 'typescript.sortImports' already exists

Seems like the command is not properly being unregistered.

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.

@copilot fix.

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.

Fixed in 87a11ca. The issue was that Session.dispose() was awaiting two setContext calls before disposing the command registrations. Those awaits yield control to the event loop, giving VS Code a chance to activate the built-in extension (which tries to register the same commands). Reordered to dispose registrations first — the d.dispose() calls in .map() run synchronously before any await yields.

…palette entries

Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/b3fccc6c-5163-4d72-8e28-b67bfc857ff2

Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
Copilot AI changed the title Add "Sort Imports" & "Remove Unused Imports" commands to VS Code extension Add "Sort Imports" &amp; "Remove Unused Imports" commands to VS Code extension Mar 31, 2026
Comment thread _extension/src/session.ts Outdated

for (const command of ["typescript.sortImports", "javascript.sortImports"]) {
this.disposables.push(vscode.commands.registerCommand(command, async () => {
await vscode.commands.executeCommand("editor.action.sourceAction", {
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 think you need to await, you can just make this non-async and return or fire-and-forget).

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.

Fixed in 67ea746 — handlers now just return the executeCommand call (non-async, fire-and-forget).

…sync

Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/7e5f78a1-e55d-424f-b346-df40585a513e

Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
@jakebailey jakebailey changed the title Add "Sort Imports" &amp; "Remove Unused Imports" commands to VS Code extension Add "Sort Imports" and "Remove Unused Imports" commands to VS Code extension Apr 6, 2026
…nt loop

Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/5fea471c-8900-4781-a94f-2c1368620df9

Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
1 pipeline(s) were filtered out due to trigger conditions.

Copilot AI changed the title Add "Sort Imports" and "Remove Unused Imports" commands to VS Code extension Add "Sort Imports" & "Remove Unused Imports" commands to VS Code extension Apr 15, 2026
Comment thread _extension/src/session.ts
Comment on lines +262 to +266
// Dispose registrations first so that commands (e.g. typescript.sortImports)
// are synchronously unregistered before yielding to the event loop. This
// avoids "command already exists" errors when the built-in TS extension
// activates after this extension is disabled.
await Promise.all(this.disposables.map(d => d.dispose()));
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 really understand how moving this upward achieves this goal.

@RyanCavanaugh RyanCavanaugh added this to the TypeScript 7.0 RC milestone Apr 17, 2026
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.

"Sort Imports" & "Remove Unused Imports" commands are missing

5 participants