From d4dbcecaae24b4b4994b558b92083dfe960c4fe5 Mon Sep 17 00:00:00 2001 From: aayushbaluni <73417844+aayushbaluni@users.noreply.github.com> Date: Mon, 17 Aug 2026 11:39:28 +0530 Subject: [PATCH] fix(clojure): declare didChangeWatchedFiles client capability Serena notifies language servers about files changed outside its own edit tools (a git checkout, another editor, a build step) by sending workspace/didChangeWatchedFiles from LanguageServerManager.poll_and_notify, whose docstring names this exact case: such edits are 'otherwise invisible to a warm language server, causing symbolic queries to answer from a stale index'. ClojureLSP never declared the corresponding client capability, so clojure-lsp was not told those notifications are sent and need not treat them as a reason to invalidate its analysis. DefaultInitializeParamsBuilder does not supply a default capabilities block, so nothing filled this in on the server's behalf. Relates to #1593, where find_symbol returned a body from a comment mentioning the symbol rather than its definition, at a position the symbol had previously occupied. --- CHANGELOG.md | 4 ++ src/solidlsp/language_servers/clojure_lsp.py | 6 +++ .../clojure/test_clojure_initialize_params.py | 42 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 test/solidlsp/clojure/test_clojure_initialize_params.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 161709e7..bba1abc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ Status of the `main` branch. Changes prior to the next official version change w * Language Servers: - Fix: Dart's `$/analyzerStatus` notifications were logged as unhandled-method warnings during analysis (#1855) + - Fix: clojure-lsp was not told that Serena sends `workspace/didChangeWatchedFiles`, so changes made + outside Serena's own edit tools (a git checkout, another editor, a build step) need not invalidate + its analysis; symbol queries could then answer from a stale index, e.g. `find_symbol` returning a + body from the position the symbol used to occupy (#1593) - Fix: Scala cross-file queries waited a fixed 5s after the first file was opened, which on a cold Metals is long before its build import, indexing and compilation have finished; the first `find_referencing_symbols` of a session could return a fraction of the references with nothing to diff --git a/src/solidlsp/language_servers/clojure_lsp.py b/src/solidlsp/language_servers/clojure_lsp.py index a8cb9d83..41851a03 100644 --- a/src/solidlsp/language_servers/clojure_lsp.py +++ b/src/solidlsp/language_servers/clojure_lsp.py @@ -325,6 +325,12 @@ class ClojureLSP(SolidLanguageServer): "workspace": { "applyEdit": True, "workspaceEdit": {"documentChanges": True}, + # Serena notifies language servers about files changed outside its own + # edit tools (git checkout, another editor, a build step) via + # workspace/didChangeWatchedFiles; see LanguageServerManager.poll_and_notify. + # Without declaring the capability, clojure-lsp is not told the client + # sends those notifications and may keep answering from its stale analysis. + "didChangeWatchedFiles": {"dynamicRegistration": True}, "symbol": {"symbolKind": {"valueSet": list(range(1, 27))}}, "workspaceFolders": True, }, diff --git a/test/solidlsp/clojure/test_clojure_initialize_params.py b/test/solidlsp/clojure/test_clojure_initialize_params.py new file mode 100644 index 00000000..54538309 --- /dev/null +++ b/test/solidlsp/clojure/test_clojure_initialize_params.py @@ -0,0 +1,42 @@ +import pytest + +from solidlsp.language_servers.clojure_lsp import ClojureLSP + +pytestmark = pytest.mark.clojure + + +def _make_server(monkeypatch: pytest.MonkeyPatch) -> ClojureLSP: + """Build a ClojureLSP without running __init__ (no clojure-lsp binary needed).""" + server = object.__new__(ClojureLSP) + monkeypatch.setattr(ClojureLSP, "_resolve_source_paths", lambda _self: None) + return server + + +def test_declares_did_change_watched_files_capability(monkeypatch: pytest.MonkeyPatch) -> None: + """clojure-lsp must announce that the client sends workspace/didChangeWatchedFiles. + + Serena notifies language servers about files changed outside its own edit tools + (git checkout, another editor, a build step) via that notification + (LanguageServerManager.poll_and_notify). A server that was never told the client + supports it may keep answering symbol queries from its own stale analysis, which + surfaces as find_symbol returning a body from the wrong location. + """ + params = _make_server(monkeypatch)._create_base_initialize_params() + + workspace = params["capabilities"]["workspace"] + assert "didChangeWatchedFiles" in workspace, ( + "clojure-lsp does not declare the didChangeWatchedFiles client capability, so external file changes may not invalidate its analysis" + ) + assert workspace["didChangeWatchedFiles"]["dynamicRegistration"] is True + + +def test_base_initialize_params_keep_existing_workspace_capabilities( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """The added capability must not displace the ones already relied upon.""" + workspace = _make_server(monkeypatch)._create_base_initialize_params()["capabilities"]["workspace"] + + assert workspace["applyEdit"] is True + assert workspace["workspaceEdit"] == {"documentChanges": True} + assert workspace["workspaceFolders"] is True + assert workspace["symbol"]["symbolKind"]["valueSet"] == list(range(1, 27))