{- |
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 :: Int
haddockableExports =
            ModuleInfo -> Int
haddockableExports ModuleInfo
moduleInfo Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
        , haddockedExports :: Int
haddockedExports =
            ModuleInfo -> Int
haddockedExports ModuleInfo
moduleInfo Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
        , numWithSince :: Int
numWithSince =
            if ExportItem -> Bool
Documentation.exportItemHasSinceVersion ExportItem
exportItem
              then ModuleInfo -> Int
numWithSince ModuleInfo
moduleInfo Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
              else ModuleInfo -> Int
numWithSince ModuleInfo
moduleInfo
        , numWithCodeBlock :: Int
numWithCodeBlock =
            if ExportItem -> Bool
Documentation.exportItemHasCodeBlock ExportItem
exportItem
              then ModuleInfo -> Int
numWithCodeBlock ModuleInfo
moduleInfo Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
              else ModuleInfo -> Int
numWithCodeBlock ModuleInfo
moduleInfo
        , numWithExample :: Int
numWithExample =
            if ExportItem -> Bool
Documentation.exportItemHasExample ExportItem
exportItem
              then ModuleInfo -> Int
numWithExample ModuleInfo
moduleInfo Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
              else ModuleInfo -> Int
numWithExample ModuleInfo
moduleInfo
        , numWithProperty :: Int
numWithProperty =
            if ExportItem -> Bool
Documentation.exportItemHasProperty ExportItem
exportItem
              then ModuleInfo -> Int
numWithProperty ModuleInfo
moduleInfo Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
              else ModuleInfo -> Int
numWithProperty ModuleInfo
moduleInfo
        , numWithWarning :: Int
numWithWarning =
            if ExportItem -> Bool
Documentation.exportItemHasWarning ExportItem
exportItem
              then ModuleInfo -> Int
numWithWarning ModuleInfo
moduleInfo Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
              else ModuleInfo -> Int
numWithWarning ModuleInfo
moduleInfo
        }
    else -- With no docs we _only_ had an export, but nothing else.

      ModuleInfo
moduleInfo
        { haddockableExports :: Int
haddockableExports =
            ModuleInfo -> Int
haddockableExports ModuleInfo
moduleInfo Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
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