@@ -10,12 +10,23 @@ namespace Lean.Elab
10
10
11
11
/-- Elaborator information with elaborator context.
12
12
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`).
15
17
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
17
21
`Info` nodes in a `CodeWithInfos`, and the associated pretty-printing
18
22
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).
19
30
-/
20
31
structure InfoWithCtx where
21
32
ctx : Elab.ContextInfo
@@ -150,16 +161,16 @@ def InfoTree.smallestInfo? (p : Info → Bool) (t : InfoTree) : Option (ContextI
150
161
infos.toArray.getMax? (fun a b => a.1 > b.1 ) |>.map fun (_, ci, i) => (ci, i)
151
162
152
163
/-- 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
155
166
let mut results := results.bind (·.getD [])
156
167
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 ])
158
169
if omitIdentApps && info.stx.isIdent then
159
170
-- if an identifier stands for an application (e.g. in the case of a typeclass projection), prefer the application
160
171
if let .ofTermInfo ti := info then
161
172
if ti.expr.isApp then
162
- results := results.filter (·.2 .2 . 1 .stx != info.stx)
173
+ results := results.filter (·.2 .info .stx != info.stx)
163
174
unless results.isEmpty do
164
175
return results -- prefer innermost results
165
176
/-
@@ -181,16 +192,16 @@ partial def InfoTree.hoverableInfoAt? (t : InfoTree) (hoverPos : String.Pos) (in
181
192
Int.negOfNat (r.stop - r.start).byteIdx,
182
193
-- prefer results for constants over variables (which overlap at declaration names)
183
194
if info matches .ofTermInfo { expr := .fvar .., .. } then 0 else 1 )
184
- [(priority, ctx, info, c )]) |>.getD []
195
+ [(priority, { ctx, info, children} )]) |>.getD []
185
196
-- sort results by lexicographical priority
186
197
let maxPrio? :=
187
198
let _ := @lexOrd
188
199
let _ := @leOfOrd.{0 }
189
200
let _ := @maxOfLe
190
201
results.map (·.1 ) |>.maximum?
191
202
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
194
205
if ti.expr.isSyntheticSorry then
195
206
return none
196
207
return res?
@@ -343,7 +354,7 @@ where
343
354
cs.any (hasNestedTactic pos tailPos)
344
355
| _ => false
345
356
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 :=
347
358
-- 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`.
348
359
hoverableInfoAt? t hoverPos (includeStop := true ) (omitAppFns := true )
349
360
0 commit comments