bookshelf-doc/DocGen4/Output/ToJson.lean

152 lines
5.0 KiB
Plaintext
Raw Permalink Normal View History

import Lean
import DocGen4.Process
import DocGen4.Output.Base
2023-08-06 13:36:43 +00:00
import DocGen4.Output.Module
import Lean.Data.RBMap
namespace DocGen4.Output
open Lean
2023-08-06 13:36:43 +00:00
structure JsonDeclarationInfo where
name : String
kind : String
doc : String
docLink : String
sourceLink : String
2023-08-06 13:36:43 +00:00
line : Nat
deriving FromJson, ToJson
2023-08-06 13:36:43 +00:00
structure JsonDeclaration where
info : JsonDeclarationInfo
header : String
deriving FromJson, ToJson
structure JsonInstance where
name : String
className : String
2022-07-23 13:40:08 +00:00
typeNames : Array String
deriving FromJson, ToJson
structure JsonModule where
name : String
declarations : List JsonDeclaration
instances : Array JsonInstance
imports : Array String
deriving FromJson, ToJson
2023-08-06 13:36:43 +00:00
structure JsonHeaderIndex where
2023-09-14 22:39:28 +00:00
declarations : List (String × JsonDeclaration) := []
2023-08-06 13:36:43 +00:00
2023-09-10 10:39:37 +00:00
structure JsonIndexedDeclarationInfo where
kind : String
docLink : String
deriving FromJson, ToJson
structure JsonIndexedModule where
importedBy : Array String
url : String
deriving FromJson, ToJson
2022-07-23 18:40:08 +00:00
structure JsonIndex where
2023-09-10 10:39:37 +00:00
declarations : List (String × JsonIndexedDeclarationInfo) := []
instances : HashMap String (RBTree String Ord.compare) := .empty
modules : HashMap String JsonIndexedModule := {}
instancesFor : HashMap String (RBTree String Ord.compare) := .empty
2022-07-23 18:40:08 +00:00
2023-08-06 13:36:43 +00:00
instance : ToJson JsonHeaderIndex where
2023-09-14 22:39:28 +00:00
toJson idx := Json.mkObj <| idx.declarations.map (fun (k, v) => (k, toJson v))
2023-08-06 13:36:43 +00:00
2022-07-23 18:40:08 +00:00
instance : ToJson JsonIndex where
toJson idx := Id.run do
2023-01-01 18:51:01 +00:00
let jsonDecls := Json.mkObj <| idx.declarations.map (fun (k, v) => (k, toJson v))
let jsonInstances := Json.mkObj <| idx.instances.toList.map (fun (k, v) => (k, toJson v.toArray))
let jsonModules := Json.mkObj <| idx.modules.toList.map (fun (k, v) => (k, toJson v))
let jsonInstancesFor := Json.mkObj <| idx.instancesFor.toList.map (fun (k, v) => (k, toJson v.toArray))
2022-07-23 18:40:08 +00:00
let finalJson := Json.mkObj [
("declarations", jsonDecls),
("instances", jsonInstances),
("modules", jsonModules),
("instancesFor", jsonInstancesFor)
]
2023-01-01 18:51:01 +00:00
return finalJson
2022-07-23 18:40:08 +00:00
2023-08-06 13:36:43 +00:00
def JsonHeaderIndex.addModule (index : JsonHeaderIndex) (module : JsonModule) : JsonHeaderIndex :=
2023-09-14 22:39:28 +00:00
let merge idx decl := { idx with declarations := (decl.info.name, decl) :: idx.declarations }
2023-08-06 13:36:43 +00:00
module.declarations.foldl merge index
2022-07-23 18:40:08 +00:00
def JsonIndex.addModule (index : JsonIndex) (module : JsonModule) : BaseHtmlM JsonIndex := do
let mut index := index
2023-09-10 10:39:37 +00:00
let newDecls := module.declarations.map (fun d => (d.info.name, {
kind := d.info.kind,
docLink := d.info.docLink,
}))
2022-07-23 18:40:08 +00:00
index := { index with
declarations := newDecls ++ index.declarations
}
2022-07-23 18:40:08 +00:00
-- TODO: In theory one could sort instances and imports by name and batch the writes
for inst in module.instances do
let mut insts := index.instances.findD inst.className {}
insts := insts.insert inst.name
2022-07-23 18:40:08 +00:00
index := { index with instances := index.instances.insert inst.className insts }
for typeName in inst.typeNames do
let mut instsFor := index.instancesFor.findD typeName {}
instsFor := instsFor.insert inst.name
2022-07-23 18:40:08 +00:00
index := { index with instancesFor := index.instancesFor.insert typeName instsFor }
-- TODO: dedup
if index.modules.find? module.name |>.isNone then
let moduleLink ← moduleNameToLink (String.toName module.name)
let indexedModule := { url := moduleLink, importedBy := #[] }
index := { index with modules := index.modules.insert module.name indexedModule }
2022-07-23 18:40:08 +00:00
for imp in module.imports do
let indexedImp ←
match index.modules.find? imp with
| some i => pure i
| none =>
let impLink ← moduleNameToLink (String.toName imp)
let indexedModule := { url := impLink, importedBy := #[] }
pure indexedModule
index := { index with
modules :=
index.modules.insert
imp
{ indexedImp with importedBy := indexedImp.importedBy.push module.name }
}
2023-01-01 18:51:01 +00:00
return index
2022-07-23 18:40:08 +00:00
def DocInfo.toJson (module : Name) (info : Process.DocInfo) : HtmlM JsonDeclaration := do
let name := info.getName.toString
let kind := info.getKind
let doc := info.getDocString.getD ""
let docLink ← declNameToLink info.getName
let sourceLink ← getSourceUrl module info.getDeclarationRange
2023-08-06 13:36:43 +00:00
let line := info.getDeclarationRange.pos.line
let header := (← docInfoHeader info).toString
let info := { name, kind, doc, docLink, sourceLink, line }
return { info, header }
def Process.Module.toJson (module : Process.Module) : HtmlM Json := do
let mut jsonDecls := []
let mut instances := #[]
2023-02-16 18:51:35 +00:00
let declInfo := Process.filterDocInfo module.members
for decl in declInfo do
2023-01-01 18:51:01 +00:00
jsonDecls := (← DocInfo.toJson module.name decl) :: jsonDecls
if let .instanceInfo i := decl then
2022-07-23 13:40:08 +00:00
instances := instances.push {
name := i.name.toString,
className := i.className.toString
typeNames := i.typeNames.map Name.toString
}
let jsonMod : JsonModule := {
name := module.name.toString,
declarations := jsonDecls,
2022-07-23 13:40:08 +00:00
instances,
imports := module.imports.map Name.toString
}
2023-01-01 18:51:01 +00:00
return ToJson.toJson jsonMod
end DocGen4.Output