fix: server: completion & goal state at EOF

This commit is contained in:
Sebastian Ullrich 2021-04-30 19:22:08 +02:00
parent 44f45f426c
commit e1cde87c43
7 changed files with 40 additions and 7 deletions

View file

@ -375,7 +375,8 @@ section RequestHandling
let text := doc.meta.text
let pos := text.lspPosToUtf8Pos p.position
-- dbg_trace ">> handleCompletion invoked {pos}"
withWaitFindSnap doc (fun s => s.endPos > pos)
-- NOTE: use `>=` since the cursor can be *after* the input
withWaitFindSnap doc (fun s => s.endPos >= pos)
(notFoundX := pure { items := #[], isIncomplete := true }) fun snap => do
for infoTree in snap.cmdState.infoState.trees do
-- for (ctx, info) in infoTree.getCompletionInfos do
@ -451,7 +452,8 @@ section RequestHandling
let doc ← st.docRef.get
let text := doc.meta.text
let hoverPos := text.lspPosToUtf8Pos p.position
withWaitFindSnap doc (fun s => s.endPos > hoverPos)
-- NOTE: use `>=` since the cursor can be *after* the input
withWaitFindSnap doc (fun s => s.endPos >= hoverPos)
(notFoundX := return none) fun snap => do
for t in snap.cmdState.infoState.trees do
if let rs@(_ :: _) := t.goalsAt? hoverPos then

View file

@ -156,11 +156,11 @@ structure GoalsAtResult where
/-
Try to retrieve `TacticInfo` for `hoverPos`.
We retrieve the `TacticInfo` `info`, if there is a node of the form `node (ofTacticInfo info) children` s.t.
- If `hoverPos <= headPos && hoverPos < endPos + getTrailingSize` and
- `hoverPos` is sufficiently inside `info`'s range (see code), and
- None of the `children` can provide satisfy the condition above. That is, for composite tactics such as
`induction`, we always give preference for information stored in nested (children) tactics.
Moreover, we instruct the LSP server to use the state after the tactic execution If hoverPos >= endPos
Moreover, we instruct the LSP server to use the state after the tactic execution if hoverPos >= endPos
-/
partial def InfoTree.goalsAt? (t : InfoTree) (hoverPos : String.Pos) : List GoalsAtResult := do
t.deepestNodes fun
@ -168,7 +168,9 @@ partial def InfoTree.goalsAt? (t : InfoTree) (hoverPos : String.Pos) : List Goal
let (some pos, some tailPos) ← pure (i.pos?, i.tailPos?)
| failure
let trailSize := i.stx.getTrailingSize
guard <| pos ≤ hoverPos ∧ hoverPos < tailPos + trailSize
-- NOTE: include position just after tactic, i.e. when the cursor is still adjacent
-- (even when `trailSize == 0`, which is the case at EOF)
guard <| pos ≤ hoverPos ∧ hoverPos < tailPos + Nat.max 1 trailSize
return { ctxInfo := ctx, tacticInfo := ti, useAfter := hoverPos > pos }
| _, _ => none

View file

@ -0,0 +1,9 @@
-- Local Variables:
-- require-final-newline: nil
-- End:
prelude
axiom And : Type
--v textDocument/completion
#check An

View file

@ -0,0 +1,3 @@
{"textDocument": {"uri": "file://completionEOF.lean"},
"position": {"line": 8, "character": 9}}
{"items": [{"label": "And", "detail": "Type"}], "isIncomplete": true}

View file

@ -0,0 +1,6 @@
-- Local Variables:
-- require-final-newline: nil
-- End:
--v $/lean/plainGoal
example : False := by rfl

View file

@ -0,0 +1,3 @@
{"textDocument": {"uri": "file://goalEOF.lean"},
"position": {"line": 5, "character": 25}}
{"rendered": "```lean\n⊢ False\n```", "goals": ["⊢ False"]}

View file

@ -20,13 +20,21 @@ partial def main (args : List String) : IO Unit := do
let mut versionNo : Nat := 2
let mut requestNo : Nat := 2
for line in text.splitOn "\n" do
match line.splitOn "--^" with
match line.splitOn "--" with
| [ws, directive] =>
let line ← match directive[0] with
| 'v' => pure <| lineNo + 1 -- TODO: support subsequent 'v'... or not
| '^' => pure <| lastActualLineNo
| _ =>
lastActualLineNo := lineNo
lineNo := lineNo + 1
continue
let directive := directive.drop 1
let colon := directive.posOf ':'
let method := directive.extract 0 colon |>.trim
-- TODO: correctly compute in presence of Unicode
let column := ws.bsize + "--".length
let pos : Lsp.Position := { line := lastActualLineNo, character := column }
let pos : Lsp.Position := { line := line, character := column }
let params := if colon < directive.bsize then directive.extract (colon + 1) directive.bsize |>.trim else "{}"
match method with
| "insert" =>