-- | 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(..), ListItem(..), parseGtkDoc)
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 "" (GtkDoc [Literal "Hello ", Literal "World!"])
-- "Hello World!"
--
-- >>> let c2h = M.fromList [(OldFunctionRef "foo", ValueIdentifier "foo")]
-- >>> formatHaddock c2h "" (GtkDoc [SymbolRef (OldFunctionRef "foo")])
-- "'foo'"
--
-- >>> let onlineDocs = "http://wiki.haskell.org"
-- >>> formatHaddock M.empty onlineDocs (GtkDoc [ExternalLink (Link "GI" "GObjectIntrospection")])
-- "<http://wiki.haskell.org/GObjectIntrospection GI>"
--
-- >>> formatHaddock M.empty "a" (GtkDoc [List [ListItem (GtkDoc [Image (Link "test" "test.png")]) []]])
-- "\n* <<a/test.png test>>\n"
formatHaddock :: M.Map CRef Hyperlink -> Text -> GtkDoc -> Text
formatHaddock :: Map CRef Hyperlink -> Text -> GtkDoc -> Text
formatHaddock Map CRef Hyperlink
c2h Text
docBase (GtkDoc [Token]
doc) = [Text] -> Text
T.concat forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map Token -> Text
formatToken [Token]
doc
  where formatToken :: Token -> Text
        formatToken :: Token -> Text
formatToken (Literal Text
l) = Text -> Text
escape Text
l
        formatToken (Comment Text
_) = Text
""
        formatToken (Verbatim Text
v) = Text
"@" forall a. Semigroup a => a -> a -> a
<> Text -> Text
escape Text
v 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 -> Int -> GtkDoc -> Text
formatSectionHeader Map CRef Hyperlink
c2h Text
docBase Int
l GtkDoc
h
        formatToken (List [ListItem]
l) = Map CRef Hyperlink -> Text -> [ListItem] -> Text
formatList Map CRef Hyperlink
c2h Text
docBase [ListItem]
l
        formatToken (SymbolRef CRef
cr) = case 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 -> CRef -> Text
formatUnknownCRef Map CRef Hyperlink
c2h CRef
cr

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

-- | Formatting for an unknown C reference.
formatCRef :: Text -> Text
formatCRef :: Text -> Text
formatCRef Text
t = Text
"@/" forall a. Semigroup a => a -> a -> a
<> Text -> Text
escape Text
t 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'" forall a. Semigroup a => a -> a -> a
<> Text
t forall a. Semigroup a => a -> a -> a
<> Text
"'"
formatHyperlink (ValueIdentifier Text
t) = Text
"'" forall a. Semigroup a => a -> a -> a
<> Text
t forall a. Semigroup a => a -> a -> a
<> Text
"'"
formatHyperlink (ModuleLink Text
m) = Text
"\"" forall a. Semigroup a => a -> a -> a
<> Text
m 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
"\"" forall a. Semigroup a => a -> a -> a
<> Text
m forall a. Semigroup a => a -> a -> a
<> Text
"#" forall a. Semigroup a => a -> a -> a
<> Text
a forall a. Semigroup a => a -> a -> a
<> Text
"\""
    Just Text
label -> Text
"[" forall a. Semigroup a => a -> a -> a
<> Text
label forall a. Semigroup a => a -> a -> a
<> Text
"](\"" forall a. Semigroup a => a -> a -> a
<> Text
m forall a. Semigroup a => a -> a -> a
<> Text
"#" forall a. Semigroup a => a -> a -> a
<> Text
a 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
""
        Just (Language Text
lang) -> Text
"\n=== /" forall a. Semigroup a => a -> a -> a
<> Text
lang forall a. Semigroup a => a -> a -> a
<> Text
" code/\n"
      birdTrack :: Text -> Text
birdTrack = [Text] -> Text
T.unlines forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (Char -> Text -> Text
T.cons Char
'>') forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
T.lines
  in Text
header 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 forall a. Semigroup a => a -> a -> a
<> Text
address
       else Text
docBase forall a. Semigroup a => a -> a -> a
<> 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' = Text -> Text -> Text -> Text
T.replace Text
">" Text
"\\>" Text
name
  in Text
"<" forall a. Semigroup a => a -> a -> a
<> Text
address' forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<>  Text
name' 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' = Text -> Text -> Text -> Text
T.replace Text
">" Text
"\\>" Text
name
  in if Text -> Bool
T.null Text
name'
     then Text
"<<" forall a. Semigroup a => a -> a -> a
<> Text
address' forall a. Semigroup a => a -> a -> a
<> Text
">>"
     else Text
"<<" forall a. Semigroup a => a -> a -> a
<> Text
address' forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<>  Text
name' 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 -> Int -> GtkDoc -> Text
formatSectionHeader :: Map CRef Hyperlink -> Text -> Int -> GtkDoc -> Text
formatSectionHeader Map CRef Hyperlink
c2h Text
docBase Int
level GtkDoc
header =
  Int -> Text -> Text
T.replicate Int
level Text
"=" forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<> Map CRef Hyperlink -> Text -> GtkDoc -> Text
formatHaddock Map CRef Hyperlink
c2h Text
docBase GtkDoc
header forall a. Semigroup a => a -> a -> a
<> Text
"\n"

-- | Format a list of items.
formatList :: M.Map CRef Hyperlink -> Text -> [ListItem] -> Text
formatList :: Map CRef Hyperlink -> Text -> [ListItem] -> Text
formatList Map CRef Hyperlink
c2h Text
docBase [ListItem]
items = Text
"\n" forall a. Semigroup a => a -> a -> a
<> [Text] -> Text
T.concat (forall a b. (a -> b) -> [a] -> [b]
map ListItem -> Text
formatListItem [ListItem]
items)
  where formatListItem :: ListItem -> Text
        formatListItem :: ListItem -> Text
formatListItem (ListItem GtkDoc
first [GtkDoc]
rest) =
          Text
"* " forall a. Semigroup a => a -> a -> a
<> GtkDoc -> Text
format GtkDoc
first forall a. Semigroup a => a -> a -> a
<> Text
"\n"
          forall a. Semigroup a => a -> a -> a
<> [Text] -> Text
T.concat (forall a b. (a -> b) -> [a] -> [b]
map ((forall a. Semigroup a => a -> a -> a
<> Text
"\n") forall b c a. (b -> c) -> (a -> b) -> a -> c
. GtkDoc -> Text
format) [GtkDoc]
rest)

        format :: GtkDoc -> Text
        format :: GtkDoc -> Text
format = Map CRef Hyperlink -> Text -> GtkDoc -> Text
formatHaddock Map CRef Hyperlink
c2h Text
docBase

-- | 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 forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` ([Char]
"\\/'`\"@<" :: [Char])
                   then 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
  Text
mod <- Config -> Text
modName forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e. CodeGen e Config
config
  Map Text Text
docsMap <- (Overrides -> Map Text Text
onlineDocsMap forall b c a. (b -> c) -> (a -> b) -> a -> c
. Config -> Overrides
overrides) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e. CodeGen e Config
config
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ case forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Text
mod Map Text Text
docsMap of
             Just Text
url -> Text
url
             Maybe Text
Nothing -> Text
"http://developer.gnome.org/" forall a. Semigroup a => a -> a -> a
<> Text -> Text
T.toLower Text
mod 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 = forall (m :: * -> *) a. Monad m => a -> m a
return ()
deprecatedPragma Text
name (Just DeprecationInfo
info) = do
  Map CRef Hyperlink
c2h <- forall e. CodeGen e (Map CRef Hyperlink)
getC2HMap
  Text
docBase <- forall e. CodeGen e Text
getDocBase
  forall e. Text -> CodeGen e ()
line forall a b. (a -> b) -> a -> b
$ Text
"{-# DEPRECATED " forall a. Semigroup a => a -> a -> a
<> Text
name forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<>
    ([Char] -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> [Char]
show) ([Text]
note forall a. Semigroup a => a -> a -> a
<> Map CRef Hyperlink -> Text -> [Text]
reason Map CRef Hyperlink
c2h Text
docBase) forall a. Semigroup a => a -> a -> a
<> Text
" #-}"
        where reason :: Map CRef Hyperlink -> Text -> [Text]
reason Map CRef Hyperlink
c2h Text
docBase =
                case DeprecationInfo -> Maybe Text
deprecationMessage DeprecationInfo
info of
                  Maybe Text
Nothing -> []
                  Just Text
msg -> forall a b. (a -> b) -> [a] -> [b]
map (Map CRef Hyperlink -> Text -> GtkDoc -> Text
formatHaddock Map CRef Hyperlink
c2h Text
docBase 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 " forall a. Semigroup a => a -> a -> a
<> Text
v 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 -> Documentation -> Text
formatDocumentation :: Map CRef Hyperlink -> Text -> Documentation -> Text
formatDocumentation Map CRef Hyperlink
c2h Text
docBase Documentation
doc = do
  let description :: Text
description = case Documentation -> Maybe Text
rawDocText Documentation
doc of
        Just Text
raw -> Map CRef Hyperlink -> Text -> GtkDoc -> Text
formatHaddock Map CRef Hyperlink
c2h Text
docBase (Text -> GtkDoc
parseGtkDoc Text
raw)
        Maybe Text
Nothing -> Text
"/No description available in the introspection data./"
  Text
description 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: " forall a. Semigroup a => a -> a -> a
<> Text
ver 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
  Map CRef Hyperlink
c2h <- forall e. CodeGen e (Map CRef Hyperlink)
getC2HMap
  Text
docBase <- forall e. CodeGen e Text
getDocBase
  forall e. RelativeDocPosition -> Text -> CodeGen e ()
writeHaddock RelativeDocPosition
pos (Map CRef Hyperlink -> Text -> Documentation -> Text
formatDocumentation Map CRef Hyperlink
c2h Text
docBase Documentation
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
"-- " forall a. Semigroup a => a -> a -> a
<> Text
marker forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<> Text
first) forall a. a -> [a] -> [a]
: forall a b. (a -> b) -> [a] -> [b]
map (Text
"-- " forall a. Semigroup a => a -> a -> a
<>) [Text]
rest
  in forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ 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 -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
    Just Text
raw -> do
      Map CRef Hyperlink
c2h <- forall e. CodeGen e (Map CRef Hyperlink)
getC2HMap
      Text
docBase <- forall e. CodeGen e Text
getDocBase
      let haddock :: Text
haddock = Text
"/@" forall a. Semigroup a => a -> a -> a
<> Text -> Text
lowerSymbol (Arg -> Text
argCName Arg
arg) forall a. Semigroup a => a -> a -> a
<> Text
"@/: " forall a. Semigroup a => a -> a -> a
<>
                    Map CRef Hyperlink -> Text -> GtkDoc -> Text
formatHaddock Map CRef Hyperlink
c2h Text
docBase (Text -> GtkDoc
parseGtkDoc Text
raw)
      forall e. RelativeDocPosition -> Text -> CodeGen e ()
writeHaddock RelativeDocPosition
DocAfterSymbol Text
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
  Map CRef Hyperlink
c2h <- forall e. CodeGen e (Map CRef Hyperlink)
getC2HMap
  Text
docBase <- forall e. CodeGen e Text
getDocBase
  let returnValInfo :: [Text]
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:__ " forall a. Semigroup a => a -> a -> a
<>
                                           Map CRef Hyperlink -> Text -> GtkDoc -> Text
formatHaddock Map CRef Hyperlink
c2h Text
docBase
                                           (Text -> GtkDoc
parseGtkDoc Text
raw)]
      throwsInfo :: [Text]
throwsInfo = if Callable -> Bool
callableThrows Callable
callable
                   then [Text
"/(Can throw 'Data.GI.Base.GError.GError')/"]
                   else []
  let fullInfo :: Text
fullInfo = Text -> [Text] -> Text
T.intercalate Text
" " ([Text]
returnValInfo forall a. [a] -> [a] -> [a]
++ [Text]
throwsInfo)
  forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Text -> Bool
T.null Text
fullInfo) forall a b. (a -> b) -> a -> b
$
    forall e. RelativeDocPosition -> Text -> CodeGen e ()
writeHaddock RelativeDocPosition
DocAfterSymbol Text
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
  Map CRef Hyperlink
c2h <- forall e. CodeGen e (Map CRef Hyperlink)
getC2HMap
  Text
docBase <- forall e. CodeGen e Text
getDocBase
  let formatted :: Text
formatted = Map CRef Hyperlink -> Text -> Documentation -> Text
formatDocumentation Map CRef Hyperlink
c2h Text
docBase Documentation
doc
  forall e. HaddockSection -> Text -> CodeGen e ()
addSectionFormattedDocs HaddockSection
section Text
formatted