Repository navigation
Conversation
…outdated ones The workspace keeps documents as Arc<Document>: requests clone the Arc and release the lock, and an edit copies the document if a request still uses it. The copy shares the document's cache, whose key-dependent entries are tagged with the generation of the content, so a request on an outdated version neither reads nor writes them. The walk and the analysis check every 64 statements whether the document changed or the request was cancelled (pgls_workspace::cancellation) and stop without caching anything. The language server runs hover, inlay hints, semantic tokens, completions, code actions and formatting on the blocking pool, cancels them when tower-lsp drops their future, and answers ContentModified when the document changed meanwhile. Diagnostics run on the blocking pool.
…ncellable # Conflicts: # crates/pgls_workspace/src/workspace/server.rs # crates/pgls_workspace/src/workspace/server/document.rs # crates/pgls_workspace/src/workspace/server/document_cache.rs
This was referenced Oct 26, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #1007. Part of the rebuild described in #997 (point 6). Replaces #931, #954 and #961.
The handlers for hover, inlay hints, semantic tokens, completions, code actions and formatting ran synchronously inside their
async fns on the tokio workers, and the workspace held the read lock of all documents for the whole request.change_fileneeds the write lock, so a request that took seconds on a long file delayed the next keystroke by as much, and$/cancelRequestcouldn't stop anything.Documents as
Arcs, with one cacheArc<Document>. Every request clones theArcand releases the lock right away (WorkspaceServer::document).change_fileusesArc::make_mut, so it copies the document if a request still works on the previous version. The copy shares the document's cache (Arc<DocumentCache>): the parse results and trees are keyed by statement text, so sharing them is correct.generation, whichupdate_contentincrements. A request on a previous generation neither reads nor writes them: it gets an empty cache for its walk, and its analysis isn't stored. Without that, a request that finished on an outdated version would leave its checkpoints in the cache of the new one.Stopping outdated and cancelled requests
pgls_workspace::cancellation(from perf(lsp): stop cancelled requests, and run diagnostics, completions and formatting off the runtime #954):with_cancellation(flag, f)sets a flag for the thread that runsf.pgls_analyser::walk_statementstakesshould_stopand checks it everySTOP_CHECK_INTERVAL = 64statements, and so doesAnalyser::analyse_until(analysenever stops). The workspace passes "the request was cancelled, or the document changed" (WorkspaceServer::should_stop), and checks it as often while collecting the statements before a walk or an analysis.pull_file_diagnosticsreturns nothing and skips the database checks, and the lint code actions are empty. The CLI never stops: its documents don't change and nothing cancels its requests.lsp-proxy, which only copies bytes to the daemon, and the daemon runs the language server with the workspace in its own process (perf(workspace): stop stale diagnostics, lint code actions and completions early #961).--use-serverCLI commands go through a transport and are not cancelled.The language server
LSPServer::run_document_requestruns a handler withspawn_blockingunder a cancellation flag that is set when tower-lsp drops the request's future, whether it finished or was cancelled. If the document's version changed while it ran, it answersContentModified(-32801), which tells the client to ask again instead of showing outdated results. Hover, inlay hints, semantic tokens (full and range), completions, code actions and formatting (full and range) go through it.Timings
Release build, the benchmark of #1005: an edit while a cold full semantic tokens request runs on the same document, on another thread.
change_fileduring the request,mainmainOn
main,change_filewaited for the read lock until the request finished.Tests
cancellation: the flag applies while the request runs, nests, and is restored.analysis_stops_when_asked(analyser): 200 statements, asked to stop at the second check, it returns the 127 statements before it andstopped.clones_only_see_the_cache_of_their_content(document): a clone shares the cache, but a request on the previous generation neither reads nor writes the entries of the new one.test_editor_requests_use_document_snapshots: a document taken before an edit keeps its content, its walk stops and leaves nothing in the cache, and a walk of the current document resolves everything.test_cancelled_requests_stop_walkingandtest_cancelled_analysis_stops: under a cancelled flag, semantic tokens, diagnostics and the lint code actions of a 200-statement file are empty (the code actions use the cached analysis while it is valid); without it they're all there.pgls_workspace(including the memory and edit-churn tests),pgls_analyserandpgls_lsppass, and clippy on the whole workspace.Not covered
$/cancelRequest: the test client can't send a notification while it awaits a request. The flag is tested at the workspace level.pgls_completions::completeitself works on one statement and isn't interrupted.