{-# LANGUAGE ScopedTypeVariables, TemplateHaskell, DeriveDataTypeable #-}
-- | This module provides an interface to the IDE backend.  It centres around
-- the idea of a single threaded IDE session, and operations for updating the
-- session or running queries given the current state of the session.
--
-- /Interaction with the compiler/
--
-- Ironically for a pure functional language, the interface to the compiler is
-- rather stateful and sequential. In part this is because it's dealing with
-- the state of files in the file system which are of course mutable variables.
--
-- So the general pattern of interaction is sequential and single-threaded.
-- The state transitions are fairly simple:
--
-- * update phase: we have a batch of updates, e.g. changes in module contents.
--   This part is declarative, we just describe what changes we want to make.
--
-- * compile phase: we apply the updates and invoke the compiler, which
--   incrementally recompiles some modules. This may be a relatively long
--   running operation and we may want progress info.
--
-- * query phase: after compiling we can collect information like source
--   errors, the list of successfully loaded modules or symbol maps.
--
-- * run phase: regardless of compilation results, we may want to run some
--   code from a module (compiled recently or compiled many updates ago),
--   interact with the running code's input and output, interrupt its
--   execution.
--
-- Then the whole process can repeat.
--
-- To clarify these different phases we use different types:
--
-- * 'IdeSession' for the query mode. This is in a sense also the default
--   mode.
--
-- * 'IdeSessionUpdate' for accumulating updates.
--
-- * 'Progress' for the progress information in the compile mode.
--
-- * 'RunActions' for handles on the running code, through which
--   one can interact with the code.
--
-- /Additional notes/
--
-- * Responsibility for managing and mutating files in the sources dir.
--
-- In general, updating and changing source files in the sources dir has to be
-- coordinated with the IdeSession, since we're in a concurrent mutable
-- setting.
--
-- The model here is that the IdeSession alone manages the files in the sources
-- directory. All file changes and file reading must be managed via the
-- session, and sequenced relative to other session state changes.
--
-- The session will manage the files carefully, including in the case of
-- exceptions and things going awry. Thus the caller does not need to duplicate
-- the file state: it can rely on putting files in, applying updates to the
-- files via the session, and extracting the files again at any time (before
-- the session is closed).
--
-- * Morally pure queries
--
-- Morally, a compiler is a pure function from the current value of the various
-- source files (and other bits of the environment) to object code and\/or
-- other information about the modules (errors, types etc).
--
-- The intention is to reflect this purity property in this interface. The
-- value of an 'IdeSession' represents the state of the files\/modules and
-- contains the other parameters supplied by the user (compiler options,
-- environment variables). It also contains or represents the result of the
-- pure compilation function. It should always be the case that we can throw
-- away all the compilation results and recover them just from the file state
-- and user parameters.
--
-- One example where this notion makes a difference is with warnings.
-- Traditionally, compilers just return the warnings for the modules they
-- compiled, skipping warnings for the modules they didn't need to recompile.
-- But this doesn't match the pure function idea, because the compilation
-- result now depends on which steps we took to get there, rather than just on
-- the current value of the files. So one of the things this wrapper can do is
-- to restore the purity in these corner cases (which otherwise the client of
-- this API would probably have to do).
--
-- * Persistent and transitory state
--
-- The persistent state is obviously the files: source files and data files, as
-- well as user-supplied parameters of the compilation.  Internally there is a
-- great deal of transitory and cached state, either in memory or on disk (such
-- as .hi files on disk or the equivalent in memory). Note that none of the
-- state persists in case of a fatal internal error (the files are wiped out
-- before shutdown) and only the files persist in case of a power failure (but
-- have to be recovered manually).
--
-- It should be possible to drop all the transitory state and recover, just at
-- the cost of some extra work, as long as the original @Session@ value is
-- available. The 'restartSession' function does almost exactly that.
--
-- This property is a useful correctness property for internal testing: the
-- results of all the queries should be the same before and after blowing away
-- all the transitory state and recovering.
module IdeSession (
    -- * Configuration
    SessionConfig(..)
  , defaultSessionConfig
  , InProcess
    -- * Updating the session
    -- ** Starting and stopping
  , IdeSession -- Abstract
  , initSession
  , SessionInitParams(..)
  , defaultSessionInitParams
  , shutdownSession
  , forceShutdownSession
  , restartSession
    -- ** Session updates
  , IdeSessionUpdate -- Abstract
  , updateSession
  , updateSourceFile
  , updateSourceFileFromFile
  , updateSourceFileDelete
  , updateGhcOpts
  , updateRtsOpts
  , updateRelativeIncludes
  , updateCodeGeneration
  , updateDataFile
  , updateDataFileFromFile
  , updateDataFileDelete
  , updateDeleteManagedFiles
  , updateEnv
  , updateArgs
  , updateStdoutBufferMode
  , updateStderrBufferMode
  , updateTargets
  , buildExe
  , buildDoc
  , buildLicenses
    -- ** Progress
  , Progress(..)
    -- ** Running code
  , RunActions(..)
  , RunResult(..)
  , RunBufferMode(..)
  , BreakInfo(..)
  , runStmt
  , runExe
  , resume
  , runWaitAll
  , setBreakpoint
  , printVar
    -- * Queries
    -- ** Types
  , Query
  , ManagedFiles(..)
  , Targets(..)
  , GhcVersion(..)
    -- ** Queries that rely on the static part of the state only
  , getSessionConfig
  , getSourcesDir
  , getDataDir
  , getDistDir
  , getSourceModule
  , getDataFile
  , getAllDataFiles
  , getCabalMacros
    -- ** Queries that do not rely on computed state
  , getCodeGeneration
  , getEnv
  , getGhcServer
  , getGhcVersion
  , getManagedFiles
  , getBreakInfo
    -- ** Queries that rely on computed state
  , getSourceErrors
  , getLoadedModules
  , getFileMap
  , getBuildExeStatus
  , getBuildDocStatus
  , getBuildLicensesStatus
  , getSpanInfo
  , getExpTypes
  , getUseSites
  , getDotCabal
  , getImports
  , getAutocompletion
  , getPkgDeps
    -- * Types for identifier info, errors, etc.
    -- ** Types
  , IdNameSpace(..)
  , Type
  , IdInfo(..)
  , IdProp(..)
  , IdScope(..)
  , SourceSpan(..)
  , EitherSpan(..)
  , SourceError(..)
  , SourceErrorKind(..)
  , ModuleName
  , ModuleId(..)
  , PackageId(..)
--  , IdMap(..)
--  , LoadedModules
  , ImportEntities(..)
  , Import(..)
  , SpanInfo(..)
    -- ** Util
  , idInfoQN
--, idInfoAtLocation
  , haddockLink
  -- * Exception types
  , ExternalException(..)
  , InvalidSessionStateQueries(..)
  -- * Re-exports from Cabal
  , PackageDBStack
  , PackageDB(..)
  -- * For internal/debugging use only
  , getGhcExitCode
  , dumpIdInfo
  , dumpAutocompletion
  , dumpFileMap
  , crashGhcServer
  , sourceExtensions
  , ideBackendApiVersion
  , buildLicsFromPkgs
  , LicenseArgs(..)
) where

import Distribution.Simple (PackageDBStack, PackageDB(..))

import IdeSession.Config
import IdeSession.GHC.API
import IdeSession.GHC.Client
import IdeSession.Query
import IdeSession.RPC.Client (ExternalException (..))
import IdeSession.State (IdeSession)
import IdeSession.Types.Progress
import IdeSession.Types.Public
import IdeSession.Update