Skip to content

Commit 9914b4c

Browse files
committed
update InfoWithCtx docs and use as return type where possible
1 parent deb0bbb commit 9914b4c

File tree

2 files changed

+28
-17
lines changed

2 files changed

+28
-17
lines changed

src/Lean/Server/FileWorker/RequestHandling.lean

+6-6
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ def handleHover (p : HoverParams)
6666
| none => pure none
6767

6868
-- now try info tree
69-
if let some (ci, i, _) := snap.infoTree.hoverableInfoAt? hoverPos then
70-
if let some range := i.range? then
69+
if let some ictx := snap.infoTree.hoverableInfoAt? hoverPos then
70+
if let some range := ictx.info.range? then
7171
-- prefer info tree if at least as specific as parser docstring
7272
if stxDoc?.all fun (_, stxRange) => stxRange.includes range then
73-
if let some hoverFmt ← i.fmtHover? ci then
73+
if let some hoverFmt ← ictx.info.fmtHover? ictx.ctx then
7474
return mkHover (toString hoverFmt) range
7575

7676
if let some (doc, range) := stxDoc? then
@@ -197,8 +197,8 @@ def handleDefinition (kind : GoToKind) (p : TextDocumentPositionParams)
197197

198198
withWaitFindSnap doc (fun s => s.endPos > hoverPos)
199199
(notFoundX := pure #[]) fun snap => do
200-
if let some (ctx, info, children) := snap.infoTree.hoverableInfoAt? (omitIdentApps := true) (includeStop := true /- #767 -/) hoverPos then
201-
locationLinksOfInfo kind { ctx, info, children } snap.infoTree
200+
if let some infoWithCtx := snap.infoTree.hoverableInfoAt? (omitIdentApps := true) (includeStop := true /- #767 -/) hoverPos then
201+
locationLinksOfInfo kind infoWithCtx snap.infoTree
202202
else return #[]
203203

204204
open RequestM in
@@ -254,7 +254,7 @@ def getInteractiveTermGoal (p : Lsp.PlainTermGoalParams)
254254
let hoverPos := text.lspPosToUtf8Pos p.position
255255
withWaitFindSnap doc (fun s => s.endPos > hoverPos)
256256
(notFoundX := pure none) fun snap => do
257-
if let some (ci, i@(Elab.Info.ofTermInfo ti), _) := snap.infoTree.termGoalAt? hoverPos then
257+
if let some {ctx := ci, info := i@(Elab.Info.ofTermInfo ti), ..} := snap.infoTree.termGoalAt? hoverPos then
258258
let ty ← ci.runMetaM i.lctx do
259259
instantiateMVars <| ti.expectedType?.getD (← Meta.inferType ti.expr)
260260
-- for binders, hide the last hypothesis (the binder itself)

src/Lean/Server/InfoUtils.lean

+22-11
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,23 @@ namespace Lean.Elab
1010

1111
/-- Elaborator information with elaborator context.
1212
13-
This is used to tag different parts of expressions in `ppExprTagged`.
14-
This is the input to the RPC call `Lean.Widget.InteractiveDiagnostics.infoToInteractive`.
13+
It can be thought of as a "thunked" elaboration computation that allows us
14+
to retroactively extract type information, symbol locations, etc.
15+
through arbitrary invocations of `runMetaM` (where the necessary context and state
16+
can be reconstructed from `ctx` and `info.lctx`).
1517
16-
The purpose of `InfoWithCtx` is to carry over information about delaborated
18+
W.r.t. widgets, this is used to tag different parts of expressions in `ppExprTagged`.
19+
This is the input to the RPC call `Lean.Widget.InteractiveDiagnostics.infoToInteractive`.
20+
It carries over information about delaborated
1721
`Info` nodes in a `CodeWithInfos`, and the associated pretty-printing
1822
functionality is purpose-specific to showing the contents of infoview popups.
23+
24+
For use in standard LSP go-to-definition (see `Lean.Server.FileWorker.locationLinksOfInfo`),
25+
all the elaborator information we need for similar tasks is already fully recoverable via
26+
the `InfoTree` structure (see `Lean.Elab.InfoTree.visitM`).
27+
There we use this as a convienience wrapper for queried nodes (e.g. the return value of
28+
`Lean.Elab.InfoTree.hoverableInfoAt?`). It also includes the children info nodes
29+
as additional context (this is unused in the RPC case, as delaboration has no notion of child nodes).
1930
-/
2031
structure InfoWithCtx where
2132
ctx : Elab.ContextInfo
@@ -150,16 +161,16 @@ def InfoTree.smallestInfo? (p : Info → Bool) (t : InfoTree) : Option (ContextI
150161
infos.toArray.getMax? (fun a b => a.1 > b.1) |>.map fun (_, ci, i) => (ci, i)
151162

152163
/-- Find an info node, if any, which should be shown on hover/cursor at position `hoverPos`. -/
153-
partial def InfoTree.hoverableInfoAt? (t : InfoTree) (hoverPos : String.Pos) (includeStop := false) (omitAppFns := false) (omitIdentApps := false) : Option (ContextInfo × Info × (PersistentArray InfoTree)) := Id.run do
154-
let results := t.visitM (m := Id) (postNode := fun ctx info c results => do
164+
partial def InfoTree.hoverableInfoAt? (t : InfoTree) (hoverPos : String.Pos) (includeStop := false) (omitAppFns := false) (omitIdentApps := false) : Option InfoWithCtx := Id.run do
165+
let results := t.visitM (m := Id) (postNode := fun ctx info children results => do
155166
let mut results := results.bind (·.getD [])
156167
if omitAppFns && info.stx.isOfKind ``Parser.Term.app && info.stx[0].isIdent then
157-
results := results.filter (·.2.2.1.stx != info.stx[0])
168+
results := results.filter (·.2.info.stx != info.stx[0])
158169
if omitIdentApps && info.stx.isIdent then
159170
-- if an identifier stands for an application (e.g. in the case of a typeclass projection), prefer the application
160171
if let .ofTermInfo ti := info then
161172
if ti.expr.isApp then
162-
results := results.filter (·.2.2.1.stx != info.stx)
173+
results := results.filter (·.2.info.stx != info.stx)
163174
unless results.isEmpty do
164175
return results -- prefer innermost results
165176
/-
@@ -181,16 +192,16 @@ partial def InfoTree.hoverableInfoAt? (t : InfoTree) (hoverPos : String.Pos) (in
181192
Int.negOfNat (r.stop - r.start).byteIdx,
182193
-- prefer results for constants over variables (which overlap at declaration names)
183194
if info matches .ofTermInfo { expr := .fvar .., .. } then 0 else 1)
184-
[(priority, ctx, info, c)]) |>.getD []
195+
[(priority, {ctx, info, children})]) |>.getD []
185196
-- sort results by lexicographical priority
186197
let maxPrio? :=
187198
let _ := @lexOrd
188199
let _ := @leOfOrd.{0}
189200
let _ := @maxOfLe
190201
results.map (·.1) |>.maximum?
191202
let res? := results.find? (·.1 == maxPrio?) |>.map (·.2)
192-
if let some (_, i, _) := res? then
193-
if let .ofTermInfo ti := i then
203+
if let some i := res? then
204+
if let .ofTermInfo ti := i.info then
194205
if ti.expr.isSyntheticSorry then
195206
return none
196207
return res?
@@ -343,7 +354,7 @@ where
343354
cs.any (hasNestedTactic pos tailPos)
344355
| _ => false
345356

346-
partial def InfoTree.termGoalAt? (t : InfoTree) (hoverPos : String.Pos) : Option (ContextInfo × Info × (PersistentArray InfoTree)) :=
357+
partial def InfoTree.termGoalAt? (t : InfoTree) (hoverPos : String.Pos) : Option InfoWithCtx :=
347358
-- In the case `f a b`, where `f` is an identifier, the term goal at `f` should be the goal for the full application `f a b`.
348359
hoverableInfoAt? t hoverPos (includeStop := true) (omitAppFns := true)
349360

0 commit comments

Comments
 (0)