feat: specify version in waitForDiagnostics

This commit is contained in:
Wojciech Nawrocki 2021-01-21 14:43:30 -05:00 committed by Sebastian Ullrich
parent b9cc6a709f
commit d9c6a992b5
8 changed files with 32 additions and 19 deletions

View file

@ -8,20 +8,22 @@ import Lean.Data.Json
import Lean.Data.JsonRpc
import Lean.Data.Lsp.Basic
/-
/-!
This file contains Lean-specific extensions to LSP.
The following additional packets are supported:
- "textDocument/waitForDiagnostics": Yields a response when all the diagnostics that were pending at the time of
arrival of the packet have been emitted. Exists for synchronization purposes, e.g. during testing or when external tools might want to use
our LSP server.
- "textDocument/waitForDiagnostics": Yields a response when all the diagnostics for a version of the document
greater or equal to the specified one have been emitted. If the request specifies a version above the most
recently processed one, the server will delay the response until it does receive the specified version.
Exists for synchronization purposes, e.g. during testing or when external tools might want to use our LSP server.
-/
namespace Lean.Lsp
open Json
structure WaitForDiagnosticsParam where
uri : DocumentUri
structure WaitForDiagnosticsParams where
uri : DocumentUri
version : Nat
deriving ToJson, FromJson
structure WaitForDiagnostics

View file

@ -50,9 +50,9 @@ def waitForExit : IpcM UInt32 := do
/-- Waits for the worker to emit all diagnostics for the current document version
and returns them as a list. -/
partial def collectDiagnostics (waitForDiagnosticsId : RequestID := 0) (target : DocumentUri)
partial def collectDiagnostics (waitForDiagnosticsId : RequestID := 0) (target : DocumentUri) (version : Nat)
: IpcM (List (Notification PublishDiagnosticsParams)) := do
writeRequest ⟨waitForDiagnosticsId, "textDocument/waitForDiagnostics", WaitForDiagnosticsParam.mk target⟩
writeRequest ⟨waitForDiagnosticsId, "textDocument/waitForDiagnostics", WaitForDiagnosticsParams.mk target version
let rec loop : IpcM (List (Notification PublishDiagnosticsParams)) := do
match ←readMessage with
| Message.response id _ =>

View file

@ -52,7 +52,7 @@ instance DefinitionParams.hasFileSource : FileSource DefinitionParams :=
instance TypeDefinitionParams.hasFileSource : FileSource TypeDefinitionParams :=
⟨fun h => fileSource h.toTextDocumentPositionParams⟩
instance WaitForDiagnosticsParam.hasFileSource : FileSource WaitForDiagnosticsParam :=
instance WaitForDiagnosticsParams.hasFileSource : FileSource WaitForDiagnosticsParams :=
⟨fun p => p.uri⟩
instance DocumentSymbolParams.hasFileSource : FileSource DocumentSymbolParams :=

View file

@ -488,12 +488,23 @@ section RequestHandling
children? := syms.toArray
} :: syms', stxs'')
def handleWaitForDiagnostics (id : RequestID) (p : WaitForDiagnosticsParam)
partial def handleWaitForDiagnostics (id : RequestID) (p : WaitForDiagnosticsParams)
: ServerM (Task (Except IO.Error (Except RequestError WaitForDiagnostics))) := do
let st ← read
let doc ← st.docRef.get
let t ← doc.cmdSnaps.waitAll
t.map fun _ => Except.ok $ Except.ok WaitForDiagnostics.mk
let rec waitLoop : IO EditableDocument := do
let doc ← st.docRef.get
if p.version ≤ doc.meta.version then
return doc
else
IO.sleep 50
waitLoop
let t ← IO.asTask waitLoop
let t ← IO.bindTask t fun
| Except.error e => unreachable!
| Except.ok doc => do
let t₁ ← doc.cmdSnaps.waitAll
return t₁.map fun _ => Except.ok WaitForDiagnostics.mk
return t.map fun _ => Except.ok <| Except.ok WaitForDiagnostics.mk
end RequestHandling
@ -531,7 +542,7 @@ section MessageHandling
st.hOut.writeLspResponseError { id := id, code := ErrorCode.internalError, message := toString e }
queueRequest id t₁
match method with
| "textDocument/waitForDiagnostics" => handle WaitForDiagnosticsParam WaitForDiagnostics handleWaitForDiagnostics
| "textDocument/waitForDiagnostics" => handle WaitForDiagnosticsParams WaitForDiagnostics handleWaitForDiagnostics
| "textDocument/hover" => handle HoverParams (Option Hover) handleHover
| "textDocument/declaration" => handle TextDocumentPositionParams (Array LocationLink) <| handleDefinition (goToType? := false)
| "textDocument/definition" => handle TextDocumentPositionParams (Array LocationLink) <| handleDefinition (goToType? := false)

View file

@ -379,7 +379,7 @@ section MessageHandling
let uri := fileSource parsedParams
tryWriteMessage uri ⟨id, method, parsedParams⟩ FileWorker.writeRequest
match method with
| "textDocument/waitForDiagnostics" => handle WaitForDiagnosticsParam
| "textDocument/waitForDiagnostics" => handle WaitForDiagnosticsParams
| "textDocument/hover" => handle HoverParams
| "textDocument/declaration" => handle DeclarationParams
| "textDocument/definition" => handle DefinitionParams

View file

@ -11,7 +11,7 @@ open IO Lean Lsp
hIn.write (←FS.readBinFile "open_content.log")
hIn.flush
let diags ← Ipc.collectDiagnostics 1 "file:///test.lean"
let diags ← Ipc.collectDiagnostics 1 "file:///test.lean" 1
if diags.isEmpty then
throw $ userError "Test failed, no diagnostics received."
else

View file

@ -12,12 +12,12 @@ open IO Lean Lsp
hIn.write (←FS.readBinFile "open_content.log")
hIn.flush
discard <| Ipc.collectDiagnostics 1 "file:///test.lean"
discard <| Ipc.collectDiagnostics 1 "file:///test.lean" 1
hIn.write (←FS.readBinFile "content_changes.log")
hIn.flush
let diags ← Ipc.collectDiagnostics 2 "file:///test.lean"
let diags ← Ipc.collectDiagnostics 2 "file:///test.lean" 7
if diags.isEmpty then
throw $ userError "Test failed, no diagnostics received."
else

View file

@ -9,7 +9,7 @@ open IO Lean Lsp
hIn.write (←FS.readBinFile "open_empty.log")
hIn.flush
let diags ← Ipc.collectDiagnostics 1 "file:///empty"
let diags ← Ipc.collectDiagnostics 1 "file:///empty" 1
assert! diags.length == 1
Ipc.writeNotification ⟨"exit", Json.null⟩