Skip to content

Vue LS: honour ls_path/ls_base_cmd and require npm only for installing - #2177

Open
karajanchang wants to merge 1 commit into
oraios:mainfrom
karajanchang:vue-ls-path-override
Open

karajanchang wants to merge 1 commit into
oraios:mainfrom
karajanchang:vue-ls-path-override

Conversation

@karajanchang

Copy link
Copy Markdown

Summary

Fixes #2176 (fixes 1 and 2 from that issue).

VueLanguageServer resolves its runtime dependencies in _setup_runtime_dependencies before
SolidLanguageServer.__init__ runs, so the generic ls_path / ls_base_cmd overrides from
LanguageServerDependencyProviderBaseCommand never apply to Vue. As a result, the only way to reuse an
existing installation is to recreate the internal vue-lsp/ layout and write a matching
.installed_version marker. On top of that, npm is required even when nothing has to be installed.

Changes

  1. ls_path / ls_base_cmd for Vue. If either is set in ls_specific_settings["vue"], Serena
    uses it as the base command (--stdio is appended, as in the managed case), installs nothing, and
    requires neither node nor npm. Vue also has to know where its companion pieces are, so three
    settings go with it:

    • ts_ls_path: the typescript-language-server executable
    • tsdk_path: the TypeScript lib directory (also used for the tsserver pin in untrusted projects)
    • vue_plugin_path: the @vue/typescript-plugin directory

    If any of them is missing, a SolidLSPException lists them by name. Silently falling back to the
    managed paths would bring the npm install back, and with it the problem being fixed.
    Precedence matches the generic provider: ls_base_cmd (must be a list, otherwise warned about and
    ignored) wins over ls_path.

  2. npm only for installing. For the managed installation, node is still checked up front (the
    shims need it to run), but npm is only checked once needs_install is true. Both checks now raise
    SolidLSPException instead of using assert, which is skipped under python -O.

To carry the extra path, _setup_runtime_dependencies now returns a small frozen VueRuntimePaths
dataclass instead of a 3-tuple. @vue/typescript-plugin was previously derived from the managed
directory inside _start_typescript_server; it is now part of the resolved paths, which also lets
self._vue_ls_dir go. The managed code path behaves the same as before: same directory layout, same
.installed_version marker, same defaults.

Not changed

  • The .installed_version format and the default versions.
  • VueTypeScriptServer (it already took explicit paths through its constructor).

Testing

New test/solidlsp/vue/test_vue_runtime_dependencies.py. It needs no node, npm or network: shutil.which
and RuntimeDependencyCollection.install are monkeypatched, and installs are recorded so the tests can
check that none happened.

  • ls_path with all companion paths → the expected VueRuntimePaths, no install, no node/npm
  • ls_base_cmd takes precedence over ls_path
  • ls_path with companion paths missing → SolidLSPException that names the missing keys
  • up-to-date managed install + node present + npm absent → resolves, no install
  • outdated managed install + npm absent → SolidLSPException ("npm is not installed"), no install
  • managed install + node absent → SolidLSPException
pytest test/solidlsp/vue/test_vue_runtime_dependencies.py test/solidlsp/test_jsx_language_ids.py
39 passed

Run against unmodified main, the new test module fails at collection (VueRuntimePaths does not
exist yet).

poe format, poe lint and poe type-check pass. ty reports one existing warning, an unused
ty: ignore at src/serena/dashboard.py:1078. That file is not touched by this PR.

End-to-end on macOS (arm64), against a real Vue LS:

  • I pointed ls_path, ts_ls_path, tsdk_path and vue_plugin_path at an existing install
    (@vue/language-server 3.1.5, TypeScript 5.9.3, typescript-language-server 5.1.3).
  • PATH held only node. npm was not on PATH at all.
  • I requested document symbols for test/resources/repos/vue/test_repo/src/App.vue.
npm = None node = .../node
SYMBOLS 21 ['appTitle', 'appVersion', 'computed() callback', 'greetingMessage', 'computed() callback', 'hour']
managed vue-lsp dir created: False

CHANGELOG.md has an entry under Unreleased → Language Servers.

Generated with MUR

Comment on lines +563 to +571
base_cmd = vue_config.get("ls_base_cmd")
if base_cmd is not None and not isinstance(base_cmd, list):
log.warning("The 'ls_base_cmd' setting should be a list of strings. Ignoring the provided value: %s", base_cmd)
base_cmd = None
if base_cmd is None:
ls_path = vue_config.get("ls_path")
if ls_path is None:
return None
base_cmd = [ls_path]

@opcode81 opcode81 Oct 19, 2026 •

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.

ls_path and ls_base_cmd support are not supposed to be implemented directly in a language server wrapper. Instead, they are centrally provided via LanguageServerDependencyProviderBaseCommand and its subclasses.
The Vue language server is an old implementation which predates the introduction of the LanguageServerDependencyProvider abstraction. To add these features, the implementation should be refactored to use a dependency provider instead of adding custom management here.

See also: memory adding_new_language_support_guide

@opcode81 opcode81 added the waiting for OP The maintainers are waiting for a response/further action from the original poster/creator. label Oct 19, 2026

This branch has not been deployed

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

Labels

waiting for OP The maintainers are waiting for a response/further action from the original poster/creator.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Vue LS: ls_path / ls_base_cmd are ignored, and an install can only be reused by forging .installed_version

2 participants