content: {- | The module contains pure function to parse GHC data types that we get from
  @.hie@ files.
  
  -}
  module Policeman.Core.Hie
      ( hieFileToModuleStructure
      , hieFilesToHashMap
      ) where
  
  import Avail (AvailInfo (..))
  import FastString (unpackFS)
  import FieldLabel (FieldLabel, FieldLbl (..))
  import HieTypes (HieFile (..))
  import Module (moduleName, moduleNameString)
  import Name (Name, nameOccName)
  import OccName (occNameString)
  
  import Policeman.Core.Package (Export (..), Module (..), ModuleStructure (..))
  
  import qualified Data.HashMap.Strict as HM
  import qualified Data.Set as Set
  
  
  {- | Creates the list of 'Export's from the given 'AvailInfo'.
  
  As the data type or type class can bring to export more than 1 entry
  'availInfoToExport' returns the list of the exports. It adds the name of the
  data type or the type class as the prefix separated with the dot @.@.
  -}
  availInfoToExport :: AvailInfo -> [Export]
  availInfoToExport (Avail name) = [ExportedFunction $ nameToText name]
  availInfoToExport (AvailTC (nameToText -> name) pieces fields) =
      ExportedType name
      :  map piecesToExport pieces
      ++ map fieldsToExport fields
    where
      piecesToExport :: Name -> Export
      piecesToExport = addPrefixName . nameToText
  
      fieldsToExport :: FieldLabel -> Export
      fieldsToExport FieldLabel{..} = addPrefixName $ toText $ unpackFS flLabel
  
      addPrefixName :: Text -> Export
      addPrefixName n = ExportedType $ name <> "." <> n
  
  nameToText :: Name -> Text
  nameToText = toText . occNameString . nameOccName
  
  
  hieFileToModuleStructure :: HieFile -> ModuleStructure
  hieFileToModuleStructure hf = ModuleStructure
      { msExports = Set.fromList $ concatMap availInfoToExport $ hie_exports hf
      }
  
  
  hieFileToModule :: HieFile -> Module
  hieFileToModule = Module . toText . moduleNameString . moduleName . hie_module
  
  hieFilesToHashMap :: [HieFile] -> HashMap Module ModuleStructure
  hieFilesToHashMap = HM.fromList . map (\hf -> (hieFileToModule hf, hieFileToModuleStructure hf))
  