{-# LANGUAGE CPP #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeFamilies #-} module Hpack.Syntax.Dependencies ( Dependencies(..) , DependencyInfo(..) , parseDependency ) where import Imports import qualified Control.Monad.Fail as Fail import qualified Data.Text as T import qualified Distribution.Package as D import qualified Distribution.Types.LibraryName as D import Distribution.Pretty (prettyShow) import Data.Map.Lazy (Map) import qualified Data.Map.Lazy as Map import GHC.Exts #if MIN_VERSION_Cabal(3,4,0) import qualified Distribution.Compat.NonEmptySet as DependencySet #else import qualified Data.Set as DependencySet #endif import Data.Aeson.Config.FromValue import Data.Aeson.Config.Types import Hpack.Syntax.DependencyVersion import Hpack.Syntax.ParseDependencies newtype Dependencies = Dependencies { Dependencies -> Map String DependencyInfo unDependencies :: Map String DependencyInfo } deriving (Dependencies -> Dependencies -> Bool (Dependencies -> Dependencies -> Bool) -> (Dependencies -> Dependencies -> Bool) -> Eq Dependencies forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a /= :: Dependencies -> Dependencies -> Bool $c/= :: Dependencies -> Dependencies -> Bool == :: Dependencies -> Dependencies -> Bool $c== :: Dependencies -> Dependencies -> Bool Eq, Int -> Dependencies -> ShowS [Dependencies] -> ShowS Dependencies -> String (Int -> Dependencies -> ShowS) -> (Dependencies -> String) -> ([Dependencies] -> ShowS) -> Show Dependencies forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [Dependencies] -> ShowS $cshowList :: [Dependencies] -> ShowS show :: Dependencies -> String $cshow :: Dependencies -> String showsPrec :: Int -> Dependencies -> ShowS $cshowsPrec :: Int -> Dependencies -> ShowS Show, b -> Dependencies -> Dependencies NonEmpty Dependencies -> Dependencies Dependencies -> Dependencies -> Dependencies (Dependencies -> Dependencies -> Dependencies) -> (NonEmpty Dependencies -> Dependencies) -> (forall b. Integral b => b -> Dependencies -> Dependencies) -> Semigroup Dependencies forall b. Integral b => b -> Dependencies -> Dependencies forall a. (a -> a -> a) -> (NonEmpty a -> a) -> (forall b. Integral b => b -> a -> a) -> Semigroup a stimes :: b -> Dependencies -> Dependencies $cstimes :: forall b. Integral b => b -> Dependencies -> Dependencies sconcat :: NonEmpty Dependencies -> Dependencies $csconcat :: NonEmpty Dependencies -> Dependencies <> :: Dependencies -> Dependencies -> Dependencies $c<> :: Dependencies -> Dependencies -> Dependencies Semigroup, Semigroup Dependencies Dependencies Semigroup Dependencies -> Dependencies -> (Dependencies -> Dependencies -> Dependencies) -> ([Dependencies] -> Dependencies) -> Monoid Dependencies [Dependencies] -> Dependencies Dependencies -> Dependencies -> Dependencies forall a. Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a mconcat :: [Dependencies] -> Dependencies $cmconcat :: [Dependencies] -> Dependencies mappend :: Dependencies -> Dependencies -> Dependencies $cmappend :: Dependencies -> Dependencies -> Dependencies mempty :: Dependencies $cmempty :: Dependencies $cp1Monoid :: Semigroup Dependencies Monoid) instance IsList Dependencies where type Item Dependencies = (String, DependencyInfo) fromList :: [Item Dependencies] -> Dependencies fromList = Map String DependencyInfo -> Dependencies Dependencies (Map String DependencyInfo -> Dependencies) -> ([(String, DependencyInfo)] -> Map String DependencyInfo) -> [(String, DependencyInfo)] -> Dependencies forall b c a. (b -> c) -> (a -> b) -> a -> c . [(String, DependencyInfo)] -> Map String DependencyInfo forall k a. Ord k => [(k, a)] -> Map k a Map.fromList toList :: Dependencies -> [Item Dependencies] toList = Map String DependencyInfo -> [(String, DependencyInfo)] forall k a. Map k a -> [(k, a)] Map.toList (Map String DependencyInfo -> [(String, DependencyInfo)]) -> (Dependencies -> Map String DependencyInfo) -> Dependencies -> [(String, DependencyInfo)] forall b c a. (b -> c) -> (a -> b) -> a -> c . Dependencies -> Map String DependencyInfo unDependencies instance FromValue Dependencies where fromValue :: Value -> Parser Dependencies fromValue = ([(String, DependencyInfo)] -> Dependencies) -> Parser [(String, DependencyInfo)] -> Parser Dependencies forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap (Map String DependencyInfo -> Dependencies Dependencies (Map String DependencyInfo -> Dependencies) -> ([(String, DependencyInfo)] -> Map String DependencyInfo) -> [(String, DependencyInfo)] -> Dependencies forall b c a. (b -> c) -> (a -> b) -> a -> c . [(String, DependencyInfo)] -> Map String DependencyInfo forall k a. Ord k => [(k, a)] -> Map k a Map.fromList) (Parser [(String, DependencyInfo)] -> Parser Dependencies) -> (Value -> Parser [(String, DependencyInfo)]) -> Value -> Parser Dependencies forall b c a. (b -> c) -> (a -> b) -> a -> c . Parse String DependencyInfo -> Value -> Parser [(String, DependencyInfo)] forall k v. Parse k v -> Value -> Parser [(k, v)] parseDependencies Parse String DependencyInfo parse where parse :: Parse String DependencyInfo parse :: Parse String DependencyInfo parse = Parse :: forall k v. (Text -> Parser (k, v)) -> (Object -> Parser v) -> (Value -> Parser v) -> (Text -> k) -> Parse k v Parse { parseString :: Text -> Parser (String, DependencyInfo) parseString = \ Text input -> do (String name, DependencyVersion version) <- String -> Text -> Parser (String, DependencyVersion) forall (m :: * -> *). MonadFail m => String -> Text -> m (String, DependencyVersion) parseDependency String "dependency" Text input (String, DependencyInfo) -> Parser (String, DependencyInfo) forall (m :: * -> *) a. Monad m => a -> m a return (String name, [String] -> DependencyVersion -> DependencyInfo DependencyInfo [] DependencyVersion version) , parseListItem :: Object -> Parser DependencyInfo parseListItem = Object -> Parser DependencyInfo objectDependencyInfo , parseDictItem :: Value -> Parser DependencyInfo parseDictItem = Value -> Parser DependencyInfo dependencyInfo , parseName :: Text -> String parseName = Text -> String T.unpack } data DependencyInfo = DependencyInfo { DependencyInfo -> [String] dependencyInfoMixins :: [String] , DependencyInfo -> DependencyVersion dependencyInfoVersion :: DependencyVersion } deriving (DependencyInfo -> DependencyInfo -> Bool (DependencyInfo -> DependencyInfo -> Bool) -> (DependencyInfo -> DependencyInfo -> Bool) -> Eq DependencyInfo forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a /= :: DependencyInfo -> DependencyInfo -> Bool $c/= :: DependencyInfo -> DependencyInfo -> Bool == :: DependencyInfo -> DependencyInfo -> Bool $c== :: DependencyInfo -> DependencyInfo -> Bool Eq, Eq DependencyInfo Eq DependencyInfo -> (DependencyInfo -> DependencyInfo -> Ordering) -> (DependencyInfo -> DependencyInfo -> Bool) -> (DependencyInfo -> DependencyInfo -> Bool) -> (DependencyInfo -> DependencyInfo -> Bool) -> (DependencyInfo -> DependencyInfo -> Bool) -> (DependencyInfo -> DependencyInfo -> DependencyInfo) -> (DependencyInfo -> DependencyInfo -> DependencyInfo) -> Ord DependencyInfo DependencyInfo -> DependencyInfo -> Bool DependencyInfo -> DependencyInfo -> Ordering DependencyInfo -> DependencyInfo -> DependencyInfo forall a. Eq a -> (a -> a -> Ordering) -> (a -> a -> Bool) -> (a -> a -> Bool) -> (a -> a -> Bool) -> (a -> a -> Bool) -> (a -> a -> a) -> (a -> a -> a) -> Ord a min :: DependencyInfo -> DependencyInfo -> DependencyInfo $cmin :: DependencyInfo -> DependencyInfo -> DependencyInfo max :: DependencyInfo -> DependencyInfo -> DependencyInfo $cmax :: DependencyInfo -> DependencyInfo -> DependencyInfo >= :: DependencyInfo -> DependencyInfo -> Bool $c>= :: DependencyInfo -> DependencyInfo -> Bool > :: DependencyInfo -> DependencyInfo -> Bool $c> :: DependencyInfo -> DependencyInfo -> Bool <= :: DependencyInfo -> DependencyInfo -> Bool $c<= :: DependencyInfo -> DependencyInfo -> Bool < :: DependencyInfo -> DependencyInfo -> Bool $c< :: DependencyInfo -> DependencyInfo -> Bool compare :: DependencyInfo -> DependencyInfo -> Ordering $ccompare :: DependencyInfo -> DependencyInfo -> Ordering $cp1Ord :: Eq DependencyInfo Ord, Int -> DependencyInfo -> ShowS [DependencyInfo] -> ShowS DependencyInfo -> String (Int -> DependencyInfo -> ShowS) -> (DependencyInfo -> String) -> ([DependencyInfo] -> ShowS) -> Show DependencyInfo forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [DependencyInfo] -> ShowS $cshowList :: [DependencyInfo] -> ShowS show :: DependencyInfo -> String $cshow :: DependencyInfo -> String showsPrec :: Int -> DependencyInfo -> ShowS $cshowsPrec :: Int -> DependencyInfo -> ShowS Show) addMixins :: Object -> DependencyVersion -> Parser DependencyInfo addMixins :: Object -> DependencyVersion -> Parser DependencyInfo addMixins Object o DependencyVersion version = do Maybe (List String) mixinsMay <- Object o Object -> Key -> Parser (Maybe (List String)) forall a. FromValue a => Object -> Key -> Parser (Maybe a) .:? Key "mixin" DependencyInfo -> Parser DependencyInfo forall (m :: * -> *) a. Monad m => a -> m a return (DependencyInfo -> Parser DependencyInfo) -> DependencyInfo -> Parser DependencyInfo forall a b. (a -> b) -> a -> b $ [String] -> DependencyVersion -> DependencyInfo DependencyInfo (Maybe (List String) -> [String] forall a. Maybe (List a) -> [a] fromMaybeList Maybe (List String) mixinsMay) DependencyVersion version objectDependencyInfo :: Object -> Parser DependencyInfo objectDependencyInfo :: Object -> Parser DependencyInfo objectDependencyInfo Object o = Object -> Parser DependencyVersion objectDependency Object o Parser DependencyVersion -> (DependencyVersion -> Parser DependencyInfo) -> Parser DependencyInfo forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= Object -> DependencyVersion -> Parser DependencyInfo addMixins Object o dependencyInfo :: Value -> Parser DependencyInfo dependencyInfo :: Value -> Parser DependencyInfo dependencyInfo = (DependencyVersion -> DependencyInfo) -> (Object -> DependencyVersion -> Parser DependencyInfo) -> Value -> Parser DependencyInfo forall a. (DependencyVersion -> a) -> (Object -> DependencyVersion -> Parser a) -> Value -> Parser a withDependencyVersion ([String] -> DependencyVersion -> DependencyInfo DependencyInfo []) Object -> DependencyVersion -> Parser DependencyInfo addMixins parseDependency :: Fail.MonadFail m => String -> Text -> m (String, DependencyVersion) parseDependency :: String -> Text -> m (String, DependencyVersion) parseDependency String subject = (Dependency -> (String, DependencyVersion)) -> m Dependency -> m (String, DependencyVersion) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap Dependency -> (String, DependencyVersion) fromCabal (m Dependency -> m (String, DependencyVersion)) -> (Text -> m Dependency) -> Text -> m (String, DependencyVersion) forall b c a. (b -> c) -> (a -> b) -> a -> c . String -> String -> m Dependency forall (m :: * -> *) a. (MonadFail m, Parsec a) => String -> String -> m a cabalParse String subject (String -> m Dependency) -> (Text -> String) -> Text -> m Dependency forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> String T.unpack where fromCabal :: D.Dependency -> (String, DependencyVersion) fromCabal :: Dependency -> (String, DependencyVersion) fromCabal Dependency d = (PackageName -> [LibraryName] -> String toName (Dependency -> PackageName D.depPkgName Dependency d) (Set LibraryName -> [LibraryName] forall a. Set a -> [a] DependencySet.toList (Set LibraryName -> [LibraryName]) -> Set LibraryName -> [LibraryName] forall a b. (a -> b) -> a -> b $ Dependency -> Set LibraryName D.depLibraries Dependency d), Maybe SourceDependency -> VersionConstraint -> DependencyVersion DependencyVersion Maybe SourceDependency forall a. Maybe a Nothing (VersionConstraint -> DependencyVersion) -> (VersionRange -> VersionConstraint) -> VersionRange -> DependencyVersion forall b c a. (b -> c) -> (a -> b) -> a -> c . VersionRange -> VersionConstraint versionConstraintFromCabal (VersionRange -> DependencyVersion) -> VersionRange -> DependencyVersion forall a b. (a -> b) -> a -> b $ Dependency -> VersionRange D.depVerRange Dependency d) toName :: D.PackageName -> [D.LibraryName] -> String toName :: PackageName -> [LibraryName] -> String toName PackageName package [LibraryName] components = PackageName -> String forall a. Pretty a => a -> String prettyShow PackageName package String -> ShowS forall a. Semigroup a => a -> a -> a <> case [LibraryName] components of [LibraryName D.LMainLibName] -> String "" [D.LSubLibName UnqualComponentName lib] -> String ":" String -> ShowS forall a. Semigroup a => a -> a -> a <> UnqualComponentName -> String forall a. Pretty a => a -> String prettyShow UnqualComponentName lib [LibraryName] xs -> String ":{" String -> ShowS forall a. Semigroup a => a -> a -> a <> (String -> [String] -> String forall a. [a] -> [[a]] -> [a] intercalate String "," ([String] -> String) -> [String] -> String forall a b. (a -> b) -> a -> b $ (UnqualComponentName -> String) -> [UnqualComponentName] -> [String] forall a b. (a -> b) -> [a] -> [b] map UnqualComponentName -> String forall a. Pretty a => a -> String prettyShow [UnqualComponentName name | D.LSubLibName UnqualComponentName name <- [LibraryName] xs]) String -> ShowS forall a. Semigroup a => a -> a -> a <> String "}"