| /- | |
| Copyright (c) 2021 Microsoft Corporation. All rights reserved. | |
| Released under Apache 2.0 license as described in the file LICENSE. | |
| Authors: Leonardo de Moura | |
| -/ | |
| import Lean.DeclarationRange | |
| import Lean.MonadEnv | |
| namespace Lean | |
| private builtin_initialize builtinDocStrings : IO.Ref (NameMap String) ← IO.mkRef {} | |
| private builtin_initialize docStringExt : MapDeclarationExtension String ← mkMapDeclarationExtension | |
| private def findLeadingSpacesSize (s : String) : Nat := | |
| let it := s.iter | |
| let it := it.find (· == '\n') |>.next | |
| consumeSpaces it 0 s.length | |
| where | |
| consumeSpaces (it : String.Iterator) (curr min : Nat) : Nat := | |
| if it.atEnd then min | |
| else if it.curr == ' ' || it.curr == '\t' then consumeSpaces it.next (curr + 1) min | |
| else if it.curr == '\n' then findNextLine it.next min | |
| else findNextLine it.next (Nat.min curr min) | |
| findNextLine (it : String.Iterator) (min : Nat) : Nat := | |
| if it.atEnd then min | |
| else if it.curr == '\n' then consumeSpaces it.next 0 min | |
| else findNextLine it.next min | |
| private def removeNumLeadingSpaces (n : Nat) (s : String) : String := | |
| consumeSpaces n s.iter "" | |
| where | |
| consumeSpaces (n : Nat) (it : String.Iterator) (r : String) : String := | |
| match n with | |
| | 0 => saveLine it r | |
| | n+1 => | |
| if it.atEnd then r | |
| else if it.curr == ' ' || it.curr == '\t' then consumeSpaces n it.next r | |
| else saveLine it r | |
| saveLine (it : String.Iterator) (r : String) : String := | |
| if it.atEnd then r | |
| else if it.curr == '\n' then consumeSpaces n it.next (r.push '\n') | |
| else saveLine it.next (r.push it.curr) | |
| termination_by | |
| consumeSpaces n it r => (it, 1) | |
| saveLine it r => (it, 0) | |
| def removeLeadingSpaces (s : String) : String := | |
| let n := findLeadingSpacesSize s | |
| if n == 0 then s else removeNumLeadingSpaces n s | |
| def addBuiltinDocString (declName : Name) (docString : String) : IO Unit := | |
| builtinDocStrings.modify (·.insert declName (removeLeadingSpaces docString)) | |
| def addDocString [MonadEnv m] (declName : Name) (docString : String) : m Unit := | |
| modifyEnv fun env => docStringExt.insert env declName (removeLeadingSpaces docString) | |
| def addDocString' [Monad m] [MonadEnv m] (declName : Name) (docString? : Option String) : m Unit := | |
| match docString? with | |
| | some docString => addDocString declName docString | |
| | none => return () | |
| def findDocString? (env : Environment) (declName : Name) (includeBuiltin := true) : IO (Option String) := | |
| if let some docStr := docStringExt.find? env declName then | |
| return some docStr | |
| else if includeBuiltin then | |
| return (← builtinDocStrings.get).find? declName | |
| else | |
| return none | |
| structure ModuleDoc where | |
| doc : String | |
| declarationRange : DeclarationRange | |
| private builtin_initialize moduleDocExt : SimplePersistentEnvExtension ModuleDoc (PersistentArray ModuleDoc) ← registerSimplePersistentEnvExtension { | |
| addImportedFn := fun _ => {} | |
| addEntryFn := fun s e => s.push e | |
| toArrayFn := fun es => es.toArray | |
| } | |
| def addMainModuleDoc (env : Environment) (doc : ModuleDoc) : Environment := | |
| moduleDocExt.addEntry env doc | |
| def getMainModuleDoc (env : Environment) : PersistentArray ModuleDoc := | |
| moduleDocExt.getState env | |
| def getModuleDoc? (env : Environment) (moduleName : Name) : Option (Array ModuleDoc) := | |
| env.getModuleIdx? moduleName |>.map fun modIdx => moduleDocExt.getModuleEntries env modIdx | |
| def getDocStringText [Monad m] [MonadError m] [MonadRef m] (stx : TSyntax `Lean.Parser.Command.docComment) : m String := | |
| match stx.raw[1] with | |
| | Syntax.atom _ val => return val.extract 0 (val.endPos - ⟨2⟩) | |
| | _ => throwErrorAt stx "unexpected doc string{indentD stx.raw[1]}" | |
| def TSyntax.getDocString (stx : TSyntax `Lean.Parser.Command.docComment) : String := | |
| match stx.raw[1] with | |
| | Syntax.atom _ val => val.extract 0 (val.endPos - ⟨2⟩) | |
| | _ => "" | |
| end Lean |