{-# LANGUAGE ViewPatterns #-}
-- | Adjust contents of a cabal file to follow
-- rearrangements of the underlying modules
module CLI.Cabal (
module CLI.Cabal,
readPackageDescription,
writeGenericPackageDescription,
showGenericPackageDescription,
) where
import CLI.Cabal.Instances
import Control.Lens
import Distribution.PackageDescription
import Distribution.PackageDescription.Parse
import Distribution.PackageDescription.PrettyPrint
import GHC.Generics (Generic)
import GHC.Generics.Lens
import Distribution.ModuleName
import qualified Language.Haskell.Modules
import Data.List
import Data.Maybe
import Language.Haskell.Modules.Common
import qualified Data.Set as S
toMN = Language.Haskell.Modules.ModuleName . intercalate "." . components
fromMN (Language.Haskell.Modules.ModuleName x) = fromString x
getModules pkgDesc = map toMN $ toListOf tinplate pkgDesc
getSrcDirs pkgDesc = hsSourceDirs =<< toListOf tinplate pkgDesc
-- merge :: Generic a => [ModuleName] -> ModuleName -> a -> a
merge (map fromMN -> old) (fromMN -> new) pkgDesc = pkgDesc & over tinplate f
where f ms = let n | any (`elem` old) ms = [new::ModuleName]
| otherwise = []
in n ++ filter (`notElem` old) ms
split (fromMN -> old) (map fromMN -> news) pkgDesc = pkgDesc & over tinplate f
where f ms = concatMap (\m -> if (m::ModuleName) == old then news else [m]) ms
update moduleResults pkgDesc = pkgDesc & over tinplate (\x -> fn x (S.fromList x))
where
r = removals moduleResults
a = additions moduleResults
fn modules ms
| S.size (ms `S.intersection` r) > 0 = filter (`S.notMember` r) modules
++ S.toList (a S.\\ ms)
| otherwise = modules :: [ModuleName]
removals rs = S.fromList $ mapMaybe remove rs
where
remove (ToBeRemoved m _) = Just (fromMN m)
remove (JustRemoved m _) = Just (fromMN m)
remove _ = Nothing
additions rs = S.fromList $ mapMaybe add rs
where
add (ToBeCreated m _) = Just (fromMN m)
add (JustCreated m _) = Just (fromMN m)
add _ = Nothing