mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 02:14:49 +00:00
typescript_vts: add initialization_options pass-through (#1507)
* typescript_vts: add initialization_options pass-through
Extends ls_specific_settings["typescript_vts"] with an optional
initialization_options key — a dict forwarded to vtsls via all three
LSP configuration channels:
- the initialize request (initializationOptions field),
- a workspace/didChangeConfiguration notification right after initialize,
- and responses to workspace/configuration pulls, looked up per section
(e.g. "typescript", "vtsls", "javascript", or dotted paths like
"typescript.tsdk").
All three channels are necessary because different parts of vtsls read
settings from different places — notably typescript.tsdk, which vtsls
pulls via workspace/configuration rather than reading from
initializationOptions. Without the pull-answer, setting tsdk had no
effect.
Primary use case: Yarn Plug'n'Play projects. Running
`yarn dlx @yarnpkg/sdks vscode` in the project root generates
.yarn/sdks/typescript/lib/tsserver.js, a PnP-aware tsserver. The user
then points vtsls at it with:
ls_specific_settings:
typescript_vts:
initialization_options:
typescript:
tsdk: "<...>/.yarn/sdks/typescript/lib"
vtsls:
autoUseWorkspaceTsdk: true
autoUseWorkspaceTsdk is required alongside tsdk because, in a headless
LSP context, there is no UI prompt to confirm switching to the
workspace TypeScript version. See yioneko/vtsls#169 for the recipe.
Default behaviour is unchanged — the field is optional, omitted from
the initialize params and didChangeConfiguration when unset or empty,
and workspace/configuration continues to answer empty sections.
This commit is contained in:
1 parent
9b292a6c8b
commit
7bf30080f6
3 files changed
+83
-10
No files matched your search
@@ -2,6 +2,12 @@
|
||||
|
||||
Status of the `main` branch. Changes prior to the next official version change will appear here.
|
||||
|
||||
* Language Servers:
|
||||
- `typescript_vts`: Add `initialization_options` setting in `ls_specific_settings.typescript_vts`.
|
||||
The dict is forwarded to vtsls via `initializationOptions`, `workspace/didChangeConfiguration`,
|
||||
and `workspace/configuration` pulls. Enables Yarn PnP setups with `typescript.tsdk` pointing
|
||||
at the Yarn-generated SDK.
|
||||
|
||||
# v1.5.3 (2026-05-26)
|
||||
|
||||
# v1.5.2 (2026-05-26)
|
||||
|
||||
@@ -1022,6 +1022,30 @@ Supported settings:
|
||||
|---|---|---|
|
||||
| `vtsls_version` | `0.2.9` | Override the `@vtsls/language-server` npm package version Serena installs. |
|
||||
| `npm_registry` | `null` | Override the npm registry Serena uses for the managed install. |
|
||||
| `initialization_options` | `null` | Dict forwarded to vtsls on three LSP channels: the `initializationOptions` field of the `initialize` request, a `workspace/didChangeConfiguration` notification sent right after initialize, and as the response to `workspace/configuration` pull requests (section-scoped). Typical use is Yarn PnP: point `typescript.tsdk` at the Yarn-generated SDK and enable `vtsls.autoUseWorkspaceTsdk`. |
|
||||
|
||||
Example (Yarn PnP project with TypeScript in a subdirectory; run `yarn dlx @yarnpkg/sdks vscode` in the project once to generate the SDK):
|
||||
|
||||
```yaml
|
||||
ls_specific_settings:
|
||||
typescript_vts:
|
||||
initialization_options:
|
||||
typescript:
|
||||
tsdk: "project/.yarn/sdks/typescript/lib"
|
||||
vtsls:
|
||||
autoUseWorkspaceTsdk: true
|
||||
```
|
||||
|
||||
vtsls reads `typescript.tsdk` through the `workspace/configuration` pull, not through `initializationOptions`, so Serena answers those pulls from the same dict (and also pushes it on `workspace/didChangeConfiguration` for compatibility with servers that expect the notification). Without `autoUseWorkspaceTsdk: true`, vtsls falls back to its bundled TypeScript and ignores `tsdk` (there is no UI prompt to confirm the switch in a headless LSP).
|
||||
|
||||
The dict is forwarded to vtsls verbatim — Serena does not validate its structure. For the list of supported keys and their expected types, refer to the vtsls [configuration schema](https://github.com/yioneko/vtsls/blob/main/packages/service/configuration.schema.json) and the underlying [VS Code TypeScript settings](https://code.visualstudio.com/docs/languages/typescript). `null` (the default) and `{}` are both treated as "unset": no `initializationOptions` are sent and no `workspace/didChangeConfiguration` notification is pushed. A non-dict value (e.g. a string or list) raises an error at server start.
|
||||
|
||||
**Troubleshooting:**
|
||||
|
||||
- *vtsls keeps using its bundled TypeScript and ignores `tsdk`* — ensure `vtsls.autoUseWorkspaceTsdk: true` is set alongside `typescript.tsdk`. Without it vtsls does not auto-switch to the workspace TS in a headless LSP.
|
||||
- *tsserver fails to start after pointing at a custom `tsdk`* — verify the path resolves to a directory containing `tsserver.js` (e.g. `.yarn/sdks/typescript/lib`, not `.yarn/sdks/typescript`). Relative paths are interpreted relative to the project root.
|
||||
- *Setting appears in `solidlsp` logs but vtsls does not react* — cross-check the key against the vtsls configuration schema linked above. The dict is forwarded as-is, so an unknown or wrong-typed key is silently ignored by vtsls.
|
||||
- *Need to inspect what Serena is actually forwarding* — the dict is logged at INFO level via the `Forwarding user-provided initializationOptions to vtsls: …` line at language server startup.
|
||||
|
||||
#### Vue
|
||||
|
||||
|
||||
@@ -34,7 +34,20 @@ DEFAULT_VTSLS_VERSION = "0.2.9"
|
||||
class VtsLanguageServer(SolidLanguageServer):
|
||||
"""
|
||||
Provides TypeScript specific instantiation of the LanguageServer class using vtsls.
|
||||
Contains various configurations and settings specific to TypeScript via vtsls wrapper.
|
||||
|
||||
Supported entries in ``ls_specific_settings["typescript_vts"]``:
|
||||
- ``vtsls_version``: version of ``@vtsls/language-server`` to install (default: ``"0.2.9"``).
|
||||
- ``npm_registry``: custom npm registry for the managed install.
|
||||
- ``initialization_options``: optional dict forwarded verbatim as LSP
|
||||
``initializationOptions``. Useful for Yarn PnP projects, e.g.::
|
||||
|
||||
initialization_options:
|
||||
typescript:
|
||||
tsdk: "project/.yarn/sdks/typescript/lib"
|
||||
vtsls:
|
||||
autoUseWorkspaceTsdk: true
|
||||
|
||||
See https://github.com/yioneko/vtsls/issues/169 for the PnP recipe.
|
||||
"""
|
||||
|
||||
def __init__(self, config: LanguageServerConfig, repository_root_path: str, solidlsp_settings: SolidLSPSettings):
|
||||
@@ -113,13 +126,30 @@ class VtsLanguageServer(SolidLanguageServer):
|
||||
assert os.path.exists(vts_executable_path), "vtsls executable not found. Please install @vtsls/language-server and try again."
|
||||
return f"{vts_executable_path} --stdio"
|
||||
|
||||
@staticmethod
|
||||
def _get_initialize_params(repository_absolute_path: str) -> InitializeParams:
|
||||
@property
|
||||
def _initialization_options(self) -> dict:
|
||||
"""
|
||||
Validated user-provided ``initializationOptions``.
|
||||
|
||||
:raises ValueError: if ``ls_specific_settings.typescript_vts.initialization_options``
|
||||
is set to a value that is not a dict.
|
||||
"""
|
||||
opts = self._custom_settings.get("initialization_options")
|
||||
if opts is None:
|
||||
return {}
|
||||
if not isinstance(opts, dict):
|
||||
raise ValueError(f"ls_specific_settings.typescript_vts.initialization_options must be a dict, got {type(opts).__name__}")
|
||||
return opts
|
||||
|
||||
def _get_initialize_params(self, repository_absolute_path: str) -> InitializeParams:
|
||||
"""
|
||||
Returns the initialize params for the VTS Language Server.
|
||||
|
||||
If ``initialization_options`` is set in ``ls_specific_settings["typescript_vts"]``,
|
||||
it is forwarded verbatim as LSP ``initializationOptions``.
|
||||
"""
|
||||
root_uri = pathlib.Path(repository_absolute_path).as_uri()
|
||||
initialize_params = {
|
||||
initialize_params: dict = {
|
||||
"locale": "en",
|
||||
"capabilities": {
|
||||
"textDocument": {
|
||||
@@ -152,6 +182,11 @@ class VtsLanguageServer(SolidLanguageServer):
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
if self._initialization_options:
|
||||
log.info("Forwarding user-provided initializationOptions to vtsls: %s", self._initialization_options)
|
||||
initialize_params["initializationOptions"] = self._initialization_options
|
||||
|
||||
return cast(InitializeParams, initialize_params)
|
||||
|
||||
def _start_server(self) -> None:
|
||||
@@ -179,12 +214,12 @@ class VtsLanguageServer(SolidLanguageServer):
|
||||
def execute_client_command_handler(params: dict) -> list:
|
||||
return []
|
||||
|
||||
def workspace_configuration_handler(params: dict) -> list[dict] | dict:
|
||||
# VTS may request workspace configuration
|
||||
# Return empty configuration for each requested item
|
||||
if "items" in params:
|
||||
return [{}] * len(params["items"])
|
||||
return {}
|
||||
init_options = self._initialization_options
|
||||
|
||||
def workspace_configuration_handler(params: dict) -> list[object]:
|
||||
# vtsls pulls settings for sections like "typescript", "vtsls", "javascript".
|
||||
# Return the matching sub-dicts from the user-provided initialization_options.
|
||||
return [init_options.get(item.get("section", ""), {}) for item in params["items"]]
|
||||
|
||||
def do_nothing(params: dict) -> None:
|
||||
return
|
||||
@@ -227,6 +262,14 @@ class VtsLanguageServer(SolidLanguageServer):
|
||||
log.debug(f"completionProvider: {init_response['capabilities']['completionProvider']}")
|
||||
|
||||
self.server.notify.initialized({})
|
||||
|
||||
# vtsls also reads settings via workspace/didChangeConfiguration (in addition
|
||||
# to initializationOptions and workspace/configuration pulls). Push the same
|
||||
# user-provided settings on all three channels for maximum compatibility,
|
||||
# e.g. so that `typescript.tsdk` is honoured for Yarn PnP projects.
|
||||
if init_options:
|
||||
self.server.notify.workspace_did_change_configuration({"settings": init_options})
|
||||
|
||||
if self.server_ready.wait(timeout=1.0):
|
||||
log.info("VTS server is ready")
|
||||
else:
|
||||
|
||||
Reference in new issue
Block a user