refactor: remove some code duplication

This commit is contained in:
Wojciech Nawrocki 2022-03-25 17:10:41 -04:00 committed by Leonardo de Moura
parent 9223bf3640
commit 96770b4d83
2 changed files with 26 additions and 20 deletions

View file

@ -89,6 +89,18 @@ def mapTask (t : Task α) (f : α → RequestM β) : RequestM (RequestTask β) :
def bindTask (t : Task α) (f : α → RequestM (RequestTask β)) : RequestM (RequestTask β) := fun rc => do
EIO.bindTask t (f · rc)
def waitFindSnapAux (notFoundX : RequestM α) (x : Snapshot → RequestM α)
: Except ElabTaskError (Option Snapshot) → RequestM α
/- The elaboration task that we're waiting for may be aborted if the file contents change.
In that case, we reply with the `fileChanged` error. Thanks to this, the server doesn't
get bogged down in requests for an old state of the document. -/
| Except.error FileWorker.ElabTaskError.aborted =>
throwThe RequestError RequestError.fileChanged
| Except.error (FileWorker.ElabTaskError.ioError e) =>
throw (e : RequestError)
| Except.ok none => notFoundX
| Except.ok (some snap) => x snap
/-- Create a task which waits for the first snapshot matching `p`, handles various errors,
and if a matching snapshot was found executes `x` with it. If not found, the task executes
`notFoundX`. -/
@ -97,16 +109,15 @@ def withWaitFindSnap (doc : EditableDocument) (p : Snapshot → Bool)
(x : Snapshot → RequestM β)
: RequestM (RequestTask β) := do
let findTask ← doc.allSnaps.waitFind? p
mapTask findTask fun
/- The elaboration task that we're waiting for may be aborted if the file contents change.
In that case, we reply with the `fileChanged` error. Thanks to this, the server doesn't
get bogged down in requests for an old state of the document. -/
| Except.error FileWorker.ElabTaskError.aborted =>
throwThe RequestError RequestError.fileChanged
| Except.error (FileWorker.ElabTaskError.ioError e) =>
throw (e : RequestError)
| Except.ok none => notFoundX
| Except.ok (some snap) => x snap
mapTask findTask <| waitFindSnapAux notFoundX x
/-- See `withWaitFindSnap`. -/
def bindWaitFindSnap (doc : EditableDocument) (p : Snapshot → Bool)
(notFoundX : RequestM (RequestTask β))
(x : Snapshot → RequestM (RequestTask β))
: RequestM (RequestTask β) := do
let findTask ← doc.allSnaps.waitFind? p
bindTask findTask <| waitFindSnapAux notFoundX x
end RequestM

View file

@ -28,16 +28,11 @@ private def handleRpcCall (p : Lsp.RpcCallParams) : RequestM (RequestTask Json)
let doc ← readDoc
let text := doc.meta.text
let callPos := text.lspPosToUtf8Pos p.position
let findTask ← doc.allSnaps.waitFind? (fun s => s.endPos >= callPos)
bindTask findTask fun
| Except.error FileWorker.ElabTaskError.aborted =>
throwThe RequestError RequestError.fileChanged
| Except.error (FileWorker.ElabTaskError.ioError e) =>
throw (e : RequestError)
| Except.ok none =>
throwThe RequestError { code := JsonRpc.ErrorCode.invalidParams
message := s!"Incorrect position '{p.toTextDocumentPositionParams}' in RPC call" }
| Except.ok (some snap) => do
bindWaitFindSnap doc (fun s => s.endPos >= callPos)
(notFoundX := throwThe RequestError
{ code := JsonRpc.ErrorCode.invalidParams
message := s!"Incorrect position '{p.toTextDocumentPositionParams}' in RPC call" })
fun snap => do
if let some proc := (← builtinRpcProcedures.get).find? p.method then
proc.wrapper p.sessionId p.params
else if let some proc := userRpcProcedures.getState snap.env |>.find? p.method then