Skip to content

TypeScript 7 VS Code extension: closing JSX tags are not inserted in content-mapped files, although tsc --lsp provides them #64564

Description

@leonidaz

In a content-mapped file, typing > after an opening JSX tag does not insert the closing tag, while the same keystroke in a .tsx file does. The language server supports it: textDocument/_vs_onAutoInsert for the content-mapped file returns the closing tag. The extension never sends that request for content-mapped files.

Repro: https://gist.github.com/leonidaz/a09cfe652d708cda59e20a112e879307, a 47-line identity content mapper (.foo files contain TSX and are returned unchanged as .tsx). TypeScript 7 extension 1.0.1, typescript@7.1.0-dev.20260930.4 through js/ts.tsdk.path, VS Code 1.140.0, macOS.

In VS Code

Type <b> between <div> and </div>:

File Hover on card After typing <b>
type-here.tsx const card: any <div><b></b></div>
type-here.foo const card: any <div><b></div>

The server log shows one textDocument/_vs_onAutoInsert, sent while typing in the .tsx file, and none for the .foo file.

The server supports it

npm run ask sends tsc --lsp the request the extension sends on >, right after <b> in card.foo and in control.tsx (both contain export const card = <div><b></div>;):

card.foo: {"_vs_textEditFormat":2,"_vs_textEdit":{"range":{"start":{"line":0,"character":28},"end":{"line":0,"character":28}},"newText":"$0</b>"}}
control.tsx: {"_vs_textEditFormat":2,"_vs_textEdit":{"range":{"start":{"line":0,"character":28},"end":{"line":0,"character":28}},"newText":"$0</b>"}}

Cause

packages/vscode-typescript/src/client.ts says content-mapped files are covered (L76-L78):

These augment the static jsTs document selector so the extension's custom language-feature providers (hover, multi-document highlight, on-auto-insert) also cover content-mapped files.

but registerSelectorScopedFeatures() registers only multi-document highlight and hover (L375-L387), and on-auto-insert is registered once with the static selector (L317):

registerOnAutoInsertFeature(this.documentSelector, this.client),

The published 1.0.1 does the same.

Suggested fix

Register on-auto-insert in registerSelectorScopedFeatures() with the selector-scoped selector, like hover. Its requireActiveDocumentSetting condition already matches the active document against the selector it is given. Happy to open a PR.

For mappers that generate code rather than copy it, the server offers the tag only when the generated JSX is still unclosed at the mapped position and the span carries FeatureAutoInsert; that part already works.

Found while adding TypeScript 7 support for .tsrx files through a content mapper (tsrx-org/tsrx#135).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions