-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Give Haskell development tools access to Cabal project environment
--   
--   The purpose of the <tt>cabal-helper</tt> library is to give Haskell
--   development tools access to the same environment which build tools
--   such as <tt>cabal</tt> and <tt>stack</tt> normally provide to the
--   compiler.
@package cabal-helper
@version 1.1.0.0


module Distribution.Helper.Discover

-- | <tt>findProjects dir</tt>. Find available project instances in
--   <tt>dir</tt>.
--   
--   For example, if the given directory contains both a
--   <tt>cabal.project</tt> and a <tt>stack.yaml</tt> file:
--   
--   <pre>
--   &gt;&gt;&gt; findProjects "."
--   [ Ex (ProjLocStackYaml "./stack.yaml"), Ex (ProjLocCabalV2File "./cabal.project") ]
--   </pre>
--   
--   Note that this function only looks for "default" project markers. If
--   you want to for example support the common pattern of having multiple
--   <tt>stack-<a>GHC_VER</a>.yaml</tt> files simply fill out a
--   <a>ProjLoc</a> yourself. In this case <a>ProjLocStackYaml</a>.
findProjects :: FilePath -> IO [Ex ProjLoc]

-- | <tt>getDefaultDistDir pl</tt>. Get the default dist-dir for the given
--   project.
--   
--   Note that the path in the returned dist-dir might not exist yet if the
--   build-tool has never been run for this project before. This is fine as
--   far as <tt>cabal-helper</tt> is concerned. It will simply invoke the
--   build-tool as needed to answer the requested queries.
getDefaultDistDir :: ProjLoc pt -> DistDir pt

-- | <tt>isValidDistDir distdir</tt>. Check if <tt>distdir</tt> looks like
--   a valid build-dir for it's project type. We just check if
--   characteristic marker files for the associated project type exist.
--   
--   If the project type does not have a way to do this (for example
--   <a>DistDirStack</a>) check we return <a>Nothing</a>.
isValidDistDir :: DistDir pt -> IO (Maybe Bool)


module Distribution.Helper

-- | A query against a package's Cabal configuration. Use <a>runQuery</a>
--   to execute it.
data Query pt a
runQuery :: Query pt a -> QueryEnv pt -> IO a

-- | The version of GHC the project is configured to use for compilation.
compilerVersion :: Query pt (String, Version)

-- | All local packages currently active in a project's build plan.
projectPackages :: Query pt (NonEmpty (Package pt))
type Package pt = Package' (NonEmpty (Unit pt))
pPackageName :: Package' units -> String
pSourceDir :: Package' units -> FilePath

-- | Cabal flags to set when configuring and building this package.
pUnits :: Package' units -> units

-- | A <a>Unit</a> is essentially a "build target". It is used to refer to
--   a set of components (exes, libs, tests etc.) which are managed by a
--   certain instance of the Cabal build-system[1]. We may get information
--   on the components in a unit by retriving the corresponding
--   <a>UnitInfo</a>.
--   
--   [1]: No I'm not talking about the cabal-install <i>build-tool</i>, I'm
--   talking about the Cabal <i>build-system</i>. Note the distinction.
--   Both cabal-install and Stack use the Cabal build-system (aka
--   <tt>lib:Cabal</tt>) underneath.
--   
--   Note that a <a>Unit</a> value is only valid within the <a>QueryEnv</a>
--   context it was created in, this is however this is not enforced by the
--   API. Furthermore if the user changes the underlying project
--   configuration while your application is running even a properly scoped
--   <a>Unit</a> could become invalid because the component it belongs to
--   was removed from the cabal file.
data Unit pt

-- | This returns the component a <a>Unit</a> corresponds to. This
--   information is only available if the correspondence happens to be
--   unique and known before querying setup-config for the respective
--   project type. Currently this only applies to <tt>pt=</tt><tt>V2</tt>.
--   
--   This is intended to be used as an optimization, to allow reducing the
--   number of helper invocations for clients that don't need to know the
--   entire project structure.
uComponentName :: Unit pt -> Maybe ChComponentName
data UnitId

-- | The information extracted from a <a>Unit</a>'s on-disk configuration
--   cache.
data UnitInfo
UnitInfo :: !UnitId -> !(String, Version) -> !Map ChComponentName ChComponentInfo -> !(String, Version) -> ![(String, Bool)] -> ![(String, Bool)] -> ![(String, Bool)] -> !UnitModTimes -> UnitInfo

-- | A unique identifier of this unit within the originating project.
[uiUnitId] :: UnitInfo -> !UnitId

-- | The package-name and version this unit belongs to.
[uiPackageId] :: UnitInfo -> !(String, Version)

-- | The components of the unit: libraries, executables, test-suites,
--   benchmarks and so on.
[uiComponents] :: UnitInfo -> !Map ChComponentName ChComponentInfo

-- | The version of GHC the unit is configured to use
[uiCompilerId] :: UnitInfo -> !(String, Version)

-- | Flag definitions from cabal file
[uiPackageFlags] :: UnitInfo -> ![(String, Bool)]

-- | Flag assignments from active configuration
[uiConfigFlags] :: UnitInfo -> ![(String, Bool)]

-- | Flag assignments from setup-config which differ from the default
--   setting. This can also include flags which cabal decided to modify,
--   i.e. don't rely on these being the flags set by the user directly.
[uiNonDefaultConfigFlags] :: UnitInfo -> ![(String, Bool)]

-- | Key for cache invalidation. When this is not equal to the value
--   returned by <tt>getUnitModTimes</tt> this <a>UnitInfo</a> is
--   considered invalid.
[uiModTimes] :: UnitInfo -> !UnitModTimes

-- | Get the <a>UnitInfo</a> for a given <a>Unit</a>. To get a <a>Unit</a>
--   see <tt>projectUnits</tt>.
unitInfo :: Unit pt -> Query pt UnitInfo

-- | Get information on all units in a project.
allUnits :: (UnitInfo -> a) -> Query pt (NonEmpty a)

-- | Environment for running a <tt>Query</tt>. The constructor is not
--   exposed in the API to allow extending it with more fields without
--   breaking user code.
--   
--   To create a <a>QueryEnv</a> use the <tt>mkQueryEnv</tt> smart
--   constructor instead. Some field accessors are exported and may be used
--   to override the defaults filled in by <tt>mkQueryEnv</tt>. See below.
--   
--   Note that this environment contains an <a>IORef</a> used as a cache.
--   If you want to take advantage of this you should not simply discard
--   the value returned by the smart constructor after one use.
type QueryEnv pt = QueryEnvI QueryCache pt
data QueryEnvI c (pt :: ProjType)

-- | <tt>mkQueryEnv projdir distdir</tt>. Smart constructor for
--   <a>QueryEnv</a>. Sets fields <a>qeProjLoc</a> and <a>qeDistDir</a> to
--   <tt>projdir</tt> and <tt>distdir</tt> respectively and provides
--   sensible defaults for the other fields.
mkQueryEnv :: ProjLoc pt -> DistDir pt -> IO (QueryEnv pt)

-- | Field accessor for <a>QueryEnv</a>. Function used to to start
--   processes and capture output. Useful if you need to, for example,
--   redirect standard error output of programs started by cabal-helper.
qeReadProcess :: QueryEnvI c pt -> ReadProcessWithCwdAndEnv

-- | Field accessor for <a>QueryEnv</a>. Function used to to start
--   processes without capturing output. See also <a>qeReadProcess</a>.
qeCallProcess :: QueryEnvI c pt -> CallProcessWithCwdAndEnv ()

-- | Field accessor for <a>QueryEnv</a>. Paths to various programs we use.
qePrograms :: QueryEnvI c pt -> Programs

-- | Field accessor for <a>QueryEnv</a>. Defines path to the project
--   directory, i.e. a directory containing a <tt>cabal.project</tt> file
qeProjLoc :: QueryEnvI c pt -> ProjLoc pt

-- | Field accessor for <a>QueryEnv</a>. Defines path to the <tt>dist/</tt>
--   or <tt>dist-newstyle/</tt> directory, aka. <i>builddir</i> in Cabal
--   terminology.
qeDistDir :: QueryEnvI c pt -> DistDir pt

-- | The kind of project being managed by a <a>QueryEnv</a> (pun intended).
--   Used as a phantom-type variable throughout to make the project type
--   being passed into various functions correspond to the correct
--   implementation.
data ProjType

-- | <tt>cabal</tt> project.
Cabal :: CabalProjType -> ProjType

-- | <tt>stack</tt> project.
Stack :: ProjType

-- | The kind of a <tt>cabal</tt> project.
data CabalProjType

-- | <tt>cabal v1-build</tt> project.
CV1 :: CabalProjType

-- | <tt>cabal v2-build</tt> project.
CV2 :: CabalProjType

-- | Location of a project context. This is usually just the path project's
--   top-level source code directory together with an optional project-type
--   specific config file path.
--   
--   To find any recognized default project contexts in a given directory
--   use <a>findProjects</a>.
--   
--   Build tools usually allow the user to specify the location of their
--   project config files manually, so we also support passing this path
--   here with the <tt>*File</tt> constructors.
--   
--   <h3>Correspondence between Project and Package Source Directories</h3>
--   
--   Note that the project's source directory does not necessarily
--   correspond to the directory containing the project config file, though
--   in some cases it does.
--   
--   For example <tt>cabal v2-build</tt> allows the <tt>cabal.project</tt>
--   file to be positively anywhere in the filesystem when specified via
--   the <tt>--cabal-project</tt> command-line flag, corresponding to the
--   <a>ProjLocV2File</a> constructor here. This config file can then refer
--   to package directories with absolute paths in the <tt>packages:</tt>
--   declaration.
--   
--   Hence it isn't actually possible to find <i>one</i> directory which
--   contains the whole project's source code but rather we have to
--   consider each package's source directory individually, see
--   <a>pSourceDir</a>
data ProjLoc (pt :: ProjType)

-- | A fully specified <tt>cabal v1-build</tt> project context. Here you
--   can specify both the path to the <tt>.cabal</tt> file and the source
--   directory of the package. The cabal file path corresponds to the
--   <tt>--cabal-file=PATH</tt> flag on the <tt>cabal</tt> command line.
--   
--   Note that more than one such files existing in a package directory is
--   a user error and while cabal will still complain about that we won't.
--   
--   Also note that for this project type the concepts of project and
--   package coincide.
[ProjLocV1CabalFile] :: {plCabalFile :: !FilePath, plProjectDirV1 :: !FilePath} -> ProjLoc ('Cabal 'CV1)

-- | A <tt>cabal v1-build</tt> project context. Essentially the same as
--   <a>ProjLocV1CabalFile</a> but this will dynamically search for the
--   cabal file for you as cabal-install does by default.
--   
--   If more than one <tt>.cabal</tt> file is found in the given directory
--   we will shamelessly throw a obscure exception so prefer
--   <a>ProjLocV1CabalFile</a> if you don't want that to happen. This
--   mainly exists for easy upgrading from the <tt>cabal-helper-0.8</tt>
--   series.
[ProjLocV1Dir] :: {plProjectDirV1 :: !FilePath} -> ProjLoc ('Cabal 'CV1)

-- | A <tt>cabal v2-build</tt> project context. The path to the
--   <tt>cabal.project</tt> file, though you can call it whatever you like.
--   This configuration file then points to the packages that make up this
--   project. This corresponds to the <tt>--cabal-project=PATH</tt> flag on
--   the <tt>cabal</tt> command line.
[ProjLocV2File] :: {plCabalProjectFile :: !FilePath, plProjectDirV2 :: !FilePath} -> ProjLoc ('Cabal 'CV2)

-- | This is equivalent to <a>ProjLocV2File</a> but using the default
--   <tt>cabal.project</tt> file name in the given directory.
[ProjLocV2Dir] :: {plProjectDirV2 :: !FilePath} -> ProjLoc ('Cabal 'CV2)

-- | A <tt>stack</tt> project context. Specify the path to the
--   <tt>stack.yaml</tt> file here. This configuration file then points to
--   the packages that make up this project. Corresponds to
--   <tt>stack</tt>'s <tt>--stack-yaml=PATH</tt> command line flag if
--   different from the default name, <tt>stack.yaml</tt>.
--   
--   Note: with Stack the invariant <tt>takeDirectory plStackYaml ==
--   projdir</tt> holds.
[ProjLocStackYaml] :: {plStackYaml :: !FilePath} -> ProjLoc 'Stack

-- | A build directory for a certain project type. The <tt>pt</tt> type
--   variable must be compatible with the <a>ProjLoc</a> used. This is
--   enforced by the type system so you can't get this wrong.
data DistDir (pt :: ProjType)

-- | A build-directory for cabal, aka. dist-dir in Cabal terminology.
--   <a>SCabalProjType</a> specifies whether we should use <i>v2-build</i>
--   or <i>v1-build</i>. This choice must correspond to <a>ProjLoc</a> 's
--   project type.
[DistDirCabal] :: !SCabalProjType pt -> !FilePath -> DistDir ('Cabal pt)

-- | A build-directory for stack, aka. <i>work-dir</i>. Optionally override
--   Stack's <i>work-dir</i>. If you just want to use Stack's default set
--   to <tt>Nothing</tt>
[DistDirStack] :: !Maybe RelativePath -> DistDir 'Stack

-- | A "singleton" datatype for <a>ProjType</a> which allows us to
--   establish a correspondence between a runtime representation of
--   <a>ProjType</a> to the compile-time value at the type level.
--   
--   If you just want to know the runtime <a>ProjType</a> use
--   <a>demoteSProjType</a> to convert to that.
data SProjType pt
[SCabal] :: !SCabalProjType pt -> SProjType ('Cabal pt)
[SStack] :: SProjType 'Stack
demoteSProjType :: SProjType pt -> ProjType
projTypeOfDistDir :: DistDir pt -> SProjType pt
projTypeOfProjLoc :: ProjLoc pt -> SProjType pt

-- | This is a singleton, like <a>SProjType</a>, but restricted to just the
--   Cabal project types. We use this to restrict some functions which
--   don't make sense for Stack to just the Cabal project types.
data SCabalProjType pt
[SCV1] :: SCabalProjType 'CV1
[SCV2] :: SCabalProjType 'CV2

-- | General purpose existential wrapper. Useful for hiding a phantom type
--   argument.
--   
--   Say you have:
--   
--   <pre>
--   {-# LANGUAGE DataKinds, GADTS #-}
--   data K = A | B | ...
--   data Q k where
--     QA :: ... -&gt; Q 'A
--     QB :: ... -&gt; Q 'B
--   </pre>
--   
--   and you want a list of <tt>Q</tt>. You can use <tt>Ex</tt> to hide the
--   phantom type argument and recover it later by matching on the GADT
--   constructors:
--   
--   <pre>
--   qa :: Q A
--   qa = QA
--   
--   qb :: Q B
--   qb = QB
--   
--   mylist :: [Ex Q]
--   mylist = [Ex qa, Ex qb]
--   </pre>
data Ex a
Ex :: a x -> Ex a

-- | Configurable paths to various programs we use.
data Programs
Programs :: !FilePath -> ![String] -> ![String] -> !FilePath -> ![String] -> ![String] -> ![(String, EnvOverride)] -> !FilePath -> !FilePath -> !FilePath -> Programs

-- | The path to the <tt>cabal</tt> program.
[cabalProgram] :: Programs -> !FilePath
[cabalProjArgs] :: Programs -> ![String]
[cabalUnitArgs] :: Programs -> ![String]

-- | The path to the <tt>stack</tt> program.
[stackProgram] :: Programs -> !FilePath
[stackProjArgs] :: Programs -> ![String]
[stackUnitArgs] :: Programs -> ![String]
[stackEnv] :: Programs -> ![(String, EnvOverride)]

-- | The path to the <tt>ghc</tt> program.
[ghcProgram] :: Programs -> !FilePath

-- | The path to the <tt>ghc-pkg</tt> program. If not changed it will be
--   derived from the path to <a>ghcProgram</a>.
[ghcPkgProgram] :: Programs -> !FilePath

-- | The path to the <tt>haddock</tt> program. If not changed it will be
--   derived from the path to <a>ghcProgram</a>.
[haddockProgram] :: Programs -> !FilePath

-- | By default all programs use their unqualified names, i.e. they will be
--   searched for on <tt>PATH</tt>.
defaultPrograms :: Programs
data EnvOverride
EnvUnset :: EnvOverride
EnvSet :: String -> EnvOverride
EnvAppend :: String -> EnvOverride
EnvPrepend :: String -> EnvOverride
data ChComponentInfo
ChComponentInfo :: ChComponentName -> [String] -> [String] -> ChEntrypoint -> ChComponentInfo

-- | The component's type and name
[ciComponentName] :: ChComponentInfo -> ChComponentName

-- | Full set of GHC options, ready for loading this component into GHCi.
[ciGhcOptions] :: ChComponentInfo -> [String]

-- | A component's <tt>hs-source-dirs</tt> field, note that this only
--   contains the directories specified by the cabal file, however cabal
--   also adds the output directory of preprocessors to GHC's search path
--   when building. TODO: make this easier to use.
[ciSourceDirs] :: ChComponentInfo -> [String]

-- | Modules or files Cabal would have the compiler build directly. Can be
--   used to compute the home module closure for a component.
[ciEntrypoints] :: ChComponentInfo -> ChEntrypoint
data ChComponentName
ChSetupHsName :: ChComponentName
ChLibName :: ChLibraryName -> ChComponentName
ChFLibName :: String -> ChComponentName
ChExeName :: String -> ChComponentName
ChTestName :: String -> ChComponentName
ChBenchName :: String -> ChComponentName
data ChLibraryName
ChMainLibName :: ChLibraryName
ChSubLibName :: String -> ChLibraryName
newtype ChModuleName
ChModuleName :: String -> ChModuleName
[unChModuleName] :: ChModuleName -> String
data ChPkgDb
ChPkgGlobal :: ChPkgDb
ChPkgUser :: ChPkgDb
ChPkgSpecific :: FilePath -> ChPkgDb
data ChEntrypoint
ChSetupEntrypoint :: FilePath -> ChEntrypoint
[chMainIs] :: ChEntrypoint -> FilePath
ChLibEntrypoint :: [ChModuleName] -> [ChModuleName] -> [ChModuleName] -> ChEntrypoint
[chExposedModules] :: ChEntrypoint -> [ChModuleName]
[chOtherModules] :: ChEntrypoint -> [ChModuleName]
[chSignatures] :: ChEntrypoint -> [ChModuleName]
ChExeEntrypoint :: FilePath -> [ChModuleName] -> ChEntrypoint
[chMainIs] :: ChEntrypoint -> FilePath
[chOtherModules] :: ChEntrypoint -> [ChModuleName]
buildPlatform :: String

-- | Get the path to the sandbox package-db in a project
getSandboxPkgDb :: String -> GhcVersion -> FilePath -> IO (Maybe FilePath)

-- | Make sure the appropriate helper executable for the given project is
--   installed and ready to run queries.
--   
--   The idea is you can run this at a convinient time instead of having
--   the helper compilation happen during a time-sensitive user
--   interaction. This will however happen automatically as needed if you
--   don't run it first.
prepare :: Query pt ()

-- | Create <tt>cabal_macros.h</tt>, <tt>Paths_&lt;pkg&gt;.hs</tt> and
--   other generated files in the usual place. See
--   <a>initialBuildSteps</a>.
--   
--   This is usually only needed on the first load of a unit or after the
--   cabal file changes.
writeAutogenFiles :: Unit pt -> Query pt ()
buildProject :: Query pt ()
buildUnits :: [Unit pt] -> Query pt ()
instance GHC.Base.Functor (Distribution.Helper.Query pt)
instance GHC.Base.Applicative (Distribution.Helper.Query pt)
instance GHC.Base.Monad (Distribution.Helper.Query pt)
