{-# 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