{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}

module Distribution.Types.PackageVersionConstraint
  ( PackageVersionConstraint (..)
  , thisPackageVersionConstraint
  , simplifyPackageVersionConstraint
  ) where

import Distribution.Compat.Prelude
import Prelude ()

import Distribution.Parsec
import Distribution.Pretty
import Distribution.Types.PackageId
import Distribution.Types.PackageName
import Distribution.Types.Version
import Distribution.Types.VersionRange.Internal
import Distribution.Version (simplifyVersionRange)

import qualified Distribution.Compat.CharParsing as P

-- | A version constraint on a package. Different from 'ExeDependency' and
-- 'Dependency' since it does not specify the need for a component, not even
-- the main library.
-- There are a few places in the codebase where 'Dependency' was used where
-- 'PackageVersionConstraint' is not used instead (#5570).
data PackageVersionConstraint = PackageVersionConstraint PackageName VersionRange
  deriving ((forall x.
 PackageVersionConstraint -> Rep PackageVersionConstraint x)
-> (forall x.
    Rep PackageVersionConstraint x -> PackageVersionConstraint)
-> Generic PackageVersionConstraint
forall x.
Rep PackageVersionConstraint x -> PackageVersionConstraint
forall x.
PackageVersionConstraint -> Rep PackageVersionConstraint x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x.
PackageVersionConstraint -> Rep PackageVersionConstraint x
from :: forall x.
PackageVersionConstraint -> Rep PackageVersionConstraint x
$cto :: forall x.
Rep PackageVersionConstraint x -> PackageVersionConstraint
to :: forall x.
Rep PackageVersionConstraint x -> PackageVersionConstraint
Generic, ReadPrec [PackageVersionConstraint]
ReadPrec PackageVersionConstraint
Int -> ReadS PackageVersionConstraint
ReadS [PackageVersionConstraint]
(Int -> ReadS PackageVersionConstraint)
-> ReadS [PackageVersionConstraint]
-> ReadPrec PackageVersionConstraint
-> ReadPrec [PackageVersionConstraint]
-> Read PackageVersionConstraint
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS PackageVersionConstraint
readsPrec :: Int -> ReadS PackageVersionConstraint
$creadList :: ReadS [PackageVersionConstraint]
readList :: ReadS [PackageVersionConstraint]
$creadPrec :: ReadPrec PackageVersionConstraint
readPrec :: ReadPrec PackageVersionConstraint
$creadListPrec :: ReadPrec [PackageVersionConstraint]
readListPrec :: ReadPrec [PackageVersionConstraint]
Read, Int -> PackageVersionConstraint -> ShowS
[PackageVersionConstraint] -> ShowS
PackageVersionConstraint -> String
(Int -> PackageVersionConstraint -> ShowS)
-> (PackageVersionConstraint -> String)
-> ([PackageVersionConstraint] -> ShowS)
-> Show PackageVersionConstraint
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PackageVersionConstraint -> ShowS
showsPrec :: Int -> PackageVersionConstraint -> ShowS
$cshow :: PackageVersionConstraint -> String
show :: PackageVersionConstraint -> String
$cshowList :: [PackageVersionConstraint] -> ShowS
showList :: [PackageVersionConstraint] -> ShowS
Show, PackageVersionConstraint -> PackageVersionConstraint -> Bool
(PackageVersionConstraint -> PackageVersionConstraint -> Bool)
-> (PackageVersionConstraint -> PackageVersionConstraint -> Bool)
-> Eq PackageVersionConstraint
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PackageVersionConstraint -> PackageVersionConstraint -> Bool
== :: PackageVersionConstraint -> PackageVersionConstraint -> Bool
$c/= :: PackageVersionConstraint -> PackageVersionConstraint -> Bool
/= :: PackageVersionConstraint -> PackageVersionConstraint -> Bool
Eq, Typeable, Typeable PackageVersionConstraint
Typeable PackageVersionConstraint =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g)
 -> PackageVersionConstraint
 -> c PackageVersionConstraint)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PackageVersionConstraint)
-> (PackageVersionConstraint -> Constr)
-> (PackageVersionConstraint -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d))
    -> Maybe (c PackageVersionConstraint))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c PackageVersionConstraint))
-> ((forall b. Data b => b -> b)
    -> PackageVersionConstraint -> PackageVersionConstraint)
-> (forall r r'.
    (r -> r' -> r)
    -> r
    -> (forall d. Data d => d -> r')
    -> PackageVersionConstraint
    -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r
    -> (forall d. Data d => d -> r')
    -> PackageVersionConstraint
    -> r)
-> (forall u.
    (forall d. Data d => d -> u) -> PackageVersionConstraint -> [u])
-> (forall u.
    Int
    -> (forall d. Data d => d -> u) -> PackageVersionConstraint -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> PackageVersionConstraint -> m PackageVersionConstraint)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> PackageVersionConstraint -> m PackageVersionConstraint)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> PackageVersionConstraint -> m PackageVersionConstraint)
-> Data PackageVersionConstraint
PackageVersionConstraint -> Constr
PackageVersionConstraint -> DataType
(forall b. Data b => b -> b)
-> PackageVersionConstraint -> PackageVersionConstraint
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u.
Int
-> (forall d. Data d => d -> u) -> PackageVersionConstraint -> u
forall u.
(forall d. Data d => d -> u) -> PackageVersionConstraint -> [u]
forall r r'.
(r -> r' -> r)
-> r
-> (forall d. Data d => d -> r')
-> PackageVersionConstraint
-> r
forall r r'.
(r' -> r -> r)
-> r
-> (forall d. Data d => d -> r')
-> PackageVersionConstraint
-> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> PackageVersionConstraint -> m PackageVersionConstraint
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> PackageVersionConstraint -> m PackageVersionConstraint
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PackageVersionConstraint
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g)
-> PackageVersionConstraint
-> c PackageVersionConstraint
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c PackageVersionConstraint)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c PackageVersionConstraint)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g)
-> PackageVersionConstraint
-> c PackageVersionConstraint
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g)
-> PackageVersionConstraint
-> c PackageVersionConstraint
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PackageVersionConstraint
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PackageVersionConstraint
$ctoConstr :: PackageVersionConstraint -> Constr
toConstr :: PackageVersionConstraint -> Constr
$cdataTypeOf :: PackageVersionConstraint -> DataType
dataTypeOf :: PackageVersionConstraint -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c PackageVersionConstraint)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c PackageVersionConstraint)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c PackageVersionConstraint)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c PackageVersionConstraint)
$cgmapT :: (forall b. Data b => b -> b)
-> PackageVersionConstraint -> PackageVersionConstraint
gmapT :: (forall b. Data b => b -> b)
-> PackageVersionConstraint -> PackageVersionConstraint
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r
-> (forall d. Data d => d -> r')
-> PackageVersionConstraint
-> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r
-> (forall d. Data d => d -> r')
-> PackageVersionConstraint
-> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r
-> (forall d. Data d => d -> r')
-> PackageVersionConstraint
-> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r
-> (forall d. Data d => d -> r')
-> PackageVersionConstraint
-> r
$cgmapQ :: forall u.
(forall d. Data d => d -> u) -> PackageVersionConstraint -> [u]
gmapQ :: forall u.
(forall d. Data d => d -> u) -> PackageVersionConstraint -> [u]
$cgmapQi :: forall u.
Int
-> (forall d. Data d => d -> u) -> PackageVersionConstraint -> u
gmapQi :: forall u.
Int
-> (forall d. Data d => d -> u) -> PackageVersionConstraint -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> PackageVersionConstraint -> m PackageVersionConstraint
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> PackageVersionConstraint -> m PackageVersionConstraint
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> PackageVersionConstraint -> m PackageVersionConstraint
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> PackageVersionConstraint -> m PackageVersionConstraint
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> PackageVersionConstraint -> m PackageVersionConstraint
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> PackageVersionConstraint -> m PackageVersionConstraint
Data)

instance Binary PackageVersionConstraint
instance Structured PackageVersionConstraint
instance NFData PackageVersionConstraint where rnf :: PackageVersionConstraint -> ()
rnf = PackageVersionConstraint -> ()
forall a. (Generic a, GNFData (Rep a)) => a -> ()
genericRnf

instance Pretty PackageVersionConstraint where
  -- Cannot do: PackageVersionConstraint have to be parseable
  -- as Dependency, due roundtrip problems. (e.g. talking to old ./Setup).
  --
  -- pretty (PackageVersionConstraint name (ThisVersion ver)) =
  --     pretty (PackageIdentifier name ver)
  pretty :: PackageVersionConstraint -> Doc
pretty (PackageVersionConstraint PackageName
name VersionRange
ver) =
    PackageName -> Doc
forall a. Pretty a => a -> Doc
pretty PackageName
name Doc -> Doc -> Doc
<+> VersionRange -> Doc
forall a. Pretty a => a -> Doc
pretty VersionRange
ver

-- |
--
-- >>> simpleParsec "foo" :: Maybe PackageVersionConstraint
-- Just (PackageVersionConstraint (PackageName "foo") (OrLaterVersion (mkVersion [0])))
--
-- >>> simpleParsec "foo >=2.0" :: Maybe PackageVersionConstraint
-- Just (PackageVersionConstraint (PackageName "foo") (OrLaterVersion (mkVersion [2,0])))
--
-- >>> simpleParsec "foo-2.0" :: Maybe PackageVersionConstraint
-- Just (PackageVersionConstraint (PackageName "foo") (ThisVersion (mkVersion [2,0])))
instance Parsec PackageVersionConstraint where
  parsec :: forall (m :: * -> *). CabalParsing m => m PackageVersionConstraint
parsec = do
    PackageIdentifier name ver <- m PackageIdentifier
forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
forall (m :: * -> *). CabalParsing m => m PackageIdentifier
parsec
    if ver == nullVersion
      then do
        P.spaces
        vr <- parsec <|> return anyVersion
        P.spaces
        return (PackageVersionConstraint name vr)
      else pure (PackageVersionConstraint name (thisVersion ver))

-- | @since 3.4.0.0
thisPackageVersionConstraint :: PackageIdentifier -> PackageVersionConstraint
thisPackageVersionConstraint :: PackageIdentifier -> PackageVersionConstraint
thisPackageVersionConstraint (PackageIdentifier PackageName
pn Version
vr) =
  PackageName -> VersionRange -> PackageVersionConstraint
PackageVersionConstraint PackageName
pn (Version -> VersionRange
thisVersion Version
vr)

-- | @since 3.4.0.0
simplifyPackageVersionConstraint :: PackageVersionConstraint -> PackageVersionConstraint
simplifyPackageVersionConstraint :: PackageVersionConstraint -> PackageVersionConstraint
simplifyPackageVersionConstraint (PackageVersionConstraint PackageName
pn VersionRange
vr) =
  PackageName -> VersionRange -> PackageVersionConstraint
PackageVersionConstraint PackageName
pn (VersionRange -> VersionRange
simplifyVersionRange VersionRange
vr)