module Distribution.Solver.Types.PackagePath
    ( PackagePath(..)
    , Namespace(..)
    , Qualifier(..)
    , dispQualifier
    , Qualified(..)
    , QPN
    , dispQPN
    , showQPN
    ) where

import Distribution.Solver.Compat.Prelude
import Prelude ()
import Distribution.Package (PackageName)
import Distribution.Pretty (pretty, flatStyle)
import qualified Text.PrettyPrint as Disp

-- | A package path consists of a namespace and a package path inside that
-- namespace.
data PackagePath = PackagePath Namespace Qualifier
  deriving (PackagePath -> PackagePath -> Bool
(PackagePath -> PackagePath -> Bool)
-> (PackagePath -> PackagePath -> Bool) -> Eq PackagePath
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PackagePath -> PackagePath -> Bool
$c/= :: PackagePath -> PackagePath -> Bool
== :: PackagePath -> PackagePath -> Bool
$c== :: PackagePath -> PackagePath -> Bool
Eq, Eq PackagePath
Eq PackagePath
-> (PackagePath -> PackagePath -> Ordering)
-> (PackagePath -> PackagePath -> Bool)
-> (PackagePath -> PackagePath -> Bool)
-> (PackagePath -> PackagePath -> Bool)
-> (PackagePath -> PackagePath -> Bool)
-> (PackagePath -> PackagePath -> PackagePath)
-> (PackagePath -> PackagePath -> PackagePath)
-> Ord PackagePath
PackagePath -> PackagePath -> Bool
PackagePath -> PackagePath -> Ordering
PackagePath -> PackagePath -> PackagePath
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 :: PackagePath -> PackagePath -> PackagePath
$cmin :: PackagePath -> PackagePath -> PackagePath
max :: PackagePath -> PackagePath -> PackagePath
$cmax :: PackagePath -> PackagePath -> PackagePath
>= :: PackagePath -> PackagePath -> Bool
$c>= :: PackagePath -> PackagePath -> Bool
> :: PackagePath -> PackagePath -> Bool
$c> :: PackagePath -> PackagePath -> Bool
<= :: PackagePath -> PackagePath -> Bool
$c<= :: PackagePath -> PackagePath -> Bool
< :: PackagePath -> PackagePath -> Bool
$c< :: PackagePath -> PackagePath -> Bool
compare :: PackagePath -> PackagePath -> Ordering
$ccompare :: PackagePath -> PackagePath -> Ordering
$cp1Ord :: Eq PackagePath
Ord, Int -> PackagePath -> ShowS
[PackagePath] -> ShowS
PackagePath -> String
(Int -> PackagePath -> ShowS)
-> (PackagePath -> String)
-> ([PackagePath] -> ShowS)
-> Show PackagePath
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PackagePath] -> ShowS
$cshowList :: [PackagePath] -> ShowS
show :: PackagePath -> String
$cshow :: PackagePath -> String
showsPrec :: Int -> PackagePath -> ShowS
$cshowsPrec :: Int -> PackagePath -> ShowS
Show)

-- | Top-level namespace
--
-- Package choices in different namespaces are considered completely independent
-- by the solver.
data Namespace =
    -- | The default namespace
    DefaultNamespace

    -- | A namespace for a specific build target
  | Independent PackageName
  deriving (Namespace -> Namespace -> Bool
(Namespace -> Namespace -> Bool)
-> (Namespace -> Namespace -> Bool) -> Eq Namespace
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Namespace -> Namespace -> Bool
$c/= :: Namespace -> Namespace -> Bool
== :: Namespace -> Namespace -> Bool
$c== :: Namespace -> Namespace -> Bool
Eq, Eq Namespace
Eq Namespace
-> (Namespace -> Namespace -> Ordering)
-> (Namespace -> Namespace -> Bool)
-> (Namespace -> Namespace -> Bool)
-> (Namespace -> Namespace -> Bool)
-> (Namespace -> Namespace -> Bool)
-> (Namespace -> Namespace -> Namespace)
-> (Namespace -> Namespace -> Namespace)
-> Ord Namespace
Namespace -> Namespace -> Bool
Namespace -> Namespace -> Ordering
Namespace -> Namespace -> Namespace
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 :: Namespace -> Namespace -> Namespace
$cmin :: Namespace -> Namespace -> Namespace
max :: Namespace -> Namespace -> Namespace
$cmax :: Namespace -> Namespace -> Namespace
>= :: Namespace -> Namespace -> Bool
$c>= :: Namespace -> Namespace -> Bool
> :: Namespace -> Namespace -> Bool
$c> :: Namespace -> Namespace -> Bool
<= :: Namespace -> Namespace -> Bool
$c<= :: Namespace -> Namespace -> Bool
< :: Namespace -> Namespace -> Bool
$c< :: Namespace -> Namespace -> Bool
compare :: Namespace -> Namespace -> Ordering
$ccompare :: Namespace -> Namespace -> Ordering
$cp1Ord :: Eq Namespace
Ord, Int -> Namespace -> ShowS
[Namespace] -> ShowS
Namespace -> String
(Int -> Namespace -> ShowS)
-> (Namespace -> String)
-> ([Namespace] -> ShowS)
-> Show Namespace
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Namespace] -> ShowS
$cshowList :: [Namespace] -> ShowS
show :: Namespace -> String
$cshow :: Namespace -> String
showsPrec :: Int -> Namespace -> ShowS
$cshowsPrec :: Int -> Namespace -> ShowS
Show)

-- | Pretty-prints a namespace. The result is either empty or
-- ends in a period, so it can be prepended onto a qualifier.
dispNamespace :: Namespace -> Disp.Doc
dispNamespace :: Namespace -> Doc
dispNamespace Namespace
DefaultNamespace = Doc
Disp.empty
dispNamespace (Independent PackageName
i) = PackageName -> Doc
forall a. Pretty a => a -> Doc
pretty PackageName
i Doc -> Doc -> Doc
<<>> String -> Doc
Disp.text String
"."

-- | Qualifier of a package within a namespace (see 'PackagePath')
data Qualifier =
    -- | Top-level dependency in this namespace
    QualToplevel

    -- | Any dependency on base is considered independent
    --
    -- This makes it possible to have base shims.
  | QualBase PackageName

    -- | Setup dependency
    --
    -- By rights setup dependencies ought to be nestable; after all, the setup
    -- dependencies of a package might themselves have setup dependencies, which
    -- are independent from everything else. However, this very quickly leads to
    -- infinite search trees in the solver. Therefore we limit ourselves to
    -- a single qualifier (within a given namespace).
  | QualSetup PackageName

    -- | If we depend on an executable from a package (via
    -- @build-tools@), we should solve for the dependencies of that
    -- package separately (since we're not going to actually try to
    -- link it.)  We qualify for EACH package separately; e.g.,
    -- @'Exe' pn1 pn2@ qualifies the @build-tools@ dependency on
    -- @pn2@ from package @pn1@.  (If we tracked only @pn1@, that
    -- would require a consistent dependency resolution for all
    -- of the depended upon executables from a package; if we
    -- tracked only @pn2@, that would require us to pick only one
    -- version of an executable over the entire install plan.)
  | QualExe PackageName PackageName
  deriving (Qualifier -> Qualifier -> Bool
(Qualifier -> Qualifier -> Bool)
-> (Qualifier -> Qualifier -> Bool) -> Eq Qualifier
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Qualifier -> Qualifier -> Bool
$c/= :: Qualifier -> Qualifier -> Bool
== :: Qualifier -> Qualifier -> Bool
$c== :: Qualifier -> Qualifier -> Bool
Eq, Eq Qualifier
Eq Qualifier
-> (Qualifier -> Qualifier -> Ordering)
-> (Qualifier -> Qualifier -> Bool)
-> (Qualifier -> Qualifier -> Bool)
-> (Qualifier -> Qualifier -> Bool)
-> (Qualifier -> Qualifier -> Bool)
-> (Qualifier -> Qualifier -> Qualifier)
-> (Qualifier -> Qualifier -> Qualifier)
-> Ord Qualifier
Qualifier -> Qualifier -> Bool
Qualifier -> Qualifier -> Ordering
Qualifier -> Qualifier -> Qualifier
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 :: Qualifier -> Qualifier -> Qualifier
$cmin :: Qualifier -> Qualifier -> Qualifier
max :: Qualifier -> Qualifier -> Qualifier
$cmax :: Qualifier -> Qualifier -> Qualifier
>= :: Qualifier -> Qualifier -> Bool
$c>= :: Qualifier -> Qualifier -> Bool
> :: Qualifier -> Qualifier -> Bool
$c> :: Qualifier -> Qualifier -> Bool
<= :: Qualifier -> Qualifier -> Bool
$c<= :: Qualifier -> Qualifier -> Bool
< :: Qualifier -> Qualifier -> Bool
$c< :: Qualifier -> Qualifier -> Bool
compare :: Qualifier -> Qualifier -> Ordering
$ccompare :: Qualifier -> Qualifier -> Ordering
$cp1Ord :: Eq Qualifier
Ord, Int -> Qualifier -> ShowS
[Qualifier] -> ShowS
Qualifier -> String
(Int -> Qualifier -> ShowS)
-> (Qualifier -> String)
-> ([Qualifier] -> ShowS)
-> Show Qualifier
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Qualifier] -> ShowS
$cshowList :: [Qualifier] -> ShowS
show :: Qualifier -> String
$cshow :: Qualifier -> String
showsPrec :: Int -> Qualifier -> ShowS
$cshowsPrec :: Int -> Qualifier -> ShowS
Show)

-- | Pretty-prints a qualifier. The result is either empty or
-- ends in a period, so it can be prepended onto a package name.
--
-- NOTE: the base qualifier is for a dependency _on_ base; the qualifier is
-- there to make sure different dependencies on base are all independent.
-- So we want to print something like @"A.base"@, where the @"A."@ part
-- is the qualifier and @"base"@ is the actual dependency (which, for the
-- 'Base' qualifier, will always be @base@).
dispQualifier :: Qualifier -> Disp.Doc
dispQualifier :: Qualifier -> Doc
dispQualifier Qualifier
QualToplevel = Doc
Disp.empty
dispQualifier (QualSetup PackageName
pn)  = PackageName -> Doc
forall a. Pretty a => a -> Doc
pretty PackageName
pn Doc -> Doc -> Doc
<<>> String -> Doc
Disp.text String
":setup."
dispQualifier (QualExe PackageName
pn PackageName
pn2) = PackageName -> Doc
forall a. Pretty a => a -> Doc
pretty PackageName
pn Doc -> Doc -> Doc
<<>> String -> Doc
Disp.text String
":" Doc -> Doc -> Doc
<<>>
                                 PackageName -> Doc
forall a. Pretty a => a -> Doc
pretty PackageName
pn2 Doc -> Doc -> Doc
<<>> String -> Doc
Disp.text String
":exe."
dispQualifier (QualBase PackageName
pn)  = PackageName -> Doc
forall a. Pretty a => a -> Doc
pretty PackageName
pn Doc -> Doc -> Doc
<<>> String -> Doc
Disp.text String
"."

-- | A qualified entity. Pairs a package path with the entity.
data Qualified a = Q PackagePath a
  deriving (Qualified a -> Qualified a -> Bool
(Qualified a -> Qualified a -> Bool)
-> (Qualified a -> Qualified a -> Bool) -> Eq (Qualified a)
forall a. Eq a => Qualified a -> Qualified a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Qualified a -> Qualified a -> Bool
$c/= :: forall a. Eq a => Qualified a -> Qualified a -> Bool
== :: Qualified a -> Qualified a -> Bool
$c== :: forall a. Eq a => Qualified a -> Qualified a -> Bool
Eq, Eq (Qualified a)
Eq (Qualified a)
-> (Qualified a -> Qualified a -> Ordering)
-> (Qualified a -> Qualified a -> Bool)
-> (Qualified a -> Qualified a -> Bool)
-> (Qualified a -> Qualified a -> Bool)
-> (Qualified a -> Qualified a -> Bool)
-> (Qualified a -> Qualified a -> Qualified a)
-> (Qualified a -> Qualified a -> Qualified a)
-> Ord (Qualified a)
Qualified a -> Qualified a -> Bool
Qualified a -> Qualified a -> Ordering
Qualified a -> Qualified a -> Qualified a
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
forall a. Ord a => Eq (Qualified a)
forall a. Ord a => Qualified a -> Qualified a -> Bool
forall a. Ord a => Qualified a -> Qualified a -> Ordering
forall a. Ord a => Qualified a -> Qualified a -> Qualified a
min :: Qualified a -> Qualified a -> Qualified a
$cmin :: forall a. Ord a => Qualified a -> Qualified a -> Qualified a
max :: Qualified a -> Qualified a -> Qualified a
$cmax :: forall a. Ord a => Qualified a -> Qualified a -> Qualified a
>= :: Qualified a -> Qualified a -> Bool
$c>= :: forall a. Ord a => Qualified a -> Qualified a -> Bool
> :: Qualified a -> Qualified a -> Bool
$c> :: forall a. Ord a => Qualified a -> Qualified a -> Bool
<= :: Qualified a -> Qualified a -> Bool
$c<= :: forall a. Ord a => Qualified a -> Qualified a -> Bool
< :: Qualified a -> Qualified a -> Bool
$c< :: forall a. Ord a => Qualified a -> Qualified a -> Bool
compare :: Qualified a -> Qualified a -> Ordering
$ccompare :: forall a. Ord a => Qualified a -> Qualified a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Qualified a)
Ord, Int -> Qualified a -> ShowS
[Qualified a] -> ShowS
Qualified a -> String
(Int -> Qualified a -> ShowS)
-> (Qualified a -> String)
-> ([Qualified a] -> ShowS)
-> Show (Qualified a)
forall a. Show a => Int -> Qualified a -> ShowS
forall a. Show a => [Qualified a] -> ShowS
forall a. Show a => Qualified a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Qualified a] -> ShowS
$cshowList :: forall a. Show a => [Qualified a] -> ShowS
show :: Qualified a -> String
$cshow :: forall a. Show a => Qualified a -> String
showsPrec :: Int -> Qualified a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Qualified a -> ShowS
Show)

-- | Qualified package name.
type QPN = Qualified PackageName

-- | Pretty-prints a qualified package name.
dispQPN :: QPN -> Disp.Doc
dispQPN :: QPN -> Doc
dispQPN (Q (PackagePath Namespace
ns Qualifier
qual) PackageName
pn) =
  Namespace -> Doc
dispNamespace Namespace
ns Doc -> Doc -> Doc
<<>> Qualifier -> Doc
dispQualifier Qualifier
qual Doc -> Doc -> Doc
<<>> PackageName -> Doc
forall a. Pretty a => a -> Doc
pretty PackageName
pn

-- | String representation of a qualified package name.
showQPN :: QPN -> String
showQPN :: QPN -> String
showQPN = Style -> Doc -> String
Disp.renderStyle Style
flatStyle (Doc -> String) -> (QPN -> Doc) -> QPN -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QPN -> Doc
dispQPN