content: module Distribution.Solver.Types.PackagePath
      ( PackagePath(..)
      , Namespace(..)
      , Qualifier(..)
      , dispQualifier
      , Qualified(..)
      , QPN
      , dispQPN
      , showQPN
      ) where
  
  import Distribution.Package
  import Distribution.Text
  import qualified Text.PrettyPrint as Disp
  import Distribution.Client.Compat.Prelude ((<<>>))
  
  -- | A package path consists of a namespace and a package path inside that
  -- namespace.
  data PackagePath = PackagePath Namespace Qualifier
    deriving (Eq, Ord, Show)
  
  -- | Top-level namespace
  --
  -- Package choices in different namespaces are considered completely independent
  -- by the solver.
  data Namespace =
      -- | The default namespace
      DefaultNamespace
  
      -- | Independent namespace
      --
      -- For now we just number these (rather than giving them more structure).
    | Independent Int
    deriving (Eq, Ord, 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 DefaultNamespace = Disp.empty
  dispNamespace (Independent i) = Disp.int i <<>> Disp.text "."
  
  -- | 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 (Eq, Ord, 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 QualToplevel = Disp.empty
  dispQualifier (QualSetup pn)  = disp pn <<>> Disp.text ":setup."
  dispQualifier (QualExe pn pn2) = disp pn <<>> Disp.text ":" <<>>
                                   disp pn2 <<>> Disp.text ":exe."
  dispQualifier (QualBase pn)  = disp pn <<>> Disp.text "."
  
  -- | A qualified entity. Pairs a package path with the entity.
  data Qualified a = Q PackagePath a
    deriving (Eq, Ord, Show)
  
  -- | Qualified package name.
  type QPN = Qualified PackageName
  
  -- | Pretty-prints a qualified package name.
  dispQPN :: QPN -> Disp.Doc
  dispQPN (Q (PackagePath ns qual) pn) =
    dispNamespace ns <<>> dispQualifier qual <<>> disp pn
  
  -- | String representation of a qualified package name.
  showQPN :: QPN -> String
  showQPN = Disp.renderStyle flatStyle . dispQPN
  