purescript-0.12.0: src/Language/PureScript/Docs/ParseInPackage.hs
module Language.PureScript.Docs.ParseInPackage
( parseFilesInPackages
) where
import Protolude
import qualified Data.Map as M
import Language.PureScript.Docs.Types
import qualified Language.PureScript as P
import System.IO.UTF8 (readUTF8FileT)
import Web.Bower.PackageMeta (PackageName)
-- |
-- Given:
--
-- * A list of local source files
-- * A list of source files from external dependencies, together with their
-- package names
--
-- This function does the following:
--
-- * Parse all of the input and dependency source files
-- * Associate each dependency module with its package name, thereby
-- distinguishing these from local modules
-- * Return the paths paired with parsed modules, and a Map of module names
-- to package names for modules which come from dependencies.
-- If a module does not exist in the map, it can safely be assumed to be
-- local.
parseFilesInPackages ::
(MonadError P.MultipleErrors m, MonadIO m) =>
[FilePath]
-> [(PackageName, FilePath)]
-> m ([(FilePath, P.Module)], Map P.ModuleName PackageName)
parseFilesInPackages inputFiles depsFiles = do
inputFiles' <- traverse (readFileAs . Local) inputFiles
depsFiles' <- traverse (readFileAs . uncurry FromDep) depsFiles
modules <- parse (inputFiles' ++ depsFiles')
let mnMap = M.fromList (mapMaybe (\(inpkg, m) -> (P.getModuleName m,) <$> inPkgToMaybe inpkg) modules)
pure (map (first fileInfoToString) modules, mnMap)
where
parse ::
(MonadError P.MultipleErrors m) =>
[(FileInfo, Text)]
-> m [(FileInfo, P.Module)]
parse =
throwLeft . P.parseModulesFromFiles fileInfoToString
inPkgToMaybe = \case
Local _ -> Nothing
FromDep pkgName _ -> Just pkgName
throwLeft :: (MonadError l m) => Either l r -> m r
throwLeft = either throwError return
-- | Specifies whether a PureScript source file is considered as:
--
-- 1) with the `Local` constructor, a target source file, i.e., we want to see
-- its modules in the output
-- 2) with the `FromDep` constructor, a dependencies source file, i.e. we do
-- not want its modules in the output; it is there to enable desugaring, and
-- to ensure that links between modules are constructed correctly.
type FileInfo = InPackage FilePath
fileInfoToString :: FileInfo -> FilePath
fileInfoToString (Local fn) = fn
fileInfoToString (FromDep _ fn) = fn
readFileAs :: (MonadIO m) => FileInfo -> m (FileInfo, Text)
readFileAs fi = liftIO . fmap ((fi,)) $ readUTF8FileT (ignorePackage fi)