packages feed

ghc-mod 5.4.0.0 → 5.5.0.0

raw patch · 62 files changed

+2452/−1525 lines, 62 filesdep +binarydep +optparse-applicativedep +safedep −asyncdep −cerealdep ~cabal-helperdep ~doctestdep ~hspecsetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: binary, optparse-applicative, safe

Dependencies removed: async, cereal

Dependency ranges changed: cabal-helper, doctest, hspec

API changes (from Hackage documentation)

- Language.Haskell.GhcMod: GMEWrongWorkingDirectory :: FilePath -> FilePath -> GhcModError
- Language.Haskell.GhcMod: [optDetailed] :: Options -> Bool
- Language.Haskell.GhcMod: [optHlintOpts] :: Options -> [String]
- Language.Haskell.GhcMod: [optOperators] :: Options -> Bool
- Language.Haskell.GhcMod: [optQualified] :: Options -> Bool
- Language.Haskell.GhcMod.Caching.Types: [tcCacheFile] :: TimedCacheFiles -> Maybe TimedFile
- Language.Haskell.GhcMod.Caching.Types: instance GHC.Show.Show Language.Haskell.GhcMod.Caching.Types.TimedCacheFiles
- Language.Haskell.GhcMod.DynFlags: setModeIntelligent :: DynFlags -> DynFlags
- Language.Haskell.GhcMod.DynFlags: setModeSimple :: DynFlags -> DynFlags
- Language.Haskell.GhcMod.Error: GMEWrongWorkingDirectory :: FilePath -> FilePath -> GhcModError
- Language.Haskell.GhcMod.Find: instance GHC.Show.Show Language.Haskell.GhcMod.Find.SymbolDb
- Language.Haskell.GhcMod.Internal: Intelligent :: CompilerMode
- Language.Haskell.GhcMod.Internal: Simple :: CompilerMode
- Language.Haskell.GhcMod.Internal: data CompilerMode
- Language.Haskell.GhcMod.Internal: getCompilerMode :: GmState m => m CompilerMode
- Language.Haskell.GhcMod.Internal: setCompilerMode :: GmState m => CompilerMode -> m ()
- Language.Haskell.GhcMod.Internal: type Package = (PackageBaseName, PackageVersion, PackageId)
- Language.Haskell.GhcMod.Internal: type PackageBaseName = String
- Language.Haskell.GhcMod.Internal: type PackageId = String
- Language.Haskell.GhcMod.Internal: type PackageVersion = String
- Language.Haskell.GhcMod.Logging: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Types.GmLog (Language.Haskell.GhcMod.Logging.LogDiscardT m)
- Language.Haskell.GhcMod.Monad.Types: GMEWrongWorkingDirectory :: FilePath -> FilePath -> GhcModError
- Language.Haskell.GhcMod.Monad.Types: Intelligent :: CompilerMode
- Language.Haskell.GhcMod.Monad.Types: Simple :: CompilerMode
- Language.Haskell.GhcMod.Monad.Types: [gmCompilerMode] :: GhcModState -> !CompilerMode
- Language.Haskell.GhcMod.Monad.Types: [gmComponents] :: GhcModState -> !(Map ChComponentName (GmComponent GMCResolved (Set ModulePath)))
- Language.Haskell.GhcMod.Monad.Types: data CompilerMode
- Language.Haskell.GhcMod.Monad.Types: getCompilerMode :: GmState m => m CompilerMode
- Language.Haskell.GhcMod.Monad.Types: instance (Control.Monad.Trans.Error.Error e, Language.Haskell.GhcMod.Types.MonadIO m) => Language.Haskell.GhcMod.Types.MonadIO (Control.Monad.Trans.Error.ErrorT e m)
- Language.Haskell.GhcMod.Monad.Types: instance (GHC.Base.Monad m, Language.Haskell.GhcMod.Monad.Types.GmLog m) => Language.Haskell.GhcMod.Monad.Types.GmLog (Control.Monad.Trans.Reader.ReaderT r m)
- Language.Haskell.GhcMod.Monad.Types: instance (GHC.Base.Monad m, Language.Haskell.GhcMod.Monad.Types.GmLog m) => Language.Haskell.GhcMod.Monad.Types.GmLog (Control.Monad.Trans.State.Strict.StateT s m)
- Language.Haskell.GhcMod.Monad.Types: instance (GHC.Base.Monoid w, Control.Monad.Writer.Class.MonadWriter w m) => Control.Monad.Writer.Class.MonadWriter w (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance (Language.Haskell.GhcMod.Types.MonadIO m, Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m) => DynFlags.HasDynFlags (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance (Language.Haskell.GhcMod.Types.MonadIO m, Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m) => Exception.ExceptionMonad (Language.Haskell.GhcMod.Monad.Types.GmOutT m)
- Language.Haskell.GhcMod.Monad.Types: instance (Language.Haskell.GhcMod.Types.MonadIO m, Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m) => Exception.ExceptionMonad (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance (Language.Haskell.GhcMod.Types.MonadIO m, Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m) => Exception.ExceptionMonad (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance (Language.Haskell.GhcMod.Types.MonadIO m, Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m) => GhcMonad.GhcMonad (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.IO.Class.MonadIO Language.Haskell.GhcMod.Monad.Types.LightGhc
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Language.Haskell.GhcMod.Monad.Types.GmOutT m)
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.Trans.Class.MonadTrans Language.Haskell.GhcMod.Monad.Types.GmOutT
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.Trans.Class.MonadTrans Language.Haskell.GhcMod.Monad.Types.GmT
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.Trans.Class.MonadTrans Language.Haskell.GhcMod.Monad.Types.GmlT
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Base.MonadBase GHC.Types.IO (Language.Haskell.GhcMod.Monad.Types.GmOutT m)
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Base.MonadBase GHC.Types.IO (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Base.MonadBase GHC.Types.IO (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO (Language.Haskell.GhcMod.Monad.Types.GmOutT m)
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.Trans.Control.MonadTransControl Language.Haskell.GhcMod.Monad.Types.GmOutT
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.Trans.Control.MonadTransControl Language.Haskell.GhcMod.Monad.Types.GmT
- Language.Haskell.GhcMod.Monad.Types: instance Control.Monad.Trans.Control.MonadTransControl Language.Haskell.GhcMod.Monad.Types.GmlT
- Language.Haskell.GhcMod.Monad.Types: instance DynFlags.HasDynFlags Language.Haskell.GhcMod.Monad.Types.LightGhc
- Language.Haskell.GhcMod.Monad.Types: instance Exception.ExceptionMonad Language.Haskell.GhcMod.Monad.Types.LightGhc
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Alternative m => GHC.Base.Alternative (Language.Haskell.GhcMod.Monad.Types.GmOutT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Applicative Language.Haskell.GhcMod.Monad.Types.LightGhc
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Applicative m => GHC.Base.Applicative (Language.Haskell.GhcMod.Monad.Types.GmOutT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Functor Language.Haskell.GhcMod.Monad.Types.LightGhc
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Functor m => GHC.Base.Functor (Language.Haskell.GhcMod.Monad.Types.GmOutT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Functor m => GHC.Base.Functor (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Functor m => GHC.Base.Functor (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad Language.Haskell.GhcMod.Monad.Types.LightGhc
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => Control.Monad.Error.Class.MonadError Language.Haskell.GhcMod.Types.GhcModError (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => Control.Monad.Error.Class.MonadError Language.Haskell.GhcMod.Types.GhcModError (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => Control.Monad.Journal.Class.MonadJournal Language.Haskell.GhcMod.Types.GhcModLog (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => GHC.Base.Alternative (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => GHC.Base.Alternative (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => GHC.Base.Applicative (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => GHC.Base.Applicative (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => GHC.Base.Monad (Language.Haskell.GhcMod.Monad.Types.GmOutT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => GHC.Base.Monad (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => GHC.Base.Monad (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => GHC.Base.MonadPlus (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => GHC.Base.MonadPlus (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Types.GmEnv (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Types.GmEnv (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Types.GmLog (Control.Monad.Trans.Journal.JournalT Language.Haskell.GhcMod.Types.GhcModLog m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Types.GmLog (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Types.GmLog (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Types.GmOut (Language.Haskell.GhcMod.Monad.Types.GmOutT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Types.GmOut (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Types.GmState (Control.Monad.Trans.State.Strict.StateT Language.Haskell.GhcMod.Types.GhcModState m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Types.GmState (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Types.GmState (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Language.Haskell.GhcMod.Monad.Types.GmOutT m)
- Language.Haskell.GhcMod.Monad.Types: instance GhcMonad.GhcMonad Language.Haskell.GhcMod.Monad.Types.LightGhc
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Monad.Types.GmEnv m => Language.Haskell.GhcMod.Monad.Types.GmEnv (Control.Monad.Trans.Error.ErrorT Language.Haskell.GhcMod.Types.GhcModError m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Monad.Types.GmEnv m => Language.Haskell.GhcMod.Monad.Types.GmEnv (Control.Monad.Trans.Journal.JournalT Language.Haskell.GhcMod.Types.GhcModLog m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Monad.Types.GmEnv m => Language.Haskell.GhcMod.Monad.Types.GmEnv (Control.Monad.Trans.State.Strict.StateT s m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Monad.Types.GmEnv m => Language.Haskell.GhcMod.Monad.Types.GmEnv (Language.Haskell.GhcMod.Monad.Types.GmOutT m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Monad.Types.GmLog m => Language.Haskell.GhcMod.Monad.Types.GmLog (Language.Haskell.GhcMod.Monad.Types.GmOutT m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Monad.Types.GmOut m => Language.Haskell.GhcMod.Monad.Types.GmOut (Control.Monad.Trans.State.Strict.StateT s m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Monad.Types.GmOut m => Language.Haskell.GhcMod.Monad.Types.GmOut (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Monad.Types.GmState m => Language.Haskell.GhcMod.Monad.Types.GmState (Control.Monad.Trans.Maybe.MaybeT m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Monad.Types.GmState m => Language.Haskell.GhcMod.Monad.Types.GmState (Control.Monad.Trans.State.Strict.StateT s m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Types.MonadIO GHC.Types.IO
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Types.MonadIO Language.Haskell.GhcMod.Monad.Types.LightGhc
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Types.MonadIO m => Language.Haskell.GhcMod.Types.MonadIO (Control.Monad.Trans.Journal.JournalT x m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Types.MonadIO m => Language.Haskell.GhcMod.Types.MonadIO (Control.Monad.Trans.Maybe.MaybeT m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Types.MonadIO m => Language.Haskell.GhcMod.Types.MonadIO (Control.Monad.Trans.Reader.ReaderT x m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Types.MonadIO m => Language.Haskell.GhcMod.Types.MonadIO (Control.Monad.Trans.State.Strict.StateT x m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Types.MonadIOC m => Language.Haskell.GhcMod.Types.MonadIO (Language.Haskell.GhcMod.Monad.Types.GmOutT m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Types.MonadIOC m => Language.Haskell.GhcMod.Types.MonadIO (Language.Haskell.GhcMod.Monad.Types.GmT m)
- Language.Haskell.GhcMod.Monad.Types: instance Language.Haskell.GhcMod.Types.MonadIOC m => Language.Haskell.GhcMod.Types.MonadIO (Language.Haskell.GhcMod.Monad.Types.GmlT m)
- Language.Haskell.GhcMod.Monad.Types: setCompilerMode :: GmState m => CompilerMode -> m ()
- Language.Haskell.GhcMod.Target: needsFallback :: ModuleGraph -> Bool
- Language.Haskell.GhcMod.Types: GMEWrongWorkingDirectory :: FilePath -> FilePath -> GhcModError
- Language.Haskell.GhcMod.Types: Intelligent :: CompilerMode
- Language.Haskell.GhcMod.Types: Simple :: CompilerMode
- Language.Haskell.GhcMod.Types: [gmCompilerMode] :: GhcModState -> !CompilerMode
- Language.Haskell.GhcMod.Types: [gmComponents] :: GhcModState -> !(Map ChComponentName (GmComponent GMCResolved (Set ModulePath)))
- Language.Haskell.GhcMod.Types: [optDetailed] :: Options -> Bool
- Language.Haskell.GhcMod.Types: [optHlintOpts] :: Options -> [String]
- Language.Haskell.GhcMod.Types: [optOperators] :: Options -> Bool
- Language.Haskell.GhcMod.Types: [optQualified] :: Options -> Bool
- Language.Haskell.GhcMod.Types: data CompilerMode
- Language.Haskell.GhcMod.Types: instance Data.Serialize.Serialize CabalHelper.Types.ChComponentName
- Language.Haskell.GhcMod.Types: instance Data.Serialize.Serialize CabalHelper.Types.ChEntrypoint
- Language.Haskell.GhcMod.Types: instance Data.Serialize.Serialize CabalHelper.Types.ChModuleName
- Language.Haskell.GhcMod.Types: instance Data.Serialize.Serialize Data.Version.Version
- Language.Haskell.GhcMod.Types: instance Data.Serialize.Serialize Distribution.Helper.Programs
- Language.Haskell.GhcMod.Types: instance Data.Serialize.Serialize Language.Haskell.GhcMod.Types.GhcPkgDb
- Language.Haskell.GhcMod.Types: instance Data.Serialize.Serialize Language.Haskell.GhcMod.Types.GmModuleGraph
- Language.Haskell.GhcMod.Types: instance Data.Serialize.Serialize Language.Haskell.GhcMod.Types.ModulePath
- Language.Haskell.GhcMod.Types: instance Data.Serialize.Serialize Module.ModuleName
- Language.Haskell.GhcMod.Types: instance Data.Serialize.Serialize eps => Data.Serialize.Serialize (Language.Haskell.GhcMod.Types.GmComponent t eps)
- Language.Haskell.GhcMod.Types: instance GHC.Classes.Eq Language.Haskell.GhcMod.Types.CompilerMode
- Language.Haskell.GhcMod.Types: instance GHC.Generics.Constructor Language.Haskell.GhcMod.Types.C1_0Version
- Language.Haskell.GhcMod.Types: instance GHC.Generics.Datatype Language.Haskell.GhcMod.Types.D1Version
- Language.Haskell.GhcMod.Types: instance GHC.Generics.Generic Data.Version.Version
- Language.Haskell.GhcMod.Types: instance GHC.Generics.Selector Language.Haskell.GhcMod.Types.S1_0_0Version
- Language.Haskell.GhcMod.Types: instance GHC.Generics.Selector Language.Haskell.GhcMod.Types.S1_0_1Version
- Language.Haskell.GhcMod.Types: instance GHC.Read.Read Language.Haskell.GhcMod.Types.CompilerMode
- Language.Haskell.GhcMod.Types: instance GHC.Read.Read Language.Haskell.GhcMod.Types.ModuleString
- Language.Haskell.GhcMod.Types: instance GHC.Show.Show Language.Haskell.GhcMod.Types.CompilerMode
- Language.Haskell.GhcMod.Types: lGmCompilerMode :: ArrowApply cat => Lens cat GhcModState CompilerMode
- Language.Haskell.GhcMod.Types: lGmComponents :: ArrowApply cat => Lens cat GhcModState (Map ChComponentName (GmComponent GMCResolved (Set ModulePath)))
- Language.Haskell.GhcMod.Types: lOptDetailed :: ArrowApply cat => Lens cat Options Bool
- Language.Haskell.GhcMod.Types: lOptHlintOpts :: ArrowApply cat => Lens cat Options [String]
- Language.Haskell.GhcMod.Types: lOptOperators :: ArrowApply cat => Lens cat Options Bool
- Language.Haskell.GhcMod.Types: lOptQualified :: ArrowApply cat => Lens cat Options Bool
- Language.Haskell.GhcMod.Types: pkgId :: Package -> PackageId
- Language.Haskell.GhcMod.Types: pkgName :: Package -> PackageBaseName
- Language.Haskell.GhcMod.Types: pkgVer :: Package -> PackageVersion
- Language.Haskell.GhcMod.Types: showPkg :: Package -> String
- Language.Haskell.GhcMod.Types: showPkgId :: Package -> String
- Language.Haskell.GhcMod.Types: type Package = (PackageBaseName, PackageVersion, PackageId)
- Language.Haskell.GhcMod.Types: type PackageBaseName = String
- Language.Haskell.GhcMod.Types: type PackageId = String
- Language.Haskell.GhcMod.Types: type PackageVersion = String
- Language.Haskell.GhcMod.Types: type PkgDb = Map Package PackageConfig
- Language.Haskell.GhcMod.Utils: type ModTime = UTCTime
- Language.Haskell.GhcMod.World: instance GHC.Show.Show Language.Haskell.GhcMod.World.World
+ Language.Haskell.GhcMod: test :: IOish m => FilePath -> GhcModT m String
+ Language.Haskell.GhcMod.Browse: BrowseOpts :: Bool -> Bool -> Bool -> BrowseOpts
+ Language.Haskell.GhcMod.Browse: [optBrowseDetailed] :: BrowseOpts -> Bool
+ Language.Haskell.GhcMod.Browse: [optBrowseOperators] :: BrowseOpts -> Bool
+ Language.Haskell.GhcMod.Browse: [optBrowseQualified] :: BrowseOpts -> Bool
+ Language.Haskell.GhcMod.Browse: data BrowseOpts
+ Language.Haskell.GhcMod.CabalHelper: withAutogen :: (IOish m, GmEnv m, GmOut m, GmLog m) => m a -> m a
+ Language.Haskell.GhcMod.Caching.Types: [tcCreated] :: TimedCacheFiles -> ModTime
+ Language.Haskell.GhcMod.Cradle: findCradleNoLog :: (IOish m, GmOut m) => m Cradle
+ Language.Haskell.GhcMod.DynFlags: setHscInterpreted :: DynFlags -> DynFlags
+ Language.Haskell.GhcMod.DynFlags: setHscNothing :: DynFlags -> DynFlags
+ Language.Haskell.GhcMod.Find: data AsyncSymbolDb
+ Language.Haskell.GhcMod.Find: getAsyncSymbolDb :: IOish m => AsyncSymbolDb -> GhcModT m SymbolDb
+ Language.Haskell.GhcMod.Find: instance Control.DeepSeq.NFData Language.Haskell.GhcMod.Find.SymbolDb
+ Language.Haskell.GhcMod.Find: instance Data.Binary.Class.Binary Language.Haskell.GhcMod.Find.SymbolDb
+ Language.Haskell.GhcMod.Find: instance GHC.Generics.Constructor Language.Haskell.GhcMod.Find.C1_0SymbolDb
+ Language.Haskell.GhcMod.Find: instance GHC.Generics.Datatype Language.Haskell.GhcMod.Find.D1SymbolDb
+ Language.Haskell.GhcMod.Find: instance GHC.Generics.Generic Language.Haskell.GhcMod.Find.SymbolDb
+ Language.Haskell.GhcMod.Find: instance GHC.Generics.Selector Language.Haskell.GhcMod.Find.S1_0_0SymbolDb
+ Language.Haskell.GhcMod.Find: instance GHC.Generics.Selector Language.Haskell.GhcMod.Find.S1_0_1SymbolDb
+ Language.Haskell.GhcMod.Find: newAsyncSymbolDb :: IOish m => GhcModT m AsyncSymbolDb
+ Language.Haskell.GhcMod.Logging: gmAppendLogQuiet :: GmLog m => GhcModLog -> m ()
+ Language.Haskell.GhcMod.Logging: gmGetLogLevel :: GmLog m => m GmLogLevel
+ Language.Haskell.GhcMod.Logging: gmLogQuiet :: GmLog m => GmLogLevel -> String -> Doc -> m ()
+ Language.Haskell.GhcMod.Logging: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Log.GmLog (Language.Haskell.GhcMod.Logging.LogDiscardT m)
+ Language.Haskell.GhcMod.Monad.Env: class Monad m => GmEnv m where gmeAsk = gmeReader id gmeReader f = f `liftM` gmeAsk
+ Language.Haskell.GhcMod.Monad.Env: gmeAsk :: GmEnv m => m GhcModEnv
+ Language.Haskell.GhcMod.Monad.Env: gmeLocal :: GmEnv m => (GhcModEnv -> GhcModEnv) -> m a -> m a
+ Language.Haskell.GhcMod.Monad.Env: gmeReader :: GmEnv m => (GhcModEnv -> a) -> m a
+ Language.Haskell.GhcMod.Monad.Env: instance (GHC.Base.Monad m, Language.Haskell.GhcMod.Monad.Env.GmEnv (Language.Haskell.GhcMod.Monad.Newtypes.GhcModT m)) => Language.Haskell.GhcMod.Monad.Env.GmEnv (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Env: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Env.GmEnv (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Env: instance Language.Haskell.GhcMod.Monad.Env.GmEnv m => Language.Haskell.GhcMod.Monad.Env.GmEnv (Control.Monad.Trans.Error.ErrorT Language.Haskell.GhcMod.Types.GhcModError m)
+ Language.Haskell.GhcMod.Monad.Env: instance Language.Haskell.GhcMod.Monad.Env.GmEnv m => Language.Haskell.GhcMod.Monad.Env.GmEnv (Control.Monad.Trans.Journal.JournalT Language.Haskell.GhcMod.Types.GhcModLog m)
+ Language.Haskell.GhcMod.Monad.Env: instance Language.Haskell.GhcMod.Monad.Env.GmEnv m => Language.Haskell.GhcMod.Monad.Env.GmEnv (Control.Monad.Trans.State.Strict.StateT s m)
+ Language.Haskell.GhcMod.Monad.Env: instance Language.Haskell.GhcMod.Monad.Env.GmEnv m => Language.Haskell.GhcMod.Monad.Env.GmEnv (Language.Haskell.GhcMod.Monad.Newtypes.GmOutT m)
+ Language.Haskell.GhcMod.Monad.Log: class Monad m => GmLog m
+ Language.Haskell.GhcMod.Monad.Log: gmlClear :: GmLog m => m ()
+ Language.Haskell.GhcMod.Monad.Log: gmlHistory :: GmLog m => m GhcModLog
+ Language.Haskell.GhcMod.Monad.Log: gmlJournal :: GmLog m => GhcModLog -> m ()
+ Language.Haskell.GhcMod.Monad.Log: instance (GHC.Base.Monad m, Language.Haskell.GhcMod.Monad.Log.GmLog (Language.Haskell.GhcMod.Monad.Newtypes.GhcModT m)) => Language.Haskell.GhcMod.Monad.Log.GmLog (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Log: instance (GHC.Base.Monad m, Language.Haskell.GhcMod.Monad.Log.GmLog m) => Language.Haskell.GhcMod.Monad.Log.GmLog (Control.Monad.Trans.Maybe.MaybeT m)
+ Language.Haskell.GhcMod.Monad.Log: instance (GHC.Base.Monad m, Language.Haskell.GhcMod.Monad.Log.GmLog m) => Language.Haskell.GhcMod.Monad.Log.GmLog (Control.Monad.Trans.Reader.ReaderT r m)
+ Language.Haskell.GhcMod.Monad.Log: instance (GHC.Base.Monad m, Language.Haskell.GhcMod.Monad.Log.GmLog m) => Language.Haskell.GhcMod.Monad.Log.GmLog (Control.Monad.Trans.State.Strict.StateT s m)
+ Language.Haskell.GhcMod.Monad.Log: instance (GHC.Base.Monad m, Language.Haskell.GhcMod.Monad.Log.GmLog m, Control.Monad.Trans.Error.Error e) => Language.Haskell.GhcMod.Monad.Log.GmLog (Control.Monad.Trans.Error.ErrorT e m)
+ Language.Haskell.GhcMod.Monad.Log: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Log.GmLog (Control.Monad.Trans.Journal.JournalT Language.Haskell.GhcMod.Types.GhcModLog m)
+ Language.Haskell.GhcMod.Monad.Log: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Log.GmLog (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Log: instance Language.Haskell.GhcMod.Monad.Log.GmLog m => Language.Haskell.GhcMod.Monad.Log.GmLog (Language.Haskell.GhcMod.Monad.Newtypes.GmOutT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: GmOutT :: ReaderT GhcModOut m a -> GmOutT m a
+ Language.Haskell.GhcMod.Monad.Newtypes: GmT :: StateT GhcModState (ErrorT GhcModError (JournalT GhcModLog (ReaderT GhcModEnv m))) a -> GmT m a
+ Language.Haskell.GhcMod.Monad.Newtypes: GmlT :: GhcModT m a -> GmlT m a
+ Language.Haskell.GhcMod.Monad.Newtypes: LightGhc :: ReaderT (IORef HscEnv) IO a -> LightGhc a
+ Language.Haskell.GhcMod.Monad.Newtypes: [unGmOutT] :: GmOutT m a -> ReaderT GhcModOut m a
+ Language.Haskell.GhcMod.Monad.Newtypes: [unGmT] :: GmT m a -> StateT GhcModState (ErrorT GhcModError (JournalT GhcModLog (ReaderT GhcModEnv m))) a
+ Language.Haskell.GhcMod.Monad.Newtypes: [unGmlT] :: GmlT m a -> GhcModT m a
+ Language.Haskell.GhcMod.Monad.Newtypes: [unLightGhc] :: LightGhc a -> ReaderT (IORef HscEnv) IO a
+ Language.Haskell.GhcMod.Monad.Newtypes: gmLiftInner :: Monad m => m a -> GmT m a
+ Language.Haskell.GhcMod.Monad.Newtypes: gmLiftWithInner :: (MonadTransControl t, Monad m, Monad (t m)) => (Run t -> m (StT t a)) -> t m a
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.Trans.Class.MonadTrans Language.Haskell.GhcMod.Monad.Newtypes.GmOutT
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.Trans.Class.MonadTrans Language.Haskell.GhcMod.Monad.Newtypes.GmT
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.Trans.Class.MonadTrans Language.Haskell.GhcMod.Monad.Newtypes.GmlT
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Base.MonadBase GHC.Types.IO (Language.Haskell.GhcMod.Monad.Newtypes.GmOutT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Base.MonadBase GHC.Types.IO (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Base.MonadBase GHC.Types.IO (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO (Language.Haskell.GhcMod.Monad.Newtypes.GmOutT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.Trans.Control.MonadTransControl Language.Haskell.GhcMod.Monad.Newtypes.GmOutT
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.Trans.Control.MonadTransControl Language.Haskell.GhcMod.Monad.Newtypes.GmT
+ Language.Haskell.GhcMod.Monad.Newtypes: instance Control.Monad.Trans.Control.MonadTransControl Language.Haskell.GhcMod.Monad.Newtypes.GmlT
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Alternative m => GHC.Base.Alternative (Language.Haskell.GhcMod.Monad.Newtypes.GmOutT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Applicative Language.Haskell.GhcMod.Monad.Newtypes.LightGhc
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Applicative m => GHC.Base.Applicative (Language.Haskell.GhcMod.Monad.Newtypes.GmOutT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Functor Language.Haskell.GhcMod.Monad.Newtypes.LightGhc
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Functor m => GHC.Base.Functor (Language.Haskell.GhcMod.Monad.Newtypes.GmOutT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Functor m => GHC.Base.Functor (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Functor m => GHC.Base.Functor (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Monad Language.Haskell.GhcMod.Monad.Newtypes.LightGhc
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Monad m => Control.Monad.Error.Class.MonadError Language.Haskell.GhcMod.Types.GhcModError (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Monad m => Control.Monad.Error.Class.MonadError Language.Haskell.GhcMod.Types.GhcModError (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Monad m => Control.Monad.Journal.Class.MonadJournal Language.Haskell.GhcMod.Types.GhcModLog (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Monad m => GHC.Base.Alternative (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Monad m => GHC.Base.Alternative (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Monad m => GHC.Base.Applicative (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Monad m => GHC.Base.Applicative (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Monad m => GHC.Base.Monad (Language.Haskell.GhcMod.Monad.Newtypes.GmOutT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Monad m => GHC.Base.Monad (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Monad m => GHC.Base.Monad (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Monad m => GHC.Base.MonadPlus (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.Monad m => GHC.Base.MonadPlus (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Language.Haskell.GhcMod.Monad.Newtypes.GmOutT m)
+ Language.Haskell.GhcMod.Monad.Newtypes: newtype GmOutT m a
+ Language.Haskell.GhcMod.Monad.Newtypes: newtype GmT m a
+ Language.Haskell.GhcMod.Monad.Newtypes: newtype GmlT m a
+ Language.Haskell.GhcMod.Monad.Newtypes: newtype LightGhc a
+ Language.Haskell.GhcMod.Monad.Newtypes: type GhcModT m = GmT (GmOutT m)
+ Language.Haskell.GhcMod.Monad.Orphans: instance (Control.Monad.Trans.Error.Error e, Language.Haskell.GhcMod.Types.MonadIO m) => Language.Haskell.GhcMod.Types.MonadIO (Control.Monad.Trans.Error.ErrorT e m)
+ Language.Haskell.GhcMod.Monad.Orphans: instance Control.Monad.IO.Class.MonadIO Language.Haskell.GhcMod.Monad.Newtypes.LightGhc
+ Language.Haskell.GhcMod.Monad.Orphans: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Language.Haskell.GhcMod.Monad.Newtypes.GmOutT m)
+ Language.Haskell.GhcMod.Monad.Orphans: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Orphans: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Orphans: instance Language.Haskell.GhcMod.Types.MonadIO GHC.Types.IO
+ Language.Haskell.GhcMod.Monad.Orphans: instance Language.Haskell.GhcMod.Types.MonadIO Language.Haskell.GhcMod.Monad.Newtypes.LightGhc
+ Language.Haskell.GhcMod.Monad.Orphans: instance Language.Haskell.GhcMod.Types.MonadIO m => Language.Haskell.GhcMod.Types.MonadIO (Control.Monad.Trans.Journal.JournalT x m)
+ Language.Haskell.GhcMod.Monad.Orphans: instance Language.Haskell.GhcMod.Types.MonadIO m => Language.Haskell.GhcMod.Types.MonadIO (Control.Monad.Trans.Maybe.MaybeT m)
+ Language.Haskell.GhcMod.Monad.Orphans: instance Language.Haskell.GhcMod.Types.MonadIO m => Language.Haskell.GhcMod.Types.MonadIO (Control.Monad.Trans.Reader.ReaderT x m)
+ Language.Haskell.GhcMod.Monad.Orphans: instance Language.Haskell.GhcMod.Types.MonadIO m => Language.Haskell.GhcMod.Types.MonadIO (Control.Monad.Trans.State.Strict.StateT x m)
+ Language.Haskell.GhcMod.Monad.Orphans: instance Language.Haskell.GhcMod.Types.MonadIOC m => Language.Haskell.GhcMod.Types.MonadIO (Language.Haskell.GhcMod.Monad.Newtypes.GmOutT m)
+ Language.Haskell.GhcMod.Monad.Orphans: instance Language.Haskell.GhcMod.Types.MonadIOC m => Language.Haskell.GhcMod.Types.MonadIO (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Orphans: instance Language.Haskell.GhcMod.Types.MonadIOC m => Language.Haskell.GhcMod.Types.MonadIO (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Out: class Monad m => GmOut m
+ Language.Haskell.GhcMod.Monad.Out: gmoAsk :: GmOut m => m GhcModOut
+ Language.Haskell.GhcMod.Monad.Out: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Out.GmOut (Language.Haskell.GhcMod.Monad.Newtypes.GmOutT m)
+ Language.Haskell.GhcMod.Monad.Out: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.Out.GmOut (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Out: instance Language.Haskell.GhcMod.Monad.Out.GmOut m => Language.Haskell.GhcMod.Monad.Out.GmOut (Control.Monad.Trans.Journal.JournalT w m)
+ Language.Haskell.GhcMod.Monad.Out: instance Language.Haskell.GhcMod.Monad.Out.GmOut m => Language.Haskell.GhcMod.Monad.Out.GmOut (Control.Monad.Trans.Maybe.MaybeT m)
+ Language.Haskell.GhcMod.Monad.Out: instance Language.Haskell.GhcMod.Monad.Out.GmOut m => Language.Haskell.GhcMod.Monad.Out.GmOut (Control.Monad.Trans.State.Strict.StateT s m)
+ Language.Haskell.GhcMod.Monad.Out: instance Language.Haskell.GhcMod.Monad.Out.GmOut m => Language.Haskell.GhcMod.Monad.Out.GmOut (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.State: class Monad m => GmState m where gmsGet = gmsState (\ s -> (s, s)) gmsPut s = gmsState (\ _ -> ((), s)) gmsState f = do { s <- gmsGet; let ~(a, s') = f s; gmsPut s'; return a }
+ Language.Haskell.GhcMod.Monad.State: gmsGet :: GmState m => m GhcModState
+ Language.Haskell.GhcMod.Monad.State: gmsPut :: GmState m => GhcModState -> m ()
+ Language.Haskell.GhcMod.Monad.State: gmsState :: GmState m => (GhcModState -> (a, GhcModState)) -> m a
+ Language.Haskell.GhcMod.Monad.State: instance (GHC.Base.Monad m, Language.Haskell.GhcMod.Monad.State.GmState (Language.Haskell.GhcMod.Monad.Newtypes.GhcModT m)) => Language.Haskell.GhcMod.Monad.State.GmState (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.State: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.State.GmState (Control.Monad.Trans.State.Strict.StateT Language.Haskell.GhcMod.Types.GhcModState m)
+ Language.Haskell.GhcMod.Monad.State: instance GHC.Base.Monad m => Language.Haskell.GhcMod.Monad.State.GmState (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.State: instance Language.Haskell.GhcMod.Monad.State.GmState m => Language.Haskell.GhcMod.Monad.State.GmState (Control.Monad.Trans.Maybe.MaybeT m)
+ Language.Haskell.GhcMod.Monad.State: instance Language.Haskell.GhcMod.Monad.State.GmState m => Language.Haskell.GhcMod.Monad.State.GmState (Control.Monad.Trans.State.Strict.StateT s m)
+ Language.Haskell.GhcMod.Monad.Types: instance (GHC.Base.Monoid w, Language.Haskell.GhcMod.Types.MonadIO m, Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m) => Exception.ExceptionMonad (Control.Monad.Trans.Journal.JournalT w m)
+ Language.Haskell.GhcMod.Monad.Types: instance (Language.Haskell.GhcMod.Types.MonadIO m, Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m) => DynFlags.HasDynFlags (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Types: instance (Language.Haskell.GhcMod.Types.MonadIO m, Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m) => Exception.ExceptionMonad (Control.Monad.Trans.Maybe.MaybeT m)
+ Language.Haskell.GhcMod.Monad.Types: instance (Language.Haskell.GhcMod.Types.MonadIO m, Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m) => Exception.ExceptionMonad (Language.Haskell.GhcMod.Monad.Newtypes.GmOutT m)
+ Language.Haskell.GhcMod.Monad.Types: instance (Language.Haskell.GhcMod.Types.MonadIO m, Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m) => Exception.ExceptionMonad (Language.Haskell.GhcMod.Monad.Newtypes.GmT m)
+ Language.Haskell.GhcMod.Monad.Types: instance (Language.Haskell.GhcMod.Types.MonadIO m, Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m) => Exception.ExceptionMonad (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Types: instance (Language.Haskell.GhcMod.Types.MonadIO m, Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m) => GhcMonad.GhcMonad (Language.Haskell.GhcMod.Monad.Newtypes.GmlT m)
+ Language.Haskell.GhcMod.Monad.Types: instance DynFlags.HasDynFlags Language.Haskell.GhcMod.Monad.Newtypes.LightGhc
+ Language.Haskell.GhcMod.Monad.Types: instance Exception.ExceptionMonad Language.Haskell.GhcMod.Monad.Newtypes.LightGhc
+ Language.Haskell.GhcMod.Monad.Types: instance GhcMonad.GhcMonad Language.Haskell.GhcMod.Monad.Newtypes.LightGhc
+ Language.Haskell.GhcMod.Output: gmReadProcess' :: GmOut m => m (FilePath -> [String] -> String -> IO ByteString)
+ Language.Haskell.GhcMod.Output: instance Language.Haskell.GhcMod.Output.ProcessOutput Data.ByteString.Lazy.Internal.ByteString
+ Language.Haskell.GhcMod.Output: instance Language.Haskell.GhcMod.Output.ProcessOutput GHC.Base.String
+ Language.Haskell.GhcMod.PathsAndFiles: autogenModulePath :: String -> String
+ Language.Haskell.GhcMod.PathsAndFiles: autogenModulesDir :: FilePath
+ Language.Haskell.GhcMod.Target: needsHscInterpreted :: ModuleGraph -> Bool
+ Language.Haskell.GhcMod.Target: type Components = [GmComponent GMCRaw (Set ModulePath)]
+ Language.Haskell.GhcMod.Target: type ResolvedComponentsMap = Map ChComponentName (GmComponent GMCResolved (Set ModulePath))
+ Language.Haskell.GhcMod.Test: runTest :: GhcMonad m => String -> m (Maybe SomeException)
+ Language.Haskell.GhcMod.Test: test :: IOish m => FilePath -> GhcModT m String
+ Language.Haskell.GhcMod.Types: BrowseOpts :: Bool -> Bool -> Bool -> BrowseOpts
+ Language.Haskell.GhcMod.Types: LintOpts :: [String] -> LintOpts
+ Language.Haskell.GhcMod.Types: [optBrowseDetailed] :: BrowseOpts -> Bool
+ Language.Haskell.GhcMod.Types: [optBrowseOperators] :: BrowseOpts -> Bool
+ Language.Haskell.GhcMod.Types: [optBrowseQualified] :: BrowseOpts -> Bool
+ Language.Haskell.GhcMod.Types: [optLintHlintOpts] :: LintOpts -> [String]
+ Language.Haskell.GhcMod.Types: data BrowseOpts
+ Language.Haskell.GhcMod.Types: data LintOpts
+ Language.Haskell.GhcMod.Types: defaultBrowseOpts :: BrowseOpts
+ Language.Haskell.GhcMod.Types: defaultLintOpts :: LintOpts
+ Language.Haskell.GhcMod.Types: instance Control.DeepSeq.NFData Language.Haskell.GhcMod.Types.ModuleString
+ Language.Haskell.GhcMod.Types: instance Data.Binary.Class.Binary CabalHelper.Types.ChComponentName
+ Language.Haskell.GhcMod.Types: instance Data.Binary.Class.Binary CabalHelper.Types.ChEntrypoint
+ Language.Haskell.GhcMod.Types: instance Data.Binary.Class.Binary CabalHelper.Types.ChModuleName
+ Language.Haskell.GhcMod.Types: instance Data.Binary.Class.Binary Distribution.Helper.Programs
+ Language.Haskell.GhcMod.Types: instance Data.Binary.Class.Binary Language.Haskell.GhcMod.Types.GhcPkgDb
+ Language.Haskell.GhcMod.Types: instance Data.Binary.Class.Binary Language.Haskell.GhcMod.Types.GmModuleGraph
+ Language.Haskell.GhcMod.Types: instance Data.Binary.Class.Binary Language.Haskell.GhcMod.Types.ModulePath
+ Language.Haskell.GhcMod.Types: instance Data.Binary.Class.Binary Language.Haskell.GhcMod.Types.ModuleString
+ Language.Haskell.GhcMod.Types: instance Data.Binary.Class.Binary Module.ModuleName
+ Language.Haskell.GhcMod.Types: instance Data.Binary.Class.Binary eps => Data.Binary.Class.Binary (Language.Haskell.GhcMod.Types.GmComponent t eps)
+ Language.Haskell.GhcMod.Types: instance GHC.Show.Show Language.Haskell.GhcMod.Types.BrowseOpts
+ Language.Haskell.GhcMod.Types: instance GHC.Show.Show Language.Haskell.GhcMod.Types.LintOpts
- Language.Haskell.GhcMod: Options :: OutputOpts -> Programs -> [GHCOption] -> Bool -> Bool -> Bool -> [String] -> [(FilePath, Maybe FilePath)] -> Options
+ Language.Haskell.GhcMod: Options :: OutputOpts -> Programs -> [GHCOption] -> [(FilePath, Maybe FilePath)] -> Options
- Language.Haskell.GhcMod: browse :: IOish m => String -> GhcModT m String
+ Language.Haskell.GhcMod: browse :: IOish m => BrowseOpts -> String -> GhcModT m String
- Language.Haskell.GhcMod: dumpSymbol :: IOish m => FilePath -> GhcModT m String
+ Language.Haskell.GhcMod: dumpSymbol :: IOish m => GhcModT m ()
- Language.Haskell.GhcMod: findCradle :: (IOish m, GmOut m) => m Cradle
+ Language.Haskell.GhcMod: findCradle :: (GmLog m, IOish m, GmOut m) => m Cradle
- Language.Haskell.GhcMod: lint :: IOish m => FilePath -> GhcModT m String
+ Language.Haskell.GhcMod: lint :: IOish m => LintOpts -> FilePath -> GhcModT m String
- Language.Haskell.GhcMod: loadSymbolDb :: IOish m => FilePath -> GhcModT m SymbolDb
+ Language.Haskell.GhcMod: loadSymbolDb :: IOish m => GhcModT m SymbolDb
- Language.Haskell.GhcMod: modules :: (IOish m, Gm m) => m String
+ Language.Haskell.GhcMod: modules :: (IOish m, Gm m) => Bool -> m String
- Language.Haskell.GhcMod: runGhcModT :: (IOish m, GmOut m) => Options -> GhcModT m a -> m (Either GhcModError a, GhcModLog)
+ Language.Haskell.GhcMod: runGhcModT :: IOish m => Options -> GhcModT m a -> m (Either GhcModError a, GhcModLog)
- Language.Haskell.GhcMod.Browse: browse :: IOish m => String -> GhcModT m String
+ Language.Haskell.GhcMod.Browse: browse :: IOish m => BrowseOpts -> String -> GhcModT m String
- Language.Haskell.GhcMod.Caching: cached :: (Gm m, MonadIO m, Serialize a, Eq d, Serialize d, Show d) => FilePath -> Cached m GhcModState d a -> d -> m a
+ Language.Haskell.GhcMod.Caching: cached :: (Gm m, MonadIO m, Binary a, Eq d, Binary d, Show d) => FilePath -> Cached m GhcModState d a -> d -> m a
- Language.Haskell.GhcMod.Caching: invalidatingInputFiles :: TimedCacheFiles -> Maybe [FilePath]
+ Language.Haskell.GhcMod.Caching: invalidatingInputFiles :: TimedCacheFiles -> [FilePath]
- Language.Haskell.GhcMod.Caching: timeCacheInput :: MonadIO m => FilePath -> FilePath -> [FilePath] -> m TimedCacheFiles
+ Language.Haskell.GhcMod.Caching: timeCacheInput :: MonadIO m => FilePath -> [FilePath] -> m [TimedFile]
- Language.Haskell.GhcMod.Caching.Types: TimedCacheFiles :: Maybe TimedFile -> [TimedFile] -> TimedCacheFiles
+ Language.Haskell.GhcMod.Caching.Types: TimedCacheFiles :: ModTime -> [TimedFile] -> TimedCacheFiles
- Language.Haskell.GhcMod.Caching.Types: type CacheContents d a = Maybe ([FilePath], d, a)
+ Language.Haskell.GhcMod.Caching.Types: type CacheContents d a = Maybe (ModTime, [FilePath], d, a)
- Language.Haskell.GhcMod.Caching.Types: type ChCacheData = (Programs, FilePath, (Version, [Char]))
+ Language.Haskell.GhcMod.Caching.Types: type ChCacheData = (Programs, FilePath, (String, String))
- Language.Haskell.GhcMod.Cradle: findCradle :: (IOish m, GmOut m) => m Cradle
+ Language.Haskell.GhcMod.Cradle: findCradle :: (GmLog m, IOish m, GmOut m) => m Cradle
- Language.Haskell.GhcMod.Cradle: findCradle' :: (IOish m, GmOut m) => FilePath -> m Cradle
+ Language.Haskell.GhcMod.Cradle: findCradle' :: (GmLog m, IOish m, GmOut m) => FilePath -> m Cradle
- Language.Haskell.GhcMod.Cradle: findSpecCradle :: (IOish m, GmOut m) => FilePath -> m Cradle
+ Language.Haskell.GhcMod.Cradle: findSpecCradle :: (GmLog m, IOish m, GmOut m) => FilePath -> m Cradle
- Language.Haskell.GhcMod.CustomPackageDb: getCustomPkgDbStack :: (IOish m, GmEnv m) => m (Maybe [GhcPkgDb])
+ Language.Haskell.GhcMod.CustomPackageDb: getCustomPkgDbStack :: (MonadIO m, GmEnv m) => m (Maybe [GhcPkgDb])
- Language.Haskell.GhcMod.Find: dumpSymbol :: IOish m => FilePath -> GhcModT m String
+ Language.Haskell.GhcMod.Find: dumpSymbol :: IOish m => GhcModT m ()
- Language.Haskell.GhcMod.Find: loadSymbolDb :: IOish m => FilePath -> GhcModT m SymbolDb
+ Language.Haskell.GhcMod.Find: loadSymbolDb :: IOish m => GhcModT m SymbolDb
- Language.Haskell.GhcMod.Lint: lint :: IOish m => FilePath -> GhcModT m String
+ Language.Haskell.GhcMod.Lint: lint :: IOish m => LintOpts -> FilePath -> GhcModT m String
- Language.Haskell.GhcMod.Modules: modules :: (IOish m, Gm m) => m String
+ Language.Haskell.GhcMod.Modules: modules :: (IOish m, Gm m) => Bool -> m String
- Language.Haskell.GhcMod.Monad: runGhcModT :: (IOish m, GmOut m) => Options -> GhcModT m a -> m (Either GhcModError a, GhcModLog)
+ Language.Haskell.GhcMod.Monad: runGhcModT :: IOish m => Options -> GhcModT m a -> m (Either GhcModError a, GhcModLog)
- Language.Haskell.GhcMod.Monad: withGhcModEnv :: (IOish m, GmOut m) => FilePath -> Options -> (GhcModEnv -> m a) -> m a
+ Language.Haskell.GhcMod.Monad: withGhcModEnv :: (IOish m, GmOut m) => FilePath -> Options -> ((GhcModEnv, GhcModLog) -> m a) -> m a
- Language.Haskell.GhcMod.Monad: withGhcModEnv' :: (IOish m, GmOut m) => (FilePath -> (Cradle -> m a) -> m a) -> FilePath -> Options -> (GhcModEnv -> m a) -> m a
+ Language.Haskell.GhcMod.Monad: withGhcModEnv' :: (IOish m, GmOut m) => (FilePath -> ((Cradle, GhcModLog) -> m a) -> m a) -> FilePath -> Options -> ((GhcModEnv, GhcModLog) -> m a) -> m a
- Language.Haskell.GhcMod.Monad.Types: GhcModState :: !(Maybe GmGhcSession) -> !(Map ChComponentName (GmComponent GMCResolved (Set ModulePath))) -> !CompilerMode -> !GhcModCaches -> !FileMappingMap -> GhcModState
+ Language.Haskell.GhcMod.Monad.Types: GhcModState :: !(Maybe GmGhcSession) -> !GhcModCaches -> !FileMappingMap -> GhcModState
- Language.Haskell.GhcMod.Stack: getStackEnv :: (IOish m, GmOut m) => FilePath -> m (Maybe StackEnv)
+ Language.Haskell.GhcMod.Stack: getStackEnv :: (IOish m, GmOut m, GmLog m) => FilePath -> m (Maybe StackEnv)
- Language.Haskell.GhcMod.Stack: readStack :: (IOish m, GmOut m) => [String] -> MaybeT m String
+ Language.Haskell.GhcMod.Stack: readStack :: (IOish m, GmOut m, GmLog m) => [String] -> MaybeT m String
- Language.Haskell.GhcMod.Target: resolveGmComponents :: (IOish m, Gm m) => Maybe [CompilationUnit] -> [GmComponent GMCRaw (Set ModulePath)] -> m (Map ChComponentName (GmComponent GMCResolved (Set ModulePath)))
+ Language.Haskell.GhcMod.Target: resolveGmComponents :: (IOish m, Gm m) => Maybe ([CompilationUnit], ResolvedComponentsMap) -> Components -> m ResolvedComponentsMap
- Language.Haskell.GhcMod.Types: GhcModState :: !(Maybe GmGhcSession) -> !(Map ChComponentName (GmComponent GMCResolved (Set ModulePath))) -> !CompilerMode -> !GhcModCaches -> !FileMappingMap -> GhcModState
+ Language.Haskell.GhcMod.Types: GhcModState :: !(Maybe GmGhcSession) -> !GhcModCaches -> !FileMappingMap -> GhcModState
- Language.Haskell.GhcMod.Types: Options :: OutputOpts -> Programs -> [GHCOption] -> Bool -> Bool -> Bool -> [String] -> [(FilePath, Maybe FilePath)] -> Options
+ Language.Haskell.GhcMod.Types: Options :: OutputOpts -> Programs -> [GHCOption] -> [(FilePath, Maybe FilePath)] -> Options

Files

ChangeLog view
@@ -1,3 +1,21 @@+2016-01-19 v5.5.0.0+	* Fix #660, cabal-helper errors when no global GHC is installed (Stack)+	* Fix #665, Reinstate internally managed CWD (no more `ghc-mod root`+	  requirement for frontends)+	* Merge #707, Support for spaces in file names when using+	  legacy-interactive+	* Merge #694, #706, #703, Rewrite command line parser using+	  optparse-applicative. Thanks @lierdakil!+	* Merge #693, Fix slowdown and bugs caused by excessive use of+	  `map-file`+	* Fix #678, "No instance nor default method for class operation put"+	* Fix #683, #684, a variety of caching related issues+	* Fix #666, The issue of the beast >:3+	* Merge #649, elisp: Add ghc-report-errors to inhibit *GHC Error*+	  logging+	* Fix #621, Preserve Cabal flag selection across automatic+	  reconfiguration+ 2015-09-16 v5.4.0.0 	* Add support for the Stack build tool 	* Fix #554, `module not interpreted` errors when using the `type`
+ Data/Binary/Generic.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, KindSignatures,+    ScopedTypeVariables, TypeOperators, TypeSynonymInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++-----------------------------------------------------------------------------+-- |+-- Module      : Data.Binary.Generic+-- Copyright   : Bryan O'Sullivan+-- License     : BSD3-style (see LICENSE)+--+-- Maintainer  : Bryan O'Sullivan <bos@serpentine.com>+-- Stability   : unstable+-- Portability : Only works with GHC 7.2 and newer+--+-- Instances for supporting GHC generics.+--+-----------------------------------------------------------------------------+module Data.Binary.Generic where++import Control.Applicative+import Data.Binary+import Data.Bits+import GHC.Generics+import Prelude++class GGBinary f where+    ggput :: f t -> Put+    ggget :: Get (f t)++-- Type without constructors+instance GGBinary V1 where+    ggput _ = return ()+    ggget   = return undefined++-- Constructor without arguments+instance GGBinary U1 where+    ggput U1 = return ()+    ggget    = return U1++-- Product: constructor with parameters+instance (GGBinary a, GGBinary b) => GGBinary (a :*: b) where+    ggput (x :*: y) = ggput x >> ggput y+    ggget = (:*:) <$> ggget <*> ggget++-- Metadata (constructor name, etc)+instance GGBinary a => GGBinary (M1 i c a) where+    ggput = ggput . unM1+    ggget = M1 <$> ggget++-- Constants, additional parameters, and rank-1 recursion+instance Binary a => GGBinary (K1 i a) where+    ggput = put . unK1+    ggget = K1 <$> get++-- Borrowed from the cereal package.++-- The following GGBinary instance for sums has support for serializing+-- types with up to 2^64-1 constructors. It will use the minimal+-- number of bytes needed to encode the constructor. For example when+-- a type has 2^8 constructors or less it will use a single byte to+-- encode the constructor. If it has 2^16 constructors or less it will+-- use two bytes, and so on till 2^64-1.++#define GUARD(WORD) (size - 1) <= fromIntegral (maxBound :: WORD)+#define PUTSUM(WORD) GUARD(WORD) = putSum (0 :: WORD) (fromIntegral size)+#define GETSUM(WORD) GUARD(WORD) = (get :: Get WORD) >>= checkGetSum (fromIntegral size)++instance ( GSum     a, GSum     b+         , GGBinary a, GGBinary b+         , SumSize    a, SumSize    b) => GGBinary (a :+: b) where+    ggput | PUTSUM(Word8) | PUTSUM(Word16) | PUTSUM(Word32) | PUTSUM(Word64)+         | otherwise = sizeError "encode" size+      where+        size = unTagged (sumSize :: Tagged (a :+: b) Word64)+    {-# INLINE ggput #-}++    ggget | GETSUM(Word8) | GETSUM(Word16) | GETSUM(Word32) | GETSUM(Word64)+         | otherwise = sizeError "decode" size+      where+        size = unTagged (sumSize :: Tagged (a :+: b) Word64)+    {-# INLINE ggget #-}++sizeError :: Show size => String -> size -> error+sizeError s size =+    error $ "Can't " ++ s ++ " a type with " ++ show size ++ " constructors"++------------------------------------------------------------------------++checkGetSum :: (Ord word, Num word, Bits word, GSum f)+            => word -> word -> Get (f a)+checkGetSum size code | code < size = getSum code size+                      | otherwise   = fail "Unknown encoding for constructor"+{-# INLINE checkGetSum #-}++class GSum f where+    getSum :: (Ord word, Num word, Bits word) => word -> word -> Get (f a)+    putSum :: (Num w, Bits w, Binary w) => w -> w -> f a -> Put++instance (GSum a, GSum b, GGBinary a, GGBinary b) => GSum (a :+: b) where+    getSum !code !size | code < sizeL = L1 <$> getSum code           sizeL+                       | otherwise    = R1 <$> getSum (code - sizeL) sizeR+        where+          sizeL = size `shiftR` 1+          sizeR = size - sizeL+    {-# INLINE getSum #-}++    putSum !code !size s = case s of+                             L1 x -> putSum code           sizeL x+                             R1 x -> putSum (code + sizeL) sizeR x+        where+          sizeL = size `shiftR` 1+          sizeR = size - sizeL+    {-# INLINE putSum #-}++instance GGBinary a => GSum (C1 c a) where+    getSum _ _ = ggget+    {-# INLINE getSum #-}++    putSum !code _ x = put code *> ggput x+    {-# INLINE putSum #-}++------------------------------------------------------------------------++class SumSize f where+    sumSize :: Tagged f Word64++newtype Tagged (s :: * -> *) b = Tagged {unTagged :: b}++instance (SumSize a, SumSize b) => SumSize (a :+: b) where+    sumSize = Tagged $ unTagged (sumSize :: Tagged a Word64) ++                       unTagged (sumSize :: Tagged b Word64)++instance SumSize (C1 c a) where+    sumSize = Tagged 1
Language/Haskell/GhcMod.hs view
@@ -44,6 +44,7 @@   , pkgDoc   , rootInfo   , types+  , test   , splits   , sig   , refine@@ -88,3 +89,4 @@ import Language.Haskell.GhcMod.Target import Language.Haskell.GhcMod.Output import Language.Haskell.GhcMod.FileMapping+import Language.Haskell.GhcMod.Test
Language/Haskell/GhcMod/Boot.hs view
@@ -12,7 +12,7 @@ boot :: IOish m => GhcModT m String boot = concat <$> sequence ms   where-    ms = [modules, languages, flags, concat <$> mapM browse preBrowsedModules]+    ms = [modules False, languages, flags, concat <$> mapM (browse (BrowseOpts False False False)) preBrowsedModules]  preBrowsedModules :: [String] preBrowsedModules = [
Language/Haskell/GhcMod/Browse.hs view
@@ -1,7 +1,9 @@ module Language.Haskell.GhcMod.Browse (-    browse+    browse,+    BrowseOpts(..)   ) where +import Safe import Control.Applicative import Control.Exception (SomeException(..)) import Data.Char@@ -13,8 +15,9 @@ import Language.Haskell.GhcMod.Convert import Language.Haskell.GhcMod.Doc (showPage, styleUnqualified) import Language.Haskell.GhcMod.Gap as Gap-import Language.Haskell.GhcMod.Monad import Language.Haskell.GhcMod.Types+import Language.Haskell.GhcMod.Monad+import Language.Haskell.GhcMod.Logging import Name (getOccString) import Outputable import TyCon (isAlgTyCon)@@ -25,29 +28,29 @@ ----------------------------------------------------------------  -- | Getting functions, classes, etc from a module.---   If 'detailed' is 'True', their types are also obtained.---   If 'operators' is 'True', operators are also returned. browse :: forall m. IOish m-       => String -- ^ A module name. (e.g. \"Data.List\", "base:Prelude")-       -> GhcModT m String-browse pkgmdl = do+           => BrowseOpts -- ^ Configuration parameters+           -> String -- ^ A module name. (e.g. \"Data.List\", "base:Prelude")+           -> GhcModT m String+browse opts pkgmdl = do     convert' . sort =<< go   where     -- TODO: Add API to Gm.Target to check if module is home module without     -- bringing up a GHC session as well then this can be made a lot cleaner-    go = ghandle (\(SomeException _) -> return []) $ do+    go = ghandle (\ex@(SomeException _) -> logException ex >> return []) $ do       goPkgModule `G.gcatch` (\(SomeException _) -> goHomeModule) +    logException ex =+        gmLog GmException "browse" $ showDoc ex+     goPkgModule = do-      opt <- options       runGmPkgGhc $-        processExports opt =<< tryModuleInfo =<< G.findModule mdlname mpkgid+        processExports opts =<< tryModuleInfo =<< G.findModule mdlname mpkgid      goHomeModule = runGmlT [Right mdlname] $ do-      opt <- options-      processExports opt =<< tryModuleInfo =<< G.findModule mdlname Nothing+      processExports opts =<< tryModuleInfo =<< G.findModule mdlname Nothing -    tryModuleInfo m = fromJust <$> G.getModuleInfo m+    tryModuleInfo m = fromJustNote "browse, tryModuleInfo" <$> G.getModuleInfo m      (mpkg, mdl) = splitPkgMdl pkgmdl     mdlname = G.mkModuleName mdl@@ -76,31 +79,31 @@ isNotOp _ = error "isNotOp"  processExports :: (G.GhcMonad m, MonadIO m, ExceptionMonad m)-               => Options -> ModuleInfo -> m [String]+               => BrowseOpts -> ModuleInfo -> m [String] processExports opt minfo = do   let     removeOps-      | optOperators opt = id+      | optBrowseOperators opt = id       | otherwise = filter (isNotOp . getOccString)   mapM (showExport opt minfo) $ removeOps $ G.modInfoExports minfo  showExport :: forall m. (G.GhcMonad m, MonadIO m, ExceptionMonad m)-           => Options -> ModuleInfo -> Name -> m String+           => BrowseOpts -> ModuleInfo -> Name -> m String showExport opt minfo e = do   mtype' <- mtype   return $ concat $ catMaybes [mqualified, Just $ formatOp $ getOccString e, mtype']   where-    mqualified = (G.moduleNameString (G.moduleName $ G.nameModule e) ++ ".") `justIf` optQualified opt+    mqualified = (G.moduleNameString (G.moduleName $ G.nameModule e) ++ ".") `justIf` optBrowseQualified opt     mtype :: m (Maybe String)     mtype-      | optDetailed opt = do+      | optBrowseDetailed opt = do         tyInfo <- G.modInfoLookupName minfo e         -- If nothing found, load dependent module and lookup global         tyResult <- maybe (inOtherModule e) (return . Just) tyInfo         dflag <- G.getSessionDynFlags         return $ do           typeName <- tyResult >>= showThing dflag-          (" :: " ++ typeName) `justIf` optDetailed opt+          (" :: " ++ typeName) `justIf` optBrowseDetailed opt       | otherwise = return Nothing     formatOp nm       | null nm    = error "formatOp"
Language/Haskell/GhcMod/CabalHelper.hs view
@@ -21,6 +21,7 @@   , getGhcMergedPkgOptions   , getCabalPackageDbStack   , prepareCabalHelper+  , withAutogen   ) #endif   where@@ -30,7 +31,8 @@ import Control.Category ((.)) import Data.Maybe import Data.Monoid-import Data.Serialize (Serialize)+import Data.Version+import Data.Binary (Binary) import Data.Traversable import Distribution.Helper hiding (Programs(..)) import qualified Distribution.Helper as CH@@ -58,7 +60,7 @@   cacheLens = Just (lGmcMergedPkgOptions . lGmCaches),   cacheFile = mergedPkgOptsCacheFile distdir,   cachedAction = \_tcf (_progs, _projdir, _ver) _ma -> do-    opts <- withCabal $ runCHQuery ghcMergedPkgOptions+    opts <- runCHQuery ghcMergedPkgOptions     return ([setupConfigPath distdir], opts)  } @@ -68,7 +70,7 @@   cacheFile = pkgDbStackCacheFile distdir,   cachedAction = \_tcf (_progs, _projdir, _ver) _ma -> do     crdl <- cradle-    dbs <- withCabal $ map chPkgToGhcPkg <$>+    dbs <- map chPkgToGhcPkg <$>              runCHQuery packageDbStack     return ([setupConfigFile crdl, sandboxConfigFile crdl], dbs)  }@@ -85,7 +87,7 @@ -- 'resolveGmComponents'. getComponents :: (Applicative m, IOish m, Gm m)               => m [GmComponent 'GMCRaw ChEntrypoint]-getComponents = chCached$ \distdir -> Cached {+getComponents = chCached $ \distdir -> Cached {     cacheLens = Just (lGmcComponents . lGmCaches),     cacheFile = cabalHelperCacheFile distdir,     cachedAction = \ _tcf (_progs, _projdir, _ver) _ma -> do@@ -111,79 +113,101 @@                  , (a', c) <- lc                  , a == a'                  ]-runCHQuery :: (IOish m, GmOut m, GmEnv m) => Query m b -> m b-runCHQuery a = do++getQueryEnv :: (IOish m, GmOut m, GmEnv m) => m QueryEnv+getQueryEnv = do   crdl <- cradle+  progs <- patchStackPrograms crdl =<< (optPrograms <$> options)+  readProc <- gmReadProcess   let projdir = cradleRootDir crdl       distdir = projdir </> cradleDistDir crdl--  opts <- options-  progs <- patchStackPrograms crdl (optPrograms opts)--  readProc <- gmReadProcess+  return (defaultQueryEnv projdir distdir) {+                  qeReadProcess = readProc+                , qePrograms = helperProgs progs+                } -  let qe = (defaultQueryEnv projdir distdir) {-               qeReadProcess = readProc-             , qePrograms = helperProgs progs-             }+runCHQuery :: (IOish m, GmOut m, GmEnv m) => Query m b -> m b+runCHQuery a = do+  qe <- getQueryEnv   runQuery qe a   prepareCabalHelper :: (IOish m, GmEnv m, GmOut m, GmLog m) => m () prepareCabalHelper = do   crdl <- cradle-  let projdir = cradleRootDir crdl-      distdir = projdir </> cradleDistDir crdl-  readProc <- gmReadProcess   when (isCabalHelperProject $ cradleProject crdl) $-       withCabal $ liftIO $ prepare readProc projdir distdir+       withCabal $ prepare' =<< getQueryEnv -withCabal :: (IOish m, GmEnv m, GmOut m, GmLog m) => m a -> m a-withCabal action = do+withAutogen :: (IOish m, GmEnv m, GmOut m, GmLog m) => m a -> m a+withAutogen action = do+    gmLog GmDebug "" $ strDoc $ "making sure autogen files exist"     crdl <- cradle-    opts <- options-    readProc <- gmReadProcess-     let projdir = cradleRootDir crdl         distdir = projdir </> cradleDistDir crdl +    (pkgName', _) <- runCHQuery packageId+     mCabalFile          <- liftIO $ timeFile `traverse` cradleCabalFile crdl-    mCabalConfig        <- liftIO $ timeMaybe (setupConfigFile crdl)-    mCabalSandboxConfig <- liftIO $ timeMaybe (sandboxConfigFile crdl)+    mCabalMacroHeader   <- liftIO $ timeMaybe (distdir </> macrosHeaderPath)+    mCabalPathsModule   <- liftIO $ timeMaybe (distdir </> autogenModulePath pkgName') -    mCusPkgDbStack <- getCustomPkgDbStack+    when (mCabalMacroHeader < mCabalFile || mCabalPathsModule < mCabalFile) $ do+      gmLog GmDebug "" $ strDoc $ "autogen files out of sync"+      writeAutogen -    pkgDbStackOutOfSync <--         case mCusPkgDbStack of-           Just cusPkgDbStack -> do-             let qe = (defaultQueryEnv projdir distdir) {-                          qeReadProcess = readProc-                        , qePrograms = helperProgs $ optPrograms opts-                        }-             pkgDb <- runQuery qe $ map chPkgToGhcPkg <$> packageDbStack-             return $ pkgDb /= cusPkgDbStack+    action -           Nothing -> return False+ where+   writeAutogen = do+     gmLog GmDebug "" $ strDoc $ "writing Cabal autogen files"+     writeAutogenFiles' =<< getQueryEnv -    proj <- cradleProject <$> cradle +withCabal :: (IOish m, GmEnv m, GmOut m, GmLog m) => m a -> m a+withCabal action = do+    crdl <- cradle+    mCabalFile          <- liftIO $ timeFile `traverse` cradleCabalFile crdl+    mCabalConfig        <- liftIO $ timeMaybe (setupConfigFile crdl)+    mCabalSandboxConfig <- liftIO $ timeMaybe (sandboxConfigFile crdl)++    let haveSetupConfig = isJust mCabalConfig++    cusPkgDb <- getCustomPkgDbStack+    (flgs, pkgDbStackOutOfSync) <- do+      if haveSetupConfig+        then runCHQuery $ do+          flgs <- nonDefaultConfigFlags+          pkgDb <- map chPkgToGhcPkg <$> packageDbStack+          return (flgs, fromMaybe False $ (pkgDb /=) <$> cusPkgDb)+        else return ([], False)+     when (isSetupConfigOutOfDate mCabalFile mCabalConfig) $-      gmLog GmDebug "" $ strDoc $ "setup configuration is out of date, reconfiguring Cabal project."+      gmLog GmDebug "" $ strDoc $ "setup configuration is out of date"      when (isSetupConfigOutOfDate mCabalSandboxConfig mCabalConfig) $-      gmLog GmDebug "" $ strDoc $ "sandbox configuration is out of date, reconfiguring Cabal project."+      gmLog GmDebug "" $ strDoc $ "sandbox configuration is out of date"      when pkgDbStackOutOfSync $-      gmLog GmDebug "" $ strDoc $ "package-db stack out of sync with ghc-mod.package-db-stack, reconfiguring Cabal project."+      gmLog GmDebug "" $ strDoc $ "package-db stack out of sync with ghc-mod.package-db-stack"      when ( isSetupConfigOutOfDate mCabalFile mCabalConfig         || pkgDbStackOutOfSync-        || isSetupConfigOutOfDate mCabalSandboxConfig mCabalConfig) $+        || isSetupConfigOutOfDate mCabalSandboxConfig mCabalConfig) $ do+          proj <- cradleProject <$> cradle+          opts <- options           case proj of-            CabalProject ->-                cabalReconfigure readProc (optPrograms opts) crdl projdir distdir-            StackProject {} ->+            CabalProject -> do+                gmLog GmDebug "" $ strDoc "reconfiguring Cabal project"+                cabalReconfigure (optPrograms opts) crdl flgs+            StackProject {} -> do+                gmLog GmDebug "" $ strDoc "reconfiguring Stack project"+                -- TODO: we could support flags for stack too, but it seems+                -- you're supposed to put those in stack.yaml so detecting which+                -- flags to pass down would be more difficult +                -- "--flag PACKAGE:[-]FLAG Override flags set in stack.yaml+                -- (applies to local packages and extra-deps)"+                 stackReconfigure crdl (optPrograms opts)             _ ->                 error $ "withCabal: unsupported project type: " ++ show proj@@ -191,13 +215,8 @@     action   where-   writeAutogen projdir distdir = do+   cabalReconfigure progs crdl flgs = do      readProc <- gmReadProcess-     gmLog GmDebug "" $ strDoc $ "writing Cabal autogen files"-     liftIO $ writeAutogenFiles readProc projdir distdir---   cabalReconfigure readProc progs crdl projdir distdir = do      withDirectory_ (cradleRootDir crdl) $ do         cusPkgStack <- maybe [] ((PackageDb "clear"):) <$> getCustomPkgDbStack         let progOpts =@@ -208,20 +227,20 @@                      then [ "--with-ghc-pkg=" ++ T.ghcPkgProgram progs ]                      else []                 ++ map pkgDbArg cusPkgStack-        liftIO $ void $ readProc (T.cabalProgram progs) ("configure":progOpts) ""-        writeAutogen projdir distdir+                ++ flagOpt -   stackReconfigure crdl progs = do-     let projdir = cradleRootDir crdl-         distdir = projdir </> cradleDistDir crdl+            toFlag (f, True) = f+            toFlag (f, False) = '-':f+            flagOpt = ["--flags", unwords $ map toFlag flgs] +        liftIO $ void $ readProc (T.cabalProgram progs) ("configure":progOpts) ""+   stackReconfigure crdl progs = do      withDirectory_ (cradleRootDir crdl) $ do        supported <- haveStackSupport        if supported           then do             spawn [T.stackProgram progs, "build", "--only-dependencies", "."]             spawn [T.stackProgram progs, "build", "--only-configure", "."]-            writeAutogen projdir distdir           else             gmLog GmWarning "" $ strDoc $ "Stack project configuration is out of date, please reconfigure manually using 'stack build' as your stack version is too old (need at least 0.1.4.0)" @@ -268,7 +287,7 @@     ghcPkgProgram = T.ghcPkgProgram progs   } -chCached :: (Applicative m, IOish m, Gm m, Serialize a)+chCached :: (Applicative m, IOish m, Gm m, Binary a)   => (FilePath -> Cached m GhcModState ChCacheData a) -> m a chCached c = do   projdir <- cradleRootDir <$> cradle@@ -276,7 +295,7 @@   d <- cacheInputData projdir   withCabal $ cached projdir (c distdir) d  where-   -- we don't need to include the disdir in the cache input because when it+   -- we don't need to include the distdir in the cache input because when it    -- changes the cache files will be gone anyways ;)    cacheInputData projdir = do                opts <- options@@ -284,7 +303,7 @@                progs' <- patchStackPrograms crdl (optPrograms opts)                return $ ( helperProgs progs'                         , projdir-                        , (gmVer, chVer)+                        , (showVersion gmVer, chVer)                         )     gmVer = GhcMod.version
Language/Haskell/GhcMod/Caching.hs view
@@ -1,4 +1,19 @@-{-# LANGUAGE OverloadedStrings #-}+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015  Daniel Gröber <dxld ÄT darkboxed DOT org>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.+{-# LANGUAGE CPP, OverloadedStrings #-} module Language.Haskell.GhcMod.Caching (     module Language.Haskell.GhcMod.Caching   , module Language.Haskell.GhcMod.Caching.Types@@ -7,64 +22,75 @@ import Control.Arrow (first) import Control.Monad import Control.Monad.Trans.Maybe+#if !MIN_VERSION_binary(0,7,0)+import Control.Exception+#endif import Data.Maybe-import Data.Serialize (Serialize, encode, decode)+import Data.Binary hiding (get) import Data.Version import Data.Label+import qualified Data.ByteString.Lazy as LBS import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as BS8 import System.FilePath+import System.Directory.ModTime import Utils (TimedFile(..), timeMaybe, mightExist) import Paths_ghc_mod (version)+import Prelude  import Language.Haskell.GhcMod.Monad.Types import Language.Haskell.GhcMod.Caching.Types import Language.Haskell.GhcMod.Logging  -- | Cache a MonadIO action with proper invalidation.-cached :: forall m a d. (Gm m, MonadIO m, Serialize a, Eq d, Serialize d, Show d)+cached :: forall m a d. (Gm m, MonadIO m, Binary a, Eq d, Binary d, Show d)        => FilePath -- ^ Directory to prepend to 'cacheFile'        -> Cached m GhcModState d a -- ^ Cache descriptor        -> d        -> m a cached dir cd d = do     mcc <- readCache-    tcfile <- liftIO $ timeMaybe (cacheFile cd)     case mcc of-      Nothing ->-          writeCache (TimedCacheFiles tcfile []) Nothing "cache missing or unreadable"-      Just (ifs, d', a) | d /= d' -> do-          tcf <- timeCacheInput dir (cacheFile cd) ifs-          writeCache tcf (Just a) $ "input data changed" -- ++ "   was: " ++ show d ++ "  is: " ++ show d'-      Just (ifs, _, a) -> do-          tcf <- timeCacheInput dir (cacheFile cd) ifs-          case invalidatingInputFiles tcf of-            Just [] -> return a-            Just _  -> writeCache tcf (Just a) "input files changed"-            Nothing -> writeCache tcf (Just a) "cache missing, existed a sec ago WTF?"+      Nothing -> do+          t <- liftIO $ getCurrentModTime+          writeCache (TimedCacheFiles t []) Nothing "cache missing or unreadable"+      Just (t, ifs, d', a) | d /= d' -> do+          tcfs <- timeCacheInput dir ifs+          writeCache (TimedCacheFiles t tcfs) (Just a) $ "input data changed" -- ++ "   was: " ++ show d ++ "  is: " ++ show d'+      Just (t, ifs, _, a) -> do+          tcfs <- timeCacheInput dir ifs+          case invalidatingInputFiles $ TimedCacheFiles t tcfs of+            [] -> return a+            _  -> writeCache (TimedCacheFiles t tcfs) (Just a) "input files changed"   where    cacheHeader = BS8.pack $ "Written by ghc-mod " ++ showVersion version ++ "\n" -   writeCache tcf ma cause = do-     (ifs', a) <- (cachedAction cd) tcf d ma+   lbsToStrict = BS.concat . LBS.toChunks+   lbsFromStrict bs = LBS.fromChunks [bs]++   writeCache tcfs ma cause = do+     (ifs', a) <- (cachedAction cd) tcfs d ma+     t <- liftIO $ getCurrentModTime      gmLog GmDebug "" $ (text "regenerating cache") <+>: text (cacheFile cd)                                                     <+> parens (text cause)      case cacheLens cd of        Nothing -> return ()        Just label -> do          gmLog GmDebug "" $ (text "writing memory cache") <+>: text (cacheFile cd)-         setLabel label $ Just (ifs', d, a)+         setLabel label $ Just (t, ifs', d, a) -     liftIO $ BS.writeFile (dir </> cacheFile cd) $-         BS.append cacheHeader $ encode (ifs', d, a)+     let c = BS.append cacheHeader $ lbsToStrict $ encode (t, ifs', d, a)++     liftIO $ BS.writeFile (dir </> cacheFile cd) c+      return a     setLabel l x = do      s <- gmsGet      gmsPut $ set l x s -   readCache :: m (Maybe ([FilePath], d, a))+   readCache :: m (Maybe (ModTime, [FilePath], d, a))    readCache = runMaybeT $ do        case cacheLens cd of          Just label -> do@@ -74,30 +100,42 @@          Nothing ->              readCacheFromFile +   readCacheFromFile :: MaybeT m (ModTime, [FilePath], d, a)    readCacheFromFile = do          f <- MaybeT $ liftIO $ mightExist $ cacheFile cd          readCacheFromFile' f +   readCacheFromFile' :: FilePath -> MaybeT m (ModTime, [FilePath], d, a)    readCacheFromFile' f = MaybeT $ do      gmLog GmDebug "" $ (text "reading cache") <+>: text (cacheFile cd)      cc <- liftIO $ BS.readFile f      case first BS8.words $ BS8.span (/='\n') cc of        (["Written", "by", "ghc-mod", ver], rest)            | BS8.unpack ver == showVersion version ->-            return $ either (const Nothing) Just $ decode $ BS.drop 1 rest+            either (const Nothing) Just+                `liftM` decodeE (lbsFromStrict $ BS.drop 1 rest)        _ -> return Nothing -timeCacheInput :: MonadIO m => FilePath -> FilePath -> [FilePath] -> m TimedCacheFiles-timeCacheInput dir cfile ifs = liftIO $ do-    -- TODO: is checking the times this way around race free?+   decodeE b = do+#if MIN_VERSION_binary(0,7,0)+     return $ case decodeOrFail b of+       Left (_rest, _offset, errmsg) -> Left errmsg+       Right (_reset, _offset, a) -> Right a+#else+     ea <- liftIO $ try $ evaluate $ decode b+     return $ case ea of+       Left (ErrorCall errmsg) -> Left errmsg+       Right a -> Right a++#endif++timeCacheInput :: MonadIO m => FilePath -> [FilePath] -> m [TimedFile]+timeCacheInput dir ifs = liftIO $ do     ins <- (timeMaybe . (dir </>)) `mapM` ifs-    mtcfile <- timeMaybe cfile-    return $ TimedCacheFiles mtcfile (catMaybes ins)+    return $ catMaybes ins -invalidatingInputFiles :: TimedCacheFiles -> Maybe [FilePath]-invalidatingInputFiles tcf =-    case tcCacheFile tcf of-      Nothing -> Nothing-      Just tcfile -> Just $ map tfPath $-                     -- get input files older than tcfile-                     filter (tcfile<) $ tcFiles tcf+invalidatingInputFiles :: TimedCacheFiles -> [FilePath]+invalidatingInputFiles (TimedCacheFiles tcreated tcfs) =+    map tfPath $+        -- get input files older than tcfile+        filter ((TimedFile "" tcreated)<) tcfs
Language/Haskell/GhcMod/Caching/Types.hs view
@@ -1,11 +1,26 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015  Daniel Gröber <dxld ÄT darkboxed DOT org>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>. module Language.Haskell.GhcMod.Caching.Types where  import Utils import Data.Label-import Data.Version+import System.Directory.ModTime import Distribution.Helper -type CacheContents d a = Maybe ([FilePath], d, a)+type CacheContents d a = Maybe (ModTime, [FilePath], d, a) type CacheLens s d a = s :-> CacheContents d a  data Cached m s d a = Cached {@@ -43,10 +58,10 @@  }  data TimedCacheFiles = TimedCacheFiles {-  tcCacheFile :: Maybe TimedFile,+  tcCreated :: ModTime,   -- ^ 'cacheFile' timestamp   tcFiles     :: [TimedFile]   -- ^ Timestamped files returned by the cached action- } deriving (Eq, Ord, Show)+ } deriving (Eq, Ord) -type ChCacheData = (Programs, FilePath, (Version, [Char]))+type ChCacheData = (Programs, FilePath, (String, String))
Language/Haskell/GhcMod/Cradle.hs view
@@ -4,6 +4,7 @@   (     findCradle   , findCradle'+  , findCradleNoLog   , findSpecCradle   , cleanupCradle   )@@ -15,14 +16,17 @@ import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Utils import Language.Haskell.GhcMod.Stack+import Language.Haskell.GhcMod.Logging+import Language.Haskell.GhcMod.Error +import Safe import Control.Applicative-import Control.Monad import Control.Monad.Trans.Maybe import Data.Maybe import System.Directory import System.FilePath import Prelude+import Control.Monad.Trans.Journal (runJournalT)  ---------------------------------------------------------------- @@ -30,19 +34,22 @@ --   Find a cabal file by tracing ancestor directories. --   Find a sandbox according to a cabal sandbox config --   in a cabal directory.-findCradle :: (IOish m, GmOut m) => m Cradle+findCradle :: (GmLog m, IOish m, GmOut m) => m Cradle findCradle = findCradle' =<< liftIO getCurrentDirectory -findCradle' :: (IOish m, GmOut m) => FilePath -> m Cradle+findCradleNoLog  :: forall m. (IOish m, GmOut m) => m Cradle+findCradleNoLog = fst <$> (runJournalT findCradle :: m (Cradle, GhcModLog))++findCradle' :: (GmLog m, IOish m, GmOut m) => FilePath -> m Cradle findCradle' dir = run $     msum [ stackCradle dir          , cabalCradle dir          , sandboxCradle dir          , plainCradle dir          ]- where run a = fillTempDir =<< (fromJust <$> runMaybeT a)+ where run a = fillTempDir =<< (fromJustNote "findCradle'" <$> runMaybeT a) -findSpecCradle :: (IOish m, GmOut m) => FilePath -> m Cradle+findSpecCradle :: (GmLog m, IOish m, GmOut m) => FilePath -> m Cradle findSpecCradle dir = do     let cfs = [stackCradleSpec, cabalCradle, sandboxCradle]     cs <- catMaybes <$> mapM (runMaybeT . ($ dir)) cfs@@ -77,8 +84,12 @@       , cradleDistDir    = "dist"       } -stackCradle :: (IOish m, GmOut m) => FilePath -> MaybeT m Cradle+stackCradle :: (GmLog m, IOish m, GmOut m) => FilePath -> MaybeT m Cradle stackCradle wdir = do+#if !MIN_VERSION_ghc(7,8,0)+    -- GHC < 7.8 is not supported by stack+    mzero+#endif     cabalFile <- MaybeT $ liftIO $ findCabalFile wdir      let cabalDir = takeDirectory cabalFile@@ -87,7 +98,9 @@      -- If dist/setup-config already exists the user probably wants to use cabal     -- rather than stack, or maybe that's just me ;)-    whenM (liftIO $ doesFileExist $ setupConfigPath "dist") $ mzero+    whenM (liftIO $ doesFileExist $ cabalDir </> setupConfigPath "dist") $ do+      gmLog GmWarning "" $ text "'dist/setup-config' exists, ignoring Stack and using cabal-install instead."+      mzero      senv <- MaybeT $ getStackEnv cabalDir @@ -100,7 +113,7 @@       , cradleDistDir    = seDistDir senv       } -stackCradleSpec :: (IOish m, GmOut m) => FilePath -> MaybeT m Cradle+stackCradleSpec :: (GmLog m, IOish m, GmOut m) => FilePath -> MaybeT m Cradle stackCradleSpec wdir = do   crdl <- stackCradle wdir   case crdl of
Language/Haskell/GhcMod/CustomPackageDb.hs view
@@ -1,6 +1,20 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015  Daniel Gröber <dxld ÄT darkboxed DOT org>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>. module Language.Haskell.GhcMod.CustomPackageDb where - import Control.Applicative import Control.Monad import Control.Category ((.))@@ -11,7 +25,6 @@ import Language.Haskell.GhcMod.PathsAndFiles import Prelude hiding ((.)) - parseCustomPackageDb :: String -> [GhcPkgDb] parseCustomPackageDb src = map parsePkgDb $ filter (not . null) $ lines src  where@@ -19,7 +32,7 @@    parsePkgDb "user" = UserDb    parsePkgDb s = PackageDb s -getCustomPkgDbStack :: (IOish m, GmEnv m) => m (Maybe [GhcPkgDb])+getCustomPkgDbStack :: (MonadIO m, GmEnv m) => m (Maybe [GhcPkgDb]) getCustomPkgDbStack = do     mCusPkgDbFile <- liftIO . (traverse readFile <=< findCustomPackageDbFile) . cradleRootDir =<< cradle     return $ parseCustomPackageDb <$> mCusPkgDbFile
Language/Haskell/GhcMod/Debug.hs view
@@ -3,6 +3,7 @@ import Control.Arrow (first) import Control.Applicative import Control.Monad+import Control.Monad.Trans.Journal import qualified Data.Map as Map import qualified Data.Set as Set import Data.Char@@ -138,5 +139,5 @@ ----------------------------------------------------------------  -- | Obtaining root information.-rootInfo :: (IOish m, GmOut m) => m String-rootInfo = (++"\n") . cradleRootDir <$> findCradle+rootInfo :: forall m. (IOish m, GmOut m) => m String+rootInfo = (++"\n") . cradleRootDir <$> fst `liftM` (runJournalT findCradle :: m (Cradle, GhcModLog))
Language/Haskell/GhcMod/DebugLogger.hs view
@@ -1,6 +1,54 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015  Daniel Gröber <dxld ÄT darkboxed DOT org>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>. {-# LANGUAGE CPP #-} module Language.Haskell.GhcMod.DebugLogger where +-- (c) The University of Glasgow 2005+--+-- The Glasgow Haskell Compiler License+--+-- Copyright 2002, The University Court of the University of Glasgow.+-- All rights reserved.+--+-- Redistribution and use in source and binary forms, with or without+-- modification, are permitted provided that the following conditions are met:+--+-- - Redistributions of source code must retain the above copyright notice,+-- this list of conditions and the following disclaimer.+--+-- - Redistributions in binary form must reproduce the above copyright notice,+-- this list of conditions and the following disclaimer in the documentation+-- and/or other materials provided with the distribution.+--+-- - Neither name of the University nor the names of its contributors may be+-- used to endorse or promote products derived from this software without+-- specific prior written permission.+--+-- THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF+-- GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,+-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND+-- FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE+-- UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE+-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+-- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+-- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+-- DAMAGE.  import GHC import FastString
Language/Haskell/GhcMod/DynFlags.hs view
@@ -25,8 +25,8 @@ -- * Friendly to foreign export -- * Not friendly to -XTemplateHaskell and -XPatternSynonyms -- * Uses little memory-setModeSimple :: DynFlags -> DynFlags-setModeSimple df = df {+setHscNothing :: DynFlags -> DynFlags+setHscNothing df = df {     ghcMode   = CompManager   , ghcLink   = NoLink   , hscTarget = HscNothing@@ -37,8 +37,8 @@ -- * Not friendly to foreign export -- * Friendly to -XTemplateHaskell and -XPatternSynonyms -- * Uses lots of memory-setModeIntelligent :: DynFlags -> DynFlags-setModeIntelligent df = df {+setHscInterpreted :: DynFlags -> DynFlags+setHscInterpreted df = df {     ghcMode   = CompManager   , ghcLink   = LinkInMemory   , hscTarget = HscInterpreted
Language/Haskell/GhcMod/Error.hs view
@@ -104,11 +104,6 @@     GMETooManyCabalFiles cfs ->         text $ "Multiple cabal files found. Possible cabal files: \""                ++ intercalate "\", \"" cfs ++"\"."-    GMEWrongWorkingDirectory projdir cdir ->-        (text $ "You must run ghc-mod in the project directory as returned by `ghc-mod root`.")-          <+> text "Currently in:" <+> showDoc cdir-          <> text "but should be in" <+> showDoc projdir-          <> text "."  ghcExceptionDoc :: GhcException -> Doc ghcExceptionDoc e@(CmdLineError _) =
Language/Haskell/GhcMod/FileMapping.hs view
@@ -20,10 +20,30 @@ import GHC import Control.Monad -loadMappedFile :: IOish m => FilePath -> FilePath -> GhcModT m ()+{- | maps 'FilePath', given as first argument to take source from+'FilePath' given as second argument. Works exactly the same as+first form of `--map-file` CLI option.++\'from\' can be either full path, or path relative to project root.+\'to\' has to be either relative to project root, or full path (preferred)+-}+loadMappedFile :: IOish m+               => FilePath -- ^ \'from\', file that will be mapped+               -> FilePath -- ^ \'to\', file to take source from+               -> GhcModT m () loadMappedFile from to = loadMappedFile' from to False -loadMappedFileSource :: IOish m => FilePath -> String -> GhcModT m ()+{- |+maps 'FilePath', given as first argument to have source as given+by second argument.++\'from\' may or may not exist, and should be either full path,+or relative to project root.+-}+loadMappedFileSource :: IOish m+                     => FilePath -- ^ \'from\', file that will be mapped+                     -> String -- ^ \'src\', source+                     -> GhcModT m () loadMappedFileSource from src = do   tmpdir <- cradleTempDir `fmap` cradle   to <- liftIO $ do@@ -37,7 +57,9 @@ loadMappedFile' from to isTemp = do   cfn <- getCanonicalFileNameSafe from   unloadMappedFile' cfn-  addMMappedFile cfn (FileMapping to isTemp)+  crdl <- cradle+  let to' = makeRelative (cradleRootDir crdl) to+  addMMappedFile cfn (FileMapping to' isTemp)  mapFile :: (IOish m, GmState m, GhcMonad m, GmEnv m) =>             HscEnv -> Target -> m Target@@ -57,7 +79,16 @@   return $ mkTarget (TargetFile (fmPath to) Nothing) taoc Nothing mkMappedTarget _ tid taoc _ = return $ mkTarget tid taoc Nothing -unloadMappedFile :: IOish m => FilePath -> GhcModT m ()+{-|+unloads previously mapped file \'file\', so that it's no longer mapped,+and removes any temporary files created when file was+mapped.++\'file\' should be either full path, or relative to project root.+-}+unloadMappedFile :: IOish m+                 => FilePath -- ^ \'file\', file to unmap+                 -> GhcModT m () unloadMappedFile = getCanonicalFileNameSafe >=> unloadMappedFile'  unloadMappedFile' :: IOish m => FilePath -> GhcModT m ()
Language/Haskell/GhcMod/Find.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, BangPatterns, DoAndIfThenElse #-}+{-# LANGUAGE CPP, DeriveGeneric #-}  module Language.Haskell.GhcMod.Find #ifndef SPEC@@ -10,32 +10,41 @@   , findSymbol   , lookupSym   , isOutdated+  -- * Load 'SymbolDb' asynchronously+  , AsyncSymbolDb+  , newAsyncSymbolDb+  , getAsyncSymbolDb   ) #endif   where -import Control.Applicative-import Control.Monad (when, void)-import Data.Function (on)-import Data.List (groupBy, sort)-import qualified GHC as G import Language.Haskell.GhcMod.Convert-import Language.Haskell.GhcMod.Gap (listVisibleModules)+import Language.Haskell.GhcMod.Gap import Language.Haskell.GhcMod.Monad-import Language.Haskell.GhcMod.PathsAndFiles+import Language.Haskell.GhcMod.Output import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Utils-import Language.Haskell.GhcMod.World (timedPackageCaches)-import Language.Haskell.GhcMod.Output-import Name (getOccString)-import Module (moduleName)-import System.Directory (doesFileExist, getModificationTime)-import System.FilePath ((</>))-import System.IO-import Prelude+import Language.Haskell.GhcMod.World +import qualified GHC as G+import Name+import Module+import Exception++import Control.Applicative+import Control.Monad+import Control.Monad.Trans.Control+import Control.Concurrent+import Control.DeepSeq+import Data.Function+import Data.List+import qualified Data.ByteString.Lazy as BS+import Data.Binary+import GHC.Generics (Generic) import Data.Map (Map) import qualified Data.Map as M+import System.Directory.ModTime+import Prelude  ---------------------------------------------------------------- @@ -43,22 +52,23 @@ type Symbol = String -- | Database from 'Symbol' to \['ModuleString'\]. data SymbolDb = SymbolDb-  { table             :: Map Symbol [ModuleString]-  , symbolDbCachePath :: FilePath-  } deriving (Show)+  { sdTable             :: Map Symbol [ModuleString]+  , sdTimestamp         :: ModTime+  } deriving (Generic) +instance Binary SymbolDb+instance NFData SymbolDb+ isOutdated :: IOish m => SymbolDb -> GhcModT m Bool isOutdated db =-  (liftIO . isOlderThan (symbolDbCachePath db)) =<< timedPackageCaches+  isOlderThan (sdTimestamp db) <$> timedPackageCaches  ----------------------------------------------------------------  -- | Looking up 'SymbolDb' with 'Symbol' to \['ModuleString'\] --   which will be concatenated. 'loadSymbolDb' is called internally. findSymbol :: IOish m => Symbol -> GhcModT m String-findSymbol sym = do-  tmpdir <- cradleTempDir <$> cradle-  loadSymbolDb tmpdir >>= lookupSymbol sym+findSymbol sym = loadSymbolDb >>= lookupSymbol sym  -- | Looking up 'SymbolDb' with 'Symbol' to \['ModuleString'\] --   which will be concatenated.@@ -66,62 +76,36 @@ lookupSymbol sym db = convert' $ lookupSym sym db  lookupSym :: Symbol -> SymbolDb -> [ModuleString]-lookupSym sym db = M.findWithDefault [] sym $ table db+lookupSym sym db = M.findWithDefault [] sym $ sdTable db  ---------------------------------------------------------------  -- | Loading a file and creates 'SymbolDb'.-loadSymbolDb :: IOish m => FilePath -> GhcModT m SymbolDb-loadSymbolDb dir = do+loadSymbolDb :: IOish m => GhcModT m SymbolDb+loadSymbolDb = do   ghcMod <- liftIO ghcModExecutable-  readProc <- gmReadProcess-  file   <- liftIO $ chop <$> readProc ghcMod ["dumpsym", dir] ""-  !db    <- M.fromAscList . map conv . lines <$> liftIO (readFile file)-  return $ SymbolDb-    { table             = db-    , symbolDbCachePath = file-    }-  where-    conv :: String -> (Symbol, [ModuleString])-    conv = read-    chop :: String -> String-    chop "" = ""-    chop xs = init xs+  readProc <- gmReadProcess'+  out <- liftIO $ readProc ghcMod ["--verbose", "error", "dumpsym"] ""+  return $!! decode out  ---------------------------------------------------------------- -- used 'ghc-mod dumpsym' --- | Dumping a set of ('Symbol',\['ModuleString'\]) to a file---   if the file does not exist or is invalid.---   The file name is printed.--dumpSymbol :: IOish m => FilePath -> GhcModT m String-dumpSymbol dir = do-  create <- (liftIO . isOlderThan cache) =<< timedPackageCaches-  runGmPkgGhc $ do-    when create $-      liftIO . writeSymbolCache cache =<< getGlobalSymbolTable-    return $ unlines [cache]-  where-    cache = dir </> symbolCacheFile--writeSymbolCache :: FilePath-                 -> [(Symbol, [ModuleString])]-                 -> IO ()-writeSymbolCache cache sm =-  void . withFile cache WriteMode $ \hdl ->-    mapM (hPrint hdl) sm+-- | Dumps a 'Binary' representation of 'SymbolDb' to stdout+dumpSymbol :: IOish m => GhcModT m ()+dumpSymbol = do+  ts <- liftIO getCurrentModTime+  st <- runGmPkgGhc getGlobalSymbolTable+  liftIO . BS.putStr $ encode SymbolDb {+      sdTable = M.fromAscList st+    , sdTimestamp = ts+    }  -- | Check whether given file is older than any file from the given set. -- Returns True if given file does not exist.-isOlderThan :: FilePath -> [TimedFile] -> IO Bool-isOlderThan cache files = do-  exist <- doesFileExist cache-  if not exist-  then return True-  else do-    tCache <- getModificationTime cache-    return $ any (tCache <=) $ map tfTime files -- including equal just in case+isOlderThan :: ModTime -> [TimedFile] -> Bool+isOlderThan tCache files =+  any (tCache <=) $ map tfTime files -- including equal just in case  -- | Browsing all functions in all system modules. getGlobalSymbolTable :: LightGhc [(Symbol, [ModuleString])]@@ -146,3 +130,38 @@ collectModules = map tieup . groupBy ((==) `on` fst) . sort   where     tieup x = (head (map fst x), map snd x)++----------------------------------------------------------------++data AsyncSymbolDb = AsyncSymbolDb (MVar (Either SomeException SymbolDb))++asyncLoadSymbolDb :: IOish m+                  => MVar (Either SomeException SymbolDb)+                  -> GhcModT m ()+asyncLoadSymbolDb mv = void $+    liftBaseWith $ \run -> forkIO $ void $ run $ do+      edb <- gtry loadSymbolDb+      liftIO $ putMVar mv edb++newAsyncSymbolDb :: IOish m => GhcModT m AsyncSymbolDb+newAsyncSymbolDb = do+    mv <- liftIO newEmptyMVar+    asyncLoadSymbolDb mv+    return $ AsyncSymbolDb mv++getAsyncSymbolDb :: forall m. IOish m => AsyncSymbolDb -> GhcModT m SymbolDb+getAsyncSymbolDb (AsyncSymbolDb mv) = do+  db <- liftIO $ handleEx <$> takeMVar mv+  outdated <- isOutdated db+  if outdated+    then do+      asyncLoadSymbolDb mv+      liftIO $ handleEx <$> readMVar mv+    else do+      liftIO $ putMVar mv $ Right db+      return db+ where+   handleEx edb =+     case edb of+       Left ex -> throw ex+       Right db -> db
Language/Haskell/GhcMod/Gap.hs view
@@ -101,6 +101,11 @@ import qualified Data.IntSet as I (IntSet, empty) #endif +#if __GLASGOW_HASKELL__ < 706+import Control.DeepSeq (NFData(rnf))+import Data.ByteString.Lazy.Internal (ByteString(..))+#endif+ import Bag import Lexer as L import Parser@@ -370,7 +375,7 @@                                         (char '\t' <> ptext (sLit "--") <+> loc)                          where loc = ptext (sLit "Defined") <+> pprNameDefnLoc' (getName thing') #else-    pprTyThingInContextLoc' pefas thing' = hang (pprTyThingInContext pefas thing') 2+    pprTyThingInContextLoc' pefas' thing' = hang (pprTyThingInContext pefas' thing') 2                                     (char '\t' <> ptext (sLit "--") <+> loc)                                where loc = ptext (sLit "Defined") <+> pprNameDefnLoc' (getName thing') #endif@@ -563,4 +568,10 @@ mkErrStyle' = Outputable.mkErrStyle #else mkErrStyle' _ = Outputable.mkErrStyle+#endif++#if __GLASGOW_HASKELL__ < 706+instance NFData ByteString where+  rnf Empty       = ()+  rnf (Chunk _ b) = rnf b #endif
Language/Haskell/GhcMod/Internal.hs view
@@ -3,10 +3,6 @@ module Language.Haskell.GhcMod.Internal (   -- * Types     GHCOption-  , Package-  , PackageBaseName-  , PackageVersion-  , PackageId   , IncludeDir   , GmlT(..)   , MonadIO(..)@@ -21,7 +17,6 @@   -- * Environment, state and logging   , GhcModEnv(..)   , GhcModState-  , CompilerMode(..)   , GhcModLog   , GmLog(..)   , GmLogLevel(..)@@ -38,8 +33,6 @@   -- ** Accessing 'GhcModEnv' and 'GhcModState'   , options   , cradle-  , getCompilerMode-  , setCompilerMode   , targetGhcOptions   , withOptions   -- * 'GhcModError'
Language/Haskell/GhcMod/Lint.hs view
@@ -4,8 +4,8 @@ import Control.Exception (SomeException(..)) import Language.Haskell.GhcMod.Logger (checkErrorPrefix) import Language.Haskell.GhcMod.Convert-import Language.Haskell.GhcMod.Monad import Language.Haskell.GhcMod.Types+import Language.Haskell.GhcMod.Monad import Language.Haskell.HLint (hlint)  import Language.Haskell.GhcMod.Utils (withMappedFile)@@ -15,12 +15,12 @@ -- | Checking syntax of a target file using hlint. --   Warnings and errors are returned. lint :: IOish m-     => FilePath  -- ^ A target file.+     => LintOpts  -- ^ Configuration parameters+     -> FilePath  -- ^ A target file.      -> GhcModT m String-lint file = do-  opt <- options+lint opt file =   withMappedFile file $ \tempfile ->-        liftIO (hlint $ tempfile : "--quiet" : optHlintOpts opt)+        liftIO (hlint $ tempfile : "--quiet" : optLintHlintOpts opt)     >>= mapM (replaceFileName tempfile)     >>= ghandle handler . pack  where
Language/Haskell/GhcMod/Logging.hs view
@@ -45,6 +45,11 @@ gmSetLogLevel level =     gmlJournal $ GhcModLog (Just level) (Last Nothing) [] +gmGetLogLevel :: forall m. GmLog m => m GmLogLevel+gmGetLogLevel = do+  GhcModLog { gmLogLevel = Just level } <-  gmlHistory+  return level+ gmSetDumpLevel :: GmLog m => Bool -> m () gmSetDumpLevel level =     gmlJournal $ GhcModLog Nothing (Last (Just level)) []@@ -71,12 +76,19 @@    let loc | loc' == "" = empty           | otherwise = text loc' <+>: empty-      msgDoc = gmLogLevelDoc level <+>: sep [loc, doc]-      msg = dropWhileEnd isSpace $ gmRenderDoc msgDoc+      msgDoc = sep [loc, doc]+      msg = dropWhileEnd isSpace $ gmRenderDoc $ gmLogLevelDoc level <+>: msgDoc    when (level <= level') $ gmErrStrLn msg+  gmLogQuiet level loc' doc -  gmlJournal (GhcModLog Nothing (Last Nothing) [(level, loc', msgDoc)])+gmLogQuiet :: GmLog m => GmLogLevel -> String -> Doc -> m ()+gmLogQuiet level loc doc =+  gmlJournal (GhcModLog Nothing (Last Nothing) [(level, loc, doc)])++gmAppendLogQuiet :: GmLog m => GhcModLog -> m ()+gmAppendLogQuiet GhcModLog { gmLogMessages } =+    forM_ gmLogMessages $ \(level, loc, doc) -> gmLogQuiet level loc doc  gmVomit :: (MonadIO m, GmLog m, GmOut m, GmEnv m) => String -> Doc -> String -> m () gmVomit filename doc content = do
Language/Haskell/GhcMod/Modules.hs view
@@ -14,13 +14,14 @@ ----------------------------------------------------------------  -- | Listing installed modules.-modules :: (IOish m, Gm m) => m String-modules = do-  Options { optDetailed } <- options+modules :: (IOish m, Gm m)+        => Bool -- ^ 'detailed', if 'True', also prints packages that modules belong to.+        -> m String+modules detailed = do   df <- runGmPkgGhc G.getSessionDynFlags   let mns = listVisibleModuleNames df       pmnss = map (first moduleNameString) $ zip mns (modulePkg df `map` mns)-  convert' $ nub [ if optDetailed then pkg ++ " " ++ mn else mn+  convert' $ nub [ if detailed then pkg ++ " " ++ mn else mn                  | (mn, pkgs) <- pmnss, pkg <- pkgs ]  where    modulePkg df = lookupModulePackageInAllPackages df
Language/Haskell/GhcMod/Monad.hs view
@@ -50,31 +50,41 @@ import Exception  import System.Directory+import System.IO.Unsafe import Prelude -withGhcModEnv :: (IOish m, GmOut m) => FilePath -> Options -> (GhcModEnv -> m a) -> m a+withGhcModEnv :: (IOish m, GmOut m) => FilePath -> Options -> ((GhcModEnv, GhcModLog)  -> m a) -> m a withGhcModEnv = withGhcModEnv' withCradle  where    withCradle dir =-       gbracket (findCradle' dir) (liftIO . cleanupCradle)+       gbracket (runJournalT $ findCradle' dir) (liftIO . cleanupCradle . fst) -withGhcModEnv' :: (IOish m, GmOut m) => (FilePath -> (Cradle -> m a) -> m a) -> FilePath -> Options -> (GhcModEnv -> m a) -> m a+cwdLock :: MVar ThreadId+cwdLock = unsafePerformIO $ newEmptyMVar+{-# NOINLINE cwdLock #-}++withGhcModEnv' :: (IOish m, GmOut m) => (FilePath -> ((Cradle, GhcModLog) -> m a) -> m a) -> FilePath -> Options -> ((GhcModEnv, GhcModLog) -> m a) -> m a withGhcModEnv' withCradle dir opts f =-    withCradle dir $ \crdl ->+    withCradle dir $ \(crdl,lg) ->       withCradleRootDir crdl $-        f $ GhcModEnv opts crdl+        f (GhcModEnv opts crdl, lg)  where+   swapCurrentDirectory ndir = do+     odir <- canonicalizePath =<< getCurrentDirectory+     setCurrentDirectory ndir+     return odir+    withCradleRootDir (cradleRootDir -> projdir) a = do-       cdir <- liftIO $ getCurrentDirectory-       eq <- liftIO $ pathsEqual projdir cdir-       if not eq-          then throw $ GMEWrongWorkingDirectory projdir cdir-          else a+       success <- liftIO $ tryPutMVar cwdLock =<< myThreadId+       if not success+         then error "withGhcModEnv': using ghc-mod from multiple threads is not supported!"+         else gbracket setup teardown (const a)+    where+      setup = liftIO $ swapCurrentDirectory projdir -   pathsEqual a b = do-     ca <- canonicalizePath a-     cb <- canonicalizePath b-     return $ ca == cb+      teardown odir = liftIO $ do+        setCurrentDirectory odir+        void $ takeMVar cwdLock  runGmOutT :: IOish m => Options -> GmOutT m a -> m a runGmOutT opts ma = do@@ -91,15 +101,17 @@ runGmOutT' gmo ma = flip runReaderT gmo $ unGmOutT ma  -- | Run a @GhcModT m@ computation.-runGhcModT :: (IOish m, GmOut m)+runGhcModT :: IOish m            => Options            -> GhcModT m a            -> m (Either GhcModError a, GhcModLog) runGhcModT opt action = liftIO (getCurrentDirectory >>= canonicalizePath) >>= \dir' -> do     runGmOutT opt $-      withGhcModEnv dir' opt $ \env ->-        first (fst <$>) <$> runGhcModT' env defaultGhcModState-          (gmSetLogLevel (ooptLogLevel $ optOutput opt) >> action)+      withGhcModEnv dir' opt $ \(env,lg) ->+        first (fst <$>) <$> runGhcModT' env defaultGhcModState (do+          gmSetLogLevel (ooptLogLevel $ optOutput opt)+          gmAppendLogQuiet lg+          action)  -- | @hoistGhcModT result@. Embed a GhcModT computation's result into a GhcModT -- computation. Note that if the computation that returned @result@ modified the
+ Language/Haskell/GhcMod/Monad/Compat.hs_h view
@@ -0,0 +1,28 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015,2016  Daniel Gröber <dxld ÄT darkboxed DOT org>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.++-- MonadUtils of GHC 7.6 or earlier defines its own MonadIO.+-- RWST does not automatically become an instance of MonadIO.+-- MonadUtils of GHC 7.8 or later imports MonadIO in Monad.Control.IO.Class.+-- So, RWST automatically becomes an instance of+#if __GLASGOW_HASKELL__ < 708+-- 'CoreMonad.MonadIO' and 'Control.Monad.IO.Class.MonadIO' are different+-- classes before ghc 7.8+#define DIFFERENT_MONADIO 1++-- RWST doen't have a MonadIO instance before ghc 7.8+#define MONADIO_INSTANCES 1+#endif
+ Language/Haskell/GhcMod/Monad/Env.hs view
@@ -0,0 +1,68 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015,2016  Daniel Gröber <dxld ÄT darkboxed DOT org>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.++{-# LANGUAGE GeneralizedNewtypeDeriving, StandaloneDeriving #-}+{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}++module Language.Haskell.GhcMod.Monad.Env where++import Language.Haskell.GhcMod.Types+import Language.Haskell.GhcMod.Monad.Newtypes++import Control.Monad+import Control.Monad.Trans.Journal (JournalT)+import Control.Monad.State.Strict (StateT(..))+import Control.Monad.Error (ErrorT(..))+import Control.Monad.Reader.Class+import Control.Monad.Trans.Class (MonadTrans(..))+import Prelude++class Monad m => GmEnv m where+    gmeAsk :: m GhcModEnv+    gmeAsk = gmeReader id++    gmeReader :: (GhcModEnv -> a) -> m a+    gmeReader f = f `liftM` gmeAsk++    gmeLocal :: (GhcModEnv -> GhcModEnv) -> m a -> m a+    {-# MINIMAL (gmeAsk | gmeReader), gmeLocal #-}++instance Monad m => GmEnv (GmT m) where+    gmeAsk = GmT ask+    gmeReader = GmT . reader+    gmeLocal f a = GmT $ local f (unGmT a)++instance GmEnv m => GmEnv (GmOutT m) where+    gmeAsk = lift gmeAsk+    gmeReader = lift . gmeReader+    gmeLocal f ma = gmLiftWithInner (\run -> gmeLocal f (run ma))++instance GmEnv m => GmEnv (StateT s m) where+    gmeAsk = lift gmeAsk+    gmeReader = lift . gmeReader+    gmeLocal f ma = gmLiftWithInner (\run -> gmeLocal f (run ma))++instance GmEnv m => GmEnv (JournalT GhcModLog m) where+    gmeAsk = lift gmeAsk+    gmeReader = lift . gmeReader+    gmeLocal f ma = gmLiftWithInner (\run -> gmeLocal f (run ma))++instance GmEnv m => GmEnv (ErrorT GhcModError m) where+    gmeAsk = lift gmeAsk+    gmeReader = lift . gmeReader+    gmeLocal f ma = gmLiftWithInner (\run -> gmeLocal f (run ma))++deriving instance (Monad m, GmEnv (GhcModT m)) => GmEnv (GmlT m)
+ Language/Haskell/GhcMod/Monad/Log.hs view
@@ -0,0 +1,71 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015,2016  Daniel Gröber <dxld ÄT darkboxed DOT org>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.++{-# LANGUAGE GeneralizedNewtypeDeriving, StandaloneDeriving #-}+{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}++module Language.Haskell.GhcMod.Monad.Log where++import Language.Haskell.GhcMod.Types+import Language.Haskell.GhcMod.Monad.Newtypes++import Control.Monad+import Control.Monad.Trans.Journal (JournalT)+import Control.Monad.Reader (ReaderT(..))+import Control.Monad.State.Strict (StateT(..))+import Control.Monad.Error (Error, ErrorT(..))+import Control.Monad.Trans.Maybe (MaybeT(..))+import Control.Monad.Journal.Class (MonadJournal(..))+import Control.Monad.Trans.Class (MonadTrans(..))+import Prelude++class Monad m => GmLog m where+    gmlJournal :: GhcModLog -> m ()+    gmlHistory :: m GhcModLog+    gmlClear   :: m ()++instance Monad m => GmLog (JournalT GhcModLog m) where+    gmlJournal = journal+    gmlHistory = history+    gmlClear   = clear++instance Monad m => GmLog (GmT m) where+    gmlJournal = GmT . lift . lift . journal+    gmlHistory = GmT $ lift $ lift history+    gmlClear   = GmT $ lift $ lift clear++instance (Monad m, GmLog m) => GmLog (ReaderT r m) where+    gmlJournal = lift . gmlJournal+    gmlHistory = lift gmlHistory+    gmlClear = lift  gmlClear++instance (Monad m, GmLog m) => GmLog (StateT s m) where+    gmlJournal = lift . gmlJournal+    gmlHistory = lift gmlHistory+    gmlClear = lift gmlClear++instance (Monad m, GmLog m, Error e) => GmLog (ErrorT e m) where+    gmlJournal = lift . gmlJournal+    gmlHistory = lift gmlHistory+    gmlClear = lift gmlClear++instance (Monad m, GmLog m) => GmLog (MaybeT m) where+    gmlJournal = lift . gmlJournal+    gmlHistory = lift gmlHistory+    gmlClear = lift gmlClear++deriving instance GmLog m => GmLog (GmOutT m)+deriving instance (Monad m, GmLog (GhcModT m)) => GmLog (GmlT m)
+ Language/Haskell/GhcMod/Monad/Newtypes.hs view
@@ -0,0 +1,176 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015,2016  Daniel Gröber <dxld ÄT darkboxed DOT org>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.++{-# LANGUAGE CPP, GeneralizedNewtypeDeriving, DeriveFunctor #-}+{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, UndecidableInstances #-}+{-# LANGUAGE RankNTypes, FlexibleInstances #-}++module Language.Haskell.GhcMod.Monad.Newtypes where++#include "Compat.hs_h"++import Language.Haskell.GhcMod.Types++import GHC++import Control.Applicative+import Control.Monad++import Control.Monad.Reader (ReaderT(..))+import Control.Monad.Error (ErrorT(..), MonadError(..))+import Control.Monad.State.Strict (StateT(..))+import Control.Monad.Trans.Journal (JournalT)+import Control.Monad.Reader.Class+import Control.Monad.State.Class (MonadState(..))+import Control.Monad.Journal.Class (MonadJournal(..))+import Control.Monad.Trans.Class (MonadTrans(..))+import Control.Monad.Trans.Control+import Control.Monad.Base (MonadBase(..), liftBase)++import Data.IORef+import Prelude++type GhcModT m = GmT (GmOutT m)++newtype GmOutT m a = GmOutT {+      unGmOutT :: ReaderT GhcModOut m a+    } deriving ( Functor+             , Applicative+             , Alternative+             , Monad+             , MonadPlus+             , MonadTrans+             )++newtype GmT m a = GmT {+      unGmT :: StateT GhcModState+                 (ErrorT GhcModError+                   (JournalT GhcModLog+                     (ReaderT GhcModEnv m) ) ) a+    } deriving ( Functor+               , Applicative+               , Alternative+               , Monad+               , MonadPlus+               , MonadError GhcModError+               )++newtype GmlT m a = GmlT { unGmlT :: GhcModT m a }+    deriving ( Functor+             , Applicative+             , Alternative+             , Monad+             , MonadPlus+             , MonadError GhcModError+             )++newtype LightGhc a = LightGhc { unLightGhc :: ReaderT (IORef HscEnv) IO a }+    deriving ( Functor+             , Applicative+             , Monad+             )++-- GmOutT ----------------------------------------+instance (MonadBaseControl IO m) => MonadBase IO (GmOutT m) where+    liftBase = GmOutT . liftBase++instance (MonadBaseControl IO m) => MonadBaseControl IO (GmOutT m) where+    type StM (GmOutT m) a = StM (ReaderT GhcModEnv m) a+    liftBaseWith = defaultLiftBaseWith+    restoreM = defaultRestoreM+    {-# INLINE liftBaseWith #-}+    {-# INLINE restoreM #-}++instance MonadTransControl GmOutT where+    type StT GmOutT a = StT (ReaderT GhcModEnv) a+    liftWith = defaultLiftWith GmOutT unGmOutT+    restoreT = defaultRestoreT GmOutT+++-- GmlT ------------------------------------------+instance (MonadBaseControl IO m) => MonadBase IO (GmlT m) where+    liftBase = GmlT . liftBase++instance (MonadBaseControl IO m) => MonadBaseControl IO (GmlT m) where+    type StM (GmlT m) a = StM (GmT m) a+    liftBaseWith = defaultLiftBaseWith+    restoreM = defaultRestoreM+    {-# INLINE liftBaseWith #-}+    {-# INLINE restoreM #-}++instance MonadTransControl GmlT where+    type StT GmlT a = StT GmT a+    liftWith f = GmlT $+      liftWith $ \runGm ->+        liftWith $ \runEnv ->+          f $ \ma -> runEnv $ runGm $ unGmlT ma+    restoreT = GmlT . restoreT . restoreT++instance MonadTrans GmlT where+    lift = GmlT . lift . lift++-- GmT ------------------------------------------++instance forall r m. MonadReader r m => MonadReader r (GmT m) where+    local f ma = gmLiftWithInner (\run -> local f (run ma))+    ask = gmLiftInner ask++instance MonadState s m => MonadState s (GmT m) where+    get = GmT $ lift $ lift $ lift get+    put = GmT . lift . lift . lift . put+    state = GmT . lift . lift . lift . state++instance Monad m => MonadJournal GhcModLog (GmT m) where+  journal  w = GmT $ lift $ lift $ (journal w)+  history    = GmT $ lift $ lift $ history+  clear      = GmT $ lift $ lift $ clear++instance (MonadBaseControl IO m) => MonadBase IO (GmT m) where+    liftBase = GmT . liftBase++instance (MonadBaseControl IO m) => MonadBaseControl IO (GmT m) where+    type StM (GmT m) a =+          StM (StateT GhcModState+                (ErrorT GhcModError+                  (JournalT GhcModLog+                    (ReaderT GhcModEnv m) ) ) ) a+    liftBaseWith f = GmT (liftBaseWith $ \runInBase ->+        f $ runInBase . unGmT)+    restoreM = GmT . restoreM+    {-# INLINE liftBaseWith #-}+    {-# INLINE restoreM #-}++instance MonadTransControl GmT where+    type StT GmT a = (Either GhcModError (a, GhcModState), GhcModLog)+    liftWith f = GmT $+      liftWith $ \runS ->+        liftWith $ \runE ->+          liftWith $ \runJ ->+            liftWith $ \runR ->+              f $ \ma -> runR $ runJ $ runE $ runS $ unGmT ma+    restoreT = GmT . restoreT . restoreT . restoreT . restoreT+    {-# INLINE liftWith #-}+    {-# INLINE restoreT #-}++instance MonadTrans GmT where+    lift = GmT . lift . lift . lift . lift++gmLiftInner :: Monad m => m a -> GmT m a+gmLiftInner = GmT . lift . lift . lift . lift++gmLiftWithInner :: (MonadTransControl t, Monad m, Monad (t m))+                => (Run t -> m (StT t a)) -> t m a+gmLiftWithInner f = liftWith f >>= restoreT . return
+ Language/Haskell/GhcMod/Monad/Orphans.hs view
@@ -0,0 +1,83 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015,2016  Daniel Gröber <dxld ÄT darkboxed DOT org>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.++{-# LANGUAGE CPP, UndecidableInstances, StandaloneDeriving #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}+module Language.Haskell.GhcMod.Monad.Orphans where++#include "Compat.hs_h"++import Language.Haskell.GhcMod.Types+import Language.Haskell.GhcMod.Monad.Newtypes++#if DIFFERENT_MONADIO+import qualified MonadUtils as GHC (MonadIO(..))+#endif+import qualified Control.Monad.IO.Class as MTL++import Control.Monad.Reader (ReaderT(..))+import Control.Monad.State.Strict (StateT(..))+import Control.Monad.Trans.Journal (JournalT)+import Control.Monad.Trans.Maybe (MaybeT(..))+import Control.Monad.Error (Error(..), ErrorT(..))++--------------------------------------------------+-- Miscellaneous instances++#if DIFFERENT_MONADIO+instance MTL.MonadIO m => GHC.MonadIO (ReaderT x m) where+    liftIO = MTL.liftIO+instance MTL.MonadIO m => GHC.MonadIO (StateT x m) where+    liftIO = MTL.liftIO+instance (Error e, MTL.MonadIO m) => GHC.MonadIO (ErrorT e m) where+    liftIO = MTL.liftIO+instance MTL.MonadIO m => GHC.MonadIO (JournalT x m) where+    liftIO = MTL.liftIO+instance MTL.MonadIO m => GHC.MonadIO (MaybeT m) where+    liftIO = MTL.liftIO+deriving instance MTL.MonadIO m => GHC.MonadIO (GmOutT m)+deriving instance MTL.MonadIO m => GHC.MonadIO (GmT m)+deriving instance MTL.MonadIO m => GHC.MonadIO (GmlT m)+deriving instance GHC.MonadIO LightGhc+#endif++deriving instance MTL.MonadIO m => MTL.MonadIO (GmOutT m)+deriving instance MTL.MonadIO m => MTL.MonadIO (GmT m)+deriving instance MTL.MonadIO m => MTL.MonadIO (GmlT m)+deriving instance MTL.MonadIO LightGhc++instance MonadIO IO where+    liftIO = id+instance MonadIO m => MonadIO (ReaderT x m) where+    liftIO = MTL.liftIO+instance MonadIO m => MonadIO (StateT x m) where+    liftIO = MTL.liftIO+instance (Error e, MonadIO m) => MonadIO (ErrorT e m) where+    liftIO = MTL.liftIO+instance MonadIO m => MonadIO (JournalT x m) where+    liftIO = MTL.liftIO+instance MonadIO m => MonadIO (MaybeT m) where+    liftIO = MTL.liftIO+instance MonadIOC m => MonadIO (GmOutT m) where+    liftIO = MTL.liftIO+instance MonadIOC m => MonadIO (GmT m) where+    liftIO = MTL.liftIO+instance MonadIOC m => MonadIO (GmlT m) where+    liftIO = MTL.liftIO+instance MonadIO LightGhc where+    liftIO = MTL.liftIO
+ Language/Haskell/GhcMod/Monad/Out.hs view
@@ -0,0 +1,52 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015,2016  Daniel Gröber <dxld ÄT darkboxed DOT org>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.++{-# LANGUAGE GeneralizedNewtypeDeriving, StandaloneDeriving #-}+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-}++module Language.Haskell.GhcMod.Monad.Out where++import Language.Haskell.GhcMod.Types+import Language.Haskell.GhcMod.Monad.Newtypes++import Control.Monad+import Control.Monad.State.Strict (StateT(..))+import Control.Monad.Trans.Journal (JournalT)+import Control.Monad.Trans.Maybe (MaybeT(..))+import Control.Monad.Reader.Class+import Control.Monad.Trans.Class (MonadTrans(..))+import Prelude++class Monad m => GmOut m where+    gmoAsk :: m GhcModOut++instance Monad m => GmOut (GmOutT m) where+    gmoAsk = GmOutT ask++instance Monad m => GmOut (GmlT m) where+    gmoAsk = GmlT $ lift $ GmOutT ask++instance GmOut m => GmOut (GmT m) where+    gmoAsk = lift gmoAsk++instance GmOut m => GmOut (StateT s m) where+    gmoAsk = lift gmoAsk++instance GmOut m => GmOut (JournalT w m) where+    gmoAsk = lift gmoAsk++instance GmOut m => GmOut (MaybeT m) where+    gmoAsk = lift gmoAsk
+ Language/Haskell/GhcMod/Monad/State.hs view
@@ -0,0 +1,67 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015,2016  Daniel Gröber <dxld ÄT darkboxed DOT org>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.++{-# LANGUAGE GeneralizedNewtypeDeriving, StandaloneDeriving #-}+{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}++module Language.Haskell.GhcMod.Monad.State where++import Language.Haskell.GhcMod.Types+import Language.Haskell.GhcMod.Monad.Newtypes++import Control.Monad+import Control.Monad.State.Strict (StateT(..))+import Control.Monad.Trans.Maybe (MaybeT(..))+import Control.Monad.State.Class (MonadState(..))+import Control.Monad.Trans.Class (MonadTrans(..))+import Prelude++class Monad m => GmState m where+    gmsGet :: m GhcModState+    gmsGet = gmsState (\s -> (s, s))++    gmsPut :: GhcModState -> m ()+    gmsPut s = gmsState (\_ -> ((), s))++    gmsState :: (GhcModState -> (a, GhcModState)) -> m a+    gmsState f = do+      s <- gmsGet+      let ~(a, s') = f s+      gmsPut s'+      return a+    {-# MINIMAL gmsState | gmsGet, gmsPut #-}++instance GmState m => GmState (StateT s m) where+    gmsGet = lift gmsGet+    gmsPut = lift . gmsPut+    gmsState = lift . gmsState++instance Monad m => GmState (StateT GhcModState m) where+    gmsGet = get+    gmsPut = put+    gmsState = state++instance Monad m => GmState (GmT m) where+    gmsGet = GmT get+    gmsPut = GmT . put+    gmsState = GmT . state++instance GmState m => GmState (MaybeT m) where+    gmsGet = MaybeT $ Just `liftM` gmsGet+    gmsPut = MaybeT . (Just `liftM`) . gmsPut+    gmsState = MaybeT . (Just `liftM`) . gmsState++deriving instance (Monad m, GmState (GhcModT m)) => GmState (GmlT m)
Language/Haskell/GhcMod/Monad/Types.hs view
@@ -36,7 +36,6 @@   , defaultGhcModState   , GmGhcSession(..)   , GmComponent(..)-  , CompilerMode(..)   -- * Accessing 'GhcModEnv', 'GhcModState' and 'GhcModLog'   , GmLogLevel(..)   , GhcModLog(..)@@ -50,8 +49,6 @@   , options   , outputOpts   , withOptions-  , getCompilerMode-  , setCompilerMode   , getMMappedFiles   , setMMappedFiles   , addMMappedFile@@ -65,21 +62,19 @@   , gmlSetSession   ) where --- MonadUtils of GHC 7.6 or earlier defines its own MonadIO.--- RWST does not automatically become an instance of MonadIO.--- MonadUtils of GHC 7.8 or later imports MonadIO in Monad.Control.IO.Class.--- So, RWST automatically becomes an instance of-#if __GLASGOW_HASKELL__ < 708--- 'CoreMonad.MonadIO' and 'Control.Monad.IO.Class.MonadIO' are different--- classes before ghc 7.8-#define DIFFERENT_MONADIO 1---- RWST doen't have a MonadIO instance before ghc 7.8-#define MONADIO_INSTANCES 1-#endif+#include "Compat.hs_h"  import Language.Haskell.GhcMod.Types +import Language.Haskell.GhcMod.Monad.Env+import Language.Haskell.GhcMod.Monad.State+import Language.Haskell.GhcMod.Monad.Log+import Language.Haskell.GhcMod.Monad.Out+import Language.Haskell.GhcMod.Monad.Newtypes+import Language.Haskell.GhcMod.Monad.Orphans ()++import Safe+ import GHC import DynFlags import Exception@@ -89,355 +84,23 @@ import Control.Monad  import Control.Monad.Reader (ReaderT(..))-import Control.Monad.Error (ErrorT(..), MonadError(..)) import Control.Monad.State.Strict (StateT(..)) import Control.Monad.Trans.Journal (JournalT)-import Control.Monad.Trans.Maybe (MaybeT(..))+import Control.Monad.Trans.Maybe (MaybeT) -import Control.Monad.Base (MonadBase(..), liftBase) import Control.Monad.Trans.Control  import Control.Monad.Reader.Class-import Control.Monad.Writer.Class-import Control.Monad.State.Class (MonadState(..))-import Control.Monad.Journal.Class (MonadJournal(..))-import Control.Monad.Trans.Class (MonadTrans(..))-import Control.Monad.Error (Error(..))-import qualified Control.Monad.IO.Class as MTL -#if DIFFERENT_MONADIO-import Data.Monoid (Monoid)-#endif- import qualified Data.Map as M import Data.Maybe import Data.Monoid import Data.IORef import Prelude -import qualified MonadUtils as GHC (MonadIO(..))--type GhcModT m = GmT (GmOutT m)--newtype GmOutT m a = GmOutT {-      unGmOutT :: ReaderT GhcModOut m a-    } deriving ( Functor-             , Applicative-             , Alternative-             , Monad-             , MonadPlus-             , MonadTrans-             , MTL.MonadIO-#if DIFFERENT_MONADIO-             , GHC.MonadIO-#endif-             , GmLog-             )--newtype GmT m a = GmT {-      unGmT :: StateT GhcModState-                 (ErrorT GhcModError-                   (JournalT GhcModLog-                     (ReaderT GhcModEnv m) ) ) a-    } deriving ( Functor-               , Applicative-               , Alternative-               , Monad-               , MonadPlus-               , MTL.MonadIO-#if DIFFERENT_MONADIO-               , GHC.MonadIO-#endif-               , MonadError GhcModError-               )--newtype GmlT m a = GmlT { unGmlT :: GhcModT m a }-    deriving ( Functor-             , Applicative-             , Alternative-             , Monad-             , MonadPlus-             , MTL.MonadIO-#if DIFFERENT_MONADIO-             , GHC.MonadIO-#endif-             , MonadError GhcModError-             , GmEnv-             , GmState-             , GmLog-             )--newtype LightGhc a = LightGhc { unLightGhc :: ReaderT (IORef HscEnv) IO a }-    deriving ( Functor-             , Applicative-             , Monad-             , MTL.MonadIO-#if DIFFERENT_MONADIO-             , GHC.MonadIO-#endif-             )------------------------------------------------------- Miscellaneous instances--#if DIFFERENT_MONADIO-instance MTL.MonadIO m => GHC.MonadIO (ReaderT x m) where-    liftIO = MTL.liftIO-instance MTL.MonadIO m => GHC.MonadIO (StateT x m) where-    liftIO = MTL.liftIO-instance (Error e, MTL.MonadIO m) => GHC.MonadIO (ErrorT e m) where-    liftIO = MTL.liftIO-instance MTL.MonadIO m => GHC.MonadIO (JournalT x m) where-    liftIO = MTL.liftIO-instance MTL.MonadIO m => GHC.MonadIO (MaybeT m) where-    liftIO = MTL.liftIO-#endif--instance MonadIO IO where-    liftIO = id-instance MonadIO m => MonadIO (ReaderT x m) where-    liftIO = MTL.liftIO-instance MonadIO m => MonadIO (StateT x m) where-    liftIO = MTL.liftIO-instance (Error e, MonadIO m) => MonadIO (ErrorT e m) where-    liftIO = MTL.liftIO-instance MonadIO m => MonadIO (JournalT x m) where-    liftIO = MTL.liftIO-instance MonadIO m => MonadIO (MaybeT m) where-    liftIO = MTL.liftIO-instance MonadIOC m => MonadIO (GmOutT m) where-    liftIO = MTL.liftIO-instance MonadIOC m => MonadIO (GmT m) where-    liftIO = MTL.liftIO-instance MonadIOC m => MonadIO (GmlT m) where-    liftIO = MTL.liftIO-instance MonadIO LightGhc where-    liftIO = MTL.liftIO--instance MonadTrans GmT where-    lift = GmT . lift . lift . lift . lift-instance MonadTrans GmlT where-    lift = GmlT . lift . lift------------------------------------------------------- Gm Classes- type Gm m = (GmEnv m, GmState m, GmLog m, GmOut m) --- GmEnv ------------------------------------------class Monad m => GmEnv m where-    gmeAsk :: m GhcModEnv-    gmeAsk = gmeReader id--    gmeReader :: (GhcModEnv -> a) -> m a-    gmeReader f = f `liftM` gmeAsk--    gmeLocal :: (GhcModEnv -> GhcModEnv) -> m a -> m a-    {-# MINIMAL (gmeAsk | gmeReader), gmeLocal #-}--instance Monad m => GmEnv (GmT m) where-    gmeAsk = GmT ask-    gmeReader = GmT . reader-    gmeLocal f a = GmT $ local f (unGmT a)--instance GmEnv m => GmEnv (GmOutT m) where-    gmeAsk = lift gmeAsk-    gmeReader = lift . gmeReader-    gmeLocal f ma = gmLiftWithInner (\run -> gmeLocal f (run ma))--instance GmEnv m => GmEnv (StateT s m) where-    gmeAsk = lift gmeAsk-    gmeReader = lift . gmeReader-    gmeLocal f ma = gmLiftWithInner (\run -> gmeLocal f (run ma))--instance GmEnv m => GmEnv (JournalT GhcModLog m) where-    gmeAsk = lift gmeAsk-    gmeReader = lift . gmeReader-    gmeLocal f ma = gmLiftWithInner (\run -> gmeLocal f (run ma))--instance GmEnv m => GmEnv (ErrorT GhcModError m) where-    gmeAsk = lift gmeAsk-    gmeReader = lift . gmeReader-    gmeLocal f ma = gmLiftWithInner (\run -> gmeLocal f (run ma))---- GmState ----------------------------------------class Monad m => GmState m where-    gmsGet :: m GhcModState-    gmsGet = gmsState (\s -> (s, s))--    gmsPut :: GhcModState -> m ()-    gmsPut s = gmsState (\_ -> ((), s))--    gmsState :: (GhcModState -> (a, GhcModState)) -> m a-    gmsState f = do-      s <- gmsGet-      let ~(a, s') = f s-      gmsPut s'-      return a-    {-# MINIMAL gmsState | gmsGet, gmsPut #-}--instance GmState m => GmState (StateT s m) where-    gmsGet = lift gmsGet-    gmsPut = lift . gmsPut-    gmsState = lift . gmsState--instance Monad m => GmState (StateT GhcModState m) where-    gmsGet = get-    gmsPut = put-    gmsState = state--instance Monad m => GmState (GmT m) where-    gmsGet = GmT get-    gmsPut = GmT . put-    gmsState = GmT . state--instance GmState m => GmState (MaybeT m) where-    gmsGet = MaybeT $ Just `liftM` gmsGet-    gmsPut = MaybeT . (Just `liftM`) . gmsPut-    gmsState = MaybeT . (Just `liftM`) . gmsState---- GmLog ------------------------------------------class Monad m => GmLog m where-    gmlJournal :: GhcModLog -> m ()-    gmlHistory :: m GhcModLog-    gmlClear   :: m ()--instance Monad m => GmLog (JournalT GhcModLog m) where-    gmlJournal = journal-    gmlHistory = history-    gmlClear   = clear--instance Monad m => GmLog (GmT m) where-    gmlJournal = GmT . lift . lift . journal-    gmlHistory = GmT $ lift $ lift history-    gmlClear   = GmT $ lift $ lift clear--instance (Monad m, GmLog m) => GmLog (ReaderT r m) where-    gmlJournal = lift . gmlJournal-    gmlHistory = lift gmlHistory-    gmlClear = lift  gmlClear--instance (Monad m, GmLog m) => GmLog (StateT s m) where-    gmlJournal = lift . gmlJournal-    gmlHistory = lift gmlHistory-    gmlClear = lift gmlClear---- GmOut ------------------------------------------class Monad m => GmOut m where-    gmoAsk :: m GhcModOut--instance Monad m => GmOut (GmOutT m) where-    gmoAsk = GmOutT ask--instance Monad m => GmOut (GmlT m) where-    gmoAsk = GmlT $ lift $ GmOutT ask--instance GmOut m => GmOut (GmT m) where-    gmoAsk = lift gmoAsk--instance GmOut m => GmOut (StateT s m) where-    gmoAsk = lift gmoAsk--instance Monad m => MonadJournal GhcModLog (GmT m) where-  journal !w = GmT $ lift $ lift $ (journal w)-  history    = GmT $ lift $ lift $ history-  clear      = GmT $ lift $ lift $ clear--instance forall r m. MonadReader r m => MonadReader r (GmT m) where-    local f ma = gmLiftWithInner (\run -> local f (run ma))-    ask = gmLiftInner ask--instance (Monoid w, MonadWriter w m) => MonadWriter w (GmT m) where-    tell = gmLiftInner . tell-    listen ma =-      liftWith (\run -> listen (run ma)) >>= \(sta, w) ->-          flip (,) w `liftM` restoreT (return sta)--    pass maww = maww >>= gmLiftInner . pass . return--instance MonadState s m => MonadState s (GmT m) where-    get = GmT $ lift $ lift $ lift get-    put = GmT . lift . lift . lift . put-    state = GmT . lift . lift . lift . state-- ----------------------------------------------------- monad-control instances---- GmOutT -----------------------------------------instance (MonadBaseControl IO m) => MonadBase IO (GmOutT m) where-    liftBase = GmOutT . liftBase--instance (MonadBaseControl IO m) => MonadBaseControl IO (GmOutT m) where-    type StM (GmOutT m) a = StM (ReaderT GhcModEnv m) a-    liftBaseWith = defaultLiftBaseWith-    restoreM = defaultRestoreM-    {-# INLINE liftBaseWith #-}-    {-# INLINE restoreM #-}--instance MonadTransControl GmOutT where-    type StT GmOutT a = StT (ReaderT GhcModEnv) a-    liftWith = defaultLiftWith GmOutT unGmOutT-    restoreT = defaultRestoreT GmOutT----- GmlT -------------------------------------------instance (MonadBaseControl IO m) => MonadBase IO (GmlT m) where-    liftBase = GmlT . liftBase--instance (MonadBaseControl IO m) => MonadBaseControl IO (GmlT m) where-    type StM (GmlT m) a = StM (GmT m) a-    liftBaseWith = defaultLiftBaseWith-    restoreM = defaultRestoreM-    {-# INLINE liftBaseWith #-}-    {-# INLINE restoreM #-}--instance MonadTransControl GmlT where-    type StT GmlT a = StT GmT a-    liftWith f = GmlT $-      liftWith $ \runGm ->-        liftWith $ \runEnv ->-          f $ \ma -> runEnv $ runGm $ unGmlT ma-    restoreT = GmlT . restoreT . restoreT----- GmT --------------------------------------------instance (MonadBaseControl IO m) => MonadBase IO (GmT m) where-    liftBase = GmT . liftBase--instance (MonadBaseControl IO m) => MonadBaseControl IO (GmT m) where-    type StM (GmT m) a =-          StM (StateT GhcModState-                (ErrorT GhcModError-                  (JournalT GhcModLog-                    (ReaderT GhcModEnv m) ) ) ) a-    liftBaseWith f = GmT (liftBaseWith $ \runInBase ->-        f $ runInBase . unGmT)-    restoreM = GmT . restoreM-    {-# INLINE liftBaseWith #-}-    {-# INLINE restoreM #-}--instance MonadTransControl GmT where-    type StT GmT a = (Either GhcModError (a, GhcModState), GhcModLog)-    liftWith f = GmT $-      liftWith $ \runS ->-        liftWith $ \runE ->-          liftWith $ \runJ ->-            liftWith $ \runR ->-              f $ \ma -> runR $ runJ $ runE $ runS $ unGmT ma-    restoreT = GmT . restoreT . restoreT . restoreT . restoreT-    {-# INLINE liftWith #-}-    {-# INLINE restoreT #-}--gmLiftInner :: Monad m => m a -> GmT m a-gmLiftInner = GmT . lift . lift . lift . lift--gmLiftWithInner :: (MonadTransControl t, Monad m, Monad (t m))-                => (Run t -> m (StT t a)) -> t m a-gmLiftWithInner f = liftWith f >>= restoreT . return---------------------------------------------------- -- GHC API instances -----------------------------  -- GHC cannot prove the following instances to be decidable automatically using@@ -452,19 +115,21 @@     getSession = gmlGetSession     setSession = gmlSetSession +-- | Get the underlying GHC session gmlGetSession :: (MonadIO m, MonadBaseControl IO m) => GmlT m HscEnv gmlGetSession = do-        ref <- gmgsSession . fromJust . gmGhcSession <$> gmsGet-        GHC.liftIO $ readIORef ref+        ref <- gmgsSession . fromJustNote "gmlGetSession" . gmGhcSession <$> gmsGet+        liftIO $ readIORef ref +-- | Set the underlying GHC session gmlSetSession :: (MonadIO m, MonadBaseControl IO m) => HscEnv -> GmlT m () gmlSetSession a = do-        ref <- gmgsSession . fromJust . gmGhcSession <$> gmsGet-        GHC.liftIO $ flip writeIORef a ref+        ref <- gmgsSession . fromJustNote "gmlSetSession" . gmGhcSession <$> gmsGet+        liftIO $ flip writeIORef a ref  instance GhcMonad LightGhc where-    getSession = (GHC.liftIO . readIORef) =<< LightGhc ask-    setSession a = (GHC.liftIO . flip writeIORef a) =<< LightGhc ask+    getSession = (liftIO . readIORef) =<< LightGhc ask+    setSession a = (liftIO . flip writeIORef a) =<< LightGhc ask  #if __GLASGOW_HASKELL__ >= 706 instance (MonadIO m, MonadBaseControl IO m) => HasDynFlags (GmlT m) where@@ -519,6 +184,21 @@     gmask = liftBaseOp gmask . liftRestore      where liftRestore f r = f $ liftBaseOp_ r +instance (Monoid w, MonadIO m, MonadBaseControl IO m) => ExceptionMonad (JournalT w m) where+    gcatch act handler = control $ \run ->+        run act `gcatch` (run . handler)++    gmask = liftBaseOp gmask . liftRestore+     where liftRestore f r = f $ liftBaseOp_ r++instance (MonadIO m, MonadBaseControl IO m) => ExceptionMonad (MaybeT m) where+    gcatch act handler = control $ \run ->+        run act `gcatch` (run . handler)++    gmask = liftBaseOp gmask . liftRestore+     where liftRestore f r = f $ liftBaseOp_ r++ ----------------------------------------------------------------  options :: GmEnv m => m Options@@ -529,12 +209,6 @@  cradle :: GmEnv m => m Cradle cradle = gmCradle `liftM` gmeAsk--getCompilerMode :: GmState m => m CompilerMode-getCompilerMode = gmCompilerMode `liftM` gmsGet--setCompilerMode :: GmState m => CompilerMode -> m ()-setCompilerMode mode = (\s -> gmsPut s { gmCompilerMode = mode } ) =<< gmsGet  getMMappedFiles :: GmState m => m FileMappingMap getMMappedFiles = gmMMappedFiles `liftM` gmsGet
Language/Haskell/GhcMod/Output.hs view
@@ -17,6 +17,7 @@ -- Derived from process:System.Process -- Copyright (c) The University of Glasgow 2004-2008 +{-# LANGUAGE FlexibleInstances #-} module Language.Haskell.GhcMod.Output (     gmPutStr   , gmErrStr@@ -27,12 +28,15 @@   , gmErrStrIO    , gmReadProcess+  , gmReadProcess'    , stdoutGateway   , flushStdoutGateway   ) where  import Data.List+import Data.ByteString.Lazy (ByteString)+import qualified Data.ByteString.Lazy as BS import qualified Data.Label as L import qualified Data.Label.Base as LB import System.IO@@ -51,7 +55,17 @@  import Language.Haskell.GhcMod.Types hiding (LineSeparator, MonadIO(..)) import Language.Haskell.GhcMod.Monad.Types hiding (MonadIO(..))+import Language.Haskell.GhcMod.Gap () +class ProcessOutput a where+  hGetContents' :: Handle -> IO a++instance ProcessOutput String where+  hGetContents' = hGetContents++instance ProcessOutput ByteString where+  hGetContents' = BS.hGetContents+ outputFns :: (GmOut m, MonadIO m')           => m (String -> m' (), String -> m' ()) outputFns =@@ -108,6 +122,9 @@     Nothing ->         return $ readProcess +gmReadProcess' :: GmOut m => m (FilePath -> [String] -> String -> IO ByteString)+gmReadProcess' = readProcessStderrChan+ flushStdoutGateway :: Chan (Either (MVar ()) (GmStream, String)) -> IO () flushStdoutGateway c = do   mv <- newEmptyMVar@@ -175,17 +192,14 @@       return (a', L.set l s' f)  readProcessStderrChan ::-    GmOut m => m (FilePath -> [String] -> String -> IO String)+    (GmOut m, ProcessOutput a, NFData a) => m (FilePath -> [String] -> String -> IO a) readProcessStderrChan = do   (_, e :: String -> IO ()) <- outputFns   return $ readProcessStderrChan' e -readProcessStderrChan' ::-    (String -> IO ()) -> FilePath -> [String] -> String -> IO String-readProcessStderrChan' pute = go pute- where-   go :: (String -> IO ()) -> FilePath -> [String] -> String -> IO String-   go putErr exe args input = do+readProcessStderrChan' :: (ProcessOutput a, NFData a) =>+    (String -> IO ()) -> FilePath -> [String] -> String -> IO a+readProcessStderrChan' putErr exe args input = do      let cp = (proc exe args) {                 std_out = CreatePipe               , std_err = CreatePipe@@ -195,7 +209,7 @@       _ <- forkIO $ reader e -     output  <- hGetContents o+     output  <- hGetContents' o      withForkWait (evaluate $ rnf output) $ \waitOut -> do         -- now write any input
Language/Haskell/GhcMod/PathsAndFiles.hs view
@@ -200,7 +200,16 @@  -- localBuildInfoFile defaultDistPref  macrosHeaderPath :: FilePath-macrosHeaderPath = "build/autogen/cabal_macros.h"+macrosHeaderPath = autogenModulesDir </> "cabal_macros.h"++autogenModulePath :: String -> String+autogenModulePath pkg_name =+    autogenModulesDir </> ("Paths_" ++ map fixchar pkg_name) <.> ".hs"+  where fixchar '-' = '_'+        fixchar c   = c++autogenModulesDir :: FilePath+autogenModulesDir = "build" </> "autogen"  ghcSandboxPkgDbDir :: String -> String ghcSandboxPkgDbDir buildPlatf = do
Language/Haskell/GhcMod/Stack.hs view
@@ -16,7 +16,7 @@  module Language.Haskell.GhcMod.Stack where -+import Safe import Control.Applicative import Control.Exception as E import Control.Monad@@ -33,6 +33,8 @@ import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Monad.Types import Language.Haskell.GhcMod.Output+import Language.Haskell.GhcMod.Logging+import Language.Haskell.GhcMod.Error import qualified Language.Haskell.GhcMod.Utils as U import Prelude @@ -46,10 +48,10 @@     } patchStackPrograms _crdl progs = return progs -getStackEnv :: (IOish m, GmOut m) => FilePath -> m (Maybe StackEnv)+getStackEnv :: (IOish m, GmOut m, GmLog m) => FilePath -> m (Maybe StackEnv) getStackEnv projdir = U.withDirectory_ projdir $ runMaybeT $ do     env <- map (liToTup . splitOn ": ") . lines <$> readStack ["path"]-    let look k = fromJust $ lookup k env+    let look k = fromJustNote "getStackEnv" $ lookup k env     return StackEnv {         seDistDir       = look "dist-dir"       , seBinPath       = splitSearchPath $ look "bin-path"@@ -80,11 +82,14 @@           exeExtension = if isWindows then "exe" else "" -readStack :: (IOish m, GmOut m) => [String] -> MaybeT m String+readStack :: (IOish m, GmOut m, GmLog m) => [String] -> MaybeT m String readStack args = do   stack <- MaybeT $ liftIO $ findExecutable "stack"   readProc <- lift gmReadProcess-  lift $ flip gcatch (\(e :: IOError) -> exToErr e) $ do+  flip gcatch handler $ do     liftIO $ evaluate =<< readProc stack args ""  where-   exToErr = throw . GMEStackBootstrap . GMEString . show+   handler (e :: IOError) = do+     gmLog GmWarning "readStack" $ gmeDoc $ exToErr e+     mzero+   exToErr = GMEStackBootstrap . GMEString . show
Language/Haskell/GhcMod/Target.hs view
@@ -40,6 +40,7 @@ import Language.Haskell.GhcMod.CustomPackageDb import Language.Haskell.GhcMod.Output +import Safe import Data.Maybe import Data.Monoid as Monoid import Data.Either@@ -104,10 +105,13 @@      Nothing -> return () -+-- | Run a GmlT action (i.e. a function in the GhcMonad) in the context+-- of certain files or modules runGmlT :: IOish m => [Either FilePath ModuleName] -> GmlT m a -> GhcModT m a runGmlT fns action = runGmlT' fns return action +-- | Run a GmlT action (i.e. a function in the GhcMonad) in the context+-- of certain files or modules, with updated GHC flags runGmlT' :: IOish m               => [Either FilePath ModuleName]               -> (DynFlags -> Ghc DynFlags)@@ -115,6 +119,9 @@               -> GhcModT m a runGmlT' fns mdf action = runGmlTWith fns mdf id action +-- | Run a GmlT action (i.e. a function in the GhcMonad) in the context+-- of certain files or modules, with updated GHC flags and a final+-- transformation runGmlTWith :: IOish m                  => [Either FilePath ModuleName]                  -> (DynFlags -> Ghc DynFlags)@@ -143,7 +150,7 @@                   | otherwise = setEmptyLogger      initSession opts' $-        setModeSimple >>> setLogger >>> mdf+        setHscNothing >>> setLogger >>> mdf      mappedStrs <- getMMappedFilePaths     let targetStrs = mappedStrs ++ map moduleNameString mns ++ cfns@@ -182,13 +189,13 @@             let cns = filter (/= ChSetupHsName) $ Map.keys mcs              gmLog GmDebug "" $ strDoc $ "Could not find a component assignment, falling back to picking library component in cabal file."-            return $ gmcGhcOpts $ fromJust $ Map.lookup (head cns) mcs+            return $ gmcGhcOpts $ fromJustNote "targetGhcOptions, no-assignment" $ Map.lookup (head cns) mcs           else do             when noCandidates $               throwError $ GMECabalCompAssignment mdlcs              let cn = pickComponent candidates-            return $ gmcGhcOpts $ fromJust $ Map.lookup cn mcs+            return $ gmcGhcOpts $ fromJustNote "targetGhcOptions" $ Map.lookup cn mcs  resolvedComponentsCache :: IOish m => FilePath ->     Cached (GhcModT m) GhcModState@@ -199,25 +206,20 @@     cacheFile = resolvedComponentsCacheFile distdir,     cachedAction = \tcfs comps ma -> do         Cradle {..} <- cradle-        let iifsM = invalidatingInputFiles tcfs+        let iifs = invalidatingInputFiles tcfs++            setupChanged =+                (cradleRootDir </> setupConfigPath distdir) `elem` iifs+             mums :: Maybe [Either FilePath ModuleName]             mums =-              case iifsM of-                Nothing -> Nothing-                Just iifs ->-                  let-                      filterOutSetupCfg =-                          filter (/= cradleRootDir </> setupConfigPath distdir)-                      changedFiles = filterOutSetupCfg iifs-                  in if null changedFiles-                       then Nothing-                       else Just $ map Left changedFiles-            setupChanged = maybe False-                                 (elem $ cradleRootDir </> setupConfigPath distdir)-                                 iifsM-        case (setupChanged, ma) of-          (False, Just mcs) -> gmsGet >>= \s -> gmsPut s { gmComponents = mcs }-          _ -> return ()+              let+                  filterOutSetupCfg =+                      filter (/= cradleRootDir </> setupConfigPath distdir)+                  changedFiles = filterOutSetupCfg iifs+              in if null changedFiles || setupChanged+                   then Nothing+                   else Just $ map Left changedFiles          let mdesc (Left f) = "file:" ++ f             mdesc (Right mn) = "module:" ++ moduleNameString mn@@ -229,7 +231,8 @@         gmLog GmDebug "resolvedComponentsCache" $               text "files changed" <+>: changedDoc -        mcs <- resolveGmComponents mums comps+        mcs <- resolveGmComponents ((,) <$> mums <*> ma) comps+         return (setupConfigPath distdir : flatten mcs , mcs)  } @@ -334,7 +337,7 @@       rms <- resolveModule env srcDirs `mapM` eps       return c { gmcEntrypoints = Set.fromList $ catMaybes rms } --- TODO: remember that he file from `main-is:` is always module `Main` and let+-- TODO: remember that the file from `main-is:` is always module `Main` and let -- ghc do the warning about it. Right now we run that module through -- resolveModule like any other resolveChEntrypoints :: FilePath -> ChEntrypoint -> IO [CompilationUnit]@@ -387,27 +390,30 @@    --     | makeRelative dir fn /= fn  type CompilationUnit = Either FilePath ModuleName+type Components =+    [GmComponent 'GMCRaw (Set ModulePath)]+type ResolvedComponentsMap =+    Map ChComponentName (GmComponent 'GMCResolved (Set ModulePath))  resolveGmComponents :: (IOish m, Gm m)-    => Maybe [CompilationUnit]+    => Maybe ([CompilationUnit], ResolvedComponentsMap)         -- ^ Updated modules-    -> [GmComponent 'GMCRaw (Set ModulePath)]-    -> m (Map ChComponentName (GmComponent 'GMCResolved (Set ModulePath)))-resolveGmComponents mumns cs = do-    s <- gmsGet-    m' <- foldrM' (gmComponents s) cs $ \c m -> do+    -> Components -> m ResolvedComponentsMap+resolveGmComponents mcache cs = do+    let rcm = fromMaybe Map.empty $ snd <$> mcache++    m' <- foldrM' rcm cs $ \c m -> do         case Map.lookup (gmcName c) m of           Nothing -> insertUpdated m c           Just c' -> if same gmcRawEntrypoints c c' && same gmcGhcSrcOpts c c'                        then return m                        else insertUpdated m c-    gmsPut s { gmComponents = m' }     return m'   where    foldrM' b fa f = foldrM f b fa    insertUpdated m c = do-     rc <- resolveGmComponent mumns c+     rc <- resolveGmComponent (fst <$> mcache) c      return $ Map.insert (gmcName rc) rc m     same :: Eq b@@ -431,21 +437,25 @@      setTargets targets -    mode <- getCompilerMode-    if mode == Intelligent-      then loadTargets' Intelligent-      else do-        mdls <- depanal [] False-        let fallback = needsFallback mdls-        if fallback then do-            resetTargets targets-            setIntelligent-            gmLog GmInfo "loadTargets" $-                text "Target needs interpeter, switching to LinkInMemory/HscInterpreted. Perfectly normal if anything is using TemplateHaskell, QuasiQuotes or PatternSynonyms."-            loadTargets' Intelligent-          else-            loadTargets' Simple+    mg <- depanal [] False +    let interp = needsHscInterpreted mg+    target <- hscTarget <$> getSessionDynFlags+    when (interp && target /= HscInterpreted) $ do+      resetTargets targets+      _ <- setSessionDynFlags . setHscInterpreted =<< getSessionDynFlags+      gmLog GmInfo "loadTargets" $ text "Target needs interpeter, switching to LinkInMemory/HscInterpreted. Perfectly normal if anything is using TemplateHaskell, QuasiQuotes or PatternSynonyms."++    target' <- hscTarget <$> getSessionDynFlags++    case target' of+      HscNothing -> do+        void $ load LoadAllTargets+        mapM_ (parseModule >=> typecheckModule >=> desugarModule) mg+      HscInterpreted -> do+        void $ load LoadAllTargets+      _ -> error ("loadTargets: unsupported hscTarget")+     gmLog GmDebug "loadTargets" $ text "Loading done"    where@@ -456,30 +466,16 @@       return $ Target tid taoc src     relativize tgt = return tgt -    loadTargets' Simple = do-        void $ load LoadAllTargets-        mapM_ (parseModule >=> typecheckModule >=> desugarModule) =<< getModuleGraph--    loadTargets' Intelligent = do-        df <- getSessionDynFlags-        void $ setSessionDynFlags (setModeIntelligent df)-        void $ load LoadAllTargets-     resetTargets targets' = do         setTargets []         void $ load LoadAllTargets         setTargets targets' -    setIntelligent = do-        newdf <- setModeIntelligent <$> getSessionDynFlags-        void $ setSessionDynFlags newdf-        setCompilerMode Intelligent-     showTargetId (Target (TargetModule s) _ _) = moduleNameString s     showTargetId (Target (TargetFile s _) _ _) = s -needsFallback :: ModuleGraph -> Bool-needsFallback = any $ \ms ->+needsHscInterpreted :: ModuleGraph -> Bool+needsHscInterpreted = any $ \ms ->                 let df = ms_hspp_opts ms in                    Opt_TemplateHaskell `xopt` df                 || Opt_QuasiQuotes     `xopt` df@@ -492,4 +488,5 @@ cabalResolvedComponents = do     crdl@(Cradle{..}) <- cradle     comps <- mapM (resolveEntrypoint crdl) =<< getComponents-    cached cradleRootDir (resolvedComponentsCache cradleDistDir) comps+    withAutogen $+      cached cradleRootDir (resolvedComponentsCache cradleDistDir) comps
+ Language/Haskell/GhcMod/Test.hs view
@@ -0,0 +1,45 @@+module Language.Haskell.GhcMod.Test where++import Control.Applicative+import Data.List+import System.FilePath+import System.Directory+import Prelude++import Language.Haskell.GhcMod.Types+import Language.Haskell.GhcMod.Monad+import Language.Haskell.GhcMod.DynFlags++import GHC+import GHC.Exception+import OccName++test :: IOish m+      => FilePath -> GhcModT m String+test f = runGmlT' [Left f] (fmap setHscInterpreted . deferErrors) $ do+    mg <- getModuleGraph+    root <- cradleRootDir <$> cradle+    f' <- makeRelative root <$> liftIO (canonicalizePath f)+    let Just ms = find ((==Just f') . ml_hs_file . ms_location) mg+        mdl = ms_mod ms+        mn = moduleName mdl++    Just mi <- getModuleInfo mdl+    let exs = map (occNameString . getOccName) $ modInfoExports mi+        cqs = filter ("prop_" `isPrefixOf`) exs++    setContext [ IIDecl $ simpleImportDecl mn+               , IIDecl $ simpleImportDecl $ mkModuleName "Test.QuickCheck"+               ]++    _res <- mapM runTest cqs++    return ""++runTest :: GhcMonad m => String -> m (Maybe SomeException)+runTest fn = do+  res <- runStmt ("quickCheck " ++ fn) RunToCompletion+  return $ case res of+    RunOk [] -> Nothing+    RunException se -> Just se+    _ -> error "runTest"
Language/Haskell/GhcMod/Types.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE CPP, DeriveDataTypeable, DeriveFunctor, DeriveGeneric, RankNTypes,-  StandaloneDeriving, DefaultSignatures, FlexibleInstances, TemplateHaskell #-}+  StandaloneDeriving, DefaultSignatures, FlexibleInstances, TemplateHaskell,+  GeneralizedNewtypeDeriving #-} {-# OPTIONS_GHC -fno-warn-orphans -fno-warn-deprecations #-} module Language.Haskell.GhcMod.Types (     module Language.Haskell.GhcMod.Types@@ -15,9 +16,9 @@ import Control.Applicative import Control.Concurrent import Control.Monad-import Data.Serialize-import Data.Version-import Data.List (intercalate)+import Control.DeepSeq+import Data.Binary+import Data.Binary.Generic import Data.Map (Map) import qualified Data.Map as Map import Data.Set (Set)@@ -35,7 +36,6 @@ #endif import GHC (ModuleName, moduleNameString, mkModuleName) import HscTypes (HscEnv)-import PackageConfig (PackageConfig) import GHC.Generics import Text.PrettyPrint (Doc) import Prelude@@ -104,13 +104,6 @@   , optPrograms       :: Programs     -- | GHC command line options set on the @ghc-mod@ command line   , optGhcUserOptions :: [GHCOption]-  -- | If 'True', 'browse' also returns operators.-  , optOperators      :: Bool-  -- | If 'True', 'browse' also returns types.-  , optDetailed       :: Bool-  -- | If 'True', 'browse' will return fully qualified name-  , optQualified      :: Bool-  , optHlintOpts      :: [String]   , optFileMappings   :: [(FilePath, Maybe FilePath)]   } deriving (Show) @@ -130,10 +123,6 @@     , stackProgram   = "stack"     }   , optGhcUserOptions = []-  , optOperators      = False-  , optDetailed       = False-  , optQualified      = False-  , optHlintOpts      = []   , optFileMappings   = []   } @@ -212,17 +201,13 @@  data GhcModState = GhcModState {       gmGhcSession   :: !(Maybe GmGhcSession)-    , gmComponents   :: !(Map ChComponentName (GmComponent 'GMCResolved (Set ModulePath)))-    , gmCompilerMode :: !CompilerMode     , gmCaches       :: !GhcModCaches     , gmMMappedFiles :: !FileMappingMap     } -data CompilerMode = Simple | Intelligent deriving (Eq,Show,Read)- defaultGhcModState :: GhcModState defaultGhcModState =-    GhcModState n Map.empty Simple (GhcModCaches n n n n) Map.empty+    GhcModState n (GhcModCaches n n n n) Map.empty  where n = Nothing  ----------------------------------------------------------------@@ -233,7 +218,9 @@               | PackageDb String                 deriving (Eq, Show, Generic) -instance Serialize GhcPkgDb+instance Binary GhcPkgDb where+    put = ggput . from+    get = to `fmap` ggget  -- | A single GHC command line option. type GHCOption = String@@ -241,40 +228,13 @@ -- | An include directory for modules. type IncludeDir = FilePath --- | A package name.-type PackageBaseName = String---- | A package version.-type PackageVersion = String---- | A package id.-type PackageId = String---- | A package's name, verson and id.-type Package = (PackageBaseName, PackageVersion, PackageId)--pkgName :: Package -> PackageBaseName-pkgName (n, _, _) = n--pkgVer :: Package -> PackageVersion-pkgVer (_, v, _) = v--pkgId :: Package -> PackageId-pkgId (_, _, i) = i--showPkg :: Package -> String-showPkg (n, v, _) = intercalate "-" [n, v]--showPkgId :: Package -> String-showPkgId (n, v, i) = intercalate "-" [n, v, i]- -- | Haskell expression. newtype Expression = Expression { getExpression :: String }   deriving (Show, Eq, Ord)  -- | Module name. newtype ModuleString = ModuleString { getModuleString :: String }-  deriving (Show, Read, Eq, Ord)+  deriving (Show, Eq, Ord, Binary, NFData)  data GmLogLevel =     GmSilent@@ -287,14 +247,11 @@   | GmVomit     deriving (Eq, Ord, Enum, Bounded, Show, Read) --- | Collection of packages-type PkgDb = (Map Package PackageConfig)- data GmModuleGraph = GmModuleGraph {     gmgGraph :: Map ModulePath (Set ModulePath)   } deriving (Eq, Ord, Show, Read, Generic, Typeable) -instance Serialize GmModuleGraph where+instance Binary GmModuleGraph where   put GmModuleGraph {..} = put (mpim, graph)     where       mpim :: Map ModulePath Integer@@ -334,13 +291,17 @@   , gmcSourceDirs      :: [FilePath]   } deriving (Eq, Ord, Show, Read, Generic, Functor) -instance Serialize eps => Serialize (GmComponent t eps)+instance Binary eps => Binary (GmComponent t eps) where+    put = ggput . from+    get = to `fmap` ggget  data ModulePath = ModulePath { mpModule :: ModuleName, mpPath :: FilePath }   deriving (Eq, Ord, Show, Read, Generic, Typeable)-instance Serialize ModulePath+instance Binary ModulePath where+    put = ggput . from+    get = to `fmap` ggget -instance Serialize ModuleName where+instance Binary ModuleName where   get = mkModuleName <$> get   put mn = put (moduleNameString mn) @@ -388,8 +349,6 @@   | GMETooManyCabalFiles [FilePath]   -- ^ Too many cabal files found. -  | GMEWrongWorkingDirectory FilePath FilePath-     deriving (Eq,Show,Typeable)  instance Error GhcModError where@@ -398,13 +357,42 @@  instance Exception GhcModError -deriving instance Generic Version-instance Serialize Version+instance Binary CabalHelper.Programs where+    put = ggput . from+    get = to `fmap` ggget+instance Binary ChModuleName where+    put = ggput . from+    get = to `fmap` ggget+instance Binary ChComponentName where+    put = ggput . from+    get = to `fmap` ggget+instance Binary ChEntrypoint where+    put = ggput . from+    get = to `fmap` ggget -instance Serialize CabalHelper.Programs-instance Serialize ChModuleName-instance Serialize ChComponentName-instance Serialize ChEntrypoint+-- | Options for "lintWith" function+data LintOpts = LintOpts {+        optLintHlintOpts :: [String]+        -- ^ options that will be passed to hlint executable+      } deriving (Show)++-- | Default "LintOpts" instance+defaultLintOpts :: LintOpts+defaultLintOpts = LintOpts []++-- | Options for "browseWith" function+data BrowseOpts = BrowseOpts {+        optBrowseOperators      :: Bool+        -- ^ If 'True', "browseWith" also returns operators.+      , optBrowseDetailed       :: Bool+        -- ^ If 'True', "browseWith" also returns types.+      , optBrowseQualified      :: Bool+        -- ^ If 'True', "browseWith" will return fully qualified name+    } deriving (Show)++-- | Default "BrowseOpts" instance+defaultBrowseOpts :: BrowseOpts+defaultBrowseOpts = BrowseOpts False False False  mkLabel ''GhcModCaches mkLabel ''GhcModState
Language/Haskell/GhcMod/Utils.hs view
@@ -70,8 +70,8 @@       | otherwise               = c  newTempDir :: FilePath -> IO FilePath-newTempDir dir =-  flip createTempDirectory (uniqTempDirName dir) =<< getTemporaryDirectory+newTempDir _dir =+  flip createTempDirectory "ghc-mod" =<< getTemporaryDirectory  whenM :: Monad m => m Bool -> m () -> m () whenM mb ma = mb >>= flip when ma
Language/Haskell/GhcMod/World.hs view
@@ -20,7 +20,7 @@   , worldCabalConfig   :: Maybe TimedFile   , worldCabalSandboxConfig :: Maybe TimedFile   , worldSymbolCache   :: Maybe TimedFile-  } deriving (Eq, Show)+  } deriving (Eq)  timedPackageCaches :: IOish m => GhcModT m [TimedFile] timedPackageCaches = do
Setup.hs view
@@ -99,7 +99,7 @@         libexecdir'      = fromPathTemplate (libexecdir idirtpl)          pd_extended      = onlyExePackageDesc [exe] pd-        install_target   = fromJust $ installTarget exe+        install_target   = fromJustNote "xInstallTarget" $ installTarget exe         install_target'  = ID.substPathTemplate env install_target         -- $libexec isn't a real thing :/ so we have to simulate it         install_target'' = substLibExec' libexecdir' install_target'@@ -140,6 +140,10 @@     case filter ((=="") . snd) $ readP_to_S parseVersion str of       [(ver, _)] -> ver       _ -> error $ "No parse (Ver) :(\n" ++ str ++ "\n"++fromJustNote :: String -> Maybe a -> a+fromJustNote _ (Just x) = x+fromJustNote note Nothing = error $ "fromJustNote ("++note++"): "  -- sanityCheckCabalVersions args cf desc lbi = do --   (cabalInstallVer, cabalVer) <- getCabalExecVer
+ System/Directory/ModTime.hs view
@@ -0,0 +1,63 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015  Daniel Gröber <dxld ÄT darkboxed DOT org>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.+{-# LANGUAGE CPP, GeneralizedNewtypeDeriving #-}+module System.Directory.ModTime where++import Control.Applicative+import Control.DeepSeq+import Data.Binary+#if MIN_VERSION_directory(1,2,0)+import Data.Time (UTCTime(..), Day(..), getCurrentTime)+#else+import System.Time (ClockTime(..), getClockTime)+#endif+import System.Directory+import Prelude++#if MIN_VERSION_directory(1,2,0)++newtype ModTime = ModTime UTCTime+    deriving (Eq, Ord, NFData)+getCurrentModTime = ModTime <$> getCurrentTime++instance Binary ModTime where+    put (ModTime (UTCTime (ModifiedJulianDay day) difftime)) =+        put day >> put (toRational difftime)+    get =+        ModTime <$> (UTCTime <$> (ModifiedJulianDay <$> get) <*> (fromRational <$> get))++#else++newtype ModTime = ModTime ClockTime+    deriving (Eq, Ord)+getCurrentModTime = ModTime <$> getClockTime++instance Binary ModTime where+    put (ModTime (TOD s ps)) =+        put s >> put ps+    get =+        ModTime <$> (TOD <$> get <*> get)++instance NFData ModTime where+    rnf (ModTime (TOD s ps)) =+        s `seq` ps `seq` (ModTime $! TOD s ps) `seq` ()++#endif++getCurrentModTime :: IO ModTime++getModTime :: FilePath -> IO ModTime+getModTime f = ModTime <$> getModificationTime f
Utils.hs view
@@ -4,29 +4,18 @@ import Control.Applicative import Data.Traversable import System.Directory+import System.Directory.ModTime -#if MIN_VERSION_directory(1,2,0)-import Data.Time (UTCTime)-#else-import System.Time (ClockTime)-#endif import Prelude --#if MIN_VERSION_directory(1,2,0)-type ModTime = UTCTime-#else-type ModTime = ClockTime-#endif- data TimedFile = TimedFile { tfPath :: FilePath, tfTime :: ModTime }-                 deriving (Eq, Show)+                 deriving (Eq)  instance Ord TimedFile where     compare (TimedFile _ a) (TimedFile _ b) = compare a b  timeFile :: FilePath -> IO TimedFile-timeFile f = TimedFile <$> pure f <*> getModificationTime f+timeFile f = TimedFile <$> pure f <*> getModTime f  mightExist :: FilePath -> IO (Maybe FilePath) mightExist f = do
elisp/ghc-comp.el view
@@ -101,7 +101,7 @@ (defun ghc-boot (n)   (prog2       (message "Initializing...")-      (ghc-sync-process "boot\n" n nil 'skip-map-file)+      (ghc-sync-process "boot\n" n)     (message "Initializing...done")))  (defun ghc-load-modules (mods)
elisp/ghc-info.el view
@@ -111,13 +111,7 @@ 	 (cn (int-to-string (1+ (current-column)))) 	 (file (buffer-file-name)) 	 (cmd (format "type %s %s %s\n" file ln cn)))-    (ghc-sync-process cmd nil 'ghc-type-fix-string)))--(defun ghc-type-fix-string ()-  (save-excursion-    (goto-char (point-min))-    (while (search-forward "[Char]" nil t)-      (replace-match "String"))))+    (ghc-sync-process cmd nil)))  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;
elisp/ghc-process.el view
@@ -1,3 +1,4 @@+;;; -*- lexical-binding: t -*- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; ghc-process.el@@ -21,12 +22,11 @@ (defvar-local ghc-process-process-name nil) (defvar-local ghc-process-original-buffer nil) (defvar-local ghc-process-original-file nil)-(defvar-local ghc-process-callback nil)-(defvar-local ghc-process-hook nil) (defvar-local ghc-process-root nil)  (defvar ghc-command "ghc-mod") +(defvar ghc-report-errors t "Report GHC errors to *GHC Error* buffer") (defvar ghc-error-buffer "*GHC Error*")  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@ -34,12 +34,12 @@ (defun ghc-get-project-root ()   (ghc-run-ghc-mod '("root"))) -(defun ghc-with-process (cmd callback &optional hook1 hook2 skip-map-file)+(defun ghc-with-process (cmd async-after-callback &optional sync-before-hook)   (unless ghc-process-process-name     (setq ghc-process-process-name (ghc-get-project-root)))   (when (and ghc-process-process-name (not ghc-process-running))     (setq ghc-process-running t)-    (if hook1 (funcall hook1))+    (if sync-before-hook (funcall sync-before-hook))     (let* ((cbuf (current-buffer)) 	   (name ghc-process-process-name) 	   (root (file-name-as-directory ghc-process-process-name))@@ -51,14 +51,13 @@       (ghc-with-current-buffer buf         (setq ghc-process-original-buffer cbuf) 	(setq ghc-process-original-file file)-	(setq ghc-process-hook hook2) 	(setq ghc-process-root root) 	(let ((pro (ghc-get-process cpro name buf root)) 	      (map-cmd (format "map-file %s\n" file)))-	  ;; map-file-	  (unless skip-map-file+;	       (unmap-cmd (format "unmap-file %s\n" file)))+	  (when (buffer-modified-p (current-buffer)) 	    (setq ghc-process-file-mapping t)-	    (setq ghc-process-callback nil)+	    (setq ghc-process-async-after-callback nil) 	    (erase-buffer) 	    (when ghc-debug 	      (ghc-with-debug-buffer@@ -69,7 +68,7 @@ 	      (save-restriction 		(widen) 		(process-send-region pro (point-min) (point-max))))-	    (process-send-string pro "\004\n")+	    (process-send-string pro "\n\004\n") 	    (condition-case nil 		(let ((inhibit-quit nil)) 		  (while ghc-process-file-mapping@@ -78,12 +77,21 @@ 	       (setq ghc-process-running nil) 	       (setq ghc-process-file-mapping nil)))) 	  ;; command-	  (setq ghc-process-callback callback)+	  (setq ghc-process-async-after-callback async-after-callback) 	  (erase-buffer) 	  (when ghc-debug 	    (ghc-with-debug-buffer 	     (insert (format "%% %s" cmd)))) 	  (process-send-string pro cmd)++	  ;;; this needs to be done asyncrounously after the command actually+	  ;;; finished, gah+	  ;; (when do-map-file+	  ;;   (when ghc-debug+	  ;;	 (ghc-with-debug-buffer+	  ;;	  (insert (format "%% %s" unmap-cmd))))+	  ;;   (process-send-string pro unmap-cmd))+ 	  pro)))))  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@@ -144,7 +152,8 @@ 		    (with-current-buffer pbuf 		      (goto-char (point-max)) 		      (insert-buffer-substring tbuf 1 end))-		  (with-current-buffer (get-buffer-create ghc-error-buffer)+		  (when ghc-report-errors+                    (with-current-buffer (get-buffer-create ghc-error-buffer) 		    (setq buffer-read-only t) 		    (let* ((buffer-read-only nil) 			   (inhibit-read-only t)@@ -156,7 +165,7 @@ 			(goto-char (point-max)) 			(insert-buffer-substring tbuf 1 end) 			(set-buffer-modified-p nil))-		      (redisplay))))+		      (redisplay))))) 		(delete-region 1 end))))) 	(goto-char (point-max)) 	(forward-line -1)@@ -164,13 +173,12 @@ 	 ((looking-at "^OK$") 	  (delete-region (point) (point-max)) 	  (setq ghc-process-file-mapping nil)-	  (when ghc-process-callback-	    (if ghc-process-hook (funcall ghc-process-hook))+	  (when ghc-process-async-after-callback 	    (goto-char (point-min))-	    (funcall ghc-process-callback 'ok)+	    (funcall ghc-process-async-after-callback 'ok) 	    (setq ghc-process-running nil))) 	 ((looking-at "^NG ")-	  (funcall ghc-process-callback 'ng)+	  (funcall ghc-process-async-after-callback 'ng) 	  (setq ghc-process-running nil)))))))  (defun ghc-process-sentinel (_process _event)@@ -183,12 +191,12 @@ (defvar ghc-process-num-of-results nil) (defvar ghc-process-results nil) -(defun ghc-sync-process (cmd &optional n hook skip-map-file)+(defun ghc-sync-process (cmd &optional n)   (unless ghc-process-running     (setq ghc-process-rendezvous nil)     (setq ghc-process-results nil)     (setq ghc-process-num-of-results (or n 1))-    (let ((pro (ghc-with-process cmd 'ghc-process-callback nil hook skip-map-file)))+    (let ((pro (ghc-with-process cmd 'ghc-sync-process-callback nil)))       ;; ghc-process-running is now t.       ;; But if the process exits abnormally, it is set to nil.       (condition-case nil@@ -199,7 +207,7 @@ 	 (setq ghc-process-running nil))))     ghc-process-results)) -(defun ghc-process-callback (status)+(defun ghc-sync-process-callback (status)   (cond    ((eq status 'ok)     (let* ((n ghc-process-num-of-results)
elisp/ghc.el view
@@ -28,7 +28,7 @@ 	       (< emacs-minor-version minor)))       (error "ghc-mod requires at least Emacs %d.%d" major minor))) -(defconst ghc-version "5.4.0.0")+(defconst ghc-version "5.5.0.0")  (defgroup ghc-mod '() "ghc-mod customization") 
ghc-mod.cabal view
@@ -1,8 +1,9 @@ Name:                   ghc-mod-Version:                5.4.0.0+Version:                5.5.0.0 Author:                 Kazu Yamamoto <kazu@iij.ad.jp>,                         Daniel Gröber <dxld@darkboxed.org>,-                        Alejandro Serrano <trupill@gmail.com>+                        Alejandro Serrano <trupill@gmail.com>,+                        Nikolay Yakimov <root@livid.pp.ru> Maintainer:             Daniel Gröber <dxld@darkboxed.org> License:                AGPL-3 License-File:           LICENSE@@ -33,6 +34,7 @@                         SetupCompat.hs                         NotCPP/*.hs                         NotCPP/COPYING+                        Language/Haskell/GhcMod/Monad/Compat.hs_h                         test/data/annotations/*.hs                         test/data/broken-cabal/*.cabal                         test/data/broken-cabal/cabal.sandbox.config.in@@ -131,6 +133,12 @@                         Language.Haskell.GhcMod.Logging                         Language.Haskell.GhcMod.Modules                         Language.Haskell.GhcMod.Monad+                        Language.Haskell.GhcMod.Monad.Env+                        Language.Haskell.GhcMod.Monad.Log+                        Language.Haskell.GhcMod.Monad.Newtypes+                        Language.Haskell.GhcMod.Monad.Orphans+                        Language.Haskell.GhcMod.Monad.Out+                        Language.Haskell.GhcMod.Monad.State                         Language.Haskell.GhcMod.Monad.Types                         Language.Haskell.GhcMod.Output                         Language.Haskell.GhcMod.PathsAndFiles@@ -140,41 +148,45 @@                         Language.Haskell.GhcMod.SrcUtils                         Language.Haskell.GhcMod.Stack                         Language.Haskell.GhcMod.Target+                        Language.Haskell.GhcMod.Test                         Language.Haskell.GhcMod.Types                         Language.Haskell.GhcMod.Utils                         Language.Haskell.GhcMod.World   Other-Modules:        Paths_ghc_mod                         Utils-  Build-Depends:        base >= 4.0 && < 5-                      , bytestring-                      , cereal >= 0.4-                      , containers-                      , cabal-helper == 0.6.* && >= 0.6.0.0-                      , deepseq-                      , directory-                      , filepath-                      , ghc-                      , ghc-paths-                      , ghc-syb-utils-                      , hlint >= 1.8.61-                      , monad-journal >= 0.4-                      , old-time-                      , pretty-                      , process-                      , syb-                      , temporary-                      , time-                      , transformers-                      , transformers-base-                      , mtl >= 2.0-                      , monad-control >= 1-                      , split-                      , haskell-src-exts-                      , text-                      , djinn-ghc >= 0.0.2.2-                      , fclabels == 2.0.*-                      , extra == 1.4.*-                      , pipes == 4.1.*+                        Data.Binary.Generic+                        System.Directory.ModTime+  Build-Depends:        base              < 5 && >= 4.0+                      , bytestring        < 0.11+                      , binary            < 0.8 && >= 0.5.1.0+                      , containers        < 0.6+                      , cabal-helper      < 0.7 && >= 0.6.3.0+                      , deepseq           < 1.5+                      , directory         < 1.3+                      , filepath          < 1.5+                      , ghc               < 7.11+                      , ghc-paths         < 0.2+                      , ghc-syb-utils     < 0.3+                      , hlint             < 1.10 && >= 1.8.61+                      , monad-journal     < 0.8 && >= 0.4+                      , old-time          < 1.2+                      , pretty            < 1.2+                      , process           < 1.3+                      , syb               < 0.7+                      , temporary         < 1.3+                      , time              < 1.6+                      , transformers      < 0.5+                      , transformers-base < 0.5+                      , mtl               < 2.3 && >= 2.0+                      , monad-control     < 1.1 && >= 1+                      , split             < 0.3+                      , haskell-src-exts  < 1.18+                      , text              < 1.3+                      , djinn-ghc         < 0.1 && >= 0.0.2.2+                      , fclabels          == 2.0.*+                      , extra             == 1.4.*+                      , pipes             == 4.1.*+                      , safe              < 0.4 && >= 0.3.9   if impl(ghc < 7.8)     Build-Depends:      convertible   if impl(ghc < 7.5)@@ -186,38 +198,47 @@   Default-Language:     Haskell2010   Main-Is:              GHCMod.hs   Other-Modules:        Paths_ghc_mod+                      , GHCMod.Options+                      , GHCMod.Options.Commands+                      , GHCMod.Version+                      , GHCMod.Options.DocUtils+                      , GHCMod.Options.ShellParse+                      , GHCMod.Options.Help   GHC-Options:          -Wall -fno-warn-deprecations -threaded   Default-Extensions:   ConstraintKinds, FlexibleContexts   HS-Source-Dirs:       src-  Build-Depends:        base >= 4.0 && < 5-                      , async-                      , directory-                      , filepath-                      , pretty-                      , process-                      , split-                      , mtl >= 2.0-                      , ghc+  Build-Depends:        base      < 5 && >= 4.0+                      , directory < 1.3+                      , filepath  < 1.5+                      , pretty    < 1.2+                      , process   < 1.3+                      , split     < 0.3+                      , mtl       < 2.3 && >= 2.0+                      , ghc       < 7.11+                      , monad-control ==1.0.*+                      , fclabels  ==2.0.*+                      , optparse-applicative >=0.11.0 && <0.13.0                       , ghc-mod-                      , fclabels == 2.0.*  Executable ghc-modi   Default-Language:     Haskell2010   Main-Is:              GHCModi.hs   Other-Modules:        Paths_ghc_mod-                        Misc                         Utils   GHC-Options:          -Wall -threaded -fno-warn-deprecations   if os(windows)       Cpp-Options:      -DWINDOWS   Default-Extensions:   ConstraintKinds, FlexibleContexts   HS-Source-Dirs:       src, .-  Build-Depends:        base >= 4.0 && < 5-                      , directory-                      , filepath-                      , process-                      , time-                      , old-time+  Build-Depends:        base      < 5 && >= 4.0+                      , binary    < 0.8 && >= 0.5.1.0+                      , deepseq   < 1.5+                      , directory < 1.3+                      , filepath  < 1.5+                      , process   < 1.3+                      , old-time  < 1.2+                      , time      < 1.6+                      , ghc-mod  Test-Suite doctest   Type:                 exitcode-stdio-1.0@@ -237,8 +258,8 @@                         ConstraintKinds, FlexibleContexts,                         DataKinds, KindSignatures, TypeOperators, ViewPatterns   Main-Is:              Main.hs-  Hs-Source-Dirs:       test, .-  Ghc-Options:          -Wall -fno-warn-deprecations+  Hs-Source-Dirs:       test, ., src+  Ghc-Options:          -Wall -fno-warn-deprecations -threaded   CPP-Options:          -DSPEC=1   Type:                 exitcode-stdio-1.0   Other-Modules:        Paths_ghc_mod@@ -257,6 +278,7 @@                         PathsAndFilesSpec                         HomeModuleGraphSpec                         FileMappingSpec+                        ShellParseSpec    Build-Depends:        hspec >= 2.0.0   if impl(ghc == 7.4.*)
src/GHCMod.hs view
@@ -2,450 +2,64 @@  module Main where -import Config (cProjectVersion)-import Control.Category import Control.Applicative-import Control.Arrow import Control.Monad import Data.Typeable (Typeable)-import Data.Version (showVersion)-import Data.Label import Data.List import Data.List.Split-import Data.Char (isSpace)-import Data.Maybe import Exception import Language.Haskell.GhcMod import Language.Haskell.GhcMod.Internal hiding (MonadIO,liftIO) import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Monad-import Paths_ghc_mod-import System.Console.GetOpt (OptDescr(..), ArgDescr(..), ArgOrder(..))-import qualified System.Console.GetOpt as O+import Language.Haskell.GhcMod.Find (AsyncSymbolDb, newAsyncSymbolDb, getAsyncSymbolDb) import System.FilePath ((</>)) import System.Directory (setCurrentDirectory, getAppUserDataDirectory,                         removeDirectoryRecursive)-import System.Environment (getArgs) import System.IO import System.Exit-import Text.PrettyPrint-import Prelude hiding ((.))--import Misc--progVersion :: String -> String-progVersion pf =-    "ghc-mod"++pf++" version " ++ showVersion version ++ " compiled by GHC "-                               ++ cProjectVersion ++ "\n"--ghcModVersion :: String-ghcModVersion = progVersion ""--ghcModiVersion :: String-ghcModiVersion = progVersion "i"--optionUsage :: (String -> String) -> [OptDescr a] -> [String]-optionUsage indent opts = concatMap optUsage opts- where-   optUsage (Option so lo dsc udsc) =-       [ concat $ intersperse ", " $ addLabel `map` allFlags-       , indent $ udsc-       , ""-       ]-    where-      allFlags = shortFlags ++ longFlags-      shortFlags = (('-':) . return) `map` so :: [String]-      longFlags  = ("--"++) `map` lo--      addLabel f@('-':'-':_) = f ++ flagLabel "="-      addLabel f@('-':_)     = f ++ flagLabel " "-      addLabel _ = undefined--      flagLabel s =-          case dsc of-            NoArg  _ -> ""-            ReqArg _ label -> s ++ label-            OptArg _ label -> s ++ "["++label++"]"---- TODO: Generate the stuff below automatically-usage :: String-usage =- "Usage: ghc-mod [OPTIONS...] COMMAND [CMD_ARGS...] \n\- \*Global Options (OPTIONS)*\n\- \    Global options can be specified before and after the command and\n\- \    interspersed with command specific options\n\- \\n"-   ++ (unlines $ indent <$> optionUsage indent globalArgSpec) ++- "*Commands*\n\- \    - version\n\- \        Print the version of the program.\n\- \\n\- \    - help\n\- \       Print this help message.\n\- \\n\- \    - list [FLAGS...] | modules [FLAGS...]\n\- \        List all visible modules.\n\- \      Flags:\n\- \        -d\n\- \            Print package modules belong to.\n\- \\n\- \    - lang\n\- \        List all known GHC language extensions.\n\- \\n\- \    - flag\n\- \        List GHC -f<bla> flags.\n\- \\n\- \    - browse [FLAGS...] [PACKAGE:]MODULE...\n\- \        List symbols in a module.\n\- \      Flags:\n\- \        -o\n\- \            Also print operators.\n\- \        -d\n\- \            Print symbols with accompanying signatures.\n\- \        -q\n\- \            Qualify symbols.\n\- \\n\- \    - check FILE...\n\- \        Load the given files using GHC and report errors/warnings, but\n\- \        don't produce output files.\n\- \\n\- \    - expand FILE...\n\- \        Like `check' but also pass `-ddump-splices' to GHC.\n\- \\n\- \    - info   FILE [MODULE] EXPR\n\- \        Look up an identifier in the context of FILE (like ghci's `:info')\n\- \        MODULE is completely ignored and only allowed for backwards\n\- \        compatibility.\n\- \\n\- \    - type FILE [MODULE] LINE COL\n\- \        Get the type of the expression under (LINE,COL).\n\- \\n\- \    - split FILE [MODULE] LINE COL\n\- \        Split a function case by examining a type's constructors.\n\- \\n\- \        For example given the following code snippet:\n\- \\n\- \            f :: [a] -> a\n\- \            f x = _body\n\- \\n\- \        would be replaced by:\n\- \\n\- \            f :: [a] -> a\n\- \            f [] = _body\n\- \            f (x:xs) = _body\n\- \\n\- \        (See https://github.com/kazu-yamamoto/ghc-mod/pull/274)\n\- \\n\- \    - sig FILE MODULE LINE COL\n\- \        Generate initial code given a signature.\n\- \\n\- \        For example when (LINE,COL) is on the signature in the following\n\- \        code snippet:\n\- \\n\- \            func :: [a] -> Maybe b -> (a -> b) -> (a,b)\n\- \\n\- \        ghc-mod would add the following on the next line:\n\- \\n\- \            func x y z f = _func_body\n\- \\n\- \        (See: https://github.com/kazu-yamamoto/ghc-mod/pull/274)\n\- \\n\- \    - refine FILE MODULE LINE COL EXPR\n\- \        Refine the typed hole at (LINE,COL) given EXPR.\n\- \\n\- \        For example if EXPR is `filter', which has type `(a -> Bool) -> [a]\n\- \          -> [a]' and (LINE,COL) is on the hole `_body' in the following\n\- \        code snippet:\n\- \\n\- \            filterNothing :: [Maybe a] -> [a]\n\- \            filterNothing xs = _body\n\- \\n\- \        ghc-mod changes the code to get a value of type `[a]', which\n\- \        results in:\n\- \\n\- \            filterNothing xs = filter _body_1 _body_2\n\- \\n\- \        (See also: https://github.com/kazu-yamamoto/ghc-mod/issues/311)\n\- \\n\- \    - auto FILE MODULE LINE COL\n\- \        Try to automatically fill the contents of a hole.\n\- \\n\- \    - find SYMBOL\n\- \        List all modules that define SYMBOL.\n\- \\n\- \    - lint FILE\n\- \        Check files using `hlint'.\n\- \      Flags:\n\- \        -h\n\- \            Option to be passed to hlint.\n\- \\n\- \    - root\n\- \        Try to find the project directory. For Cabal projects this is the\n\- \        directory containing the cabal file, for projects that use a cabal\n\- \        sandbox but have no cabal file this is the directory containing the\n\- \        cabal.sandbox.config file and otherwise this is the current\n\- \        directory.\n\- \\n\- \    - doc MODULE\n\- \        Try finding the html documentation directory for the given MODULE.\n\- \\n\- \    - debug\n\- \        Print debugging information. Please include the output in any bug\n\- \        reports you submit.\n\- \\n\- \    - debugComponent [MODULE_OR_FILE...]\n\- \        Debugging information related to cabal component resolution.\n\- \\n\- \    - boot\n\- \         Internal command used by the emacs frontend.\n\- \\n\- \    - legacy-interactive\n\- \         ghc-modi compatibility mode.\n"- where-   indent = ("    "++)--cmdUsage :: String -> String -> String-cmdUsage cmd realUsage =-  let-      -- Find command head-      a = dropWhile (not . isCmdHead) $ lines realUsage-      -- Take til the end of the current command block-      b = flip takeWhile a $ \l ->-            all isSpace l || (isIndented l && (isCmdHead l || isNotCmdHead l))-      -- Drop extra newline from the end-      c = dropWhileEnd (all isSpace) b--      isIndented    = ("    " `isPrefixOf`)-      isNotCmdHead  = ( not .  ("    - " `isPrefixOf`))--      containsAnyCmdHead s = (("    - ") `isInfixOf` s)-      containsCurrCmdHead s = (("    - " ++ cmd) `isInfixOf` s)-      isCmdHead s =-          containsAnyCmdHead s &&-            or [ containsCurrCmdHead s-               , any (cmd `isPrefixOf`) (splitOn " | " s)-               ]--      unindent (' ':' ':' ':' ':l) = l-      unindent l = l-  in unlines $ unindent <$> c+import Text.PrettyPrint hiding ((<>))+import GHCMod.Options+import Prelude  ghcModStyle :: Style ghcModStyle = style { lineLength = 80, ribbonsPerLine = 1.2 }  ---------------------------------------------------------------- -option :: [Char] -> [String] -> String -> ArgDescr a -> OptDescr a-option s l udsc dsc = Option s l dsc udsc--reqArg :: String -> (String -> a) -> ArgDescr a-reqArg udsc dsc = ReqArg dsc udsc--optArg :: String -> (Maybe String -> a) -> ArgDescr a-optArg udsc dsc = OptArg dsc udsc--intToLogLevel :: Int -> GmLogLevel-intToLogLevel = toEnum--globalArgSpec :: [OptDescr (Options -> Either [String] Options)]-globalArgSpec =-      [ option "v" ["verbose"] "Increase or set log level. (0-7)" $-          optArg "LEVEL" $ \ml o -> Right $ case ml of-              Nothing ->-                  modify (lOoptLogLevel . lOptOutput) increaseLogLevel o-              Just l ->-                  set (lOoptLogLevel . lOptOutput) (toEnum $ min 7 $ read l) o--      , option "s" [] "Be silent, set log level to 0" $-          NoArg $ \o -> Right $ set (lOoptLogLevel . lOptOutput) (toEnum 0) o--      , option "l" ["tolisp"] "Format output as an S-Expression" $-          NoArg $ \o -> Right $ set (lOoptStyle . lOptOutput) LispStyle o--      , option "b" ["boundary", "line-seperator"] "Output line separator"$-          reqArg "SEP" $ \s o -> Right $ set (lOoptLineSeparator . lOptOutput) (LineSeparator s) o--      , option "" ["line-prefix"] "Output line separator"$-          reqArg "OUT,ERR" $ \s o -> let-                [out, err] = splitOn "," s-              in Right $ set (lOoptLinePrefix . lOptOutput) (Just (out, err)) o--      , option "g" ["ghcOpt", "ghc-option"] "Option to be passed to GHC" $-          reqArg "OPT" $ \g o -> Right $-              o { optGhcUserOptions = g : optGhcUserOptions o }--{--File map docs:--CLI options:-* `--map-file "file1.hs=file2.hs"` can be used to tell-    ghc-mod that it should take source code for `file1.hs` from `file2.hs`.-    `file1.hs` can be either full path, or path relative to project root.-    `file2.hs` has to be either relative to project root,-    or full path (preferred).-* `--map-file "file.hs"` can be used to tell ghc-mod that it should take-    source code for `file.hs` from stdin. File end marker is `\EOT\n`,-    i.e. `\x04\x0A`. `file.hs` may or may not exist, and should be-    either full path, or relative to project root.--Interactive commands:-* `map-file file.hs` -- tells ghc-modi to read `file.hs` source from stdin.-    Works the same as second form of `--map-file` CLI option.-* `unmap-file file.hs` -- unloads previously mapped file, so that it's-    no longer mapped. `file.hs` can be full path or relative to-    project root, either will work.--Exposed functions:-* `loadMappedFile :: FilePath -> FilePath -> GhcModT m ()` -- maps `FilePath`,-    given as first argument to take source from `FilePath` given as second-    argument. Works exactly the same as first form of `--map-file`-    CLI option.-* `loadMappedFileSource :: FilePath -> String -> GhcModT m ()` -- maps-    `FilePath`, given as first argument to have source as given-    by second argument. Works exactly the same as second form of `--map-file`-    CLI option, sans reading from stdin.-* `unloadMappedFile :: FilePath -> GhcModT m ()` -- unmaps `FilePath`, given as-    first argument, and removes any temporary files created when file was-    mapped. Works exactly the same as `unmap-file` interactive command--}-      , option "" ["map-file"] "Redirect one file to another, --map-file \"file1.hs=file2.hs\"" $-          reqArg "OPT" $ \g o ->-             let m = case second (drop 1) $ span (/='=') g of-                       (s,"") -> (s, Nothing)-                       (f,t)  -> (f, Just t)-             in-             Right $ o { optFileMappings = m : optFileMappings o }--      , option "" ["with-ghc"] "GHC executable to use" $-          reqArg "PATH" $ \p o -> Right $ set (lGhcProgram . lOptPrograms) p o--      , option "" ["with-ghc-pkg"] "ghc-pkg executable to use (only needed when guessing from GHC path fails)" $-          reqArg "PATH" $ \p o -> Right $ set (lGhcPkgProgram . lOptPrograms) p o--      , option "" ["with-cabal"] "cabal-install executable to use" $-          reqArg "PATH" $ \p o -> Right $ set (lCabalProgram . lOptPrograms) p o--      , option "" ["with-stack"] "stack executable to use" $-          reqArg "PATH" $ \p o -> Right $ set (lStackProgram . lOptPrograms) p o--      , option "" ["version"] "print version information" $-          NoArg $ \_ -> Left ["version"]--      , option "" ["help"] "print this help message" $-          NoArg $ \_ -> Left ["help"]-  ]----parseGlobalArgs :: [String] -> Either InvalidCommandLine (Options, [String])-parseGlobalArgs argv-    = case O.getOpt' RequireOrder globalArgSpec argv of-        (o,r,u,[]) -> case foldr (=<<) (Right defaultOptions) o of-                        Right o' -> Right (o', u ++ r)-                        Left c -> Right (defaultOptions, c)-        (_,_,u,e)  -> Left $ InvalidCommandLine $ Right $-            "Parsing command line options failed: "-               ++ concat (e ++ map errUnrec u)- where-   errUnrec :: String -> String-   errUnrec optStr = "unrecognized option `" ++ optStr ++ "'\n"--parseCommandArgs :: [OptDescr (Options -> Either [String] Options)]-                 -> [String]-                 -> Options-                 -> (Options, [String])-parseCommandArgs spec argv opts-    = case O.getOpt RequireOrder (globalArgSpec ++ spec) argv of-        (o,r,[])   -> case foldr (=<<) (Right opts) o of-                        Right o' -> (o', r)-                        Left c -> (defaultOptions, c)-        (_,_,errs) ->-            fatalError $ "Parsing command options failed: " ++ concat errs--------------------------------------------------------------------data CmdError = UnknownCommand String-              | NoSuchFileError String-              | LibraryError GhcModError--                deriving (Show, Typeable)--instance Exception CmdError--data InteractiveOptions = InteractiveOptions {-      ghcModExtensions :: Bool-    }- handler :: IOish m => GhcModT m a -> GhcModT m a-handler = flip gcatches $-          [ GHandler $ \(FatalError msg) -> exitError msg-          , GHandler $ \e@(ExitSuccess) -> throw e-          , GHandler $ \e@(ExitFailure _) -> throw e-          , GHandler $ \(InvalidCommandLine e) -> do-                case e of-                  Left cmd ->-                      exitError $ "Usage for `"++cmd++"' command:\n\n"-                                  ++ (cmdUsage cmd usage) ++ "\n"-                                  ++ "ghc-mod: Invalid command line form."-                  Right msg -> exitError $ "ghc-mod: " ++ msg+handler = flip gcatches+          [ GHandler $ \(e :: ExitCode) -> throw e           , GHandler $ \(SomeException e) -> exitError $ "ghc-mod: " ++ show e           ]  main :: IO () main = do     hSetEncoding stdout utf8-    args <- getArgs-    case parseGlobalArgs args of-      Left e -> throw e-      Right res@(globalOptions,_) -> catches (progMain res) [-            Handler $ \(e :: GhcModError) ->-              runGmOutT globalOptions $ exitError $ renderStyle ghcModStyle (gmeDoc e)-          ]--progMain :: (Options,[String]) -> IO ()-progMain (globalOptions,cmdArgs) = runGmOutT globalOptions $-    case globalCommands cmdArgs of-      Just s -> gmPutStr s-      Nothing -> wrapGhcCommands globalOptions cmdArgs+    parseArgs >>= \res@(globalOptions, _) ->+      catches (progMain res) [+              Handler $ \(e :: GhcModError) ->+                runGmOutT globalOptions $ exitError $ renderStyle ghcModStyle (gmeDoc e)+            ] -globalCommands :: [String] -> Maybe String-globalCommands (cmd:_)-    | cmd == "help"    = Just usage-    | cmd == "version" = Just ghcModVersion-globalCommands _       = Nothing+progMain :: (Options, GhcModCommands) -> IO ()+progMain (globalOptions, commands) = runGmOutT globalOptions $+  wrapGhcCommands globalOptions commands  -- ghc-modi legacyInteractive :: IOish m => GhcModT m () legacyInteractive = do-    opt <- options     prepareCabalHelper-    tmpdir <- cradleTempDir <$> cradle-    gmo <- gmoAsk-    symdbreq <- liftIO $ newSymDbReq opt gmo tmpdir+    asyncSymbolDb <- newAsyncSymbolDb     world <- getCurrentWorld-    legacyInteractiveLoop symdbreq world--bug :: IOish m => String -> GhcModT m ()-bug msg = do-  gmPutStrLn $ notGood $ "BUG: " ++ msg-  liftIO exitFailure--notGood :: String -> String-notGood msg = "NG " ++ escapeNewlines msg--escapeNewlines :: String -> String-escapeNewlines = replace "\n" "\\n" . replace "\\n" "\\\\n"--replace :: String -> String -> String -> String-replace needle replacement = intercalate replacement . splitOn needle+    legacyInteractiveLoop asyncSymbolDb world -legacyInteractiveLoop :: IOish m-                      => SymDbReq -> World -> GhcModT m ()-legacyInteractiveLoop symdbreq world = do+legacyInteractiveLoop :: IOish m => AsyncSymbolDb -> World -> GhcModT m ()+legacyInteractiveLoop asyncSymbolDb world = do     liftIO . setCurrentDirectory =<< cradleRootDir <$> cradle      -- blocking-    cmdArg <- liftIO $ getLine+    cmdArg <- liftIO getLine      -- after blocking, we need to see if the world has changed. @@ -455,72 +69,53 @@                 then getCurrentWorld -- TODO: gah, we're hitting the fs twice                 else return world -    when changed $ do-        dropSession--    let (cmd':args') = split (keepDelimsR $ condense $ whenElt isSpace) cmdArg-        arg = concat args'-        cmd = dropWhileEnd isSpace cmd'-        args = dropWhileEnd isSpace `map` args'--    res <- flip gcatches interactiveHandlers $ case dropWhileEnd isSpace cmd of-        "check"  -> checkSyntaxCmd [arg]-        "lint"   -> lintCmd [arg]-        "find"    -> do-            db <- getDb symdbreq >>= checkDb symdbreq-            lookupSymbol arg db--        "info"   -> infoCmd [head args, concat $ tail args']-        "type"   -> typesCmd args-        "split"  -> splitsCmd args--        "sig"    -> sigCmd args-        "auto"   -> autoCmd args-        "refine" -> refineCmd args--        "boot"   -> bootCmd []-        "browse" -> browseCmd args--        "map-file"   ->  liftIO getFileSourceFromStdin-                     >>= loadMappedFileSource arg-                     >>  return ""--        "unmap-file" ->  unloadMappedFile arg-                     >>  return ""+    when changed dropSession -        "quit"   -> liftIO $ exitSuccess-        ""       -> liftIO $ exitSuccess-        _        -> fatalError $ "unknown command: `" ++ cmd ++ "'"+    res <- flip gcatches interactiveHandlers $ do+      pargs <- either (throw . InvalidCommandLine . Right) return+              $ parseArgsInteractive cmdArg+      case pargs of+        CmdFind symbol ->+            lookupSymbol symbol =<< getAsyncSymbolDb asyncSymbolDb+        -- other commands are handled here+        x              -> ghcCommands x      gmPutStr res >> gmPutStrLn "OK" >> liftIO (hFlush stdout)-    legacyInteractiveLoop symdbreq world'+    legacyInteractiveLoop asyncSymbolDb world'  where-   interactiveHandlers =-          [ GHandler $ \e@(FatalError _) -> throw e-          , GHandler $ \e@(ExitSuccess) -> throw e-          , GHandler $ \e@(ExitFailure _) -> throw e+    interactiveHandlers =+          [ GHandler $ \(e :: ExitCode) -> throw e+          , GHandler $ \(InvalidCommandLine e) -> do+              let err = notGood $ either ("Invalid command line: "++) Prelude.id e+              liftIO $ do+                putStr err+                exitFailure           , GHandler $ \(SomeException e) -> gmErrStrLn (show e) >> return ""           ]+    notGood msg = "NG " ++ escapeNewlines msg+    escapeNewlines = replace "\n" "\\n" . replace "\\n" "\\\\n"+    replace needle replacement = intercalate replacement . splitOn needle  getFileSourceFromStdin :: IO String getFileSourceFromStdin = do-  let loop' acc = do-        line <- getLine-        if not (null line) && last line == '\EOT'-        then return $ acc ++ init line-        else loop' (acc++line++"\n")-  loop' ""+  linesIn <- readStdin'+  return (intercalate "\n" linesIn)+  where+    readStdin' = do+      x <- getLine+      if x/="\EOT"+        then fmap (x:) readStdin'+        else return []  -- Someone please already rewrite the cmdline parsing code *weep* :'(-wrapGhcCommands :: (IOish m, GmOut m) => Options -> [String] -> m ()-wrapGhcCommands _opts []            = fatalError "No command given (try --help)"-wrapGhcCommands _opts ("root":_) = gmPutStr =<< rootInfo-wrapGhcCommands opts args = do+wrapGhcCommands :: (IOish m, GmOut m) => Options -> GhcModCommands -> m ()+wrapGhcCommands _opts CmdRoot = gmPutStr =<< rootInfo+wrapGhcCommands opts cmd =     handleGmError $ runGhcModT opts $ handler $ do       forM_ (reverse $ optFileMappings opts) $         uncurry loadMMappedFiles -      ghcCommands args+      gmPutStr =<< ghcCommands cmd  where    handleGmError action = do      (e, _l) <- liftIO . evaluate =<< action@@ -536,37 +131,39 @@        loadMappedFileSource from src  -ghcCommands :: IOish m => [String] -> GhcModT m ()-ghcCommands []         = fatalError "No command given (try --help)"-ghcCommands (cmd:args) = gmPutStr =<< action args- where-   action = case cmd of-     _ | cmd == "list" || cmd == "modules" -> modulesCmd-     "lang"    -> languagesCmd-     "flag"    -> flagsCmd-     "browse"  -> browseCmd-     "check"   -> checkSyntaxCmd-     "expand"  -> expandTemplateCmd-     "debug"   -> debugInfoCmd-     "debug-component" -> componentInfoCmd-     "info"    -> infoCmd-     "type"    -> typesCmd-     "split"   -> splitsCmd-     "sig"     -> sigCmd-     "refine"  -> refineCmd-     "auto"    -> autoCmd-     "find"    -> findSymbolCmd-     "lint"    -> lintCmd---     "root"    -> rootInfoCmd-     "doc"     -> pkgDocCmd-     "dumpsym" -> dumpSymbolCmd-     "boot"    -> bootCmd-     "legacy-interactive" -> legacyInteractiveCmd---     "nuke-caches" -> nukeCachesCmd-     _         -> fatalError $ "unknown command: `" ++ cmd ++ "'"--newtype FatalError = FatalError String deriving (Show, Typeable)-instance Exception FatalError+ghcCommands :: IOish m => GhcModCommands -> GhcModT m String+-- ghcCommands cmd = action args+ghcCommands (CmdLang) = languages+ghcCommands (CmdFlag) = flags+ghcCommands (CmdDebug) = debugInfo+ghcCommands (CmdDebugComponent ts) = componentInfo ts+ghcCommands (CmdBoot) = boot+-- ghcCommands (CmdNukeCaches) = nukeCaches >> return ""+-- ghcCommands (CmdRoot) = undefined -- handled in wrapGhcCommands+ghcCommands (CmdLegacyInteractive) = legacyInteractive >> return ""+ghcCommands (CmdModules detail) = modules detail+ghcCommands (CmdDumpSym) = dumpSymbol >> return ""+ghcCommands (CmdFind symb) = findSymbol symb+ghcCommands (CmdDoc m) = pkgDoc m+ghcCommands (CmdLint opts file) = lint opts file+ghcCommands (CmdBrowse opts ms) = concat <$> browse opts `mapM` ms+ghcCommands (CmdCheck files) = checkSyntax files+ghcCommands (CmdExpand files) = expandTemplate files+ghcCommands (CmdInfo file symb) = info file $ Expression symb+ghcCommands (CmdType file (line, col)) = types file line col+ghcCommands (CmdSplit file (line, col)) = splits file line col+ghcCommands (CmdSig file (line, col)) = sig file line col+ghcCommands (CmdAuto file (line, col)) = auto file line col+ghcCommands (CmdRefine file (line, col) expr) = refine file line col $ Expression expr+-- interactive-only commands+ghcCommands (CmdMapFile f) =+      liftIO getFileSourceFromStdin+  >>= loadMappedFileSource f+  >>  return ""+ghcCommands (CmdUnmapFile f) = unloadMappedFile f >> return ""+ghcCommands (CmdQuit) = liftIO exitSuccess+ghcCommands (CmdTest file) = test file+ghcCommands cmd = throw $ InvalidCommandLine $ Left $ show cmd  newtype InvalidCommandLine = InvalidCommandLine (Either String String)     deriving (Show, Typeable)@@ -574,117 +171,6 @@  exitError :: (MonadIO m, GmOut m) => String -> m a exitError msg = gmErrStrLn (dropWhileEnd (=='\n') msg) >> liftIO exitFailure--fatalError :: String -> a-fatalError s = throw $ FatalError $ "ghc-mod: " ++ s--withParseCmd :: IOish m-             => [OptDescr (Options -> Either [String] Options)]-             -> ([String] -> GhcModT m a)-             -> [String]-             -> GhcModT m a-withParseCmd spec action args  = do-  (opts', rest) <- parseCommandArgs spec args <$> options-  withOptions (const opts') $ action rest--withParseCmd' :: (IOish m, ExceptionMonad m)-              => String-              -> [OptDescr (Options -> Either [String] Options)]-              -> ([String] -> GhcModT m a)-              -> [String]-              -> GhcModT m a-withParseCmd' cmd spec action args =-    catchArgs cmd $ withParseCmd spec action args--catchArgs :: (Monad m, ExceptionMonad m) => String -> m a -> m a-catchArgs cmd action =-    action `gcatch` \(PatternMatchFail _) ->-        throw $ InvalidCommandLine (Left cmd)--modulesCmd, languagesCmd, flagsCmd, browseCmd, checkSyntaxCmd, expandTemplateCmd,-  debugInfoCmd, componentInfoCmd, infoCmd, typesCmd, splitsCmd, sigCmd,-  refineCmd, autoCmd, findSymbolCmd, lintCmd, pkgDocCmd,-  dumpSymbolCmd, bootCmd, legacyInteractiveCmd, nukeCachesCmd-  :: IOish m => [String] -> GhcModT m String--modulesCmd    = withParseCmd' "modules" s $ \[] -> modules- where s = modulesArgSpec-languagesCmd  = withParseCmd' "lang"    [] $ \[] -> languages-flagsCmd      = withParseCmd' "flag"    [] $ \[] -> flags-debugInfoCmd  = withParseCmd' "debug"   [] $ \[] -> debugInfo-componentInfoCmd = withParseCmd' "debugComponent" [] $ \ts -> componentInfo ts--- internal-bootCmd       = withParseCmd' "boot" [] $ \[] -> boot-nukeCachesCmd = withParseCmd' "nuke-caches" [] $ \[] -> nukeCaches >> return ""--dumpSymbolCmd     = withParseCmd' "dump" [] $ \[tmpdir] -> dumpSymbol tmpdir-findSymbolCmd     = withParseCmd' "find" [] $ \[sym]  -> findSymbol sym-pkgDocCmd         = withParseCmd' "doc"  [] $ \[mdl]  -> pkgDoc mdl-lintCmd           = withParseCmd' "lint" s  $ \[file] -> lint file- where s = hlintArgSpec-browseCmd         = withParseCmd s $ \mdls -> concat <$> browse `mapM` mdls- where s = browseArgSpec-checkSyntaxCmd    = withParseCmd [] $ checkAction checkSyntax-expandTemplateCmd = withParseCmd [] $ checkAction expandTemplate--typesCmd      = withParseCmd [] $ locAction  "type"  types-splitsCmd     = withParseCmd [] $ locAction  "split" splits-sigCmd        = withParseCmd [] $ locAction  "sig"    sig-autoCmd       = withParseCmd [] $ locAction  "auto"   auto-refineCmd     = withParseCmd [] $ locAction' "refine" refine--infoCmd       = withParseCmd [] $ action-  where action [file,_,expr] = info file $ Expression expr-        action [file,expr]   = info file $ Expression expr-        action _ = throw $ InvalidCommandLine (Left "info")--legacyInteractiveCmd = withParseCmd [] go- where-   go [] =-       legacyInteractive >> return ""-   go ("help":[]) =-       return usage-   go ("version":[]) =-       return ghcModiVersion-   go _ = throw $ InvalidCommandLine (Left "legacy-interactive")--checkAction :: ([t] -> a) -> [t] -> a-checkAction _ []         = throw $ InvalidCommandLine (Right "No files given.")-checkAction action files = action files--locAction :: String -> (String -> Int -> Int -> a) -> [String] -> a-locAction _ action [file,_,line,col] = action file (read line) (read col)-locAction _ action [file,  line,col] = action file (read line) (read col)-locAction cmd _ _ = throw $ InvalidCommandLine (Left cmd)--locAction' :: String -> (String -> Int -> Int -> Expression -> a) -> [String] -> a-locAction' _ action [f,_,line,col,expr] = action f (read line) (read col) (Expression expr)-locAction' _ action [f,  line,col,expr] = action f (read line) (read col) (Expression expr)-locAction' cmd _ _ = throw $ InvalidCommandLine (Left cmd)---modulesArgSpec :: [OptDescr (Options -> Either [String] Options)]-modulesArgSpec =-    [ option "d" ["detailed"] "Print package modules belong to." $-             NoArg $ \o -> Right $ o { optDetailed = True }-    ]---hlintArgSpec :: [OptDescr (Options -> Either [String] Options)]-hlintArgSpec =-    [ option "h" ["hlintOpt"] "Option to be passed to hlint" $-             reqArg "hlintOpt" $ \h o -> Right $ o { optHlintOpts = h : optHlintOpts o }-    ]--browseArgSpec :: [OptDescr (Options -> Either [String] Options)]-browseArgSpec =-    [ option "o" ["operators"] "Also print operators." $-             NoArg $ \o -> Right $ o { optOperators = True }-    , option "d" ["detailed"] "Print symbols with accompanying signature." $-             NoArg $ \o -> Right $ o { optDetailed = True }-    , option "q" ["qualified"] "Qualify symbols" $-             NoArg $ \o -> Right $ o { optQualified = True }-    ]  nukeCaches :: IOish m => GhcModT m () nukeCaches = do
+ src/GHCMod/Options.hs view
@@ -0,0 +1,201 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015  Nikolay Yakimov <root@livid.pp.ru>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}++module GHCMod.Options (+  parseArgs,+  parseArgsInteractive,+  GhcModCommands(..)+) where++import Options.Applicative+import Options.Applicative.Types+import Language.Haskell.GhcMod.Types+import Control.Arrow+import Data.Char (toUpper, toLower)+import Data.List (intercalate)+import Language.Haskell.GhcMod.Read+import GHCMod.Options.Commands+import GHCMod.Version+import GHCMod.Options.DocUtils+import GHCMod.Options.Help+import GHCMod.Options.ShellParse++parseArgs :: IO (Options, GhcModCommands)+parseArgs =+  execParser opts+  where+    opts = info (argAndCmdSpec <**> helpVersion)+           $$  fullDesc+           <=> header "ghc-mod: Happy Haskell Programming"++parseArgsInteractive :: String -> Either String GhcModCommands+parseArgsInteractive args =+  handle $ execParserPure (prefs idm) opts $ parseCmdLine args+  where+    opts = info interactiveCommandsSpec $$ fullDesc+    handle (Success a) = Right a+    handle (Failure failure) =+          Left $ fst $ renderFailure failure ""+    handle _ = Left "Completion invoked"++helpVersion :: Parser (a -> a)+helpVersion =+      helper+  <*> abortOption (InfoMsg ghcModVersion)+      $$  long "version"+      <=> help "Print the version of the program."+  <*> argument r+      $$  value id+      <=> metavar ""+  where+    r :: ReadM (a -> a)+    r = do+      v <- readerAsk+      case v of+        "help" -> readerAbort ShowHelpText+        "version" -> readerAbort $ InfoMsg ghcModVersion+        _ -> return id++argAndCmdSpec :: Parser (Options, GhcModCommands)+argAndCmdSpec = (,) <$> globalArgSpec <*> commandsSpec++splitOn :: Eq a => a -> [a] -> ([a], [a])+splitOn c = second (drop 1) . break (==c)++logLevelParser :: Parser GmLogLevel+logLevelParser =+    logLevelSwitch <*>+           logLevelOption+      <||> silentSwitch+  where+    logLevelOption =+      option parseLL+        $$  long "verbose"+        <=> metavar "LEVEL"+        <=> value GmWarning+        <=> showDefaultWith showLL+        <=> help' $$$ do+          "Set log level ("+            <> int' (fromEnum (minBound :: GmLogLevel))+            <> "-"+            <> int' (fromEnum (maxBound :: GmLogLevel))+            <> ")"+          "You can also use strings (case-insensitive):"+          para'+            $ intercalate ", "+            $ map showLL ([minBound..maxBound] :: [GmLogLevel])+    logLevelSwitch =+      repeatAp succ' . length <$> many $$ flag' ()+        $$  short 'v'+        <=> help "Increase log level"+    silentSwitch = flag' GmSilent+        $$  long "silent"+        <=> short 's'+        <=> help "Be silent, set log level to 'silent'"+    showLL = drop 2 . map toLower . show+    repeatAp f n = foldr (.) id (replicate n f)+    succ' x | x == maxBound = x+            | otherwise     = succ x+    parseLL = do+      v <- readerAsk+      let+        il'= toEnum . min maxBound <$> readMaybe v+        ll' = readMaybe ("Gm" ++ capFirst v)+      maybe (readerError $ "Not a log level \"" ++ v ++ "\"") return $ ll' <|> il'+    capFirst (h:t) = toUpper h : map toLower t+    capFirst [] = []++outputOptsSpec :: Parser OutputOpts+outputOptsSpec = OutputOpts+      <$> logLevelParser+      <*> flag PlainStyle LispStyle+          $$  long "tolisp"+          <=> short 'l'+          <=> help "Format output as an S-Expression"+      <*> LineSeparator <$$> strOption+          $$  long "boundary"+          <=> long "line-separator"+          <=> short 'b'+          <=> metavar "SEP"+          <=> value "\0"+          <=> showDefault+          <=> help "Output line separator"+      <*> optional $$ splitOn ',' <$$> strOption+          $$  long "line-prefix"+          <=> metavar "OUT,ERR"+          <=> help "Output prefixes"++programsArgSpec :: Parser Programs+programsArgSpec = Programs+      <$> strOption+          $$  long "with-ghc"+          <=> value "ghc"+          <=> showDefault+          <=> help "GHC executable to use"+      <*> strOption+          $$  long "with-ghc-pkg"+          <=> value "ghc-pkg"+          <=> showDefault+          <=> help "ghc-pkg executable to use (only needed when guessing from GHC path fails)"+      <*> strOption+          $$  long "with-cabal"+          <=> value "cabal"+          <=> showDefault+          <=> help "cabal-install executable to use"+      <*> strOption+          $$  long "with-stack"+          <=> value "stack"+          <=> showDefault+          <=> help "stack executable to use"++globalArgSpec :: Parser Options+globalArgSpec = Options+      <$> outputOptsSpec+      <*> programsArgSpec+      <*> many $$ strOption+          $$  long "ghcOpt"+          <=> long "ghc-option"+          <=> short 'g'+          <=> metavar "OPT"+          <=> help "Option to be passed to GHC"+      <*> many fileMappingSpec+  where+    fileMappingSpec =+      getFileMapping . splitOn '=' <$> strOption+        $$  long "map-file"+        <=> metavar "MAPPING"+        <=> fileMappingHelp+    fileMappingHelp = help' $ do+        "Redirect one file to another"+        "--map-file \"file1.hs=file2.hs\""+        indent 4 $ do+          "can be used to tell ghc-mod"+            \\ "that it should take source code"+            \\ "for `file1.hs` from `file2.hs`."+          "`file1.hs` can be either full path,"+            \\ "or path relative to project root."+          "`file2.hs` has to be either relative to project root,"+            \\  "or full path (preferred)"+        "--map-file \"file.hs\""+        indent 4 $ do+          "can be used to tell ghc-mod that it should take"+            \\ "source code for `file.hs` from stdin. File end"+            \\ "marker is `\\n\\EOT\\n`, i.e. `\\x0A\\x04\\x0A`."+            \\ "`file.hs` may or may not exist, and should be"+            \\ "either full path, or relative to project root."+    getFileMapping = second (\i -> if null i then Nothing else Just i)
+ src/GHCMod/Options/Commands.hs view
@@ -0,0 +1,292 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015  Nikolay Yakimov <root@livid.pp.ru>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}++module GHCMod.Options.Commands where++import Options.Applicative+import Options.Applicative.Types+import Options.Applicative.Builder.Internal+import Language.Haskell.GhcMod.Types+import Language.Haskell.GhcMod.Read+import GHCMod.Options.DocUtils+import GHCMod.Options.Help++type Symbol = String+type Expr = String+type Module = String+type Line = Int+type Col = Int+type Point = (Line, Col)++data GhcModCommands =+    CmdLang+  | CmdFlag+  | CmdDebug+  | CmdBoot+  | CmdNukeCaches+  | CmdRoot+  | CmdLegacyInteractive+  | CmdModules Bool+  | CmdDumpSym+  | CmdFind Symbol+  | CmdDoc Module+  | CmdLint LintOpts FilePath+  | CmdBrowse BrowseOpts [Module]+  | CmdDebugComponent [String]+  | CmdCheck [FilePath]+  | CmdExpand [FilePath]+  | CmdInfo FilePath Symbol+  | CmdType FilePath Point+  | CmdSplit FilePath Point+  | CmdSig FilePath Point+  | CmdAuto FilePath Point+  | CmdRefine FilePath Point Expr+  | CmdTest FilePath+  -- interactive-only commands+  | CmdMapFile FilePath+  | CmdUnmapFile FilePath+  | CmdQuit+  deriving (Show)++commandsSpec :: Parser GhcModCommands+commandsSpec =+  hsubparser commands++commands :: Mod CommandFields GhcModCommands+commands =+       command "lang"+          $$  info (pure CmdLang)+          $$  progDesc "List all known GHC language extensions"+    <> command "flag"+          $$  info (pure CmdFlag)+          $$  progDesc "List GHC -f<foo> flags"+    <> command "debug"+          $$  info (pure CmdDebug)+          $$  progDesc' $$$ do+              "Print debugging information. Please include"+                \\ "the output in any bug reports you submit"+    <> command "debug-component"+          $$  info debugComponentArgSpec+          $$  progDesc' $$$ do+              "Debugging information related to cabal component"+                \\ "resolution"+    <> command "boot"+          $$  info (pure CmdBoot)+          $$  progDesc "Internal command used by the emacs frontend"+    -- <> command "nuke-caches"+    --       $$  info (pure CmdNukeCaches) idm+    <> command "root"+          $$  info (pure CmdRoot)+          $$  progDesc'+              "Try to find the project directory."+          <=> desc $$$ do+              "For Cabal projects this is the"+                \\ "directory containing the cabal file, for projects"+                \\ "that use a cabal sandbox but have no cabal file"+                \\ "this is the directory containing the cabal.sandbox.config"+                \\ "file and otherwise this is the current directory"+    <> command "legacy-interactive"+          $$  info legacyInteractiveArgSpec+          $$  progDesc "ghc-modi compatibility mode"+    <> command "list"+          $$  info modulesArgSpec+          $$  progDesc "List all visible modules"+    <> command "modules"+          $$  info modulesArgSpec+          $$  progDesc "List all visible modules"+    <> command "dumpsym"+          $$  info (pure CmdDumpSym) idm+    <> command "find"+          $$  info findArgSpec+          $$  progDesc "List all modules that define SYMBOL"+    <> command "doc"+          $$  info docArgSpec+          $$  progDesc' $$$ do+              "Try finding the html documentation directory"+                \\ "for the given MODULE"+    <> command "lint"+          $$  info lintArgSpec+          $$  progDesc "Check files using `hlint'"+    <> command "browse"+          $$  info browseArgSpec+          $$  progDesc "List symbols in a module"+    <> command "check"+          $$  info checkArgSpec+          $$  progDesc' $$$ do+              "Load the given files using GHC and report errors/warnings,"+                \\ "but don't produce output files"+    <> command "expand"+          $$  info expandArgSpec+          $$  progDesc "Like `check' but also pass `-ddump-splices' to GHC"+    <> command "info"+          $$  info infoArgSpec+          $$  progDesc' $$$ do+              "Look up an identifier in the context"+                \\ "of FILE (like ghci's `:info')"+    <> command "type"+          $$  info typeArgSpec+          $$  progDesc "Get the type of the expression under (LINE,COL)"+    <> command "split"+          $$  info splitArgSpec+          $$  progDesc+                  "Split a function case by examining a type's constructors"+          <=> desc $$$ do+                "For example given the following code snippet:"+                code $ do+                  "f :: [a] -> a"+                  "f x = _body"+                "would be replaced by:"+                code $ do+                  "f :: [a] -> a"+                  "f [] = _body"+                  "f (x:xs) = _body"+                "(See https://github.com/kazu-yamamoto/ghc-mod/pull/274)"+    <> command "sig"+          $$  info sigArgSpec+          $$  progDesc "Generate initial code given a signature"+          <=> desc $$$ do+              "For example when (LINE,COL) is on the"+                \\ "signature in the following code snippet:"+              code "func :: [a] -> Maybe b -> (a -> b) -> (a,b)"+              "ghc-mod would add the following on the next line:"+              code "func x y z f = _func_body"+              "(See: https://github.com/kazu-yamamoto/ghc-mod/pull/274)"+    <> command "auto"+          $$  info autoArgSpec+          $$  progDesc "Try to automatically fill the contents of a hole"+    <> command "refine"+          $$  info refineArgSpec+          $$  progDesc "Refine the typed hole at (LINE,COL) given EXPR"+          <=> desc $$$ do+              "For example if EXPR is `filter', which has type"+                \\ "`(a -> Bool) -> [a] -> [a]' and (LINE,COL) is on"+                \\ " the hole `_body' in the following code snippet:"+              code $ do+                "filterNothing :: [Maybe a] -> [a]"+                "filterNothing xs = _body"+              "ghc-mod changes the code to get a value of type"+                \\ " `[a]', which results in:"+              code "filterNothing xs = filter _body_1 _body_2"+              "(See also: https://github.com/kazu-yamamoto/ghc-mod/issues/311)"+    <> command "test"+          $$  info (CmdTest <$> strArg "FILE")+          $$  progDesc ""+++interactiveCommandsSpec :: Parser GhcModCommands+interactiveCommandsSpec =+    hsubparser'+        $  commands+        <> command "map-file"+              $$  info mapArgSpec+              $$  progDesc "tells ghc-modi to read `file.hs` source from stdin"+              <=> desc $$$ do+                "Works the same as second form of"+                  \\ "`--map-file` CLI option."+        <> command "unmap-file"+              $$  info unmapArgSpec+              $$  progDesc' $$$ do+                    "unloads previously mapped file,"+                      \\ "so that it's no longer mapped."+              <=> desc $$$ do+                    "`file.hs` can be full path or relative"+                      \\ "to project root, either will work."+        <> command "quit"+              $$ info (pure CmdQuit)+              $$ progDesc "Exit interactive mode"+        <> command ""+              $$ info (pure CmdQuit) idm++strArg :: String -> Parser String+strArg = argument str . metavar++filesArgsSpec :: ([String] -> b) -> Parser b+filesArgsSpec x = x <$> some (strArg "FILES..")++locArgSpec :: (String -> (Int, Int) -> b) -> Parser b+locArgSpec x = x+  <$> strArg "FILE"+  <*> ( (,)+        <$> argument int (metavar "LINE")+        <*> argument int (metavar "COL")+      )++modulesArgSpec, docArgSpec, findArgSpec,+  lintArgSpec, browseArgSpec, checkArgSpec, expandArgSpec,+  infoArgSpec, typeArgSpec, autoArgSpec, splitArgSpec,+  sigArgSpec, refineArgSpec, debugComponentArgSpec,+  mapArgSpec, unmapArgSpec, legacyInteractiveArgSpec :: Parser GhcModCommands++modulesArgSpec = CmdModules+  <$> switch+        $$  long "detailed"+        <=> short 'd'+        <=> help "Print package modules belong to"+findArgSpec = CmdFind <$> strArg "SYMBOL"+docArgSpec = CmdDoc <$> strArg "MODULE"+lintArgSpec = CmdLint+  <$> LintOpts <$$> many $$ strOption+      $$  long "hlintOpt"+      <=> short 'h'+      <=> help "Option to be passed to hlint"+  <*> strArg "FILE"+browseArgSpec = CmdBrowse+  <$> (BrowseOpts+        <$> switch+            $$  long "operators"+            <=> short 'o'+            <=> help "Also print operators"+        <*> switch+            $$  long "detailed"+            <=> short 'd'+            <=> help "Print symbols with accompanying signature"+        <*> switch+            $$  long "qualified"+            <=> short 'q'+            <=> help "Qualify symbols"+      )+  <*> some (strArg "MODULE")+debugComponentArgSpec = filesArgsSpec CmdDebugComponent+checkArgSpec = filesArgsSpec CmdCheck+expandArgSpec = filesArgsSpec CmdExpand+infoArgSpec = CmdInfo+    <$> strArg "FILE"+    <*> strArg "SYMBOL"+typeArgSpec = locArgSpec CmdType+autoArgSpec = locArgSpec CmdAuto+splitArgSpec = locArgSpec CmdSplit+sigArgSpec = locArgSpec CmdSig+refineArgSpec = locArgSpec CmdRefine <*> strArg "SYMBOL"+mapArgSpec = CmdMapFile <$> strArg "FILE"+unmapArgSpec = CmdUnmapFile <$> strArg "FILE"+legacyInteractiveArgSpec = const CmdLegacyInteractive <$>+  optional interactiveCommandsSpec++hsubparser' :: Mod CommandFields a -> Parser a+hsubparser' m = mkParser d g rdr+  where+    Mod _ d g = m `mappend` metavar ""+    (cmds, subs) = mkCommand m+    rdr = CmdReader cmds (fmap add_helper . subs)+    add_helper pinfo = pinfo+      { infoParser = infoParser pinfo <**> helper }++int :: ReadM Int+int = do+  v <- readerAsk+  maybe (readerError $ "Not a number \"" ++ v ++ "\"") return $ readMaybe v
+ src/GHCMod/Options/DocUtils.hs view
@@ -0,0 +1,48 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015  Nikolay Yakimov <root@livid.pp.ru>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.++module GHCMod.Options.DocUtils (+  ($$),+  ($$$),+  (<=>),+  (<$$>),+  (<||>)+) where++import Options.Applicative+import Data.Monoid+import Prelude++infixl 6 <||>+infixr 7 <$$>+infixr 7 $$+infixr 8 <=>+infixr 9 $$$++($$) :: (a -> b) -> a -> b+($$) = ($)++($$$) :: (a -> b) -> a -> b+($$$) = ($)++(<||>) :: Alternative a => a b -> a b -> a b+(<||>) = (<|>)++(<=>) :: Monoid m => m -> m -> m+(<=>) = (<>)++(<$$>) :: Functor f => (a -> b) -> f a -> f b+(<$$>) = (<$>)
+ src/GHCMod/Options/Help.hs view
@@ -0,0 +1,79 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015  Nikolay Yakimov <root@livid.pp.ru>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.+{-# LANGUAGE OverloadedStrings, FlexibleInstances, GeneralizedNewtypeDeriving #-}++module GHCMod.Options.Help where++import Options.Applicative+import Options.Applicative.Help.Pretty (Doc)+import qualified Options.Applicative.Help.Pretty as PP+import Control.Monad.State+import GHC.Exts( IsString(..) )+import Data.Maybe+import Data.Monoid+import Prelude++newtype MyDocM s a = MyDoc {unwrapState :: State s a}+  deriving (Monad, Functor, Applicative, MonadState s)+type MyDoc = MyDocM (Maybe Doc) ()++instance IsString (MyDocM (Maybe Doc) a) where+    fromString = append . para++instance Monoid (MyDocM (Maybe Doc) ()) where+  mappend a b = append $ doc a <> doc b+  mempty = append PP.empty++para :: String -> Doc+para = PP.fillSep . map PP.text . words++append :: Doc -> MyDocM (Maybe Doc) a+append s = modify m >> return undefined+  where+    m :: Maybe Doc -> Maybe Doc+    m Nothing = Just s+    m (Just old) = Just $ old PP..$. s++infixr 7 \\+(\\) :: MyDoc -> MyDoc -> MyDoc+(\\) a b = append $ doc a PP.<+> doc b++doc :: MyDoc -> Doc+doc = fromMaybe PP.empty . flip execState Nothing . unwrapState++help' :: MyDoc -> Mod f a+help' = helpDoc . Just . doc++desc :: MyDoc -> InfoMod a+desc = footerDoc . Just . doc . indent 2++code :: MyDoc -> MyDoc+code x = do+  _ <- " "+  indent 4 x+  " "++progDesc' :: MyDoc -> InfoMod a+progDesc' = progDescDoc . Just . doc++indent :: Int -> MyDoc -> MyDoc+indent n = append . PP.indent n . doc++int' :: Int -> MyDoc+int' = append . PP.int++para' :: String -> MyDoc+para' = append . para
+ src/GHCMod/Options/ShellParse.hs view
@@ -0,0 +1,44 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015  Nikolay Yakimov <root@livid.pp.ru>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.+module GHCMod.Options.ShellParse (parseCmdLine) where++import Data.Char+import Data.List++go :: String -> String -> [String] -> Bool -> [String]+-- result+go [] curarg accargs _ = reverse $ reverse curarg : accargs+go (c:cl) curarg accargs quotes+  -- open quotes+  | c == '\STX', not quotes+  = go cl curarg accargs True+  -- close quotes+  | c == '\ETX', quotes+  = go cl curarg accargs False+  -- space separates arguments outside quotes+  | isSpace c, not quotes+  = if null curarg+      then go cl curarg accargs quotes+      else go cl [] (reverse curarg : accargs) quotes+  -- general character+  | otherwise = go cl (c:curarg) accargs quotes++parseCmdLine :: String -> [String]+parseCmdLine comline'+  | Just comline <- stripPrefix "ascii-escape " $ dropWhile isSpace comline'+  = go (dropWhile isSpace comline) [] [] False+parseCmdLine [] = [""]+parseCmdLine comline = words comline
+ src/GHCMod/Version.hs view
@@ -0,0 +1,32 @@+-- ghc-mod: Making Haskell development *more* fun+-- Copyright (C) 2015  Nikolay Yakimov <root@livid.pp.ru>+--+-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU Affero General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- (at your option) any later version.+--+-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+-- GNU Affero General Public License for more details.+--+-- You should have received a copy of the GNU Affero General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.++module GHCMod.Version where++import Paths_ghc_mod+import Data.Version (showVersion)+import Config (cProjectVersion)++progVersion :: String -> String+progVersion pf =+    "ghc-mod"++pf++" version " ++ showVersion version ++ " compiled by GHC "+                               ++ cProjectVersion++ghcModVersion :: String+ghcModVersion = progVersion ""++ghcModiVersion :: String+ghcModiVersion = progVersion "i"
src/GHCModi.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables, DeriveDataTypeable #-}+{-# LANGUAGE ScopedTypeVariables #-}  -- | WARNING -- This program is deprecated, use `ghc-mod legacy-interactive` instead.
− src/Misc.hs
@@ -1,48 +0,0 @@-{-# LANGUAGE DeriveDataTypeable, CPP #-}--module Misc (-    SymDbReq-  , newSymDbReq-  , getDb-  , checkDb-  ) where--import Control.Concurrent.Async (Async, async, wait)-import Data.IORef (IORef, newIORef, readIORef, writeIORef)-import Prelude--import Language.Haskell.GhcMod-import Language.Haskell.GhcMod.Internal hiding (MonadIO,liftIO)-import Language.Haskell.GhcMod.Types-import Language.Haskell.GhcMod.Monad--------------------------------------------------------------------type SymDbReqAction = (Either GhcModError SymbolDb, GhcModLog)-data SymDbReq = SymDbReq (IORef (Async SymDbReqAction)) (IO SymDbReqAction)--newSymDbReq :: Options -> GhcModOut -> FilePath -> IO SymDbReq-newSymDbReq opt gmo tmpdir = do-    let act = runGmOutT' gmo $ runGhcModT opt $ loadSymbolDb tmpdir-    req <- async act-    ref <- newIORef req-    return $ SymDbReq ref act--getDb :: IOish m => SymDbReq -> GhcModT m SymbolDb-getDb (SymDbReq ref _) = do-    req <- liftIO $ readIORef ref-    -- 'wait' really waits for the asynchronous action at the fist time.-    -- Then it reads a cached value from the second time.-    hoistGhcModT =<< liftIO (wait req)--checkDb :: IOish m => SymDbReq -> SymbolDb -> GhcModT m SymbolDb-checkDb (SymDbReq ref act) db = do-    outdated <- isOutdated db-    if outdated then do-        -- async and wait here is unnecessary because this is essentially-        -- synchronous. But Async can be used a cache.-        req <- liftIO $ async act-        liftIO $ writeIORef ref req-        hoistGhcModT =<< liftIO (wait req)-      else-        return db
test/BrowseSpec.hs view
@@ -12,23 +12,23 @@ spec = do     describe "browse Data.Map" $ do         it "contains at least `differenceWithKey'" $ do-            syms <- runD $ lines <$> browse "Data.Map"+            syms <- runD $ lines <$> browse defaultBrowseOpts "Data.Map"             syms `shouldContain` ["differenceWithKey"]      describe "browse -d Data.Either" $ do         it "contains functions (e.g. `either') including their type signature" $ do-            syms <- run defaultOptions { optDetailed = True }-                    $ lines <$> browse "Data.Either"+            syms <- runD+                    $ lines <$> browse defaultBrowseOpts{ optBrowseDetailed = True } "Data.Either"             syms `shouldContain` ["either :: (a -> c) -> (b -> c) -> Either a b -> c"]          it "contains type constructors (e.g. `Left') including their type signature" $ do-            syms <- run defaultOptions { optDetailed = True}-                    $ lines <$> browse "Data.Either"+            syms <- runD+                    $ lines <$> browse defaultBrowseOpts{ optBrowseDetailed = True } "Data.Either"             syms `shouldContain` ["Left :: a -> Either a b"]      describe "`browse' in a project directory" $ do         it "can list symbols defined in a a local module" $ do             withDirectory_ "test/data/ghc-mod-check/" $ do-                syms <- runD $ lines <$> browse "Data.Foo"+                syms <- runD $ lines <$> browse defaultBrowseOpts "Data.Foo"                 syms `shouldContain` ["foo"]                 syms `shouldContain` ["fibonacci"]
test/FileMappingSpec.hs view
@@ -122,13 +122,13 @@           withDirectory_ "test/data/file-mapping" $ do             res <- runD $ do               loadMappedFile "File.hs" "File_Redir_Lint.hs"-              lint "File.hs"+              lint defaultLintOpts "File.hs"             res `shouldBe` "File.hs:4:1: Error: Eta reduce\NULFound:\NUL  func a b = (*) a b\NULWhy not:\NUL  func = (*)\n"         it "lints in-memory file if one is specified and outputs original filename" $ do           withDirectory_ "test/data/file-mapping" $ do             res <- runD $ do               loadMappedFileSource "File.hs" "func a b = (++) a b\n"-              lint "File.hs"+              lint defaultLintOpts "File.hs"             res `shouldBe` "File.hs:1:1: Error: Eta reduce\NULFound:\NUL  func a b = (++) a b\NULWhy not:\NUL  func = (++)\n"         it "shows types of the expression for redirected files" $ do             let tdir = "test/data/file-mapping"@@ -163,6 +163,14 @@               mapM_ (uncurry loadMappedFile) fm               checkSyntax ["File.hs"]             res `shouldBe` "File.hs:3:1:Warning: Top-level binding with no type signature: main :: IO ()\n"+        it "works with full path as well" $ do+          withDirectory_ "test/data/file-mapping/preprocessor" $ do+            cwd <- getCurrentDirectory+            let fm = [("File.hs", cwd </> "File_Redir.hs")]+            res <- run defaultOptions $ do+              mapM_ (uncurry loadMappedFile) fm+              checkSyntax ["File.hs"]+            res `shouldBe` "File.hs:3:1:Warning: Top-level binding with no type signature: main :: IO ()\n"         it "checks in-memory file" $ do           withDirectory_ "test/data/file-mapping/preprocessor" $ do             src <- readFile "File_Redir.hs"@@ -175,14 +183,14 @@           withDirectory_ "test/data/file-mapping/preprocessor" $ do             res <- runD $ do               loadMappedFile "File.hs" "File_Redir_Lint.hs"-              lint "File.hs"+              lint defaultLintOpts "File.hs"             res `shouldBe` "File.hs:6:1: Error: Eta reduce\NULFound:\NUL  func a b = (*) a b\NULWhy not:\NUL  func = (*)\n"         it "lints in-memory file if one is specified and outputs original filename" $ do           withDirectory_ "test/data/file-mapping/preprocessor" $ do             src <- readFile "File_Redir_Lint.hs"             res <- runD $ do               loadMappedFileSource "File.hs" src-              lint "File.hs"+              lint defaultLintOpts "File.hs"             res `shouldBe` "File.hs:6:1: Error: Eta reduce\NULFound:\NUL  func a b = (*) a b\NULWhy not:\NUL  func = (*)\n"       describe "literate haskell tests" $ do         it "checks redirected file if one is specified and outputs original filename" $ do
test/LintSpec.hs view
@@ -8,10 +8,10 @@ spec = do     describe "lint" $ do         it "can detect a redundant import" $ do-            res <- runD $ lint "test/data/hlint/hlint.hs"+            res <- runD $ lint defaultLintOpts "test/data/hlint/hlint.hs"             res `shouldBe` "test/data/hlint/hlint.hs:4:8: Error: Redundant do\NULFound:\NUL  do putStrLn \"Hello, world!\"\NULWhy not:\NUL  putStrLn \"Hello, world!\"\n"          context "when no suggestions are given" $ do             it "doesn't output an empty line" $ do-                res <- runD $ lint "test/data/ghc-mod-check/lib/Data/Foo.hs"+                res <- runD $ lint defaultLintOpts "test/data/ghc-mod-check/lib/Data/Foo.hs"                 res `shouldBe` ""
test/ListSpec.hs view
@@ -10,5 +10,5 @@ spec = do     describe "modules" $ do         it "contains at least `Data.Map'" $ do-            mdls <- runD $ lines <$> modules+            mdls <- runD $ lines <$> modules False             mdls `shouldContain` ["Data.Map"]
test/MonadSpec.hs view
@@ -3,6 +3,8 @@ import Test.Hspec import TestUtils import Control.Monad.Error.Class+import Control.Concurrent+import Control.Exception  spec :: Spec spec = do@@ -15,3 +17,30 @@                          return "hello"                      `catchError` (const $ fail "oh noes")              a `shouldBe` (Left $ GMEString "oh noes")++    describe "runGhcModT" $+        it "throws an exception when run in multiple threads" $ do++          mv_ex :: MVar (Either SomeException ())+              <- newEmptyMVar+          mv_startup_barrier :: MVar () <- newEmptyMVar++          _t1 <- forkOS $ do+                 putMVar mv_startup_barrier ()+                 -- wait (inside GhcModT) for t2 to receive the exception+                 _ <- runD $ liftIO $ readMVar mv_ex+                 return ()++          _t2 <- forkOS $ do+                 readMVar mv_startup_barrier -- wait for t1 to start up+                 res <- try $ runD $ return ()+                 res' <- evaluate res+                 putMVar mv_ex res'++          ex <- takeMVar mv_ex++          isLeft ex `shouldBe` True++isLeft :: Either a b -> Bool+isLeft (Right _) = False+isLeft (Left _) = True
+ test/ShellParseSpec.hs view
@@ -0,0 +1,34 @@+module ShellParseSpec where+++import GHCMod.Options.ShellParse++import Test.Hspec++spec :: Spec+spec =+  describe "parseCmdLine" $ do+    it "splits arguments" $ do+      parseCmdLine "test command line" `shouldBe` ["test", "command", "line"]+      parseCmdLine "ascii-escape test command line" `shouldBe` ["test", "command", "line"]+    it "honors quoted segments if turned on" $+      parseCmdLine "ascii-escape test command line \STXwith quoted segment\ETX"+        `shouldBe` ["test", "command", "line", "with quoted segment"]+    it "doesn't honor quoted segments if turned off" $+      parseCmdLine "test command line \STXwith quoted segment\ETX"+        `shouldBe` words "test command line \STXwith quoted segment\ETX"+    it "squashes multiple spaces" $ do+      parseCmdLine "test       command"+        `shouldBe` ["test", "command"]+      parseCmdLine "ascii-escape           test       command"+        `shouldBe` ["test", "command"]+    it "ingores leading spaces" $ do+      parseCmdLine "     test       command"+        `shouldBe` ["test", "command"]+      parseCmdLine "   ascii-escape           test       command"+        `shouldBe` ["test", "command"]+    it "parses empty string as no argument" $ do+      parseCmdLine ""+        `shouldBe` [""]+      parseCmdLine "ascii-escape "+        `shouldBe` [""]
test/TestUtils.hs view
@@ -43,22 +43,9 @@     Right a ->  return a     Left e -> error $ show e -withSpecCradle :: (IOish m, GmOut m) => FilePath -> (Cradle -> m a) -> m a+withSpecCradle :: (IOish m, GmOut m) => FilePath -> ((Cradle, GhcModLog) -> m a) -> m a withSpecCradle cradledir f = do-    gbracket (findSpecCradle cradledir) (liftIO . cleanupCradle) $ \crdl ->-      bracketWorkingDirectory (cradleRootDir crdl) $-        f crdl--bracketWorkingDirectory ::-    (ExceptionMonad m, MonadIO m) => FilePath -> m c -> m c-bracketWorkingDirectory dir a =-    gbracket (swapWorkingDirectory dir) (liftIO . setCurrentDirectory) (const a)--swapWorkingDirectory :: MonadIO m => FilePath -> m FilePath-swapWorkingDirectory ndir = liftIO $ do-  odir <- getCurrentDirectory >>= canonicalizePath-  setCurrentDirectory $ ndir-  return odir+    gbracket (runJournalT $ findSpecCradle cradledir) (liftIO . cleanupCradle . fst) f  runGhcModTSpec :: Options -> GhcModT IO a -> IO (Either GhcModError a, GhcModLog) runGhcModTSpec opt action = do@@ -69,7 +56,7 @@     => FilePath -> Options -> GhcModT m b -> m (Either GhcModError b, GhcModLog) runGhcModTSpec' dir opt action = liftIO (canonicalizePath dir) >>= \dir' -> do   runGmOutT opt $-    withGhcModEnv' withSpecCradle dir' opt $ \env -> do+    withGhcModEnv' withSpecCradle dir' opt $ \(env,_) -> do       first (fst <$>) <$> runGhcModT' env defaultGhcModState         (gmSetLogLevel (ooptLogLevel $ optOutput opt) >> action)