|
| 1 | +/- |
| 2 | +Copyright (c) 2025 Lean FRO LLC. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Author: Joseph Rotella |
| 5 | +-/ |
| 6 | + |
| 7 | +import Manual.Meta.ErrorExplanation |
| 8 | + |
| 9 | +open Lean |
| 10 | +open Verso Doc Elab Genre Manual |
| 11 | + |
| 12 | +namespace Manual |
| 13 | + |
| 14 | +set_option pp.rawOnError true |
| 15 | +set_option guard_msgs.diff true |
| 16 | + |
| 17 | + |
| 18 | +def Inline.errorExplanationLink (errorName : Name) : Manual.Inline where |
| 19 | + name := `Manual.Inline.errorExplanationLink |
| 20 | + data := toJson errorName |
| 21 | + |
| 22 | +@[inline_extension Inline.errorExplanationLink] |
| 23 | +def Inline.errorExplanationLink.descr : InlineDescr where |
| 24 | + traverse := fun _ _ _ => pure none |
| 25 | + toTeX := none |
| 26 | + toHtml := some fun go _ data content => |
| 27 | + open Verso.Output.Html Verso.Doc.Html.HtmlT in do |
| 28 | + let xref ← state |
| 29 | + let .ok name := FromJson.fromJson? (α := String) data |
| 30 | + | logError s!"Failed to parse error explanation link JSON: expected string, but found:\n{data}" |
| 31 | + content.mapM go |
| 32 | + let some obj := (← read).traverseState.getDomainObject? errorExplanationDomain name |
| 33 | + | logError s!"Could not find explanation domain entry for name '{name}'" |
| 34 | + content.mapM go |
| 35 | + let some id := obj.getId |
| 36 | + | logError s!"Could not find retrieve ID from explanation domain entry for name '{name}'" |
| 37 | + content.mapM go |
| 38 | + if let some { path, htmlId } := xref.externalTags.get? id then |
| 39 | + let addr := path.link (some htmlId.toString) |
| 40 | + pure {{<a class="technical-term" href={{addr}}>{{← content.mapM go}}</a>}} |
| 41 | + else |
| 42 | + logError s!"Could not find external tag for error explanation '{name}' corresponding to ID '{id}'" |
| 43 | + content.mapM go |
| 44 | + |
| 45 | +@[block_role_expander error_explanation_table] |
| 46 | +def error_explanation_table : BlockRoleExpander |
| 47 | + | #[], #[] => do |
| 48 | + let entries ← getErrorExplanationsSorted |
| 49 | + let columns := 4 |
| 50 | + let header := true |
| 51 | + let name := "diagnostic-table" |
| 52 | + let alignment : Option TableConfig.Alignment := none |
| 53 | + let headers ← #["Name", "Summary", "Severity", "Since"] |
| 54 | + |>.mapM fun s => ``(Verso.Doc.Block.para #[Doc.Inline.text $(quote s)]) |
| 55 | + let vals ← entries.flatMapM fun (name, explan) => do |
| 56 | + let sev := quote <| |
| 57 | + if explan.metadata.severity == .warning then "Warning" else "Error" |
| 58 | + let sev ← ``(Doc.Inline.text $sev) |
| 59 | + let nameStr := toString name |
| 60 | + let nameLink ← ``(Doc.Inline.other (Inline.errorExplanationLink $(quote name)) #[Doc.Inline.text $(quote nameStr)]) |
| 61 | + let summary ← ``(Doc.Inline.text $(quote explan.metadata.summary)) |
| 62 | + let since ← ``(Doc.Inline.text $(quote explan.metadata.sinceVersion)) |
| 63 | + #[nameLink, summary, sev, since] |
| 64 | + |>.mapM fun s => ``(Verso.Doc.Block.para #[$s]) |
| 65 | + let blocks := (headers ++ vals).map fun c => Syntax.TSepArray.mk #[c] |
| 66 | + pure #[← ``(Block.other (Block.table $(quote columns) $(quote header) $(quote name) $(quote alignment)) #[Block.ul #[$[Verso.Doc.ListItem.mk #[$blocks,*]],*]])] |
| 67 | + | _, _ => throwError "unexpected syntax" |
| 68 | + |
| 69 | +-- Elaborating explanations can exceed the default heartbeat maximum: |
| 70 | +set_option maxHeartbeats 1000000 |
| 71 | + |
| 72 | +#doc (Manual) "Error Explanations" => |
| 73 | +%%% |
| 74 | +number := false |
| 75 | +htmlToc := false |
| 76 | +%%% |
| 77 | + |
| 78 | +This section provides explanations of errors and warnings that may be generated |
| 79 | +by Lean when processing a source file. |
| 80 | + |
| 81 | +{error_explanation_table} |
| 82 | + |
| 83 | +{make_explanations} |
0 commit comments