microsoft / microsoft/typespec

Migrate typespec-vscode language client from push to pull configuration model

Open
#11,829 0 comments 1 reaction 0 assignees View on GitHub
ide
Dominant language
Java
Stars
5.9k
Forks
394
Avg merge
1d 23h
Merged PRs (30d)
104

Description

## Context

`packages/typespec-vscode/src/tsp-language-client.ts` uses the deprecated `synchronize.configurationSection` option of `vscode-languageclient` (LSP "push" configuration model):

```ts
const options: LanguageClientOptions = {
synchronize: {
// oxlint-disable-next-line typescript/no-deprecated
configurationSection: "typespec",
fileEvents: watchers,
},
...
};
```

This surfaced as a deprecation warning after the `vscode-languageclient` bump in #11643. Migrating to the "pull" configuration model was left out of that dependency-update PR (the `oxlint-disable` remains) and is tracked here.

## What's actually deprecated

Only the LSP *push* model via `synchronize.configurationSection`. The server (`packages/compiler/src/server/client-config-provider.ts`) **already uses the pull API** for the initial load:

```ts
const configs = await connection.workspace.getConfiguration("typespec"); // already pull
```

The only piece depending on the deprecated push is the change-notification handler, which reads the pushed payload:

```ts
connection.onDidChangeConfiguration((params) => { config = params.settings?.typespec; });
```

Config is consumed read-only in two spots in `compile-service.ts` (`config?.lsp?.emit` and `config?.entrypoint`); those are unaffected.

## Proposed migration

1. **`tsp-language-client.ts`** — remove `configurationSection: "typespec"` (and its comments / `oxlint-disable`); keep `fileEvents: watchers`.
2. **`server.ts` `onInitialize`** — capture `params.capabilities.workspace?.didChangeConfiguration?.dynamicRegistration`.
3. **`client-config-provider.ts`** — when that capability is present, register for change notifications in the pull model:
```ts
connection.client.register(DidChangeConfigurationNotification.type, { section: "typespec" });
```
Registering *with* the section means `vscode-languageclient` still sends `params.settings.typespec`, so the existing `onDidChangeConfiguration` handler keeps working. (Alternatively, register section-less and re-pull via `getConfiguration("typespec")` inside the handler.)

This is the first dynamic `client.register` in the server, so guard it behind the capability so non-VS-Code consumers (playground / standalone CLI) don't error.

## Testing

There are no automated tests for the config-sync path, so this needs manual verification in the VS Code extension:
- Settings load correctly on server startup.
- Settings live-update on change (e.g. toggling `typespec.lsp.emit`).
- Non-VS-Code language-server consumers still initialize without errors.

## References

- Deprecated usage: `packages/typespec-vscode/src/tsp-language-client.ts` (`configurationSection`)
- Server side: `packages/compiler/src/server/client-config-provider.ts`
- Introduced/deferred in #11643

Contributor guide

Open the contributing guide

Research direction

Read packages/typespec-vscode/src/tsp-language-client.ts, packages/compiler/src/server/server.ts, and packages/compiler/src/server/client-config-provider.ts, starting with the existing pull-based configuration load and change handler. Follow the onInitialize capability data through the server configuration provider. Done means VS Code settings load and update live, while playground and standalone CLI consumers still initialize without errors; verify these manually in the extension.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript, vscode
Domain
developer-experience, devtools
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.