{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}

module Distribution.Client.Types.PackageSpecifier
  ( PackageSpecifier (..)
  , pkgSpecifierTarget
  , pkgSpecifierConstraints
  , mkNamedPackage
  ) where

import Distribution.Client.Compat.Prelude
import Prelude ()

import Distribution.Package (Package (..), PackageIdentifier (..), packageName, packageVersion)
import Distribution.Types.PackageName (PackageName)
import Distribution.Version (nullVersion, thisVersion)

import Distribution.Solver.Types.ConstraintSource
import Distribution.Solver.Types.LabeledPackageConstraint
import Distribution.Solver.Types.PackageConstraint

-- | A fully or partially resolved reference to a package.
data PackageSpecifier pkg
  = -- | A partially specified reference to a package (either source or
    -- installed). It is specified by package name and optionally some
    -- required properties. Use a dependency resolver to pick a specific
    -- package satisfying these properties.
    NamedPackage PackageName [PackageProperty]
  | -- | A fully specified source package.
    SpecificSourcePackage pkg
  deriving (PackageSpecifier pkg -> PackageSpecifier pkg -> Bool
(PackageSpecifier pkg -> PackageSpecifier pkg -> Bool)
-> (PackageSpecifier pkg -> PackageSpecifier pkg -> Bool)
-> Eq (PackageSpecifier pkg)
forall pkg.
Eq pkg =>
PackageSpecifier pkg -> PackageSpecifier pkg -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall pkg.
Eq pkg =>
PackageSpecifier pkg -> PackageSpecifier pkg -> Bool
== :: PackageSpecifier pkg -> PackageSpecifier pkg -> Bool
$c/= :: forall pkg.
Eq pkg =>
PackageSpecifier pkg -> PackageSpecifier pkg -> Bool
/= :: PackageSpecifier pkg -> PackageSpecifier pkg -> Bool
Eq, Int -> PackageSpecifier pkg -> ShowS
[PackageSpecifier pkg] -> ShowS
PackageSpecifier pkg -> String
(Int -> PackageSpecifier pkg -> ShowS)
-> (PackageSpecifier pkg -> String)
-> ([PackageSpecifier pkg] -> ShowS)
-> Show (PackageSpecifier pkg)
forall pkg. Show pkg => Int -> PackageSpecifier pkg -> ShowS
forall pkg. Show pkg => [PackageSpecifier pkg] -> ShowS
forall pkg. Show pkg => PackageSpecifier pkg -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall pkg. Show pkg => Int -> PackageSpecifier pkg -> ShowS
showsPrec :: Int -> PackageSpecifier pkg -> ShowS
$cshow :: forall pkg. Show pkg => PackageSpecifier pkg -> String
show :: PackageSpecifier pkg -> String
$cshowList :: forall pkg. Show pkg => [PackageSpecifier pkg] -> ShowS
showList :: [PackageSpecifier pkg] -> ShowS
Show, (forall a b. (a -> b) -> PackageSpecifier a -> PackageSpecifier b)
-> (forall a b. a -> PackageSpecifier b -> PackageSpecifier a)
-> Functor PackageSpecifier
forall a b. a -> PackageSpecifier b -> PackageSpecifier a
forall a b. (a -> b) -> PackageSpecifier a -> PackageSpecifier b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> PackageSpecifier a -> PackageSpecifier b
fmap :: forall a b. (a -> b) -> PackageSpecifier a -> PackageSpecifier b
$c<$ :: forall a b. a -> PackageSpecifier b -> PackageSpecifier a
<$ :: forall a b. a -> PackageSpecifier b -> PackageSpecifier a
Functor, (forall x. PackageSpecifier pkg -> Rep (PackageSpecifier pkg) x)
-> (forall x. Rep (PackageSpecifier pkg) x -> PackageSpecifier pkg)
-> Generic (PackageSpecifier pkg)
forall x. Rep (PackageSpecifier pkg) x -> PackageSpecifier pkg
forall x. PackageSpecifier pkg -> Rep (PackageSpecifier pkg) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall pkg x. Rep (PackageSpecifier pkg) x -> PackageSpecifier pkg
forall pkg x. PackageSpecifier pkg -> Rep (PackageSpecifier pkg) x
$cfrom :: forall pkg x. PackageSpecifier pkg -> Rep (PackageSpecifier pkg) x
from :: forall x. PackageSpecifier pkg -> Rep (PackageSpecifier pkg) x
$cto :: forall pkg x. Rep (PackageSpecifier pkg) x -> PackageSpecifier pkg
to :: forall x. Rep (PackageSpecifier pkg) x -> PackageSpecifier pkg
Generic)

instance Binary pkg => Binary (PackageSpecifier pkg)
instance Structured pkg => Structured (PackageSpecifier pkg)

pkgSpecifierTarget :: Package pkg => PackageSpecifier pkg -> PackageName
pkgSpecifierTarget :: forall pkg. Package pkg => PackageSpecifier pkg -> PackageName
pkgSpecifierTarget (NamedPackage PackageName
name [PackageProperty]
_) = PackageName
name
pkgSpecifierTarget (SpecificSourcePackage pkg
pkg) = pkg -> PackageName
forall pkg. Package pkg => pkg -> PackageName
packageName pkg
pkg

pkgSpecifierConstraints
  :: Package pkg
  => PackageSpecifier pkg
  -> [LabeledPackageConstraint]
pkgSpecifierConstraints :: forall pkg.
Package pkg =>
PackageSpecifier pkg -> [LabeledPackageConstraint]
pkgSpecifierConstraints (NamedPackage PackageName
name [PackageProperty]
props) = (PackageProperty -> LabeledPackageConstraint)
-> [PackageProperty] -> [LabeledPackageConstraint]
forall a b. (a -> b) -> [a] -> [b]
map PackageProperty -> LabeledPackageConstraint
toLpc [PackageProperty]
props
  where
    toLpc :: PackageProperty -> LabeledPackageConstraint
toLpc PackageProperty
prop =
      PackageConstraint -> ConstraintSource -> LabeledPackageConstraint
LabeledPackageConstraint
        (ConstraintScope -> PackageProperty -> PackageConstraint
PackageConstraint (PackageName -> ConstraintScope
scopeToplevel PackageName
name) PackageProperty
prop)
        ConstraintSource
ConstraintSourceUserTarget
pkgSpecifierConstraints (SpecificSourcePackage pkg
pkg) =
  [PackageConstraint -> ConstraintSource -> LabeledPackageConstraint
LabeledPackageConstraint PackageConstraint
pc ConstraintSource
ConstraintSourceUserTarget]
  where
    pc :: PackageConstraint
pc =
      ConstraintScope -> PackageProperty -> PackageConstraint
PackageConstraint
        (PackageName -> ConstraintScope
ScopeTarget (PackageName -> ConstraintScope) -> PackageName -> ConstraintScope
forall a b. (a -> b) -> a -> b
$ pkg -> PackageName
forall pkg. Package pkg => pkg -> PackageName
packageName pkg
pkg)
        (VersionRange -> PackageProperty
PackagePropertyVersion (VersionRange -> PackageProperty)
-> VersionRange -> PackageProperty
forall a b. (a -> b) -> a -> b
$ Version -> VersionRange
thisVersion (pkg -> Version
forall pkg. Package pkg => pkg -> Version
packageVersion pkg
pkg))

mkNamedPackage :: PackageIdentifier -> PackageSpecifier pkg
mkNamedPackage :: forall pkg. PackageIdentifier -> PackageSpecifier pkg
mkNamedPackage PackageIdentifier
pkgId =
  PackageName -> [PackageProperty] -> PackageSpecifier pkg
forall pkg.
PackageName -> [PackageProperty] -> PackageSpecifier pkg
NamedPackage
    (PackageIdentifier -> PackageName
pkgName PackageIdentifier
pkgId)
    ( if PackageIdentifier -> Version
pkgVersion PackageIdentifier
pkgId Version -> Version -> Bool
forall a. Eq a => a -> a -> Bool
== Version
nullVersion
        then []
        else [VersionRange -> PackageProperty
PackagePropertyVersion (Version -> VersionRange
thisVersion (PackageIdentifier -> Version
pkgVersion PackageIdentifier
pkgId))]
    )