    module Distribution.Types.DependencyMap
      ( DependencyMap
      , toDepMap
      , fromDepMap
      , constrainBy
      ) where

    import Distribution.Compat.Prelude
    import Prelude ()

    import Distribution.Types.Dependency
    import Distribution.Types.LibraryName
    import Distribution.Types.PackageName
    import Distribution.Types.PackageVersionConstraint
    import Distribution.Version

    import qualified Data.Map.Lazy as Map

    -- | A map of dependencies.  Newtyped since the default monoid instance is not
    --   appropriate.  The monoid instance uses 'intersectVersionRanges'.
    newtype DependencyMap = DependencyMap {DependencyMap
    -> Map PackageName (VersionRange, NonEmptySet LibraryName)
    unDependencyMap :: Map PackageName (VersionRange, NonEmptySet LibraryName)}
      deriving (Int -> DependencyMap -> ShowS
    [DependencyMap] -> ShowS
    DependencyMap -> String
    (Int -> DependencyMap -> ShowS)
    -> (DependencyMap -> String)
    -> ([DependencyMap] -> ShowS)
    -> Show DependencyMap
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> DependencyMap -> ShowS
    showsPrec :: Int -> DependencyMap -> ShowS
    $cshow :: DependencyMap -> String
    show :: DependencyMap -> String
    $cshowList :: [DependencyMap] -> ShowS
    showList :: [DependencyMap] -> ShowS
    Show, ReadPrec [DependencyMap]
    ReadPrec DependencyMap
    Int -> ReadS DependencyMap
    ReadS [DependencyMap]
    (Int -> ReadS DependencyMap)
    -> ReadS [DependencyMap]
    -> ReadPrec DependencyMap
    -> ReadPrec [DependencyMap]
    -> Read DependencyMap
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS DependencyMap
    readsPrec :: Int -> ReadS DependencyMap
    $creadList :: ReadS [DependencyMap]
    readList :: ReadS [DependencyMap]
    $creadPrec :: ReadPrec DependencyMap
    readPrec :: ReadPrec DependencyMap
    $creadListPrec :: ReadPrec [DependencyMap]
    readListPrec :: ReadPrec [DependencyMap]
    Read, DependencyMap -> DependencyMap -> Bool
    (DependencyMap -> DependencyMap -> Bool)
    -> (DependencyMap -> DependencyMap -> Bool) -> Eq DependencyMap
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: DependencyMap -> DependencyMap -> Bool
    == :: DependencyMap -> DependencyMap -> Bool
    $c/= :: DependencyMap -> DependencyMap -> Bool
    /= :: DependencyMap -> DependencyMap -> Bool
    Eq)

    instance Monoid DependencyMap where
      mempty :: DependencyMap
    mempty = Map PackageName (VersionRange, NonEmptySet LibraryName)
    -> DependencyMap
    DependencyMap Map PackageName (VersionRange, NonEmptySet LibraryName)
    forall k a. Map k a
    Map.empty
      mappend :: DependencyMap -> DependencyMap -> DependencyMap
    mappend = DependencyMap -> DependencyMap -> DependencyMap
    forall a. Semigroup a => a -> a -> a
    (<>)

    instance Semigroup DependencyMap where
      (DependencyMap Map PackageName (VersionRange, NonEmptySet LibraryName)
    a) <> :: DependencyMap -> DependencyMap -> DependencyMap
    <> (DependencyMap Map PackageName (VersionRange, NonEmptySet LibraryName)
    b) =
        Map PackageName (VersionRange, NonEmptySet LibraryName)
    -> DependencyMap
    DependencyMap (((VersionRange, NonEmptySet LibraryName)
     -> (VersionRange, NonEmptySet LibraryName)
     -> (VersionRange, NonEmptySet LibraryName))
    -> Map PackageName (VersionRange, NonEmptySet LibraryName)
    -> Map PackageName (VersionRange, NonEmptySet LibraryName)
    -> Map PackageName (VersionRange, NonEmptySet LibraryName)
    forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a
    Map.unionWith (VersionRange, NonEmptySet LibraryName)
    -> (VersionRange, NonEmptySet LibraryName)
    -> (VersionRange, NonEmptySet LibraryName)
    intersectVersionRangesAndJoinComponents Map PackageName (VersionRange, NonEmptySet LibraryName)
    a Map PackageName (VersionRange, NonEmptySet LibraryName)
    b)

    intersectVersionRangesAndJoinComponents
      :: (VersionRange, NonEmptySet LibraryName)
      -> (VersionRange, NonEmptySet LibraryName)
      -> (VersionRange, NonEmptySet LibraryName)
    intersectVersionRangesAndJoinComponents :: (VersionRange, NonEmptySet LibraryName)
    -> (VersionRange, NonEmptySet LibraryName)
    -> (VersionRange, NonEmptySet LibraryName)
    intersectVersionRangesAndJoinComponents (VersionRange
    va, NonEmptySet LibraryName
    ca) (VersionRange
    vb, NonEmptySet LibraryName
    cb) =
      (VersionRange -> VersionRange -> VersionRange
    intersectVersionRanges VersionRange
    va VersionRange
    vb, NonEmptySet LibraryName
    ca NonEmptySet LibraryName
    -> NonEmptySet LibraryName -> NonEmptySet LibraryName
    forall a. Semigroup a => a -> a -> a
    <> NonEmptySet LibraryName
    cb)

    toDepMap :: [Dependency] -> DependencyMap
    toDepMap :: [Dependency] -> DependencyMap
    toDepMap [Dependency]
    ds =
      Map PackageName (VersionRange, NonEmptySet LibraryName)
    -> DependencyMap
    DependencyMap (Map PackageName (VersionRange, NonEmptySet LibraryName)
     -> DependencyMap)
    -> Map PackageName (VersionRange, NonEmptySet LibraryName)
    -> DependencyMap
    forall a b. (a -> b) -> a -> b
    $ ((VersionRange, NonEmptySet LibraryName)
     -> (VersionRange, NonEmptySet LibraryName)
     -> (VersionRange, NonEmptySet LibraryName))
    -> [(PackageName, (VersionRange, NonEmptySet LibraryName))]
    -> Map PackageName (VersionRange, NonEmptySet LibraryName)
    forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
    Map.fromListWith (VersionRange, NonEmptySet LibraryName)
    -> (VersionRange, NonEmptySet LibraryName)
    -> (VersionRange, NonEmptySet LibraryName)
    intersectVersionRangesAndJoinComponents [(PackageName
    p, (VersionRange
    vr, NonEmptySet LibraryName
    cs)) | Dependency PackageName
    p VersionRange
    vr NonEmptySet LibraryName
    cs <- [Dependency]
    ds]

    fromDepMap :: DependencyMap -> [Dependency]
    fromDepMap :: DependencyMap -> [Dependency]
    fromDepMap DependencyMap
    m = [PackageName
    -> VersionRange -> NonEmptySet LibraryName -> Dependency
    Dependency PackageName
    p VersionRange
    vr NonEmptySet LibraryName
    cs | (PackageName
    p, (VersionRange
    vr, NonEmptySet LibraryName
    cs)) <- Map PackageName (VersionRange, NonEmptySet LibraryName)
    -> [(PackageName, (VersionRange, NonEmptySet LibraryName))]
    forall k a. Map k a -> [(k, a)]
    Map.toList (DependencyMap
    -> Map PackageName (VersionRange, NonEmptySet LibraryName)
    unDependencyMap DependencyMap
    m)]

    -- Apply extra constraints to a dependency map.
    -- Combines dependencies where the result will only contain keys from the left
    -- (first) map.  If a key also exists in the right map, both constraints will
    -- be intersected.
    constrainBy
      :: DependencyMap
      -> [PackageVersionConstraint]
      -> DependencyMap
    constrainBy :: DependencyMap -> [PackageVersionConstraint] -> DependencyMap
    constrainBy = (DependencyMap -> PackageVersionConstraint -> DependencyMap)
    -> DependencyMap -> [PackageVersionConstraint] -> DependencyMap
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' DependencyMap -> PackageVersionConstraint -> DependencyMap
    tightenConstraint
      where
        tightenConstraint :: DependencyMap -> PackageVersionConstraint -> DependencyMap
    tightenConstraint (DependencyMap Map PackageName (VersionRange, NonEmptySet LibraryName)
    l) (PackageVersionConstraint PackageName
    pn VersionRange
    vr) = Map PackageName (VersionRange, NonEmptySet LibraryName)
    -> DependencyMap
    DependencyMap (Map PackageName (VersionRange, NonEmptySet LibraryName)
     -> DependencyMap)
    -> Map PackageName (VersionRange, NonEmptySet LibraryName)
    -> DependencyMap
    forall a b. (a -> b) -> a -> b
    $
          case PackageName
    -> Map PackageName (VersionRange, NonEmptySet LibraryName)
    -> Maybe (VersionRange, NonEmptySet LibraryName)
    forall k a. Ord k => k -> Map k a -> Maybe a
    Map.lookup PackageName
    pn Map PackageName (VersionRange, NonEmptySet LibraryName)
    l of
            Maybe (VersionRange, NonEmptySet LibraryName)
    Nothing -> Map PackageName (VersionRange, NonEmptySet LibraryName)
    l
            Just (VersionRange
    vr', NonEmptySet LibraryName
    cs) -> PackageName
    -> (VersionRange, NonEmptySet LibraryName)
    -> Map PackageName (VersionRange, NonEmptySet LibraryName)
    -> Map PackageName (VersionRange, NonEmptySet LibraryName)
    forall k a. Ord k => k -> a -> Map k a -> Map k a
    Map.insert PackageName
    pn (VersionRange -> VersionRange -> VersionRange
    intersectVersionRanges VersionRange
    vr' VersionRange
    vr, NonEmptySet LibraryName
    cs) Map PackageName (VersionRange, NonEmptySet LibraryName)
    l