Skip to content

lsp-mode ignores scopeUri in workspace/configuration requests #4857

@nelhage

Description

@nelhage
  • I am using the latest version of lsp-mode related packages.
  • I checked FAQ and Troubleshooting sections
  • You may also try reproduce the issue using clean environment using the following command: M-x lsp-start-plain

Bug description

The LSP workspace/configuration RPC (from server to client) passes a list of ConfigurationItems, which contain a scopeUri and a section (spec link).

When handling workspace/configuration RPCs, lsp-mode ignores the scopeUri, and selects an arbitrary buffer associated with the workspace, which will then govern the settings of buffer-local variables when computing the configuration:

lsp-mode/lsp-mode.el

Lines 7040 to 7046 in 11f7b17

((equal method "workspace/configuration")
(with-lsp-workspace workspace
(if-let* ((buf (car buffers)))
(lsp-with-current-buffer buf
(lsp--build-workspace-configuration-response params))
(lsp--with-workspace-temp-buffer (lsp--workspace-root workspace)
(lsp--build-workspace-configuration-response params)))))

However, multi-root servers (I debugged this using Pyright / lsp-pyright) may wish to configure configuration per-root, instead of per-workspace. For Pyright, for instance, each root may configure a different Python path or different virtual environment. Thus, if a scopeUri is present, it is important that we select a buffer (if possible) which is actually located under that scope, in order to find the correct configuration.

Steps to reproduce

Create an example root with two Python virtual environments, like so:

mkdir /tmp/python-envs
cd /tmp/python-envs
mkdir root_a root_b
python -m venv root_a/venv
python -m venv root_b/venv
touch root_a/main_a.py root_b/main_b.py

Configure root_a/ and root_b/ as separate roots, open both buffers, and start lsp-mode in both.

Expected behavior

I expect to see root_a and root_b passing in their respective configuration (python.pythonPath) pointing at their own virtual environments, as seen in their buffer-local variables:

(with-current-buffer "main_a.py"
  (lsp-pyright-locate-python))
"/tmp/python-envs/root_a/venv/bin/python"

(with-current-buffer "main_b.py"
  (lsp-pyright-locate-python))
"/tmp/python-envs/root_b/venv/bin/python"

However, looking at the LSP server log, I see identical configuration being passed for each:

[Trace - 12:22:03 p.m.] Received request 'workspace/configuration - (1).
Params: {
  "items": [
    {
      "scopeUri": "file:///tmp/python-envs/root_b",
      "section": "python"
    }
  ]
}


[Trace - 12:22:03 p.m.] Sending response 'workspace/configuration - (1)'. Processing request took 0ms
Params: {
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "analysis": {
        "diagnosticSeverityOverrides": {},
        "typeCheckingMode": "standard",
        "autoImportCompletions": true,
        "diagnosticMode": "openFilesOnly",
        "logLevel": "info",
        "autoSearchPaths": true,
        "extraPaths": []
      },
      "pythonPath": "/tmp/python-envs/root_a/venv/bin/python",
      "venvPath": ""
    }
  ]
}


[Trace - 12:22:03 p.m.] Received request 'workspace/configuration - (2).
Params: {
  "items": [
    {
      "scopeUri": "file:///tmp/python-envs/root_a",
      "section": "python"
    }
  ]
}


[Trace - 12:22:03 p.m.] Sending response 'workspace/configuration - (2)'. Processing request took 0ms
Params: {
  "jsonrpc": "2.0",
  "id": 2,
  "result": [
    {
      "analysis": {
        "diagnosticSeverityOverrides": {},
        "typeCheckingMode": "standard",
        "autoImportCompletions": true,
        "diagnosticMode": "openFilesOnly",
        "logLevel": "info",
        "autoSearchPaths": true,
        "extraPaths": []
      },
      "pythonPath": "/tmp/python-envs/root_a/venv/bin/python",
      "venvPath": ""
    }
  ]
}

Which Language Server did you use?

lsp-pyright

OS

Linux

Error callstack

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions