{-# OPTIONS -Wall #-} -------------------------------------------------------------------------------- -- | -- Module : Precis.Cabal.InterimDatatypes -- Copyright : (c) Stephen Tetley 2010 -- License : BSD3 -- -- Maintainer : Stephen Tetley -- Stability : highly unstable -- Portability : to be determined. -- -- Datatype for working with Cabal files... -- -------------------------------------------------------------------------------- module Precis.Cabal.InterimDatatypes ( FileExtension , CabalFilePath , cabalFilePath , pathToCabalFile , directoriesToCabalFile , ExeMainPath(..) , CabalSourceDir , cabalSourceDir , directoriesToSource , ModName , modName , getModName , ModuleDesc , moduleDesc , moduleDescName , moduleDirectories , CabalPrecis(..) , CabalLibrary(..) , CabalExe(..) ) where import qualified Distribution.ModuleName as D import Data.List ( intersperse ) import System.FilePath type FileExtension = String -- | 'CabalFilePath' is both the full, normalized path to the -- cabal file and the directory parts to the file. -- -- This is an opaque type - construct with 'cabalFilePath'. -- data CabalFilePath = CabalFilePath { cabal_full_loc :: FilePath , cabal_path_to_split :: [FilePath] } deriving (Eq,Ord,Show) -- | Constructor for 'CabalFilePath' - the input FilePath is -- normalized before constructing the data type. -- cabalFilePath :: FilePath -> CabalFilePath cabalFilePath path = CabalFilePath { cabal_full_loc = full, cabal_path_to_split = parts } where full = normalise path parts = splitPath $ dropFileName full pathToCabalFile :: CabalFilePath -> FilePath pathToCabalFile = cabal_full_loc directoriesToCabalFile :: CabalFilePath -> [FilePath] directoriesToCabalFile = cabal_path_to_split newtype ExeMainPath = ExeMainPath { relPathToExeMain :: FilePath } deriving (Eq,Ord,Show) data CabalSourceDir = CabalSourceDir { srcdir_rel_loc :: FilePath , srcdir_path_to_split :: [FilePath] } deriving (Eq,Ord,Show) cabalSourceDir :: FilePath -> CabalSourceDir cabalSourceDir path = CabalSourceDir { srcdir_rel_loc = rel, srcdir_path_to_split = parts } where rel = normalise path parts = splitPath rel directoriesToSource :: CabalSourceDir -> [FilePath] directoriesToSource = srcdir_path_to_split newtype ModName = ModName { mod_name :: String } deriving (Eq,Ord,Show) modName :: D.ModuleName -> ModName modName = ModName . concat . intersperse "." . D.components getModName :: ModName -> String getModName = mod_name data ModuleDesc = ModuleDesc { module_desc_name :: ModName , module_components :: [FilePath] } deriving (Eq,Ord,Show) moduleDesc :: D.ModuleName -> ModuleDesc moduleDesc mname = ModuleDesc { module_desc_name = name, module_components = parts } where xs = D.components mname name = ModName $ concat $ intersperse "." xs -- Add separator to inits but not last... parts = foldr fn [] xs where fn e [] = [e] fn e ac = (e++[pathSeparator]):ac moduleDescName :: ModuleDesc -> ModName moduleDescName = module_desc_name moduleDirectories :: ModuleDesc -> [FilePath] moduleDirectories = module_components -- Do we want /resolution/ during the building -- the CabalPrecis or afterwards? -- -- i.e. when do we query the file system to locate the modules? -- Because of CondTree/Conditional a Cabal file can appear as -- though it contains more than one Library, some normalization -- has to be performed on this structure... -- data CabalPrecis = CabalPrecis { pkg_name :: String , pkg_version :: String , path_to_cabal_file :: CabalFilePath , cond_libraries :: [CabalLibrary] , cond_exes :: [CabalExe] } deriving (Eq,Show) -- One library per cabal file / package. data CabalLibrary = CabalLibrary { library_src_dirs :: [CabalSourceDir] , public_modules :: [ModuleDesc] , private_modules :: [ModuleDesc] } deriving (Eq,Ord,Show) -- Zero / one or more exe per cabal file / package. -- The executable file will include the extension... data CabalExe = CabalExe { exe_main_module :: ExeMainPath , exe_src_dirs :: [CabalSourceDir] , exe_other_modules :: [ModuleDesc] } deriving (Eq,Ord,Show)