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

module Distribution.Types.ComponentLocalBuildInfo (
  ComponentLocalBuildInfo(..),
  componentIsIndefinite,
  maybeComponentInstantiatedWith,
  ) where

import Prelude ()
import Distribution.Compat.Prelude
import Distribution.ModuleName

import Distribution.Backpack
import Distribution.Compat.Graph
import Distribution.Types.ComponentId
import Distribution.Types.MungedPackageId
import Distribution.Types.UnitId
import Distribution.Types.ComponentName
import Distribution.Types.MungedPackageName
import Distribution.Types.ModuleRenaming

import qualified Distribution.InstalledPackageInfo as Installed

-- | The first five fields are common across all algebraic variants.
data ComponentLocalBuildInfo
  = LibComponentLocalBuildInfo {
    -- | It would be very convenient to store the literal Library here,
    -- but if we do that, it will get serialized (via the Binary)
    -- instance twice.  So instead we just provide the ComponentName,
    -- which can be used to find the Component in the
    -- PackageDescription.  NB: eventually, this will NOT uniquely
    -- identify the ComponentLocalBuildInfo.
    ComponentLocalBuildInfo -> ComponentName
componentLocalName :: ComponentName,
    -- | The computed 'ComponentId' of this component.
    ComponentLocalBuildInfo -> ComponentId
componentComponentId :: ComponentId,
    -- | The computed 'UnitId' which uniquely identifies this
    -- component.  Might be hashed.
    ComponentLocalBuildInfo -> UnitId
componentUnitId :: UnitId,
    -- | Is this an indefinite component (i.e. has unfilled holes)?
    ComponentLocalBuildInfo -> Bool
componentIsIndefinite_ :: Bool,
    -- | How the component was instantiated
    ComponentLocalBuildInfo -> [(ModuleName, OpenModule)]
componentInstantiatedWith :: [(ModuleName, OpenModule)],
    -- | Resolved internal and external package dependencies for this component.
    -- The 'BuildInfo' specifies a set of build dependencies that must be
    -- satisfied in terms of version ranges. This field fixes those dependencies
    -- to the specific versions available on this machine for this compiler.
    ComponentLocalBuildInfo -> [(UnitId, MungedPackageId)]
componentPackageDeps :: [(UnitId, MungedPackageId)],
    -- | The set of packages that are brought into scope during
    -- compilation, including a 'ModuleRenaming' which may used
    -- to hide or rename modules.  This is what gets translated into
    -- @-package-id@ arguments.  This is a modernized version of
    -- 'componentPackageDeps', which is kept around for BC purposes.
    ComponentLocalBuildInfo -> [(OpenUnitId, ModuleRenaming)]
componentIncludes :: [(OpenUnitId, ModuleRenaming)],
    ComponentLocalBuildInfo -> [UnitId]
componentExeDeps :: [UnitId],
    -- | The internal dependencies which induce a graph on the
    -- 'ComponentLocalBuildInfo' of this package.  This does NOT
    -- coincide with 'componentPackageDeps' because it ALSO records
    -- 'build-tool' dependencies on executables.  Maybe one day
    -- @cabal-install@ will also handle these correctly too!
    ComponentLocalBuildInfo -> [UnitId]
componentInternalDeps :: [UnitId],
    -- | Compatibility "package key" that we pass to older versions of GHC.
    ComponentLocalBuildInfo -> String
componentCompatPackageKey :: String,
    -- | Compatibility "package name" that we register this component as.
    ComponentLocalBuildInfo -> MungedPackageName
componentCompatPackageName :: MungedPackageName,
    -- | A list of exposed modules (either defined in this component,
    -- or reexported from another component.)
    ComponentLocalBuildInfo -> [ExposedModule]
componentExposedModules :: [Installed.ExposedModule],
    -- | Convenience field, specifying whether or not this is the
    -- "public library" that has the same name as the package.
    ComponentLocalBuildInfo -> Bool
componentIsPublic :: Bool
  }
  -- TODO: refactor all these duplicates
  | FLibComponentLocalBuildInfo {
    componentLocalName :: ComponentName,
    componentComponentId :: ComponentId,
    componentUnitId :: UnitId,
    componentPackageDeps :: [(UnitId, MungedPackageId)],
    componentIncludes :: [(OpenUnitId, ModuleRenaming)],
    componentExeDeps :: [UnitId],
    componentInternalDeps :: [UnitId]
  }
  | ExeComponentLocalBuildInfo {
    componentLocalName :: ComponentName,
    componentComponentId :: ComponentId,
    componentUnitId :: UnitId,
    componentPackageDeps :: [(UnitId, MungedPackageId)],
    componentIncludes :: [(OpenUnitId, ModuleRenaming)],
    componentExeDeps :: [UnitId],
    componentInternalDeps :: [UnitId]
  }
  | TestComponentLocalBuildInfo {
    componentLocalName :: ComponentName,
    componentComponentId :: ComponentId,
    componentUnitId :: UnitId,
    componentPackageDeps :: [(UnitId, MungedPackageId)],
    componentIncludes :: [(OpenUnitId, ModuleRenaming)],
    componentExeDeps :: [UnitId],
    componentInternalDeps :: [UnitId]

  }
  | BenchComponentLocalBuildInfo {
    componentLocalName :: ComponentName,
    componentComponentId :: ComponentId,
    componentUnitId :: UnitId,
    componentPackageDeps :: [(UnitId, MungedPackageId)],
    componentIncludes :: [(OpenUnitId, ModuleRenaming)],
    componentExeDeps :: [UnitId],
    componentInternalDeps :: [UnitId]
  }
  deriving ((forall x.
 ComponentLocalBuildInfo -> Rep ComponentLocalBuildInfo x)
-> (forall x.
    Rep ComponentLocalBuildInfo x -> ComponentLocalBuildInfo)
-> Generic ComponentLocalBuildInfo
forall x. Rep ComponentLocalBuildInfo x -> ComponentLocalBuildInfo
forall x. ComponentLocalBuildInfo -> Rep ComponentLocalBuildInfo x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ComponentLocalBuildInfo -> Rep ComponentLocalBuildInfo x
$cto :: forall x. Rep ComponentLocalBuildInfo x -> ComponentLocalBuildInfo
Generic, ReadPrec [ComponentLocalBuildInfo]
ReadPrec ComponentLocalBuildInfo
Int -> ReadS ComponentLocalBuildInfo
ReadS [ComponentLocalBuildInfo]
(Int -> ReadS ComponentLocalBuildInfo)
-> ReadS [ComponentLocalBuildInfo]
-> ReadPrec ComponentLocalBuildInfo
-> ReadPrec [ComponentLocalBuildInfo]
-> Read ComponentLocalBuildInfo
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS ComponentLocalBuildInfo
readsPrec :: Int -> ReadS ComponentLocalBuildInfo
$creadList :: ReadS [ComponentLocalBuildInfo]
readList :: ReadS [ComponentLocalBuildInfo]
$creadPrec :: ReadPrec ComponentLocalBuildInfo
readPrec :: ReadPrec ComponentLocalBuildInfo
$creadListPrec :: ReadPrec [ComponentLocalBuildInfo]
readListPrec :: ReadPrec [ComponentLocalBuildInfo]
Read, Int -> ComponentLocalBuildInfo -> ShowS
[ComponentLocalBuildInfo] -> ShowS
ComponentLocalBuildInfo -> String
(Int -> ComponentLocalBuildInfo -> ShowS)
-> (ComponentLocalBuildInfo -> String)
-> ([ComponentLocalBuildInfo] -> ShowS)
-> Show ComponentLocalBuildInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ComponentLocalBuildInfo -> ShowS
showsPrec :: Int -> ComponentLocalBuildInfo -> ShowS
$cshow :: ComponentLocalBuildInfo -> String
show :: ComponentLocalBuildInfo -> String
$cshowList :: [ComponentLocalBuildInfo] -> ShowS
showList :: [ComponentLocalBuildInfo] -> ShowS
Show, Typeable)

instance Binary ComponentLocalBuildInfo
instance Structured ComponentLocalBuildInfo

instance IsNode ComponentLocalBuildInfo where
    type Key ComponentLocalBuildInfo = UnitId
    nodeKey :: ComponentLocalBuildInfo -> Key ComponentLocalBuildInfo
nodeKey = ComponentLocalBuildInfo -> Key ComponentLocalBuildInfo
ComponentLocalBuildInfo -> UnitId
componentUnitId
    nodeNeighbors :: ComponentLocalBuildInfo -> [Key ComponentLocalBuildInfo]
nodeNeighbors = ComponentLocalBuildInfo -> [Key ComponentLocalBuildInfo]
ComponentLocalBuildInfo -> [UnitId]
componentInternalDeps

componentIsIndefinite :: ComponentLocalBuildInfo -> Bool
componentIsIndefinite :: ComponentLocalBuildInfo -> Bool
componentIsIndefinite LibComponentLocalBuildInfo{ componentIsIndefinite_ :: ComponentLocalBuildInfo -> Bool
componentIsIndefinite_ = Bool
b } = Bool
b
componentIsIndefinite ComponentLocalBuildInfo
_ = Bool
False

maybeComponentInstantiatedWith :: ComponentLocalBuildInfo -> Maybe [(ModuleName, OpenModule)]
maybeComponentInstantiatedWith :: ComponentLocalBuildInfo -> Maybe [(ModuleName, OpenModule)]
maybeComponentInstantiatedWith
    LibComponentLocalBuildInfo { componentInstantiatedWith :: ComponentLocalBuildInfo -> [(ModuleName, OpenModule)]
componentInstantiatedWith = [(ModuleName, OpenModule)]
insts } = [(ModuleName, OpenModule)] -> Maybe [(ModuleName, OpenModule)]
forall a. a -> Maybe a
Just [(ModuleName, OpenModule)]
insts
maybeComponentInstantiatedWith ComponentLocalBuildInfo
_ = Maybe [(ModuleName, OpenModule)]
forall a. Maybe a
Nothing