{- |
Module:  Pollock.ModuleInfo.ModuleInfo
Copyright: (c) Trevis Elser 2023
License:  MIT
Maintainer: trevis@flipstone.com
Stability: experimental
Portability: portable
-}
module Pollock.ModuleInfo.ModuleInfo
  ( ModuleInfo (..)
  , buildModuleInfo
  ) where

import qualified Data.Maybe as Maybe

import qualified Pollock.CompatGHC as CompatGHC
import qualified Pollock.Documentation as Documentation
import qualified Pollock.ModuleInfo.ModuleHeader as ModuleHeader

data ModuleInfo = ModuleInfo
  { ModuleInfo -> ModuleHeader
moduleHeader :: !ModuleHeader.ModuleHeader
  -- ^ The haddock module header
  , ModuleInfo -> Int
haddockableExports :: !Int
  -- ^ How many exported items that could have documentation attached.
  , ModuleInfo -> Int
haddockedExports :: !Int
  -- ^ How many exported items that do have haddock attached.
  , ModuleInfo -> Int
numWithSince :: !Int
  -- ^ How many exported items have a since annotation.
  , ModuleInfo -> Int
numWithCodeBlock :: !Int
  -- ^ How many exported items have a code block included in the documentation.
  , ModuleInfo -> Int
numWithExample :: !Int
  -- ^ How many exported items have an example included in the documentation.
  , ModuleInfo -> Int
numWithProperty :: !Int
  -- ^ How many exported items have a property included in the documentation.
  , ModuleInfo -> Int
numWithWarning :: !Int
  -- ^ How many exported items have a warning attached to them.
  }

buildModuleInfo :: Maybe CompatGHC.HsDocString -> [Documentation.ExportItem] -> ModuleInfo
buildModuleInfo :: Maybe HsDocString -> [ExportItem] -> ModuleInfo
buildModuleInfo Maybe HsDocString
str =
  let
    initialModuleInfo :: ModuleInfo
initialModuleInfo =
      ModuleInfo
        { moduleHeader :: ModuleHeader
moduleHeader = Maybe HsDocString -> ModuleHeader
ModuleHeader.processModuleHeader Maybe HsDocString
str
        , haddockableExports :: Int
haddockableExports = Int
0
        , haddockedExports :: Int
haddockedExports = Int
0
        , numWithSince :: Int
numWithSince = Int
0
        , numWithCodeBlock :: Int
numWithCodeBlock = Int
0
        , numWithExample :: Int
numWithExample = Int
0
        , numWithProperty :: Int
numWithProperty = Int
0
        , numWithWarning :: Int
numWithWarning = Int
0
        }
   in
    (ExportItem -> ModuleInfo -> ModuleInfo)
-> ModuleInfo -> [ExportItem] -> ModuleInfo
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ExportItem -> ModuleInfo -> ModuleInfo
foldExportItemInfo ModuleInfo
initialModuleInfo

foldExportItemInfo :: Documentation.ExportItem -> ModuleInfo -> ModuleInfo
foldExportItemInfo :: ExportItem -> ModuleInfo -> ModuleInfo
foldExportItemInfo ExportItem
exportItem ModuleInfo
moduleInfo =
  if ExportItem -> Bool
hasDoc ExportItem
exportItem
    then
      ModuleInfo
moduleInfo
        { haddockableExports =
            haddockableExports moduleInfo + 1
        , haddockedExports =
            haddockedExports moduleInfo + 1
        , numWithSince =
            if Documentation.exportItemHasSinceVersion exportItem
              then numWithSince moduleInfo + 1
              else numWithSince moduleInfo
        , numWithCodeBlock =
            if Documentation.exportItemHasCodeBlock exportItem
              then numWithCodeBlock moduleInfo + 1
              else numWithCodeBlock moduleInfo
        , numWithExample =
            if Documentation.exportItemHasExample exportItem
              then numWithExample moduleInfo + 1
              else numWithExample moduleInfo
        , numWithProperty =
            if Documentation.exportItemHasProperty exportItem
              then numWithProperty moduleInfo + 1
              else numWithProperty moduleInfo
        , numWithWarning =
            if Documentation.exportItemHasWarning exportItem
              then numWithWarning moduleInfo + 1
              else numWithWarning moduleInfo
        }
    else -- With no docs we _only_ had an export, but nothing else.

      ModuleInfo
moduleInfo
        { haddockableExports =
            haddockableExports moduleInfo + 1
        }

hasDoc :: Documentation.ExportItem -> Bool
hasDoc :: ExportItem -> Bool
hasDoc
  ( Documentation.ExportItemDecl
      (Documentation.ExportDecl (Documentation.DocumentationForDecl Maybe MetaAndDoc
d Maybe Doc
_ FnArgsDoc
_))
    ) = Maybe MetaAndDoc -> Bool
forall a. Maybe a -> Bool
Maybe.isJust Maybe MetaAndDoc
d
hasDoc ExportItem
_ = Bool
True