lean4-htt/src/Lean/Server/FileWorker/WidgetRequests.lean
2022-06-24 19:02:00 +02:00

139 lines
4.7 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
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