Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dafny language server resolves program character by character (even with option onsave) #1448

Closed
mschlaipfer opened this issue Sep 20, 2021 · 3 comments · Fixed by #1456
Closed
Labels
kind: enhancement Enhancements, feature requests, etc. These are NOT bugs, but ways we can improve Dafny part: language server Support for LSP in Dafny (server part; client is in ide-vscode repo)

Comments

@mschlaipfer
Copy link
Member

When adding a precondition, say requires foo.bar(x) the language server resolves the file for the following versions of that line:

  • f
  • fo
  • foo
  • foo.b
  • ...

each of which takes a while (maybe about a second each), until finally the program with the full line can be resolved and verification is performed.

This is with the option onsave of the VSCode extension.

DafnyLS: 3.2.0.30713
VSCode extension: 1.8.0

@mschlaipfer mschlaipfer added the part: language server Support for LSP in Dafny (server part; client is in ide-vscode repo) label Sep 20, 2021
@keyboardDrummer
Copy link
Member

@camrein do you know if the LSP server will queue a parsing+resolution task for each textDocument/didChange request it receives? If so, can we make the queue have a maximum size of one, so only the latest code is analysed?

I know there is some batching of changes on the client side. I vaguely recall it sends out a didChange if there's no more edits for 200 ms, but since a parse+resolution task may take more than 200 ms, it's still possible that these tasks could get queued on the server.

The behavior that I think might be nice is:

User does:

  • type 'A' and wait 200ms
  • type 'B' and wait 200ms
  • type 'C' and wait 200ms

Server does:

  • Receive didChange for 'A' and start analysing 'A'
  • Receive didChange for 'B' and queue the analysis of 'AB'
  • Receive didChange for 'C', queue the analysis of 'ABC' and drop the analysis of 'AB'
  • Finish the analysis of 'A', start analysis of 'ABC'.

@camrein
Copy link
Member

camrein commented Sep 21, 2021

This issue is closely related to dafny-lang/ide-vscode#31.

@camrein do you know if the LSP server will queue a parsing+resolution task for each textDocument/didChange request it receives? If so, can we make the queue have a maximum size of one, so only the latest code is analysed?

All document related events (for example change/save/open/close) are synchronous/serial. See for example DidChangeTextDocumentParams.
If any request is processed on a handler with the Serial-Attribute, it blocks all other requests - including the ones with the Parallel-Attribute. Unfortunately, I don't know how this mechanic is achieved in the LSP library behind the scenes. I.e., if there's a queue or that it simply blocks the input (that'd be stdin for Dafny VSCode).

I have the feeling that we have to implement this behavior ourselves. But there are a few challenges we have to keep in mind:

  • Offload any incoming document events into a separate task/document queue. That way, we can complete the document request immediately; thus, new changes can be received.
  • The event in the task/queue will then be processed, if not overtaken by a newer event (ABC will be processed in place of AB as in your example). If a change is overtaken, we have to process the change but can leave parsing/resolution/verification aside.
  • Since all other queries such as hover can now run concurrently to the document updates, we have to make sure that these queries happen on the correct document version.

Maybe we could combine it with a debouncing of the automatic verification in a later iteration.

@keyboardDrummer
Copy link
Member

keyboardDrummer commented Sep 21, 2021

If any request is processed on a handler with the Serial-Attribute, it blocks all other requests

I'm guessing that if you process the request in a fresh thread then the block is lifted. For example by adding the request data to a thread-safe queue and then letting a worker thread manage it.

But there are a few challenges we have to keep in mind...

One option is to merge consecutive textDocument/didChange requests, and otherwise process the requests sequentially, where processing a didChange request also includes computing diagnostics.

Another option might be to cancel any currently running analysis, including computing diagnostics, as soon as a didChange comes in, so we never do processing on an out of date document state.

@robin-aws robin-aws added the kind: enhancement Enhancements, feature requests, etc. These are NOT bugs, but ways we can improve Dafny label Sep 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: enhancement Enhancements, feature requests, etc. These are NOT bugs, but ways we can improve Dafny part: language server Support for LSP in Dafny (server part; client is in ide-vscode repo)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants