-- | Functions to operate with @exposed-modules@ and @other-modules@ -- parts of .cabal file. module Importify.Cabal.Module ( modulePaths , splitOnExposedAndOther ) where import Universum hiding (fromString) import Data.List (partition) import Distribution.ModuleName (ModuleName, fromString, toFilePath) import qualified Distribution.ModuleName as Cabal import Distribution.PackageDescription (BuildInfo (..), Library (..)) import qualified Language.Haskell.Exts as HSE import Path (Abs, Dir, File, Path, Rel, parseRelDir, parseRelFile, ()) import Path.IO (doesFileExist) import Importify.Syntax (getModuleTitle) -- | Split list of modules into /exposed/ modules and /other/ modules for given library. -- __First__ element of pair represents /exposed/ modules. -- __Second__ element of paris represents /other/ modules. splitOnExposedAndOther :: Library -> [HSE.Module l] -> ([HSE.Module l], [HSE.Module l]) splitOnExposedAndOther Library{..} = partition ((`elem` exposedModules) . Cabal.fromString . getModuleTitle) -- | Returns list of absolute paths to all modules inside given target. modulePaths :: Path Abs Dir -- ^ Absolute path to project directory -> BuildInfo -- ^ 'BuildInfo' for given target -> Either [ModuleName] FilePath -- ^ Modules for Library and path for others -> IO [Path Abs File] modulePaths packagePath BuildInfo{..} extra = do let (cur, others) = partition (== ".") hsSourceDirs case (cur, others) of (_here, []) -> collectModulesHere ([] , paths) -> collectModulesThere paths (_here, paths) -> liftA2 (++) collectModulesHere (collectModulesThere paths) where modulesToPaths :: [ModuleName] -> IO [Path Rel File] modulesToPaths = mapM (parseRelFile . (++ ".hs") . toFilePath) targetModulePaths :: IO [Path Rel File] targetModulePaths = case extra of Left modules -> modulesToPaths $ otherModules ++ modules Right path -> liftA2 (:) (parseRelFile path) (modulesToPaths otherModules) addDir :: Path Abs Dir -> [Path Rel File] -> [Path Abs File] addDir dir = map (dir ) collectModulesHere :: IO [Path Abs File] collectModulesHere = do paths <- targetModulePaths let packagePaths = addDir packagePath paths keepExistingModules packagePaths collectModulesThere :: [FilePath] -> IO [Path Abs File] collectModulesThere dirs = do dirPaths <- mapM parseRelDir dirs modPaths <- targetModulePaths concatForM dirPaths $ \dir -> keepExistingModules $ addDir (packagePath dir) modPaths keepExistingModules :: [Path Abs File] -> IO [Path Abs File] keepExistingModules = filterM doesFileExist