@@ -13,6 +13,7 @@ public import Lean.Data.Lsp.Communication
1313public import Lean.Data.Lsp.Diagnostics
1414public import Lean.Data.Lsp.Extra
1515import Init.Data.List.Sort .Basic
16+ public import Lean.Data.Lsp.LanguageFeatures
1617
1718public section
1819
@@ -160,10 +161,191 @@ where
160161 | Except.error inner => throw $ userError s! "Cannot decode publishDiagnostics parameters\n { inner} "
161162 | _ => loop
162163
163- def runWith (lean : System.FilePath) (args : Array String := #[]) (test : IpcM α) : IO α := do
164+ structure CallHierarchy where
165+ item : CallHierarchyItem
166+ fromRanges : Array Range
167+ children : Array CallHierarchy
168+ deriving FromJson, ToJson
169+
170+ partial def expandIncomingCallHierarchy (requestNo : Nat) (uri : DocumentUri) (pos : Lsp.Position) : IpcM (Array CallHierarchy × Nat) := do
171+ writeRequest {
172+ id := requestNo
173+ method := "textDocument/prepareCallHierarchy"
174+ param := {
175+ textDocument := { uri }
176+ position := pos
177+ : CallHierarchyPrepareParams
178+ }
179+ }
180+ let r ← readResponseAs requestNo (Option (Array CallHierarchyItem))
181+ let mut requestNo := requestNo + 1
182+ let roots := r.result.getD #[]
183+ let mut hierarchies := #[]
184+ for root in roots do
185+ let (hierarchy, rootRequestNo) ← go requestNo root #[] {}
186+ requestNo := rootRequestNo
187+ hierarchies := hierarchies.push hierarchy
188+ return (hierarchies, requestNo)
189+ where
190+ go (requestNo : Nat) (item : CallHierarchyItem) (fromRanges : Array Range) (visited : Std.TreeSet String) : IpcM (CallHierarchy × Nat) := do
191+ if visited.contains item.name then
192+ return ({ item, fromRanges := #[], children := #[] }, requestNo)
193+ writeRequest {
194+ id := requestNo
195+ method := "callHierarchy/incomingCalls"
196+ param := {
197+ item
198+ : CallHierarchyIncomingCallsParams
199+ }
200+ }
201+ let r ← readResponseAs requestNo (Option (Array CallHierarchyIncomingCall))
202+ let visited : Std.TreeSet String := visited.insert item.name
203+ let mut requestNo := requestNo + 1
204+ let children := r.result.getD #[]
205+ let mut childHierarchies := #[]
206+ for c in children do
207+ let (childHierarchy, childRequestNo) ← go requestNo c.from c.fromRanges visited
208+ childHierarchies := childHierarchies.push childHierarchy
209+ requestNo := childRequestNo
210+ return ({ item, fromRanges, children := childHierarchies }, requestNo)
211+
212+ partial def expandOutgoingCallHierarchy (requestNo : Nat) (uri : DocumentUri) (pos : Lsp.Position) : IpcM (Array CallHierarchy × Nat) := do
213+ writeRequest {
214+ id := requestNo
215+ method := "textDocument/prepareCallHierarchy"
216+ param := {
217+ textDocument := { uri }
218+ position := pos
219+ : CallHierarchyPrepareParams
220+ }
221+ }
222+ let r ← readResponseAs requestNo (Option (Array CallHierarchyItem))
223+ let mut requestNo := requestNo + 1
224+ let roots := r.result.getD #[]
225+ let mut hierarchies := #[]
226+ for root in roots do
227+ let (hierarchy, rootRequestNo) ← go requestNo root #[] {}
228+ requestNo := rootRequestNo
229+ hierarchies := hierarchies.push hierarchy
230+ return (hierarchies, requestNo)
231+ where
232+ go (requestNo : Nat) (item : CallHierarchyItem) (fromRanges : Array Range) (visited : Std.TreeSet String) : IpcM (CallHierarchy × Nat) := do
233+ if visited.contains item.name then
234+ return ({ item, fromRanges := #[], children := #[] }, requestNo)
235+ writeRequest {
236+ id := requestNo
237+ method := "callHierarchy/outgoingCalls"
238+ param := {
239+ item
240+ : CallHierarchyOutgoingCallsParams
241+ }
242+ }
243+ let r ← readResponseAs requestNo (Option (Array CallHierarchyOutgoingCall))
244+ let visited : Std.TreeSet String := visited.insert item.name
245+ let mut requestNo := requestNo + 1
246+ let children := r.result.getD #[]
247+ let mut childHierarchies := #[]
248+ for c in children do
249+ let (childHierarchy, childRequestNo) ← go requestNo c.to c.fromRanges visited
250+ childHierarchies := childHierarchies.push childHierarchy
251+ requestNo := childRequestNo
252+ return ({ item, fromRanges, children := childHierarchies }, requestNo)
253+
254+ structure ModuleHierarchy where
255+ item : LeanImport
256+ children : Array ModuleHierarchy
257+ deriving FromJson, ToJson
258+
259+ partial def expandModuleHierarchyImports (requestNo : Nat) (uri : DocumentUri) : IpcM (Option ModuleHierarchy × Nat) := do
260+ writeRequest {
261+ id := requestNo
262+ method := "$/lean/prepareModuleHierarchy"
263+ param := {
264+ textDocument := { uri }
265+ : LeanPrepareModuleHierarchyParams
266+ }
267+ }
268+ let r ← readResponseAs requestNo (Option LeanModule)
269+ let mut requestNo := requestNo + 1
270+ let some root := r.result
271+ | return (none, requestNo)
272+ let root := {
273+ module := root
274+ kind := { isAll := false , isPrivate := false , metaKind := .full }
275+ }
276+ let (hierarchy, rootRequestNo) ← go requestNo root {}
277+ requestNo := rootRequestNo
278+ return (hierarchy, requestNo)
279+ where
280+ go (requestNo : Nat) (item : LeanImport) (visited : Std.TreeSet String) : IpcM (ModuleHierarchy × Nat) := do
281+ if visited.contains item.module.name then
282+ return ({ item, children := #[] }, requestNo)
283+ writeRequest {
284+ id := requestNo
285+ method := "$/lean/moduleHierarchy/imports"
286+ param := {
287+ module := item.module
288+ : LeanModuleHierarchyImportsParams
289+ }
290+ }
291+ let r ← readResponseAs requestNo (Array LeanImport)
292+ let visited : Std.TreeSet String := visited.insert item.module.name
293+ let mut requestNo := requestNo + 1
294+ let children := r.result
295+ let mut childHierarchies := #[]
296+ for c in children do
297+ let (childHierarchy, childRequestNo) ← go requestNo c visited
298+ childHierarchies := childHierarchies.push childHierarchy
299+ requestNo := childRequestNo
300+ return ({ item, children := childHierarchies }, requestNo)
301+
302+ partial def expandModuleHierarchyImportedBy (requestNo : Nat) (uri : DocumentUri) : IpcM (Option ModuleHierarchy × Nat) := do
303+ writeRequest {
304+ id := requestNo
305+ method := "$/lean/prepareModuleHierarchy"
306+ param := {
307+ textDocument := { uri }
308+ : LeanPrepareModuleHierarchyParams
309+ }
310+ }
311+ let r ← readResponseAs requestNo (Option LeanModule)
312+ let mut requestNo := requestNo + 1
313+ let some root := r.result
314+ | return (none, requestNo)
315+ let root := {
316+ module := root
317+ kind := { isAll := false , isPrivate := false , metaKind := .full }
318+ }
319+ let (hierarchy, rootRequestNo) ← go requestNo root {}
320+ requestNo := rootRequestNo
321+ return (hierarchy, requestNo)
322+ where
323+ go (requestNo : Nat) (item : LeanImport) (visited : Std.TreeSet String) : IpcM (ModuleHierarchy × Nat) := do
324+ if visited.contains item.module.name then
325+ return ({ item, children := #[] }, requestNo)
326+ writeRequest {
327+ id := requestNo
328+ method := "$/lean/moduleHierarchy/importedBy"
329+ param := {
330+ module := item.module
331+ : LeanModuleHierarchyImportedByParams
332+ }
333+ }
334+ let r ← readResponseAs requestNo (Array LeanImport)
335+ let visited : Std.TreeSet String := visited.insert item.module.name
336+ let mut requestNo := requestNo + 1
337+ let children := r.result
338+ let mut childHierarchies := #[]
339+ for c in children do
340+ let (childHierarchy, childRequestNo) ← go requestNo c visited
341+ childHierarchies := childHierarchies.push childHierarchy
342+ requestNo := childRequestNo
343+ return ({ item, children := childHierarchies }, requestNo)
344+
345+ def runWith (lean : String) (args : Array String := #[]) (test : IpcM α) : IO α := do
164346 let proc ← Process.spawn {
165347 toStdioConfig := ipcStdioConfig
166- cmd := lean.toString
348+ cmd := lean
167349 args := args }
168350 ReaderT.run test proc
169351
0 commit comments