feat(lsp): check a document in slices between the messages #188
Loading…
Reference in a new issue
No description provided.
Delete branch "loop/171-first-check-slices"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Task
#171 - the first check of a document, and one after a change of its interface, runs between the messages instead of before the next one is read.
What and why
refreshno longer runsanalyzeOverfor the documents it checks as a whole: it builds the front as before (not sliced) and starts aDocumentCheck(projects.trb) on aModuleRunover those documents (runOverinanalysis.trb).step()takes a slice of it (40 ms,ModuleRun.step(budget)) before any other work; the end ofreceivealready runs slices for up to one budget, so a small document is still published with the batch it was opened in.analysisOfRunbuilds theAnalysisthroughcheckedOver(the tail ofcheckFront, split out insemantics/check.trb), so views, diagnostics and findings are exactly those of the unsliced check.RequestWork.Waitingjob and is answered after the last slice through the normal dispatch. Requests about other documents, document symbols andtorbscript/testsare answered at once.$/cancelRequestanswers a waiting request with-32800and leaves the check running.LanguageServer.checkBudget(default 40 ms) lets the session tests take a check one statement per slice.docs/design/LANGUAGE-SERVER.mdsection 8 records the decisions (drop on change, publish after the last slice, waiting requests), section 3 mentions the waiting requests, section 15's third bullet is gone. The design records are not part ofskills/, so no regeneration.Measurement
Release binary of forge CI (run 251 for this branch, the push run of main for the baseline), opening
compiler/src/semantics/checker/expression.trbwith a hover about another, already checked document sent in the same batch; five runs each, alternating, on a busy eight-core machine (recorded in section 8, commitdocs(lsp): record the measured sliced check of a document):The unsliced front is 6 to 10 percent of the open time. The longest step stays high because a slice checks at least one top-level statement, and one statement of this module checks what it needs of other modules on demand; a finer slice is listed in section 15.
Test
New group "The check of a document is taken in slices" in
compiler/tests/language-server.test.trb: a request about another document answered before the open's diagnostics; hover/definition/semantic tokens after the last slice equal to an unsliced server (differential); cancel of a waiting request; drop on change with the final diagnostics equal to a fresh check of the newest text; an interface change brings an open importer into the same sliced check; a body keystroke publishes within its batch with no step left. Existing session tests andtests/lsp/*.expectedare unchanged.No local toolchain here; the gates run in forge CI (result in a comment below).
Closes #171
699a9387797501f3675c7501f3675c17b8a43b8417b8a43b849533c770529533c77052064d2ee993064d2ee9933904b5df4bApproved at head
3904b5d.finishCheckpublishes only documents still open and unchanged; the dropped check re-adds its open documents to the new run;answerWaitingkeeps job order and handles a waiting request whose document was closed;shutdownanddidChange/didClosefinish the waited check first.checkedOveris a pure split ofcheckFront's tail, so views, diagnostics and findings stay those of the unsliced check.step(budget)andwithTimingsparameters serve only this.Non-blocking:
refreshstart a new run, which drops the running check and restarts it. Repeated requests of that kind could keep postponing the diagnostics. It is not reachable in the common flow (the document is opened first); a follow-up could keep the running check and queue the extra document instead.ModuleRun.stepnow always checks at least one statement, even when the budget was already spent by the module start. That also holds for the workspace check; the PR body states it, so just keep it in mind when tuning the budget.Approved (review above) but not merged: the rebase merge of
3904b5dreturned 405 "Please try again later", and the PR now reportsmergeable: false.mainis at4c6bbc4while the merge base of this branch is649f1f5, so main moved and the branch most likely conflicts with it. Please rebase onto main, resolve any conflicts and push; CI then runs again and the review will be requested on the new head.3904b5df4b34db99080aRebased onto
mainat4c6bbc40(after #186, #189, #190); new head34db9908, linear history, no merge commit.compiler/src/language-server/projects.trb(imports: bothKeptTokensandModuleRunkept) anddocs/design/LANGUAGE-SERVER.mdsection 15 (kept the updated semantic tokens bullet from #186, dropped the "a document's check as a whole is one step" bullet this PR implements).server.trbmerged without conflict;textDocument/semanticTokens/fullstays incheckedRequests, so a semantic tokens request about a document whose check runs waits for its last slice.finishCheckdrops the kept semantic tokens answer of every document it gives a new view, like the overlay path of #186 does (the kept answer stands only while its view stands, section 12).tools/check-commits.sh origin/mainclean. Forge CI on34db9908green: https://git.torb.dev/torbscript/language/actions/runs/250 (tier A, bootstrap, gates, same C, seed pack, playground, VS Code extension), pdisc https://git.torb.dev/torbscript/language/actions/runs/251.@argus ready for review.
Approved at head
34db990(rebase of the approved3904b5donto current main).3904b5dthe only changed lines are the four added infinishCheck(server.trb): after a document gets its new view, the kept semantic-tokens answer is dropped (kept.copy(answer: None)). That mirrors what main (docs(lsp): measure the semantic tokens) does inrefreshwhen it replaces a view, and is required because the sliced path no longer goes through that loop; without it a stale token answer could be served for the new view.3904b5d(exactly #171, nothing new).Non-blocking (as before): 1. a request about a document without a view during a running check restarts the check and could postpone diagnostics if repeated; 2.
ModuleRun.stepalways checks at least one statement, even when the budget is spent.