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)