/- Copyright (c) 2021 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Wojciech Nawrocki -/ import Lean.Widget.Basic import Lean.Widget.InteractiveCode import Lean.Widget.InteractiveGoal import Lean.Widget.InteractiveDiagnostic import Lean.Server.Rpc.RequestHandling import Lean.Server.FileWorker.RequestHandling /-! Registers all widget-related RPC procedures. -/ namespace Lean.Widget open Server structure MsgToInteractive where msg : WithRpcRef MessageData indent : Nat deriving Inhabited, RpcEncoding builtin_initialize registerBuiltinRpcProcedure `Lean.Widget.InteractiveDiagnostics.msgToInteractive MsgToInteractive (TaggedText MsgEmbed) fun ⟨⟨m⟩, i⟩ => RequestM.asTask do msgToInteractive m i (hasWidgets := true) /-- The information that the infoview uses to render a popup for when the user hovers over an expression. -/ structure InfoPopup where type : Option CodeWithInfos /-- Show the term with the implicit arguments. -/ exprExplicit : Option CodeWithInfos /-- Docstring. In markdown. -/ doc : Option String deriving Inhabited, RpcEncoding /-- Given elaborator info for a particular subexpression. Produce the `InfoPopup`. The intended usage of this is for the infoview to pass the `InfoWithCtx` which was stored for a particular `SubexprInfo` tag in a `TaggedText` generated with `ppExprTagged`. -/ def makePopup : WithRpcRef InfoWithCtx → RequestM (RequestTask InfoPopup) | ⟨i⟩ => RequestM.asTask do i.ctx.runMetaM i.info.lctx do let type? ← match (← i.info.type?) with | some type => some <$> ppExprTagged type | none => pure none let exprExplicit? ← match i.info with | Elab.Info.ofTermInfo ti => let ti ← ppExprTagged ti.expr (explicit := true) -- remove top-level expression highlight pure <| some <| match ti with | .tag _ tt => tt | tt => tt | Elab.Info.ofFieldInfo fi => pure <| some <| TaggedText.text fi.fieldName.toString | _ => pure none return { type := type? exprExplicit := exprExplicit? doc := ← i.info.docString? : InfoPopup } builtin_initialize registerBuiltinRpcProcedure `Lean.Widget.InteractiveDiagnostics.infoToInteractive (WithRpcRef InfoWithCtx) InfoPopup makePopup builtin_initialize registerBuiltinRpcProcedure `Lean.Widget.getInteractiveGoals Lsp.PlainGoalParams (Option InteractiveGoals) FileWorker.getInteractiveGoals builtin_initialize registerBuiltinRpcProcedure `Lean.Widget.getInteractiveTermGoal Lsp.PlainTermGoalParams (Option InteractiveTermGoal) FileWorker.getInteractiveTermGoal structure GetInteractiveDiagnosticsParams where /-- Return diagnostics for these lines only if present, otherwise return all diagnostics. -/ lineRange? : Option Lsp.LineRange deriving Inhabited, FromJson, ToJson open RequestM in def getInteractiveDiagnostics (params : GetInteractiveDiagnosticsParams) : RequestM (RequestTask (Array InteractiveDiagnostic)) := do let doc ← readDoc let rangeEnd := params.lineRange?.map fun range => doc.meta.text.lspPosToUtf8Pos ⟨range.«end», 0⟩ let t ← doc.cmdSnaps.waitAll fun snap => rangeEnd.all (snap.beginPos < ·) pure <| t.map fun (snaps, _) => let diags? := snaps.getLast?.map fun snap => snap.interactiveDiags.toArray.filter fun diag => params.lineRange?.all fun ⟨s, e⟩ => -- does [s,e) intersect [diag.fullRange.start.line,diag.fullRange.end.line)? s ≤ diag.fullRange.start.line ∧ diag.fullRange.start.line < e ∨ diag.fullRange.start.line ≤ s ∧ s < diag.fullRange.end.line pure <| diags?.getD #[] builtin_initialize registerBuiltinRpcProcedure `Lean.Widget.getInteractiveDiagnostics GetInteractiveDiagnosticsParams (Array InteractiveDiagnostic) getInteractiveDiagnostics structure GetGoToLocationParams where kind : GoToKind info : WithRpcRef InfoWithCtx deriving RpcEncoding builtin_initialize registerBuiltinRpcProcedure `Lean.Widget.getGoToLocation GetGoToLocationParams (Array Lsp.LocationLink) fun ⟨kind, ⟨i⟩⟩ => RequestM.asTask do let rc ← read let ls ← FileWorker.locationLinksOfInfo kind i.ctx i.info if !ls.isEmpty then return ls -- TODO(WN): unify handling of delab'd (infoview) and elab'd (editor) applications let .ofTermInfo ti := i.info | return #[] let .app _ _ _ := ti.expr | return #[] let some nm := ti.expr.getAppFn.constName? | return #[] i.ctx.runMetaM ti.lctx <| locationLinksFromDecl rc.srcSearchPath.get rc.doc.meta.uri nm none end Lean.Widget