    -- | Render an abstract representation of documentation (as produced
    -- by `parseGtkDoc`) as Haddock formatted documentation.
    module Data.GI.CodeGen.Haddock
      ( deprecatedPragma
      , writeDocumentation
      , RelativeDocPosition(..)
      , writeHaddock
      , writeArgDocumentation
      , writeReturnDocumentation
      , addSectionDocumentation
      ) where

    #if !MIN_VERSION_base(4,13,0)
    import Control.Monad (mapM_, unless)
    #else
    import Control.Monad (unless)
    #endif
    import qualified Data.Map as M
    #if !MIN_VERSION_base(4,11,0)
    import Data.Monoid ((<>))
    #endif
    import qualified Data.Text as T
    import Data.Text (Text)

    import Data.GI.GIR.Arg (Arg(..))
    import Data.GI.GIR.BasicTypes (Name(Name))
    import Data.GI.GIR.Callable (Callable(..))
    import Data.GI.GIR.Deprecation (DeprecationInfo(..))
    import Data.GI.GIR.Documentation (Documentation(..))

    import Data.GI.CodeGen.Code (CodeGen, config, line, HaddockSection,
                                 getC2HMap, addSectionFormattedDocs)
    import Data.GI.CodeGen.Config (modName, overrides)
    import Data.GI.CodeGen.CtoHaskellMap (Hyperlink(..))
    import Data.GI.CodeGen.GtkDoc (GtkDoc(..), Token(..), CRef(..), Language(..),
                                   Link(..), parseGtkDoc,
                                   DocSymbolName(..), resolveDocSymbol, docName)
    import Data.GI.CodeGen.Overrides (onlineDocsMap)
    import Data.GI.CodeGen.SymbolNaming (lowerSymbol, signalHaskellName,
                                         haddockSignalAnchor)

    -- | Where is the documentation located with respect to the relevant
    -- symbol, useful for determining whether we want to start with @|@ or @^@.
    data RelativeDocPosition = DocBeforeSymbol
                             | DocAfterSymbol

    -- | Given a `GtkDoc`, a map from C identifiers to Haskell symbols,
    -- and a location online where to find the C documentation, render the
    -- corresponding Haddock-formatted text. Note that the comment
    -- delimiters are not included in the output.
    --
    -- === __Examples__
    -- >>> formatHaddock M.empty "" "Test" (GtkDoc [Literal "Hello ", Literal "World!"])
    -- "Hello World!"
    --
    -- >>> formatHaddock M.empty "" "Test" (GtkDoc [Literal "This is a **bold** world!"])
    -- "This is a __bold__ world!"
    --
    -- >>> let c2h = M.fromList [(OldFunctionRef "foo", ValueIdentifier "foo")]
    -- >>> formatHaddock c2h "" "Test" (GtkDoc [SymbolRef (OldFunctionRef "foo")])
    -- "'foo'"
    --
    -- >>> let onlineDocs = "http://wiki.haskell.org"
    -- >>> formatHaddock M.empty onlineDocs "Test" (GtkDoc [ExternalLink (Link "GI" "GObjectIntrospection")])
    -- "<http://wiki.haskell.org/GObjectIntrospection GI>"
    --
    -- >>> formatHaddock M.empty "a" "Test" (GtkDoc [UnnumberedList [GtkDoc [Image (Link "test" "test.png")]]])
    -- "* <<a/test.png test>>\n"
    --
    -- >>> formatHaddock M.empty "a" "Test" (GtkDoc [NumberedList [("1", GtkDoc [Literal "Hi!"]), ("2", GtkDoc [Literal "Second and very long, so split\n line."])]])
    -- "1. Hi!\n\n2. Second and very long, so split\n   line.\n\n"
    formatHaddock :: M.Map CRef Hyperlink -> Text -> Text -> GtkDoc -> Text
    formatHaddock :: Map CRef Hyperlink -> Text -> Text -> GtkDoc -> Text
    formatHaddock Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS (GtkDoc [Token]
    tokens) = [Text] -> Text
    T.concat ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ (Token -> Text) -> [Token] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Token -> Text
    formatToken [Token]
    tokens
      where formatToken :: Token -> Text
            formatToken :: Token -> Text
    formatToken (Literal Text
    l) = Text -> Text
    escape (Text -> Text
    convertBold Text
    l)
            formatToken (Comment Text
    _) = Text
    ""
            formatToken (Verbatim Text
    v) = Text
    "@" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    escape Text
    v Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "@"
            formatToken (CodeBlock Maybe Language
    l Text
    c) = Maybe Language -> Text -> Text
    formatCodeBlock Maybe Language
    l Text
    c
            formatToken (ExternalLink Link
    l) = Link -> Text -> Text
    formatLink Link
    l Text
    docBase
            formatToken (Image Link
    l) = Link -> Text -> Text
    formatImage Link
    l Text
    docBase
            formatToken (SectionHeader Int
    l GtkDoc
    h) =
              Map CRef Hyperlink -> Text -> Text -> Int -> GtkDoc -> Text
    formatSectionHeader Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS Int
    l GtkDoc
    h
            formatToken (UnnumberedList [GtkDoc]
    l) =
              Map CRef Hyperlink -> Text -> Text -> [GtkDoc] -> Text
    formatUnnumberedList Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS [GtkDoc]
    l
            formatToken (NumberedList [(Text, GtkDoc)]
    l) =
              Map CRef Hyperlink -> Text -> Text -> [(Text, GtkDoc)] -> Text
    formatNumberedList Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS [(Text, GtkDoc)]
    l
            formatToken (SymbolRef CRef
    cr) = case CRef -> Map CRef Hyperlink -> Maybe Hyperlink
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup CRef
    cr Map CRef Hyperlink
    c2h of
              Just Hyperlink
    hr -> Hyperlink -> Text
    formatHyperlink Hyperlink
    hr
              Maybe Hyperlink
    Nothing -> Map CRef Hyperlink -> Text -> CRef -> Text
    formatUnknownCRef Map CRef Hyperlink
    c2h Text
    defaultNS CRef
    cr

            -- Markdown accepts both two underscores and two stars as
            -- indicating bold, but Haddock only accepts two underscores.
            convertBold :: Text -> Text
            convertBold :: Text -> Text
    convertBold Text
    l = HasCallStack => Text -> Text -> Text -> Text
    Text -> Text -> Text -> Text
    T.replace Text
    "**" Text
    "__" Text
    l

    -- | Format a `CRef` whose Haskell representation is not known, using
    -- a provided default namespace for relative symbols.
    formatUnknownCRef :: M.Map CRef Hyperlink -> Text -> CRef -> Text
    formatUnknownCRef :: Map CRef Hyperlink -> Text -> CRef -> Text
    formatUnknownCRef Map CRef Hyperlink
    _ Text
    _ (OldFunctionRef Text
    f) = Text -> Text
    formatCRef (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Text
    f Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "()"
    formatUnknownCRef Map CRef Hyperlink
    _ Text
    defaultNS (FunctionRef DocSymbolName
    n) =
      Text -> Text
    formatCRef (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ DocSymbolName -> Text -> Text
    formatDocSymbol DocSymbolName
    n Text
    defaultNS
    formatUnknownCRef Map CRef Hyperlink
    _ Text
    _ (ParamRef Text
    p) = Text
    "/@" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    lowerSymbol Text
    p Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "@/"
    formatUnknownCRef Map CRef Hyperlink
    _ Text
    _ (LocalSignalRef Text
    s) =
      let sn :: Text
    sn = Text -> Text
    signalHaskellName Text
    s
      in Text
    "[" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    sn Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "](#" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    haddockSignalAnchor Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    sn Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ")"
    formatUnknownCRef Map CRef Hyperlink
    c2h Text
    defaultNS (SignalRef DocSymbolName
    docSymbol Text
    signal) =
      let owner :: Name
    owner@(Name Text
    ns Text
    n) = DocSymbolName -> Text -> Name
    resolveDocSymbol DocSymbolName
    docSymbol Text
    defaultNS
      in case CRef -> Map CRef Hyperlink -> Maybe Hyperlink
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup (DocSymbolName -> CRef
    TypeRef (Name -> DocSymbolName
    docName Name
    owner)) Map CRef Hyperlink
    c2h of
        Maybe Hyperlink
    Nothing -> Text -> Text
    formatCRef (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Text
    ns Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    n Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "::" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    signal
        Just Hyperlink
    r -> Hyperlink -> Text
    formatHyperlink Hyperlink
    r Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "::" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    formatCRef Text
    signal
    formatUnknownCRef Map CRef Hyperlink
    c2h Text
    _ (OldSignalRef Text
    owner Text
    signal) =
      case CRef -> Map CRef Hyperlink -> Maybe Hyperlink
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup (Text -> CRef
    CTypeRef Text
    owner) Map CRef Hyperlink
    c2h of
        Maybe Hyperlink
    Nothing -> Text -> Text
    formatCRef (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Text
    owner Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "::" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    signal
        Just Hyperlink
    r -> Hyperlink -> Text
    formatHyperlink Hyperlink
    r Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "::" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    formatCRef Text
    signal
    formatUnknownCRef Map CRef Hyperlink
    c2h Text
    _ (OldPropertyRef Text
    owner Text
    prop) =
      case CRef -> Map CRef Hyperlink -> Maybe Hyperlink
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup (Text -> CRef
    CTypeRef Text
    owner) Map CRef Hyperlink
    c2h of
        Maybe Hyperlink
    Nothing -> Text -> Text
    formatCRef (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Text
    owner Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ":" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    prop
        Just Hyperlink
    r -> Hyperlink -> Text
    formatHyperlink Hyperlink
    r Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ":" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    formatCRef Text
    prop
    formatUnknownCRef Map CRef Hyperlink
    c2h Text
    defaultNS (PropertyRef DocSymbolName
    docSymbol Text
    prop) =
      let owner :: Name
    owner@(Name Text
    ns Text
    n) = DocSymbolName -> Text -> Name
    resolveDocSymbol DocSymbolName
    docSymbol Text
    defaultNS
      in case CRef -> Map CRef Hyperlink -> Maybe Hyperlink
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup (DocSymbolName -> CRef
    TypeRef (Name -> DocSymbolName
    docName Name
    owner)) Map CRef Hyperlink
    c2h of
        Maybe Hyperlink
    Nothing -> Text -> Text
    formatCRef (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Text
    ns Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    n Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ":" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    prop
        Just Hyperlink
    r -> Hyperlink -> Text
    formatHyperlink Hyperlink
    r Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ":" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    formatCRef Text
    prop
    formatUnknownCRef Map CRef Hyperlink
    c2h Text
    _ (VMethodRef Text
    owner Text
    vmethod) =
      case CRef -> Map CRef Hyperlink -> Maybe Hyperlink
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup (Text -> CRef
    CTypeRef Text
    owner) Map CRef Hyperlink
    c2h of
        Maybe Hyperlink
    Nothing -> Text -> Text
    formatCRef (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Text
    owner Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    vmethod Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "()"
        Just Hyperlink
    r -> Hyperlink -> Text
    formatHyperlink Hyperlink
    r Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    formatCRef Text
    vmethod Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "()"
    formatUnknownCRef Map CRef Hyperlink
    c2h Text
    defaultNS (VFuncRef DocSymbolName
    docSymbol Text
    vmethod) =
      let owner :: Name
    owner@(Name Text
    ns Text
    n) = DocSymbolName -> Text -> Name
    resolveDocSymbol DocSymbolName
    docSymbol Text
    defaultNS
      in case CRef -> Map CRef Hyperlink -> Maybe Hyperlink
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup (DocSymbolName -> CRef
    TypeRef (Name -> DocSymbolName
    docName Name
    owner)) Map CRef Hyperlink
    c2h of
        Maybe Hyperlink
    Nothing -> Text -> Text
    formatCRef (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Text
    ns Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    n Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    vmethod Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "()"
        Just Hyperlink
    r -> Hyperlink -> Text
    formatHyperlink Hyperlink
    r Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    formatCRef Text
    vmethod Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "()"
    formatUnknownCRef Map CRef Hyperlink
    c2h Text
    defaultNS(MethodRef DocSymbolName
    docSymbol Text
    method) =
      let owner :: Name
    owner@(Name Text
    ns Text
    n) = DocSymbolName -> Text -> Name
    resolveDocSymbol DocSymbolName
    docSymbol Text
    defaultNS
      in case CRef -> Map CRef Hyperlink -> Maybe Hyperlink
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup (DocSymbolName -> CRef
    TypeRef (Name -> DocSymbolName
    docName Name
    owner)) Map CRef Hyperlink
    c2h of
        Maybe Hyperlink
    Nothing -> Text -> Text
    formatCRef (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Text
    ns Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    n Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    method Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "()"
        Just Hyperlink
    r -> Hyperlink -> Text
    formatHyperlink Hyperlink
    r Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    formatCRef Text
    method Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "()"
    formatUnknownCRef Map CRef Hyperlink
    c2h Text
    _ (StructFieldRef Text
    owner Text
    field) =
      case CRef -> Map CRef Hyperlink -> Maybe Hyperlink
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup (Text -> CRef
    CTypeRef Text
    owner) Map CRef Hyperlink
    c2h of
        Maybe Hyperlink
    Nothing -> Text -> Text
    formatCRef (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Text
    owner Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    field
        Just Hyperlink
    r -> Hyperlink -> Text
    formatHyperlink Hyperlink
    r Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    formatCRef Text
    field
    formatUnknownCRef Map CRef Hyperlink
    _ Text
    _ (CTypeRef Text
    t) = Text -> Text
    formatCRef Text
    t
    formatUnknownCRef Map CRef Hyperlink
    _ Text
    defaultNS (TypeRef DocSymbolName
    n) =
      Text -> Text
    formatCRef (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ DocSymbolName -> Text -> Text
    formatDocSymbol DocSymbolName
    n Text
    defaultNS
    formatUnknownCRef Map CRef Hyperlink
    _ Text
    _ (ConstantRef Text
    t) = Text -> Text
    formatCRef Text
    t
    formatUnknownCRef Map CRef Hyperlink
    c2h Text
    defaultNS (EnumMemberRef DocSymbolName
    docSymbol Text
    member) =
      let owner :: Name
    owner@(Name Text
    ns Text
    n) = DocSymbolName -> Text -> Name
    resolveDocSymbol DocSymbolName
    docSymbol Text
    defaultNS
      in case CRef -> Map CRef Hyperlink -> Maybe Hyperlink
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup (DocSymbolName -> CRef
    TypeRef (Name -> DocSymbolName
    docName Name
    owner)) Map CRef Hyperlink
    c2h of
        Maybe Hyperlink
    Nothing -> Text -> Text
    formatCRef (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Text
    ns Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    n Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    member
        Just Hyperlink
    r -> Hyperlink -> Text
    formatHyperlink Hyperlink
    r Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    formatCRef Text
    member

    -- | Format the given symbol name in a fully qualified way, using the
    -- default namespace if needed.
    formatDocSymbol :: DocSymbolName -> Text -> Text
    formatDocSymbol :: DocSymbolName -> Text -> Text
    formatDocSymbol (RelativeName Text
    n) Text
    defaultNS = Text
    defaultNS Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    n
    formatDocSymbol (AbsoluteName Text
    ns Text
    n) Text
    _ = Text
    ns Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    n

    -- | Formatting for an unknown C reference.
    formatCRef :: Text -> Text
    formatCRef :: Text -> Text
    formatCRef Text
    t = Text
    "@/" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    escape Text
    t Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "/@"

    -- | Format a `Hyperlink` into plain `Text`.
    formatHyperlink :: Hyperlink -> Text
    formatHyperlink :: Hyperlink -> Text
    formatHyperlink (TypeIdentifier Text
    t) = Text
    "t'" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    t Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "'"
    formatHyperlink (ValueIdentifier Text
    t) = Text
    "'" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    t Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "'"
    formatHyperlink (ModuleLink Text
    m) = Text
    "\"" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    m Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "\""
    formatHyperlink (ModuleLinkWithAnchor Maybe Text
    mLabel Text
    m Text
    a) =
      case Maybe Text
    mLabel of
        Maybe Text
    Nothing -> Text
    "\"" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    m Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "#" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    a Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "\""
        Just Text
    label -> Text
    "[" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    label Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "](\"" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    m Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "#" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    a Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "\")"

    -- | Format a code block in a specified language.
    formatCodeBlock :: Maybe Language -> Text -> Text
    formatCodeBlock :: Maybe Language -> Text -> Text
    formatCodeBlock Maybe Language
    maybeLang Text
    code =
      let header :: Text
    header = case Maybe Language
    maybeLang of
            Maybe Language
    Nothing -> Text
    "\n\t\n"  -- This is to convince haddock that we
                                 -- are indeed starting a code block
            Just (Language Text
    lang) -> Text
    "\n=== /" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    lang Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    " code/\n"
          birdTrack :: Text -> Text
    birdTrack = [Text] -> Text
    T.unlines ([Text] -> Text) -> (Text -> [Text]) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Text -> Text) -> [Text] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (Char -> Text -> Text
    T.cons Char
    '>') ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> [Text]
    T.lines
      in Text
    header Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    birdTrack Text
    code

    -- | Qualify the given address with the docBase, if it is not an
    -- absolute address.
    qualifiedWith :: Text -> Text -> Text
    qualifiedWith :: Text -> Text -> Text
    qualifiedWith Text
    address Text
    docBase =
      if Text
    "http://" Text -> Text -> Bool
    `T.isPrefixOf` Text
    address Bool -> Bool -> Bool
    || Text
    "https://" Text -> Text -> Bool
    `T.isPrefixOf` Text
    address
      then Text
    address
      else if Text
    "/" Text -> Text -> Bool
    `T.isSuffixOf` Text
    docBase
           then Text
    docBase Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    address
           else Text
    docBase Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "/" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    address

    -- | Format a link to some external resource.
    formatLink :: Link -> Text -> Text
    formatLink :: Link -> Text -> Text
    formatLink (Link {linkName :: Link -> Text
    linkName = Text
    name, linkAddress :: Link -> Text
    linkAddress = Text
    address}) Text
    docBase =
      let address' :: Text
    address' = Text
    address Text -> Text -> Text
    `qualifiedWith` Text
    docBase
          name' :: Text
    name' = HasCallStack => Text -> Text -> Text -> Text
    Text -> Text -> Text -> Text
    T.replace Text
    ">" Text
    "\\>" Text
    name
      in Text
    "<" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    address' Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    " " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <>  Text
    name' Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ">"

    -- | Format an embedded image.
    formatImage :: Link -> Text -> Text
    formatImage :: Link -> Text -> Text
    formatImage (Link {linkName :: Link -> Text
    linkName = Text
    name, linkAddress :: Link -> Text
    linkAddress = Text
    address}) Text
    docBase =
      let address' :: Text
    address' = Text
    address Text -> Text -> Text
    `qualifiedWith` Text
    docBase
          name' :: Text
    name' = HasCallStack => Text -> Text -> Text -> Text
    Text -> Text -> Text -> Text
    T.replace Text
    ">" Text
    "\\>" Text
    name
      in if Text -> Bool
    T.null Text
    name'
         then Text
    "<<" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    address' Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ">>"
         else Text
    "<<" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    address' Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    " " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <>  Text
    name' Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ">>"

    -- | Format a section header of the given level and with the given
    -- text. Note that the level will be truncated to 2, if it is larger
    -- than that.
    formatSectionHeader :: M.Map CRef Hyperlink -> Text -> Text -> Int -> GtkDoc -> Text
    formatSectionHeader :: Map CRef Hyperlink -> Text -> Text -> Int -> GtkDoc -> Text
    formatSectionHeader Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS Int
    level GtkDoc
    header =
      Int -> Text -> Text
    T.replicate Int
    level Text
    "=" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    " " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Map CRef Hyperlink -> Text -> Text -> GtkDoc -> Text
    formatHaddock Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS GtkDoc
    header Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "\n"

    -- | Format a list of items.
    formatUnnumberedList :: M.Map CRef Hyperlink -> Text -> Text -> [GtkDoc]
                         -> Text
    formatUnnumberedList :: Map CRef Hyperlink -> Text -> Text -> [GtkDoc] -> Text
    formatUnnumberedList Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS [GtkDoc]
    items =
      [Text] -> Text
    T.concat ((GtkDoc -> Text) -> [GtkDoc] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map GtkDoc -> Text
    formatListItem [GtkDoc]
    items)
      where formatListItem :: GtkDoc -> Text
            formatListItem :: GtkDoc -> Text
    formatListItem GtkDoc
    doc =
              let indent :: Text -> Text
    indent Text
    l = Text
    "  " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    T.stripStart Text
    l
                  formatted :: Text
    formatted = Map CRef Hyperlink -> Text -> Text -> GtkDoc -> Text
    formatHaddock Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS GtkDoc
    doc
                  indented :: Text
    indented = ([Text] -> Text
    T.unlines ([Text] -> Text) -> (Text -> [Text]) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Text -> Text) -> [Text] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Text -> Text
    indent ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> [Text]
    T.lines) Text
    formatted
              in Text
    "* " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    T.stripStart Text
    indented

    -- | Format a numbered list of items.
    formatNumberedList :: M.Map CRef Hyperlink -> Text -> Text -> [(Text, GtkDoc)]
                       -> Text
    formatNumberedList :: Map CRef Hyperlink -> Text -> Text -> [(Text, GtkDoc)] -> Text
    formatNumberedList Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS [(Text, GtkDoc)]
    items =
      [Text] -> Text
    T.concat ([(Text, GtkDoc)] -> [Text]
    formatEnumeration [(Text, GtkDoc)]
    items)
      where
        formatEnumeration :: [(Text, GtkDoc)] -> [Text]
        formatEnumeration :: [(Text, GtkDoc)] -> [Text]
    formatEnumeration [] = []
        formatEnumeration ((Text
    idx, GtkDoc
    doc):[(Text, GtkDoc)]
    rest) =
          Text -> GtkDoc -> Text
    formatListItem Text
    idx GtkDoc
    doc Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "\n" Text -> [Text] -> [Text]
    forall a. a -> [a] -> [a]
    : [(Text, GtkDoc)] -> [Text]
    formatEnumeration [(Text, GtkDoc)]
    rest

        formatListItem :: Text -> GtkDoc -> Text
        formatListItem :: Text -> GtkDoc -> Text
    formatListItem Text
    idx GtkDoc
    doc =
          let indent :: Text -> Text
    indent Text
    l = Int -> Text -> Text
    T.replicate (Text -> Int
    T.length Text
    idx Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    2) Text
    " " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    T.stripStart Text
    l
              formatted :: Text
    formatted = Map CRef Hyperlink -> Text -> Text -> GtkDoc -> Text
    formatHaddock Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS GtkDoc
    doc
              indented :: Text
    indented = ([Text] -> Text
    T.unlines ([Text] -> Text) -> (Text -> [Text]) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Text -> Text) -> [Text] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Text -> Text
    indent ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> [Text]
    T.lines) Text
    formatted
          in Text
    idx Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ". " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    T.stripStart Text
    indented

    -- | Escape the reserved Haddock characters in a given `Text`.
    --
    -- === __Examples__
    -- >>> escape "\""
    -- "\\\""
    --
    -- >>> escape "foo@bar.com"
    -- "foo\\@bar.com"
    --
    -- >>> escape "C:\\Applications"
    -- "C:\\\\Applications"
    escape :: Text -> Text
    escape :: Text -> Text
    escape = (Char -> Text) -> Text -> Text
    T.concatMap Char -> Text
    escapeChar
      where
        escapeChar :: Char -> Text
        escapeChar :: Char -> Text
    escapeChar Char
    c = if Char
    c Char -> String -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` (String
    "\\/'`\"@<" :: [Char])
                       then Text
    "\\" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Char -> Text
    T.singleton Char
    c
                       else Char -> Text
    T.singleton Char
    c

    -- | Get the base url for the online C language documentation for the
    -- module being currently generated.
    getDocBase :: CodeGen e Text
    getDocBase :: forall e. CodeGen e Text
    getDocBase = do
      mod <- Config -> Text
    modName (Config -> Text)
    -> ReaderT
         CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Config
    -> ReaderT
         CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ReaderT
      CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) Config
    forall e. CodeGen e Config
    config
      docsMap <- (onlineDocsMap . overrides) <$> config
      return $ case M.lookup mod docsMap of
                 Just Text
    url -> Text
    url
                 Maybe Text
    Nothing -> Text
    "http://developer.gnome.org/" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    T.toLower Text
    mod Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <>
                            Text
    "/stable"

    -- | Write the deprecation pragma for the given `DeprecationInfo`, if
    -- not `Nothing`.
    deprecatedPragma :: Text -> Maybe DeprecationInfo -> CodeGen e ()
    deprecatedPragma :: forall e. Text -> Maybe DeprecationInfo -> CodeGen e ()
    deprecatedPragma Text
    _  Maybe DeprecationInfo
    Nothing = ()
    -> ReaderT
         CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) ()
    forall a.
    a
    -> ReaderT
         CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    deprecatedPragma Text
    name (Just DeprecationInfo
    info) = do
      c2h <- CodeGen e (Map CRef Hyperlink)
    forall e. CodeGen e (Map CRef Hyperlink)
    getC2HMap
      docBase <- getDocBase
      defaultNS <- modName <$> config
      line $ "{-# DEPRECATED " <> name <> " " <>
        (T.pack . show) (note <> reason c2h docBase defaultNS) <> " #-}"
            where reason :: Map CRef Hyperlink -> Text -> Text -> [Text]
    reason Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS =
                    case DeprecationInfo -> Maybe Text
    deprecationMessage DeprecationInfo
    info of
                      Maybe Text
    Nothing -> []
                      Just Text
    msg -> (Text -> Text) -> [Text] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (Map CRef Hyperlink -> Text -> Text -> GtkDoc -> Text
    formatHaddock Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS
                                       (GtkDoc -> Text) -> (Text -> GtkDoc) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> GtkDoc
    parseGtkDoc)
                                      (Text -> [Text]
    T.lines Text
    msg)
                  note :: [Text]
    note = case DeprecationInfo -> Maybe Text
    deprecatedSinceVersion DeprecationInfo
    info of
                           Maybe Text
    Nothing -> []
                           Just Text
    v -> [Text
    "(Since version " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    v Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ")"]

    -- | Format the given documentation into a set of lines. Note that
    -- this does include the opening or ending comment delimiters.
    formatDocumentation :: M.Map CRef Hyperlink -> Text -> Text -> Documentation -> Text
    formatDocumentation :: Map CRef Hyperlink -> Text -> Text -> Documentation -> Text
    formatDocumentation Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS Documentation
    doc = do
      let description :: Text
    description = case Documentation -> Maybe Text
    rawDocText Documentation
    doc of
            Just Text
    raw -> Map CRef Hyperlink -> Text -> Text -> GtkDoc -> Text
    formatHaddock Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS (Text -> GtkDoc
    parseGtkDoc Text
    raw)
            Maybe Text
    Nothing -> Text
    "/No description available in the introspection data./"
      Text
    description Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> case Documentation -> Maybe Text
    sinceVersion Documentation
    doc of
                       Maybe Text
    Nothing -> Text
    ""
                       Just Text
    ver -> Text
    "\n\n/Since: " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ver Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "/"

    -- | Write the given documentation into generated code.
    writeDocumentation :: RelativeDocPosition -> Documentation -> CodeGen e ()
    writeDocumentation :: forall e. RelativeDocPosition -> Documentation -> CodeGen e ()
    writeDocumentation RelativeDocPosition
    pos Documentation
    doc = do
      c2h <- CodeGen e (Map CRef Hyperlink)
    forall e. CodeGen e (Map CRef Hyperlink)
    getC2HMap
      docBase <- getDocBase
      defaultNS <- modName <$> config
      writeHaddock pos (formatDocumentation c2h docBase defaultNS doc)

    -- | Like `writeDocumentation`, but allows us to pass explicitly the
    -- Haddock comment to write.
    writeHaddock :: RelativeDocPosition -> Text -> CodeGen e ()
    writeHaddock :: forall e. RelativeDocPosition -> Text -> CodeGen e ()
    writeHaddock RelativeDocPosition
    pos Text
    haddock =
      let marker :: Text
    marker = case RelativeDocPosition
    pos of
            RelativeDocPosition
    DocBeforeSymbol -> Text
    "|"
            RelativeDocPosition
    DocAfterSymbol -> Text
    "^"
          lines :: [Text]
    lines = case Text -> [Text]
    T.lines Text
    haddock of
            [] -> []
            (Text
    first:[Text]
    rest) -> (Text
    "-- " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    marker Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    " " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    first) Text -> [Text] -> [Text]
    forall a. a -> [a] -> [a]
    : (Text -> Text) -> [Text] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (Text
    "-- " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <>) [Text]
    rest
      in (Text
     -> ReaderT
          CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) ())
    -> [Text]
    -> ReaderT
         CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ Text
    -> ReaderT
         CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) ()
    forall e. Text -> CodeGen e ()
    line [Text]
    lines

    -- | Write the documentation for the given argument.
    writeArgDocumentation :: Arg -> CodeGen e ()
    writeArgDocumentation :: forall e. Arg -> CodeGen e ()
    writeArgDocumentation Arg
    arg =
      case Documentation -> Maybe Text
    rawDocText (Arg -> Documentation
    argDoc Arg
    arg) of
        Maybe Text
    Nothing -> () -> CodeGen e ()
    forall a.
    a
    -> ReaderT
         CodeGenConfig (StateT (CGState, ModuleInfo) (Except e)) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
        Just Text
    raw -> do
          c2h <- CodeGen e (Map CRef Hyperlink)
    forall e. CodeGen e (Map CRef Hyperlink)
    getC2HMap
          docBase <- getDocBase
          defaultNS <- modName <$> config
          let haddock = Text
    "/@" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    lowerSymbol (Arg -> Text
    argCName Arg
    arg) Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "@/: " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <>
                        Map CRef Hyperlink -> Text -> Text -> GtkDoc -> Text
    formatHaddock Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS (Text -> GtkDoc
    parseGtkDoc Text
    raw)
          writeHaddock DocAfterSymbol haddock

    -- | Write the documentation for the given return value.
    writeReturnDocumentation :: Callable -> Bool -> CodeGen e ()
    writeReturnDocumentation :: forall e. Callable -> Bool -> CodeGen e ()
    writeReturnDocumentation Callable
    callable Bool
    skip = do
      c2h <- CodeGen e (Map CRef Hyperlink)
    forall e. CodeGen e (Map CRef Hyperlink)
    getC2HMap
      docBase <- getDocBase
      defaultNS <- modName <$> config
      let returnValInfo = if Bool
    skip
                          then []
                          else case Documentation -> Maybe Text
    rawDocText (Callable -> Documentation
    returnDocumentation Callable
    callable) of
                                 Maybe Text
    Nothing -> []
                                 Just Text
    raw -> [Text
    "__Returns:__ " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <>
                                               Map CRef Hyperlink -> Text -> Text -> GtkDoc -> Text
    formatHaddock Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS
                                               (Text -> GtkDoc
    parseGtkDoc Text
    raw)]
          throwsInfo = if Callable -> Bool
    callableThrows Callable
    callable
                       then [Text
    "/(Can throw 'Data.GI.Base.GError.GError')/"]
                       else []
      let fullInfo = Text -> [Text] -> Text
    T.intercalate Text
    " " ([Text]
    returnValInfo [Text] -> [Text] -> [Text]
    forall a. [a] -> [a] -> [a]
    ++ [Text]
    throwsInfo)
      unless (T.null fullInfo) $
        writeHaddock DocAfterSymbol fullInfo

    -- | Add the given text to the documentation for the section being generated.
    addSectionDocumentation :: HaddockSection -> Documentation -> CodeGen e ()
    addSectionDocumentation :: forall e. HaddockSection -> Documentation -> CodeGen e ()
    addSectionDocumentation HaddockSection
    section Documentation
    doc = do
      c2h <- CodeGen e (Map CRef Hyperlink)
    forall e. CodeGen e (Map CRef Hyperlink)
    getC2HMap
      docBase <- getDocBase
      defaultNS <- modName <$> config
      let formatted = Map CRef Hyperlink -> Text -> Text -> Documentation -> Text
    formatDocumentation Map CRef Hyperlink
    c2h Text
    docBase Text
    defaultNS Documentation
    doc
      addSectionFormattedDocs section formatted