ide-backend 0.9.0.11 → 0.10.0
raw patch · 96 files changed
+5064/−951 lines, 96 filesdep +monads-tfdep +paralleldep ~aesondep ~ide-backend-commonnew-uploaderPVP ok
version bump matches the API change (PVP)
Dependencies added: monads-tf, parallel
Dependency ranges changed: aeson, ide-backend-common
API changes (from Hackage documentation)
+ IdeSession: IdeCallbacks :: LogFunc -> IdeCallbacks
+ IdeSession: ProgramSearchPathDefault :: ProgramSearchPathEntry
+ IdeSession: ProgramSearchPathDir :: FilePath -> ProgramSearchPathEntry
+ IdeSession: UpdateStatusCrashRestart :: Text -> UpdateStatus
+ IdeSession: UpdateStatusDone :: UpdateStatus
+ IdeSession: UpdateStatusFailed :: Text -> UpdateStatus
+ IdeSession: UpdateStatusProgress :: Progress -> UpdateStatus
+ IdeSession: UpdateStatusRequiredRestart :: UpdateStatus
+ IdeSession: UpdateStatusServerDied :: Text -> UpdateStatus
+ IdeSession: configIdeBackendExeCabal :: SessionConfig -> (ProgramSearchPath, FilePath)
+ IdeSession: configIdeBackendServer :: SessionConfig -> (ProgramSearchPath, FilePath)
+ IdeSession: configLocalWorkingDir :: SessionConfig -> Maybe FilePath
+ IdeSession: data IdeCallbacks
+ IdeSession: data ProgramSearchPathEntry :: *
+ IdeSession: data UpdateStatus :: *
+ IdeSession: defaultIdeCallbacks :: IdeCallbacks
+ IdeSession: ideCallbacksLogFunc :: IdeCallbacks -> LogFunc
+ IdeSession: initSessionWithCallbacks :: IdeCallbacks -> SessionInitParams -> SessionConfig -> IO IdeSession
+ IdeSession: sessionConfigFromEnv :: IO SessionConfig
+ IdeSession: sessionInitDistDir :: SessionInitParams -> !(Maybe FilePath)
+ IdeSession: type ProgramSearchPath = [ProgramSearchPathEntry]
+ IdeSession.Cabal: BuildExeArgs :: PackageDBStack -> [FilePath] -> FilePath -> FilePath -> FilePath -> FilePath -> [FilePath] -> [String] -> [Dependency] -> [ModuleName] -> BuildExeArgs
+ IdeSession.Cabal: ExeCabalDone :: ExitCode -> ExeCabalResponse
+ IdeSession.Cabal: ExeCabalProgress :: Progress -> ExeCabalResponse
+ IdeSession.Cabal: LicenseArgs :: PackageDBStack -> [FilePath] -> [String] -> FilePath -> FilePath -> FilePath -> [(String, (Maybe License, Maybe FilePath, Maybe String))] -> FilePath -> [PackageId] -> LicenseArgs
+ IdeSession.Cabal: ReqExeBuild :: BuildExeArgs -> [(ModuleName, FilePath)] -> ExeCabalRequest
+ IdeSession.Cabal: ReqExeCc :: RunCcArgs -> ExeCabalRequest
+ IdeSession.Cabal: ReqExeDoc :: BuildExeArgs -> ExeCabalRequest
+ IdeSession.Cabal: ReqExeLic :: LicenseArgs -> ExeCabalRequest
+ IdeSession.Cabal: RunCcArgs :: PackageDBStack -> [FilePath] -> FilePath -> FilePath -> FilePath -> FilePath -> FilePath -> FilePath -> [FilePath] -> [String] -> RunCcArgs
+ IdeSession.Cabal: beDistDir :: BuildExeArgs -> FilePath
+ IdeSession.Cabal: beExtraPathDirs :: BuildExeArgs -> [FilePath]
+ IdeSession.Cabal: beGhcOpts :: BuildExeArgs -> [String]
+ IdeSession.Cabal: beLibDeps :: BuildExeArgs -> [Dependency]
+ IdeSession.Cabal: beLoadedMs :: BuildExeArgs -> [ModuleName]
+ IdeSession.Cabal: bePackageDBStack :: BuildExeArgs -> PackageDBStack
+ IdeSession.Cabal: beRelativeIncludes :: BuildExeArgs -> [FilePath]
+ IdeSession.Cabal: beSourcesDir :: BuildExeArgs -> FilePath
+ IdeSession.Cabal: beStderrLog :: BuildExeArgs -> FilePath
+ IdeSession.Cabal: beStdoutLog :: BuildExeArgs -> FilePath
+ IdeSession.Cabal: buildDeps :: Strict Maybe Computed -> IO ([ModuleName], [PackageId])
+ IdeSession.Cabal: buildDotCabal :: FilePath -> [FilePath] -> [String] -> Computed -> IO (String -> Version -> ByteString)
+ IdeSession.Cabal: buildLicsFromPkgs :: Bool -> LicenseArgs -> IO ExitCode
+ IdeSession.Cabal: configureAndBuild :: BuildExeArgs -> [(ModuleName, FilePath)] -> IO ExitCode
+ IdeSession.Cabal: configureAndHaddock :: BuildExeArgs -> IO ExitCode
+ IdeSession.Cabal: data BuildExeArgs
+ IdeSession.Cabal: data ExeCabalRequest
+ IdeSession.Cabal: data ExeCabalResponse
+ IdeSession.Cabal: data LicenseArgs
+ IdeSession.Cabal: data RunCcArgs
+ IdeSession.Cabal: externalDeps :: Monad m => [PackageId] -> m [Dependency]
+ IdeSession.Cabal: generateMacros :: PackageDBStack -> [FilePath] -> IO String
+ IdeSession.Cabal: instance Binary BuildExeArgs
+ IdeSession.Cabal: instance Binary ExeCabalRequest
+ IdeSession.Cabal: instance Binary ExeCabalResponse
+ IdeSession.Cabal: instance Binary ExitCode
+ IdeSession.Cabal: instance Binary LicenseArgs
+ IdeSession.Cabal: instance Binary RunCcArgs
+ IdeSession.Cabal: instance Typeable ExeCabalRequest
+ IdeSession.Cabal: instance Typeable ExeCabalResponse
+ IdeSession.Cabal: liCabalsDir :: LicenseArgs -> FilePath
+ IdeSession.Cabal: liDistDir :: LicenseArgs -> FilePath
+ IdeSession.Cabal: liExtraPathDirs :: LicenseArgs -> [FilePath]
+ IdeSession.Cabal: liLicenseExc :: LicenseArgs -> [String]
+ IdeSession.Cabal: liPackageDBStack :: LicenseArgs -> PackageDBStack
+ IdeSession.Cabal: liPkgs :: LicenseArgs -> [PackageId]
+ IdeSession.Cabal: liStderrLog :: LicenseArgs -> FilePath
+ IdeSession.Cabal: liStdoutLog :: LicenseArgs -> FilePath
+ IdeSession.Cabal: licenseFixed :: LicenseArgs -> [(String, (Maybe License, Maybe FilePath, Maybe String))]
+ IdeSession.Cabal: rcAbsC :: RunCcArgs -> FilePath
+ IdeSession.Cabal: rcAbsObj :: RunCcArgs -> FilePath
+ IdeSession.Cabal: rcDistDir :: RunCcArgs -> FilePath
+ IdeSession.Cabal: rcExtraPathDirs :: RunCcArgs -> [FilePath]
+ IdeSession.Cabal: rcIncludeDirs :: RunCcArgs -> [FilePath]
+ IdeSession.Cabal: rcOptions :: RunCcArgs -> [String]
+ IdeSession.Cabal: rcPackageDBStack :: RunCcArgs -> PackageDBStack
+ IdeSession.Cabal: rcPref :: RunCcArgs -> FilePath
+ IdeSession.Cabal: rcStderrLog :: RunCcArgs -> FilePath
+ IdeSession.Cabal: rcStdoutLog :: RunCcArgs -> FilePath
+ IdeSession.Cabal: runComponentCc :: RunCcArgs -> IO ExitCode
+ IdeSession.Config: ProgramSearchPathDefault :: ProgramSearchPathEntry
+ IdeSession.Config: ProgramSearchPathDir :: FilePath -> ProgramSearchPathEntry
+ IdeSession.Config: SessionConfig :: FilePath -> Maybe FilePath -> [FilePath] -> InProcess -> Bool -> PackageDBStack -> [String] -> [(String, (Maybe License, Maybe FilePath, Maybe String))] -> (String -> IO ()) -> Bool -> (ProgramSearchPath, FilePath) -> (ProgramSearchPath, FilePath) -> SessionConfig
+ IdeSession.Config: configDeleteTempFiles :: SessionConfig -> Bool
+ IdeSession.Config: configDir :: SessionConfig -> FilePath
+ IdeSession.Config: configExtraPathDirs :: SessionConfig -> [FilePath]
+ IdeSession.Config: configGenerateModInfo :: SessionConfig -> Bool
+ IdeSession.Config: configIdeBackendExeCabal :: SessionConfig -> (ProgramSearchPath, FilePath)
+ IdeSession.Config: configIdeBackendServer :: SessionConfig -> (ProgramSearchPath, FilePath)
+ IdeSession.Config: configInProcess :: SessionConfig -> InProcess
+ IdeSession.Config: configLicenseExc :: SessionConfig -> [String]
+ IdeSession.Config: configLicenseFixed :: SessionConfig -> [(String, (Maybe License, Maybe FilePath, Maybe String))]
+ IdeSession.Config: configLocalWorkingDir :: SessionConfig -> Maybe FilePath
+ IdeSession.Config: configLog :: SessionConfig -> String -> IO ()
+ IdeSession.Config: configPackageDBStack :: SessionConfig -> PackageDBStack
+ IdeSession.Config: data ProgramSearchPathEntry :: *
+ IdeSession.Config: data SessionConfig
+ IdeSession.Config: defaultSessionConfig :: SessionConfig
+ IdeSession.Config: sessionConfigFromEnv :: IO SessionConfig
+ IdeSession.Config: type InProcess = Bool
+ IdeSession.Config: type ProgramSearchPath = [ProgramSearchPathEntry]
+ IdeSession.ExeCabalClient: invokeExeCabal :: IdeStaticInfo -> IdeCallbacks -> ExeCabalRequest -> (UpdateStatus -> IO ()) -> IO ExitCode
+ IdeSession.GHC.Client: InProcess :: RpcConversation -> ThreadId -> GhcServer
+ IdeSession.GHC.Client: OutProcess :: RpcServer -> GhcServer
+ IdeSession.GHC.Client: RunActions :: IO (Either ByteString a) -> IO () -> (ByteString -> IO ()) -> IO () -> RunActions a
+ IdeSession.GHC.Client: data GhcServer
+ IdeSession.GHC.Client: data RunActions a
+ IdeSession.GHC.Client: forceCancel :: RunActions a -> IO ()
+ IdeSession.GHC.Client: forceShutdownGhcServer :: GhcServer -> IO ()
+ IdeSession.GHC.Client: forkGhcServer :: [String] -> [FilePath] -> [String] -> IdeStaticInfo -> IdeCallbacks -> IO (Either ExternalException (GhcServer, GhcVersion))
+ IdeSession.GHC.Client: getGhcExitCode :: GhcServer -> IO (Maybe ExitCode)
+ IdeSession.GHC.Client: interrupt :: RunActions a -> IO ()
+ IdeSession.GHC.Client: rpcBreakpoint :: GhcServer -> ModuleName -> SourceSpan -> Bool -> IO (Maybe Bool)
+ IdeSession.GHC.Client: rpcCompile :: GhcServer -> Bool -> Targets -> (UpdateStatus -> IO ()) -> IO GhcCompileResult
+ IdeSession.GHC.Client: rpcCrash :: GhcServer -> Maybe Int -> IO ()
+ IdeSession.GHC.Client: rpcLoad :: GhcServer -> [FilePath] -> IO (Maybe String)
+ IdeSession.GHC.Client: rpcPrint :: GhcServer -> Name -> Bool -> Bool -> IO VariableEnv
+ IdeSession.GHC.Client: rpcRun :: GhcServer -> RunCmd -> (Maybe RunResult -> IO a) -> IO (RunActions a)
+ IdeSession.GHC.Client: rpcSetArgs :: GhcServer -> [String] -> IO ()
+ IdeSession.GHC.Client: rpcSetEnv :: GhcServer -> [(String, Maybe String)] -> IO ()
+ IdeSession.GHC.Client: rpcSetGhcOpts :: GhcServer -> [String] -> IO ([String], [String])
+ IdeSession.GHC.Client: rpcUnload :: GhcServer -> [FilePath] -> IO ()
+ IdeSession.GHC.Client: runWait :: RunActions a -> IO (Either ByteString a)
+ IdeSession.GHC.Client: runWaitAll :: RunActions a -> IO (ByteString, a)
+ IdeSession.GHC.Client: shutdownGhcServer :: GhcServer -> IO ()
+ IdeSession.GHC.Client: supplyStdin :: RunActions a -> ByteString -> IO ()
+ IdeSession.GHC.Client: type InProcess = Bool
+ IdeSession.Licenses: apache20 :: License
+ IdeSession.Licenses: bsd3 :: String -> String -> License
+ IdeSession.Licenses: gplv2 :: License
+ IdeSession.Licenses: gplv3 :: License
+ IdeSession.Licenses: lgpl2 :: License
+ IdeSession.Licenses: lgpl3 :: License
+ IdeSession.Licenses: type License = String
+ IdeSession.Query: InvalidSessionStateQueries :: InvalidSessionStateQueries
+ IdeSession.Query: ManagedFiles :: [FilePath] -> [FilePath] -> ManagedFiles
+ IdeSession.Query: data InvalidSessionStateQueries
+ IdeSession.Query: data ManagedFiles
+ IdeSession.Query: dataFiles :: ManagedFiles -> [FilePath]
+ IdeSession.Query: dumpAutocompletion :: IdeSession -> IO ()
+ IdeSession.Query: dumpFileMap :: IdeSession -> IO ()
+ IdeSession.Query: dumpIdInfo :: IdeSession -> IO ()
+ IdeSession.Query: getAllDataFiles :: Query [FilePath]
+ IdeSession.Query: getArgs :: Query [String]
+ IdeSession.Query: getAutocompletion :: Query (ModuleName -> String -> [IdInfo])
+ IdeSession.Query: getBreakInfo :: Query (Maybe BreakInfo)
+ IdeSession.Query: getBuildDocStatus :: Query (Maybe ExitCode)
+ IdeSession.Query: getBuildExeStatus :: Query (Maybe ExitCode)
+ IdeSession.Query: getBuildLicensesStatus :: Query (Maybe ExitCode)
+ IdeSession.Query: getCabalMacros :: Query ByteString
+ IdeSession.Query: getCodeGeneration :: Query Bool
+ IdeSession.Query: getDataDir :: Query FilePath
+ IdeSession.Query: getDataFile :: FilePath -> Query ByteString
+ IdeSession.Query: getDistDir :: Query FilePath
+ IdeSession.Query: getDotCabal :: Query (String -> Version -> ByteString)
+ IdeSession.Query: getEnv :: Query [(String, Maybe String)]
+ IdeSession.Query: getExpTypes :: Query (ModuleName -> SourceSpan -> [(SourceSpan, Text)])
+ IdeSession.Query: getFileMap :: Query (FilePath -> Maybe ModuleId)
+ IdeSession.Query: getGhcServer :: Query GhcServer
+ IdeSession.Query: getGhcVersion :: Query GhcVersion
+ IdeSession.Query: getImports :: Query (ModuleName -> Maybe [Import])
+ IdeSession.Query: getLoadedModules :: Query [ModuleName]
+ IdeSession.Query: getManagedFiles :: Query ManagedFiles
+ IdeSession.Query: getPkgDeps :: Query (ModuleName -> Maybe [PackageId])
+ IdeSession.Query: getSessionConfig :: Query SessionConfig
+ IdeSession.Query: getSourceErrors :: Query [SourceError]
+ IdeSession.Query: getSourceModule :: FilePath -> Query ByteString
+ IdeSession.Query: getSourcesDir :: Query FilePath
+ IdeSession.Query: getSpanInfo :: Query (ModuleName -> SourceSpan -> [(SourceSpan, SpanInfo)])
+ IdeSession.Query: getUseSites :: Query (ModuleName -> SourceSpan -> [SourceSpan])
+ IdeSession.Query: instance Exception InvalidSessionStateQueries
+ IdeSession.Query: instance Show InvalidSessionStateQueries
+ IdeSession.Query: instance Show ManagedFiles
+ IdeSession.Query: instance Typeable InvalidSessionStateQueries
+ IdeSession.Query: sourceFiles :: ManagedFiles -> [FilePath]
+ IdeSession.Query: type Query a = IdeSession -> IO a
+ IdeSession.RPC.Client: ExternalException :: String -> Maybe IOException -> ExternalException
+ IdeSession.RPC.Client: RpcConversation :: (forall a. (Typeable * a, Binary a) => IO a) -> (forall a. (Typeable * a, Binary a) => a -> IO ()) -> RpcConversation
+ IdeSession.RPC.Client: connectToRpcServer :: FilePath -> FilePath -> FilePath -> (RpcServer -> IO a) -> IO a
+ IdeSession.RPC.Client: data ExternalException :: *
+ IdeSession.RPC.Client: data RpcConversation :: *
+ IdeSession.RPC.Client: data RpcServer
+ IdeSession.RPC.Client: externalException :: ExternalException -> Maybe IOException
+ IdeSession.RPC.Client: externalStdErr :: ExternalException -> String
+ IdeSession.RPC.Client: findProgram :: LogFunc -> ProgramSearchPath -> FilePath -> IO (Maybe FilePath)
+ IdeSession.RPC.Client: forceShutdown :: RpcServer -> IO ()
+ IdeSession.RPC.Client: forkRpcServer :: FilePath -> [String] -> Maybe FilePath -> Maybe [(String, String)] -> IO RpcServer
+ IdeSession.RPC.Client: get :: RpcConversation -> forall a. (Typeable * a, Binary a) => IO a
+ IdeSession.RPC.Client: getRpcExitCode :: RpcServer -> IO (Maybe ExitCode)
+ IdeSession.RPC.Client: illscopedConversationException :: IOException
+ IdeSession.RPC.Client: put :: RpcConversation -> forall a. (Typeable * a, Binary a) => a -> IO ()
+ IdeSession.RPC.Client: rpc :: (Typeable req, Typeable resp, Binary req, Binary resp) => RpcServer -> req -> IO resp
+ IdeSession.RPC.Client: rpcConversation :: RpcServer -> (RpcConversation -> IO a) -> IO a
+ IdeSession.RPC.Client: serverKilledException :: Maybe IOException -> ExternalException
+ IdeSession.RPC.Client: shutdown :: RpcServer -> IO ()
+ IdeSession.State: Computed :: !(Strict [] SourceError) -> !(Strict [] ModuleName) -> !(Strict (Map FilePath) ModuleId) -> !(Strict (Map ModuleName) (Strict [] Import)) -> !(Strict (Map ModuleName) (Strict Trie (Strict [] IdInfo))) -> !(Strict (Map ModuleName) IdMap) -> !(Strict (Map ModuleName) ExpMap) -> !(Strict (Map ModuleName) UseSites) -> !(Strict (Map ModuleName) (Strict [] PackageId)) -> !ExplicitSharingCache -> Computed
+ IdeSession.State: IdeCallbacks :: LogFunc -> IdeCallbacks
+ IdeSession.State: IdeIdleState :: !LogicalTimestamp -> !(Strict Maybe Computed) -> ![String] -> ![FilePath] -> !Bool -> !ManagedFilesInternal -> !ObjectFiles -> !(Maybe ExitCode) -> !(Maybe ExitCode) -> !(Maybe ExitCode) -> ![(String, Maybe String)] -> ![String] -> GhcServer -> GhcVersion -> !RunBufferMode -> !RunBufferMode -> !(Strict Maybe BreakInfo) -> !Targets -> [String] -> IdeIdleState
+ IdeSession.State: IdeSession :: IdeStaticInfo -> StrictMVar IdeSessionState -> IdeCallbacks -> IdeSession
+ IdeSession.State: IdeSessionIdle :: IdeIdleState -> IdeSessionState
+ IdeSession.State: IdeSessionServerDied :: ExternalException -> IdeIdleState -> IdeSessionState
+ IdeSession.State: IdeSessionShutdown :: IdeSessionState
+ IdeSession.State: IdeStaticInfo :: !SessionConfig -> !FilePath -> !FilePath -> IdeStaticInfo
+ IdeSession.State: InProcess :: RpcConversation -> ThreadId -> GhcServer
+ IdeSession.State: ManagedFilesInternal :: [ManagedFile] -> [ManagedFile] -> ManagedFilesInternal
+ IdeSession.State: OutProcess :: RpcServer -> GhcServer
+ IdeSession.State: RunActions :: IO (Either ByteString a) -> IO () -> (ByteString -> IO ()) -> IO () -> RunActions a
+ IdeSession.State: _ideArgs :: IdeIdleState -> ![String]
+ IdeSession.State: _ideBreakInfo :: IdeIdleState -> !(Strict Maybe BreakInfo)
+ IdeSession.State: _ideBuildDocStatus :: IdeIdleState -> !(Maybe ExitCode)
+ IdeSession.State: _ideBuildExeStatus :: IdeIdleState -> !(Maybe ExitCode)
+ IdeSession.State: _ideBuildLicensesStatus :: IdeIdleState -> !(Maybe ExitCode)
+ IdeSession.State: _ideComputed :: IdeIdleState -> !(Strict Maybe Computed)
+ IdeSession.State: _ideEnv :: IdeIdleState -> ![(String, Maybe String)]
+ IdeSession.State: _ideGenerateCode :: IdeIdleState -> !Bool
+ IdeSession.State: _ideGhcOpts :: IdeIdleState -> ![String]
+ IdeSession.State: _ideGhcServer :: IdeIdleState -> GhcServer
+ IdeSession.State: _ideGhcVersion :: IdeIdleState -> GhcVersion
+ IdeSession.State: _ideLogicalTimestamp :: IdeIdleState -> !LogicalTimestamp
+ IdeSession.State: _ideManagedFiles :: IdeIdleState -> !ManagedFilesInternal
+ IdeSession.State: _ideObjectFiles :: IdeIdleState -> !ObjectFiles
+ IdeSession.State: _ideRelativeIncludes :: IdeIdleState -> ![FilePath]
+ IdeSession.State: _ideRtsOpts :: IdeIdleState -> [String]
+ IdeSession.State: _ideStderrBufferMode :: IdeIdleState -> !RunBufferMode
+ IdeSession.State: _ideStdoutBufferMode :: IdeIdleState -> !RunBufferMode
+ IdeSession.State: _ideTargets :: IdeIdleState -> !Targets
+ IdeSession.State: _managedData :: ManagedFilesInternal -> [ManagedFile]
+ IdeSession.State: _managedSource :: ManagedFilesInternal -> [ManagedFile]
+ IdeSession.State: computedAutoMap :: Computed -> !(Strict (Map ModuleName) (Strict Trie (Strict [] IdInfo)))
+ IdeSession.State: computedCache :: Computed -> !ExplicitSharingCache
+ IdeSession.State: computedErrors :: Computed -> !(Strict [] SourceError)
+ IdeSession.State: computedExpTypes :: Computed -> !(Strict (Map ModuleName) ExpMap)
+ IdeSession.State: computedFileMap :: Computed -> !(Strict (Map FilePath) ModuleId)
+ IdeSession.State: computedImports :: Computed -> !(Strict (Map ModuleName) (Strict [] Import))
+ IdeSession.State: computedLoadedModules :: Computed -> !(Strict [] ModuleName)
+ IdeSession.State: computedPkgDeps :: Computed -> !(Strict (Map ModuleName) (Strict [] PackageId))
+ IdeSession.State: computedSpanInfo :: Computed -> !(Strict (Map ModuleName) IdMap)
+ IdeSession.State: computedUseSites :: Computed -> !(Strict (Map ModuleName) UseSites)
+ IdeSession.State: data Computed
+ IdeSession.State: data GhcServer
+ IdeSession.State: data IdeCallbacks
+ IdeSession.State: data IdeIdleState
+ IdeSession.State: data IdeSession
+ IdeSession.State: data IdeSessionState
+ IdeSession.State: data IdeStaticInfo
+ IdeSession.State: data ManagedFilesInternal
+ IdeSession.State: data RunActions a
+ IdeSession.State: defaultIdeCallbacks :: IdeCallbacks
+ IdeSession.State: forceCancel :: RunActions a -> IO ()
+ IdeSession.State: ideArgs :: Accessor IdeIdleState [String]
+ IdeSession.State: ideBreakInfo :: Accessor IdeIdleState (Strict Maybe BreakInfo)
+ IdeSession.State: ideBuildDocStatus :: Accessor IdeIdleState (Maybe ExitCode)
+ IdeSession.State: ideBuildExeStatus :: Accessor IdeIdleState (Maybe ExitCode)
+ IdeSession.State: ideBuildLicensesStatus :: Accessor IdeIdleState (Maybe ExitCode)
+ IdeSession.State: ideCallbacks :: IdeSession -> IdeCallbacks
+ IdeSession.State: ideCallbacksLogFunc :: IdeCallbacks -> LogFunc
+ IdeSession.State: ideComputed :: Accessor IdeIdleState (Strict Maybe Computed)
+ IdeSession.State: ideConfig :: IdeStaticInfo -> !SessionConfig
+ IdeSession.State: ideDataDir :: IdeStaticInfo -> FilePath
+ IdeSession.State: ideDistDir :: IdeStaticInfo -> !FilePath
+ IdeSession.State: ideEnv :: Accessor IdeIdleState [(String, Maybe String)]
+ IdeSession.State: ideGenerateCode :: Accessor IdeIdleState Bool
+ IdeSession.State: ideGhcOpts :: Accessor IdeIdleState [String]
+ IdeSession.State: ideGhcServer :: Accessor IdeIdleState GhcServer
+ IdeSession.State: ideGhcVersion :: Accessor IdeIdleState GhcVersion
+ IdeSession.State: ideLogFunc :: IdeSession -> LogFunc
+ IdeSession.State: ideLogicalTimestamp :: Accessor IdeIdleState LogicalTimestamp
+ IdeSession.State: ideManagedFiles :: Accessor IdeIdleState ManagedFilesInternal
+ IdeSession.State: ideObjectFiles :: Accessor IdeIdleState ObjectFiles
+ IdeSession.State: ideRelativeIncludes :: Accessor IdeIdleState [FilePath]
+ IdeSession.State: ideRtsOpts :: Accessor IdeIdleState [String]
+ IdeSession.State: ideSessionDir :: IdeStaticInfo -> !FilePath
+ IdeSession.State: ideSourceDir :: IdeStaticInfo -> FilePath
+ IdeSession.State: ideState :: IdeSession -> StrictMVar IdeSessionState
+ IdeSession.State: ideStaticInfo :: IdeSession -> IdeStaticInfo
+ IdeSession.State: ideStderrBufferMode :: Accessor IdeIdleState RunBufferMode
+ IdeSession.State: ideStdoutBufferMode :: Accessor IdeIdleState RunBufferMode
+ IdeSession.State: ideTargets :: Accessor IdeIdleState Targets
+ IdeSession.State: instance Show Computed
+ IdeSession.State: interrupt :: RunActions a -> IO ()
+ IdeSession.State: managedData :: Accessor ManagedFilesInternal [ManagedFile]
+ IdeSession.State: managedSource :: Accessor ManagedFilesInternal [ManagedFile]
+ IdeSession.State: runWait :: RunActions a -> IO (Either ByteString a)
+ IdeSession.State: supplyStdin :: RunActions a -> ByteString -> IO ()
+ IdeSession.State: type LogicalTimestamp = EpochTime
+ IdeSession.State: type ManagedFile = (FilePath, (MD5Digest, LogicalTimestamp))
+ IdeSession.Update: LicenseArgs :: PackageDBStack -> [FilePath] -> [String] -> FilePath -> FilePath -> FilePath -> [(String, (Maybe License, Maybe FilePath, Maybe String))] -> FilePath -> [PackageId] -> LicenseArgs
+ IdeSession.Update: SessionInitParams :: Maybe ByteString -> [String] -> [FilePath] -> Targets -> [String] -> !(Maybe FilePath) -> SessionInitParams
+ IdeSession.Update: buildDoc :: IdeSessionUpdate
+ IdeSession.Update: buildExe :: [String] -> [(ModuleName, FilePath)] -> IdeSessionUpdate
+ IdeSession.Update: buildLicenses :: FilePath -> IdeSessionUpdate
+ IdeSession.Update: buildLicsFromPkgs :: Bool -> LicenseArgs -> IO ExitCode
+ IdeSession.Update: crashGhcServer :: IdeSession -> Maybe Int -> IO ()
+ IdeSession.Update: data IdeSessionUpdate
+ IdeSession.Update: data LicenseArgs
+ IdeSession.Update: data SessionInitParams
+ IdeSession.Update: defaultSessionInitParams :: SessionInitParams
+ IdeSession.Update: forceShutdownSession :: IdeSession -> IO ()
+ IdeSession.Update: initSession :: SessionInitParams -> SessionConfig -> IO IdeSession
+ IdeSession.Update: initSessionWithCallbacks :: IdeCallbacks -> SessionInitParams -> SessionConfig -> IO IdeSession
+ IdeSession.Update: instance Show SessionInitParams
+ IdeSession.Update: liCabalsDir :: LicenseArgs -> FilePath
+ IdeSession.Update: liDistDir :: LicenseArgs -> FilePath
+ IdeSession.Update: liExtraPathDirs :: LicenseArgs -> [FilePath]
+ IdeSession.Update: liLicenseExc :: LicenseArgs -> [String]
+ IdeSession.Update: liPackageDBStack :: LicenseArgs -> PackageDBStack
+ IdeSession.Update: liPkgs :: LicenseArgs -> [PackageId]
+ IdeSession.Update: liStderrLog :: LicenseArgs -> FilePath
+ IdeSession.Update: liStdoutLog :: LicenseArgs -> FilePath
+ IdeSession.Update: licenseFixed :: LicenseArgs -> [(String, (Maybe License, Maybe FilePath, Maybe String))]
+ IdeSession.Update: printVar :: IdeSession -> Name -> Bool -> Bool -> IO VariableEnv
+ IdeSession.Update: restartSession :: IdeSession -> IO ()
+ IdeSession.Update: resume :: IdeSession -> IO (RunActions RunResult)
+ IdeSession.Update: runExe :: IdeSession -> String -> IO (RunActions ExitCode)
+ IdeSession.Update: runStmt :: IdeSession -> String -> String -> IO (RunActions RunResult)
+ IdeSession.Update: runStmtPty :: IdeSession -> String -> String -> IO (RunActions RunResult)
+ IdeSession.Update: sessionInitCabalMacros :: SessionInitParams -> Maybe ByteString
+ IdeSession.Update: sessionInitDistDir :: SessionInitParams -> !(Maybe FilePath)
+ IdeSession.Update: sessionInitGhcOptions :: SessionInitParams -> [String]
+ IdeSession.Update: sessionInitRelativeIncludes :: SessionInitParams -> [FilePath]
+ IdeSession.Update: sessionInitRtsOpts :: SessionInitParams -> [String]
+ IdeSession.Update: sessionInitTargets :: SessionInitParams -> Targets
+ IdeSession.Update: setBreakpoint :: IdeSession -> ModuleName -> SourceSpan -> Bool -> IO (Maybe Bool)
+ IdeSession.Update: shutdownSession :: IdeSession -> IO ()
+ IdeSession.Update: updateArgs :: [String] -> IdeSessionUpdate
+ IdeSession.Update: updateCodeGeneration :: Bool -> IdeSessionUpdate
+ IdeSession.Update: updateDataFile :: FilePath -> ByteString -> IdeSessionUpdate
+ IdeSession.Update: updateDataFileDelete :: FilePath -> IdeSessionUpdate
+ IdeSession.Update: updateDataFileFromFile :: FilePath -> FilePath -> IdeSessionUpdate
+ IdeSession.Update: updateDeleteManagedFiles :: IdeSessionUpdate
+ IdeSession.Update: updateEnv :: [(String, Maybe String)] -> IdeSessionUpdate
+ IdeSession.Update: updateGhcOpts :: [String] -> IdeSessionUpdate
+ IdeSession.Update: updateRelativeIncludes :: [FilePath] -> IdeSessionUpdate
+ IdeSession.Update: updateRtsOpts :: [String] -> IdeSessionUpdate
+ IdeSession.Update: updateSession :: IdeSession -> IdeSessionUpdate -> (UpdateStatus -> IO ()) -> IO ()
+ IdeSession.Update: updateSourceFile :: FilePath -> ByteString -> IdeSessionUpdate
+ IdeSession.Update: updateSourceFileDelete :: FilePath -> IdeSessionUpdate
+ IdeSession.Update: updateSourceFileFromFile :: FilePath -> IdeSessionUpdate
+ IdeSession.Update: updateStderrBufferMode :: RunBufferMode -> IdeSessionUpdate
+ IdeSession.Update: updateStdoutBufferMode :: RunBufferMode -> IdeSessionUpdate
+ IdeSession.Update: updateTargets :: Targets -> IdeSessionUpdate
+ IdeSession.Update.ExecuteSessionUpdate: instance (Dummy a, Dummy b) => Dummy (a, b)
+ IdeSession.Update.ExecuteSessionUpdate: instance Applicative ExecuteSessionUpdate
+ IdeSession.Update.ExecuteSessionUpdate: instance Dummy ()
+ IdeSession.Update.ExecuteSessionUpdate: instance Dummy (Maybe a)
+ IdeSession.Update.ExecuteSessionUpdate: instance Dummy (Strict (Map k) a)
+ IdeSession.Update.ExecuteSessionUpdate: instance Dummy (Strict IntMap a)
+ IdeSession.Update.ExecuteSessionUpdate: instance Dummy (Strict [] a)
+ IdeSession.Update.ExecuteSessionUpdate: instance Dummy ExplicitSharingCache
+ IdeSession.Update.ExecuteSessionUpdate: instance Dummy GhcCompileResult
+ IdeSession.Update.ExecuteSessionUpdate: instance Dummy [a]
+ IdeSession.Update.ExecuteSessionUpdate: instance Functor ExecuteSessionUpdate
+ IdeSession.Update.ExecuteSessionUpdate: instance Monad ExecuteSessionUpdate
+ IdeSession.Update.ExecuteSessionUpdate: instance MonadIO ExecuteSessionUpdate
+ IdeSession.Update.ExecuteSessionUpdate: instance MonadReader IdeSessionUpdateEnv ExecuteSessionUpdate
+ IdeSession.Update.ExecuteSessionUpdate: instance MonadState IdeIdleState ExecuteSessionUpdate
+ IdeSession.Update.ExecuteSessionUpdate: runSessionUpdate :: Bool -> IdeSessionUpdate -> IdeStaticInfo -> (UpdateStatus -> IO ()) -> IdeCallbacks -> IdeIdleState -> IO (IdeIdleState, Maybe ExternalException)
+ IdeSession.Update.IdeSessionUpdate: FileCopy :: FileInfo -> FilePath -> FileCmd
+ IdeSession.Update.IdeSessionUpdate: FileDelete :: FileInfo -> FileCmd
+ IdeSession.Update.IdeSessionUpdate: FileInfo :: (IdeStaticInfo -> FilePath) -> FilePath -> Accessor ManagedFilesInternal [ManagedFile] -> FileInfo
+ IdeSession.Update.IdeSessionUpdate: FileWrite :: FileInfo -> ByteString -> FileCmd
+ IdeSession.Update.IdeSessionUpdate: IdeSessionUpdate :: [FileCmd] -> Bool -> Maybe [String] -> Maybe [FilePath] -> Maybe Bool -> Maybe [(String, Maybe String)] -> Maybe [String] -> Maybe RunBufferMode -> Maybe RunBufferMode -> Maybe Targets -> [([String], [(ModuleName, FilePath)])] -> Bool -> [FilePath] -> Maybe [String] -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: buildDoc :: IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: buildExe :: [String] -> [(ModuleName, FilePath)] -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: buildLicenses :: FilePath -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: data FileCmd
+ IdeSession.Update.IdeSessionUpdate: data FileInfo
+ IdeSession.Update.IdeSessionUpdate: data IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: fileInfoAccessor :: FileInfo -> Accessor ManagedFilesInternal [ManagedFile]
+ IdeSession.Update.IdeSessionUpdate: fileInfoRemoteDir :: FileInfo -> IdeStaticInfo -> FilePath
+ IdeSession.Update.IdeSessionUpdate: fileInfoRemoteFile :: FileInfo -> FilePath
+ IdeSession.Update.IdeSessionUpdate: ideUpdateArgs :: IdeSessionUpdate -> Maybe [String]
+ IdeSession.Update.IdeSessionUpdate: ideUpdateCodeGen :: IdeSessionUpdate -> Maybe Bool
+ IdeSession.Update.IdeSessionUpdate: ideUpdateDeleteFiles :: IdeSessionUpdate -> Bool
+ IdeSession.Update.IdeSessionUpdate: ideUpdateDocs :: IdeSessionUpdate -> Bool
+ IdeSession.Update.IdeSessionUpdate: ideUpdateEnv :: IdeSessionUpdate -> Maybe [(String, Maybe String)]
+ IdeSession.Update.IdeSessionUpdate: ideUpdateExes :: IdeSessionUpdate -> [([String], [(ModuleName, FilePath)])]
+ IdeSession.Update.IdeSessionUpdate: ideUpdateFileCmds :: IdeSessionUpdate -> [FileCmd]
+ IdeSession.Update.IdeSessionUpdate: ideUpdateGhcOpts :: IdeSessionUpdate -> Maybe [String]
+ IdeSession.Update.IdeSessionUpdate: ideUpdateLicenses :: IdeSessionUpdate -> [FilePath]
+ IdeSession.Update.IdeSessionUpdate: ideUpdateRelIncls :: IdeSessionUpdate -> Maybe [FilePath]
+ IdeSession.Update.IdeSessionUpdate: ideUpdateRtsOpts :: IdeSessionUpdate -> Maybe [String]
+ IdeSession.Update.IdeSessionUpdate: ideUpdateStderrMode :: IdeSessionUpdate -> Maybe RunBufferMode
+ IdeSession.Update.IdeSessionUpdate: ideUpdateStdoutMode :: IdeSessionUpdate -> Maybe RunBufferMode
+ IdeSession.Update.IdeSessionUpdate: ideUpdateTargets :: IdeSessionUpdate -> Maybe Targets
+ IdeSession.Update.IdeSessionUpdate: instance Monoid IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: instance Show FileCmd
+ IdeSession.Update.IdeSessionUpdate: instance Show FileInfo
+ IdeSession.Update.IdeSessionUpdate: instance Show IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateArgs :: [String] -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateCodeGeneration :: Bool -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateDataFile :: FilePath -> ByteString -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateDataFileDelete :: FilePath -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateDataFileFromFile :: FilePath -> FilePath -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateDeleteManagedFiles :: IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateEnv :: [(String, Maybe String)] -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateGhcOpts :: [String] -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateRelativeIncludes :: [FilePath] -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateRtsOpts :: [String] -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateSourceFile :: FilePath -> ByteString -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateSourceFileDelete :: FilePath -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateSourceFileFromFile :: FilePath -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateStderrBufferMode :: RunBufferMode -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateStdoutBufferMode :: RunBufferMode -> IdeSessionUpdate
+ IdeSession.Update.IdeSessionUpdate: updateTargets :: Targets -> IdeSessionUpdate
- IdeSession: SessionConfig :: FilePath -> [FilePath] -> InProcess -> Bool -> PackageDBStack -> [String] -> [(String, (Maybe License, Maybe FilePath, Maybe String))] -> (String -> IO ()) -> Bool -> SessionConfig
+ IdeSession: SessionConfig :: FilePath -> Maybe FilePath -> [FilePath] -> InProcess -> Bool -> PackageDBStack -> [String] -> [(String, (Maybe License, Maybe FilePath, Maybe String))] -> (String -> IO ()) -> Bool -> (ProgramSearchPath, FilePath) -> (ProgramSearchPath, FilePath) -> SessionConfig
- IdeSession: SessionInitParams :: Maybe ByteString -> [String] -> [FilePath] -> Targets -> [String] -> SessionInitParams
+ IdeSession: SessionInitParams :: Maybe ByteString -> [String] -> [FilePath] -> Targets -> [String] -> !(Maybe FilePath) -> SessionInitParams
- IdeSession: updateSession :: IdeSession -> IdeSessionUpdate -> (Progress -> IO ()) -> IO ()
+ IdeSession: updateSession :: IdeSession -> IdeSessionUpdate -> (UpdateStatus -> IO ()) -> IO ()
Files
- IdeSession.hs +8/−1
- IdeSession/Config.hs +63/−3
- IdeSession/ExeCabalClient.hs +23/−20
- IdeSession/GHC/Client.hs +23/−29
- IdeSession/Query.hs +10/−12
- IdeSession/RPC/Client.hs +27/−1
- IdeSession/State.hs +59/−2
- IdeSession/Update.hs +61/−37
- IdeSession/Update/ExecuteSessionUpdate.hs +87/−72
- IdeSession/Update/IdeSessionUpdate.hs +7/−8
- README.md +0/−588
- TestSuite/TestSuite.hs +35/−2
- TestSuite/TestSuite/Assertions.hs +2/−2
- TestSuite/TestSuite/Session.hs +31/−16
- TestSuite/TestSuite/State.hs +73/−45
- TestSuite/TestSuite/Tests/BuildDoc.hs +7/−7
- TestSuite/TestSuite/Tests/BuildLicenses.hs +2/−2
- TestSuite/TestSuite/Tests/C.hs +5/−5
- TestSuite/TestSuite/Tests/Compilation.hs +15/−73
- TestSuite/TestSuite/Tests/FFI.hs +11/−8
- TestSuite/TestSuite/Tests/Integration.hs +6/−2
- TestSuite/TestSuite/Tests/Issues.hs +5/−3
- TestSuite/TestSuite/Tests/Packages.hs +4/−4
- TestSuite/TestSuite/Tests/Performance.hs +4/−4
- TestSuite/inputs/ABerror/A.hs +6/−0
- TestSuite/inputs/ABerror/B.hs +4/−0
- TestSuite/inputs/ABnoError/A.hs +8/−0
- TestSuite/inputs/ABnoError/B.hs +4/−0
- TestSuite/inputs/AerrorB/A.hs +6/−0
- TestSuite/inputs/AerrorB/B.hs +4/−0
- TestSuite/inputs/AnotherA/A.hs +8/−0
- TestSuite/inputs/AnotherB/B.hs +8/−0
- TestSuite/inputs/FFI/A.hs +17/−0
- TestSuite/inputs/FFI/Main.hs +7/−0
- TestSuite/inputs/FFI/Main2.hs +7/−0
- TestSuite/inputs/FFI/Main3.hs +22/−0
- TestSuite/inputs/FFI/ffiles/life.c +6/−0
- TestSuite/inputs/FFI/ffiles/life.h +3/−0
- TestSuite/inputs/FFI/ffiles/local.h +1/−0
- TestSuite/inputs/FFI/life.c +5/−0
- TestSuite/inputs/FFI/life.h +3/−0
- TestSuite/inputs/MainModule/ParFib.hs +4/−0
- TestSuite/inputs/MainModule/ParFib/Main.hs +50/−0
- TestSuite/inputs/MainModule/cabals/base.cabal +253/−0
- TestSuite/inputs/MainModule/cabals/ghc-prim.cabal +48/−0
- TestSuite/inputs/MainModule/cabals/integer-gmp.cabal +36/−0
- TestSuite/inputs/MainModule/cabals/old-locale.cabal +23/−0
- TestSuite/inputs/MainModule/cabals/old-time.cabal +38/−0
- TestSuite/inputs/MainModule/cabals/parallel.cabal +33/−0
- TestSuite/inputs/Puns/GHC/RTS/EventLogFormat.h +282/−0
- TestSuite/inputs/Puns/GHC/RTS/EventParserUtils.hs +198/−0
- TestSuite/inputs/Puns/GHC/RTS/EventTypes.hs +389/−0
- TestSuite/inputs/Puns/GHC/RTS/Events.hs +1367/−0
- TestSuite/inputs/Puns/cabals/array.cabal +56/−0
- TestSuite/inputs/Puns/cabals/base.cabal +253/−0
- TestSuite/inputs/Puns/cabals/binary.cabal +60/−0
- TestSuite/inputs/Puns/cabals/bytestring.cabal +91/−0
- TestSuite/inputs/Puns/cabals/containers.cabal +44/−0
- TestSuite/inputs/Puns/cabals/deepseq.cabal +35/−0
- TestSuite/inputs/Puns/cabals/mtl.cabal +51/−0
- TestSuite/inputs/Puns/cabals/no_text_error/array.cabal +0/−0
- TestSuite/inputs/Puns/cabals/no_text_error/base.cabal +0/−0
- TestSuite/inputs/Puns/cabals/no_text_error/binary.cabal +0/−0
- TestSuite/inputs/Puns/cabals/no_text_error/bytestring.cabal +0/−0
- TestSuite/inputs/Puns/cabals/no_text_error/containers.cabal +0/−0
- TestSuite/inputs/Puns/cabals/no_text_error/deepseq.cabal +0/−0
- TestSuite/inputs/Puns/cabals/no_text_error/ghc-prim.cabal +0/−0
- TestSuite/inputs/Puns/cabals/no_text_error/integer-gmp.cabal +0/−0
- TestSuite/inputs/Puns/cabals/no_text_error/mtl.cabal +52/−0
- TestSuite/inputs/Puns/cabals/parse_error/array.cabal +0/−0
- TestSuite/inputs/Puns/cabals/parse_error/base.cabal +253/−0
- TestSuite/inputs/Puns/cabals/parse_error/binary.cabal +0/−0
- TestSuite/inputs/Puns/cabals/parse_error/bytestring.cabal +0/−0
- TestSuite/inputs/Puns/cabals/parse_error/containers.cabal +0/−0
- TestSuite/inputs/Puns/cabals/parse_error/deepseq.cabal +0/−0
- TestSuite/inputs/Puns/cabals/parse_error/ghc-prim.cabal +0/−0
- TestSuite/inputs/Puns/cabals/parse_error/integer-gmp.cabal +0/−0
- TestSuite/inputs/Puns/cabals/parse_error/mtl.cabal +0/−0
- TestSuite/inputs/Puns/cabals/transformers.cabal +68/−0
- TestSuite/inputs/README.md +4/−0
- TestSuite/inputs/TH/BlockingOps.hs +103/−0
- TestSuite/inputs/TH/TH.hs +17/−0
- TestSuite/inputs/bootMods/A.hs +8/−0
- TestSuite/inputs/bootMods/A.hs-boot +2/−0
- TestSuite/inputs/bootMods/B.hs +8/−0
- TestSuite/inputs/bootMods/C.hs +6/−0
- TestSuite/inputs/compiler/utils/Exception.hs +109/−0
- TestSuite/inputs/compiler/utils/Maybes.lhs +158/−0
- TestSuite/inputs/compiler/utils/OrdList.lhs +93/−0
- TestSuite/inputs/compiler/utils/Subdir/Main.lhs +90/−0
- TestSuite/inputs/simple-lib17/LICENSE +30/−0
- TestSuite/inputs/simple-lib17/Setup.hs +2/−0
- TestSuite/inputs/simple-lib17/SimpleLib.hs +4/−0
- TestSuite/inputs/simple-lib17/build.sh +2/−0
- TestSuite/inputs/simple-lib17/simple-lib17.cabal +19/−0
- ide-backend.cabal +38/−5
IdeSession.hs view
@@ -102,14 +102,20 @@ module IdeSession ( -- * Configuration SessionConfig(..)+ , sessionConfigFromEnv , defaultSessionConfig , InProcess+ , ProgramSearchPath+ , ProgramSearchPathEntry(..) -- * Updating the session -- ** Starting and stopping , IdeSession -- Abstract , initSession+ , initSessionWithCallbacks , SessionInitParams(..) , defaultSessionInitParams+ , IdeCallbacks(..)+ , defaultIdeCallbacks , shutdownSession , forceShutdownSession , restartSession@@ -137,6 +143,7 @@ , buildLicenses -- ** Progress , Progress(..)+ , UpdateStatus(..) -- ** Running code , RunActions(..) , RunResult(..)@@ -233,7 +240,7 @@ import IdeSession.GHC.Client import IdeSession.Query import IdeSession.RPC.Client (ExternalException (..))-import IdeSession.State (IdeSession)+import IdeSession.State (IdeSession, IdeCallbacks(..), defaultIdeCallbacks) import IdeSession.Types.Progress import IdeSession.Types.Public import IdeSession.Update
IdeSession/Config.hs view
@@ -1,11 +1,17 @@ module IdeSession.Config ( SessionConfig(..) , InProcess+ , ProgramSearchPath, ProgramSearchPathEntry(..)+ , sessionConfigFromEnv , defaultSessionConfig ) where import Distribution.License (License (..)) import Distribution.Simple (PackageDB (..), PackageDBStack)+import Distribution.Simple.Program.Find (ProgramSearchPath,ProgramSearchPathEntry(..),defaultProgramSearchPath)+import System.FilePath (splitSearchPath)+import System.Directory (getCurrentDirectory, getTemporaryDirectory)+import System.Environment (lookupEnv) type InProcess = Bool @@ -15,6 +21,18 @@ data SessionConfig = SessionConfig { -- | The directory to use for all session files. configDir :: FilePath+ -- | When set to Just "<filepath>", we'll use the files in that+ -- directory as source and datafiles. This means that the+ -- ide-backend is no longer directly managing the files, and+ -- file updates like 'updateSourceFile' will fail.+ --+ -- Note that this feature is experimental and does not have a+ -- suite of tests.+ --+ -- Since this is likely used with an existing cabal project, which+ -- might have multiple source directories, you'll likely want to+ -- use 'TargetsInclude' instead of 'TargetsExclude'.+ , configLocalWorkingDir :: Maybe FilePath -- | Extra directories in which to look for programs, including ghc -- and other tools. Note that the @$PATH@ is still searched /first/, these -- directories are extra.@@ -41,15 +59,52 @@ -- | Delete temporary files when session finishes? -- (Defaults to True; mostly for internal debugging purposes) , configDeleteTempFiles :: Bool+ -- | The name of the ide-backend-server program to use, and where to find it.+ -- The default is @(defaultProgramSearchPath,"ide-backend-server")@,+ -- that is, to look for a program called ide-backend-server on the system+ -- search path only.+ , configIdeBackendServer :: (ProgramSearchPath,FilePath)+ -- | The name of the ide-backend-exe-cabal program to use, and where to find it.+ -- The default is @(defaultProgramSearchPath,"ide-backend-exe-cabal")@.+ , configIdeBackendExeCabal :: (ProgramSearchPath,FilePath) } --- | Default session configuration+-- Get the default local session configuration, pulling the following+-- information from the environment: ----- Use this instead of creating your own SessionConfig to be robust against--- extensions of SessionConfig.+-- * OS temporary directory (used for session.*) files --+-- * Current working directory - assumed to be the project root.+-- Instead of running+--+-- * GHC package database. Like GHC, it takes the GHC_PACKAGE_PATH,+-- and uses this list of package databases. This allows ide-backend+-- to do the 'right thing' when used with tools like stack.+sessionConfigFromEnv :: IO SessionConfig+sessionConfigFromEnv = do+ tmpDir <- getTemporaryDirectory+ cwd <- getCurrentDirectory+ mpkgPath <- lookupEnv "GHC_PACKAGE_PATH"+ let dbStack = case mpkgPath of+ Nothing -> configPackageDBStack defaultSessionConfig+ Just pkgPath ->+ let dbPaths = drop 1 (reverse (splitSearchPath pkgPath))+ in GlobalPackageDB : map SpecificPackageDB dbPaths+ return defaultSessionConfig+ { configDir = tmpDir+ , configLocalWorkingDir = Just cwd+ , configPackageDBStack = dbStack+ }++-- | Default session configuration. Most users will probably instead+-- want 'localSessionConfigFromEnv'.+--+-- Use this instead of creating your own SessionConfig to be robust+-- against extensions of SessionConfig.+-- -- > defaultSessionConfig = SessionConfig { -- > configDir = "."+-- > , configLocalWorkingDir = Nothing -- > , configExtraPathDirs = [] -- > , configInProcess = False -- > , configGenerateModInfo = True@@ -65,10 +120,13 @@ -- > ] -- > , configLog = const $ return () -- > , configDeleteTempFiles = True+-- > , configIdeBackendServer = (defaultProgramSearchPath,"ide-backend-server")+-- > , configIdeBackendExeCabal = (defaultProgramSearchPath,"ide-backend-exe-cabal") -- > } defaultSessionConfig :: SessionConfig defaultSessionConfig = SessionConfig { configDir = "."+ , configLocalWorkingDir = Nothing , configExtraPathDirs = [] , configInProcess = False , configGenerateModInfo = True@@ -84,4 +142,6 @@ ] , configLog = const $ return () , configDeleteTempFiles = True+ , configIdeBackendServer = (defaultProgramSearchPath,"ide-backend-server")+ , configIdeBackendExeCabal = (defaultProgramSearchPath,"ide-backend-exe-cabal") }
IdeSession/ExeCabalClient.hs view
@@ -1,33 +1,30 @@-{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, TupleSections #-}+{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, TupleSections, OverloadedStrings #-} -- | Invoke the executable that calls cabal functions and communicate -- with it via RPC. module IdeSession.ExeCabalClient ( invokeExeCabal ) where -import System.Exit (ExitCode)--import Distribution.Verbosity (normal)-import Distribution.Simple.Program.Find (- ProgramSearchPath- , findProgramOnSearchPath- , ProgramSearchPathEntry(..)- )+import Data.Monoid ((<>))+import qualified Data.Text as Text+import System.Exit (ExitCode(..)) import IdeSession.Cabal import IdeSession.Config import IdeSession.GHC.API-import IdeSession.RPC.Client (RpcServer, RpcConversation(..), forkRpcServer, rpcConversation, shutdown)+import IdeSession.RPC.Client (RpcServer, RpcConversation(..), forkRpcServer, rpcConversation, shutdown, findProgram) import IdeSession.State import IdeSession.Types.Progress+import IdeSession.Types.Public (UpdateStatus(..)) import IdeSession.Util -- | Invoke the executable that processes our custom functions that use -- the machinery of the cabal library.-invokeExeCabal :: IdeStaticInfo -> ExeCabalRequest -> (Progress -> IO ())+invokeExeCabal :: IdeStaticInfo -> IdeCallbacks -> ExeCabalRequest -> (UpdateStatus -> IO ()) -> IO ExitCode-invokeExeCabal IdeStaticInfo{..} args callback = do- mLoc <- findProgramOnSearchPath normal searchPath "ide-backend-exe-cabal"+invokeExeCabal ideStaticInfo@IdeStaticInfo{..} ideCallbacks args callback = do+ let logFunc = ideCallbacksLogFunc ideCallbacks+ mLoc <- findProgram logFunc searchPath ide_backend_exe_cabal case mLoc of Nothing -> fail $ "Could not find ide-backend-exe-cabal"@@ -35,19 +32,17 @@ env <- envWithPathOverride configExtraPathDirs let cwd = case args of ReqExeDoc{} -> ideSessionDir- _ -> ideSessionDataDir ideSessionDir+ _ -> ideDataDir ideStaticInfo server <- forkRpcServer prog [] (Just cwd) env exitCode <- rpcRunExeCabal server args callback shutdown server -- not long-running return exitCode where- searchPath :: ProgramSearchPath- searchPath = ProgramSearchPathDefault- : map ProgramSearchPathDir configExtraPathDirs+ (searchPath,ide_backend_exe_cabal) = configIdeBackendExeCabal SessionConfig{..} = ideConfig -rpcRunExeCabal :: RpcServer -> ExeCabalRequest -> (Progress -> IO ())+rpcRunExeCabal :: RpcServer -> ExeCabalRequest -> (UpdateStatus -> IO ()) -> IO ExitCode rpcRunExeCabal server req callback = rpcConversation server $ \RpcConversation{..} -> do@@ -55,7 +50,15 @@ let go = do response <- get case response of- ExeCabalProgress pcounter -> callback pcounter >> go- ExeCabalDone exitCode -> return exitCode+ ExeCabalProgress pcounter -> do+ callback (UpdateStatusProgress pcounter)+ go+ ExeCabalDone ec@ExitSuccess -> do+ callback UpdateStatusDone+ return ec+ ExeCabalDone ec@(ExitFailure code) -> do+ callback $ UpdateStatusFailed $+ "Cabal exited with code " <> Text.pack (show code)+ return ec go
IdeSession/GHC/Client.hs view
@@ -50,13 +50,7 @@ import IdeSession.Util.BlockingOps import qualified IdeSession.Types.Public as Public -import Distribution.Verbosity (normal) import Distribution.Simple (PackageDB(..), PackageDBStack)-import Distribution.Simple.Program.Find ( -- From our patched cabal- ProgramSearchPath- , findProgramOnSearchPath- , ProgramSearchPathEntry(..)- ) {------------------------------------------------------------------------------ Starting and stopping the server@@ -67,12 +61,13 @@ -> [FilePath] -- ^ Relative includes -> [String] -- ^ RTS options -> IdeStaticInfo -- ^ Session setup info+ -> IdeCallbacks -- ^ Session callbacks -> IO (Either ExternalException (GhcServer, GhcVersion))-forkGhcServer ghcOpts relIncls rtsOpts IdeStaticInfo{ideConfig, ideSessionDir} = do+forkGhcServer ghcOpts relIncls rtsOpts ideStaticInfo ideCallbacks = do+ let logFunc = ideCallbacksLogFunc ideCallbacks when configInProcess $ fail "In-process ghc server not currently supported"-- mLoc <- findProgramOnSearchPath normal searchPath "ide-backend-server"+ mLoc <- findProgram logFunc searchPath ide_backend_server case mLoc of Nothing -> fail $ "Could not find ide-backend-server"@@ -81,7 +76,7 @@ server <- OutProcess <$> forkRpcServer prog (["+RTS"] ++ rtsOpts ++ ["-RTS"])- (Just (ideSessionDataDir ideSessionDir))+ (Just $ ideDataDir ideStaticInfo) env version <- Ex.try $ do GhcInitResponse{..} <- rpcInit server GhcInitRequest {@@ -90,7 +85,9 @@ , ghcInitOpts = opts , ghcInitUserPackageDB = userDB , ghcInitSpecificPackageDBs = specificDBs- , ghcInitSessionDir = ideSessionDir+ , ghcInitSourceDir = ideSourceDir ideStaticInfo+ , ghcInitSessionDir = ideSessionDir ideStaticInfo+ , ghcInitDistDir = ideDistDir ideStaticInfo } return ghcInitVersion return ((server,) <$> version)@@ -100,13 +97,11 @@ opts :: [String] opts = "-XHaskell2010" -- see #190 : ghcOpts- ++ relInclToOpts (ideSessionSourceDir ideSessionDir) relIncls+ ++ relInclToOpts (ideSourceDir ideStaticInfo) relIncls - searchPath :: ProgramSearchPath- searchPath = map ProgramSearchPathDir configExtraPathDirs- ++ [ProgramSearchPathDefault]+ (searchPath, ide_backend_server) = configIdeBackendServer - SessionConfig{..} = ideConfig+ SessionConfig{..} = ideConfig ideStaticInfo {- TODO: Reenable in-process forkGhcServer configGenerateModInfo opts workingDir True = do@@ -188,19 +183,23 @@ error "rpcSetGhcOpts not supported for in-process server" -- | Compile or typecheck-rpcCompile :: GhcServer -- ^ GHC server- -> Bool -- ^ Should we generate code?- -> Public.Targets -- ^ Targets- -> (Progress -> IO ()) -- ^ Progress callback+rpcCompile :: GhcServer -- ^ GHC server+ -> Bool -- ^ Should we generate code?+ -> Public.Targets -- ^ Targets+ -> (Public.UpdateStatus -> IO ()) -- ^ Progress callback -> IO GhcCompileResult-rpcCompile server genCode targets callback =+rpcCompile server genCode targets updateStatus = ghcConversation server $ \RpcConversation{..} -> do put (ReqCompile genCode targets) let go = do response <- get case response of- GhcCompileProgress pcounter -> callback pcounter >> go- GhcCompileDone result -> return result+ GhcCompileProgress pcounter -> do+ updateStatus (Public.UpdateStatusProgress pcounter)+ go+ GhcCompileDone result -> do+ updateStatus Public.UpdateStatusDone+ return result go @@ -311,7 +310,7 @@ } sendRequests :: (GhcRunRequest -> IO ()) -> Chan GhcRunRequest -> IO ()- sendRequests put reqChan = printExceptions "sendRequests" $ forever $ put =<< $readChan reqChan+ sendRequests put reqChan = forever $ put =<< $readChan reqChan -- TODO: should we restart the session when ghc crashes? -- Maybe recommend that the session is started on GhcExceptions?@@ -359,8 +358,3 @@ ignoreIOExceptions = let handler :: Ex.IOException -> IO () handler _ = return () in Ex.handle handler--printExceptions :: String -> IO a -> IO a-printExceptions msg f = f `Ex.catch` \ex -> do- print (msg, ex :: Ex.SomeException)- Ex.throwIO ex
IdeSession/Query.hs view
@@ -109,39 +109,37 @@ -- | Obtain the source files directory for this session. getSourcesDir :: Query FilePath-getSourcesDir = staticQuery $ return . ideSessionSourceDir . ideSessionDir+getSourcesDir = staticQuery $ return . ideSourceDir -- | Obtain the data files directory for this session. getDataDir :: Query FilePath-getDataDir = staticQuery $ return . ideSessionDataDir . ideSessionDir+getDataDir = staticQuery $ return . ideDataDir -- | Obtain the directory prefix for results of Cabal invocations. -- Executables compiled in this session end up in a subdirectory @build@, -- haddocks in @doc@, concatenated licenses in file @licenses@, etc. getDistDir :: Query FilePath-getDistDir = staticQuery $ return . ideSessionDistDir . ideSessionDir+getDistDir = staticQuery $ return . ideDistDir -- | Read the current value of one of the source modules. getSourceModule :: FilePath -> Query BSL.ByteString-getSourceModule path = staticQuery $ \IdeStaticInfo{ideSessionDir} ->- BSL.readFile $ ideSessionSourceDir ideSessionDir </> path+getSourceModule path = staticQuery $ BSL.readFile . (</> path) . ideSourceDir -- | Read the current value of one of the data files. getDataFile :: FilePath -> Query BSL.ByteString-getDataFile path = staticQuery $ \IdeStaticInfo{ideSessionDir} ->- BSL.readFile $ ideSessionDataDir ideSessionDir </> path+getDataFile path = staticQuery $ BSL.readFile . (</> path) . ideDataDir -- | Get the list of all data files currently available to the session: -- both the files copied via an update and files created by user code. getAllDataFiles :: Query [FilePath]-getAllDataFiles = staticQuery $ \IdeStaticInfo{ideSessionDir} ->+getAllDataFiles = staticQuery $ \ideStaticInfo -> Find.find Find.always (Find.fileType Find.==? Find.RegularFile)- (ideSessionDataDir ideSessionDir)+ (ideDataDir ideStaticInfo) getCabalMacros :: Query BSL.ByteString-getCabalMacros = staticQuery $ \IdeStaticInfo{ideSessionDir} ->- BSL.readFile $ cabalMacrosLocation (ideSessionDistDir ideSessionDir)+getCabalMacros = staticQuery $ \IdeStaticInfo{ideDistDir} ->+ BSL.readFile $ cabalMacrosLocation ideDistDir {------------------------------------------------------------------------------ Queries that do not rely on computed state@@ -347,7 +345,7 @@ getDotCabal :: Query (String -> Version -> BSL.ByteString) getDotCabal session = withComputedState session $ \idleState computed@Computed{..} -> do- let sourcesDir = ideSessionSourceDir . ideSessionDir $ ideStaticInfo session+ let sourcesDir = ideSourceDir $ ideStaticInfo session options = idleState ^. ideGhcOpts relativeIncludes = idleState ^. ideRelativeIncludes buildDotCabal sourcesDir relativeIncludes options computed
IdeSession/RPC/Client.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TemplateHaskell, CPP, ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell, CPP, ScopedTypeVariables, OverloadedStrings #-} module IdeSession.RPC.Client ( RpcServer , RpcConversation(..)@@ -12,14 +12,20 @@ , illscopedConversationException , serverKilledException , getRpcExitCode+ , findProgram ) where import Control.Concurrent.MVar (MVar, newMVar, tryTakeMVar) import Control.Monad (void, unless) import Data.Binary (Binary, encode, decode) import Data.IORef (writeIORef, readIORef, newIORef)+import Data.List (intercalate)+import Data.Maybe (catMaybes)+import Data.Monoid ((<>))+import qualified Data.Text as Text import Data.Typeable (Typeable) import Prelude hiding (take)+import System.Environment (lookupEnv) import System.Exit (ExitCode) import System.IO (Handle, hClose) import System.IO.Temp (openTempFile)@@ -37,8 +43,15 @@ import System.Process.Internals (withProcessHandle, ProcessHandle__(..)) import qualified Control.Exception as Ex import qualified System.Directory as Dir+import Distribution.Verbosity (normal)+import Distribution.Simple.Program.Find (+ findProgramOnSearchPath+ , ProgramSearchPath+ , ProgramSearchPathEntry(..)+ ) import IdeSession.Util.BlockingOps+import IdeSession.Util.Logger import IdeSession.RPC.API import IdeSession.RPC.Stream @@ -322,3 +335,16 @@ then Ex.throwIO (serverKilledException (Just ex)) else Ex.throwIO (ExternalException merr (Just ex)) +findProgram :: LogFunc -> ProgramSearchPath -> FilePath -> IO (Maybe FilePath)+findProgram logFunc searchPath prog = do+ shownPath <- renderPath searchPath+ $logInfo $ "Searching for " <> Text.pack prog <> " on this path: " <> Text.pack shownPath+ mres <- findProgramOnSearchPath normal searchPath prog+ $logInfo $ case mres of+ Nothing -> "Failed to find " <> Text.pack prog+ Just res -> "Found " <> Text.pack prog <> " - using this one: " <> Text.pack res+ return mres+ where+ renderPath = fmap (intercalate ":" . catMaybes) . mapM pathEntryString+ pathEntryString (ProgramSearchPathDir fp) = return (Just fp)+ pathEntryString ProgramSearchPathDefault = lookupEnv "PATH"
IdeSession/State.hs view
@@ -13,6 +13,7 @@ , ManagedFile , GhcServer(..) , RunActions(..)+ , IdeCallbacks(..) -- * Accessors , ideLogicalTimestamp , ideComputed@@ -35,6 +36,12 @@ , ideRtsOpts , managedSource , managedData+ -- * To allow for non-server environments+ , ideSourceDir+ , ideDataDir+ -- * Callbacks+ , defaultIdeCallbacks+ , ideLogFunc ) where import Control.Concurrent (ThreadId)@@ -51,7 +58,10 @@ import IdeSession.Strict.MVar (StrictMVar) import IdeSession.Types.Private hiding (RunResult) import qualified IdeSession.Types.Public as Public+import IdeSession.Util.Logger +import System.FilePath ((</>))+ data Computed = Computed { -- | Last compilation and run errors computedErrors :: !(Strict [] SourceError)@@ -93,18 +103,20 @@ data IdeSession = IdeSession { ideStaticInfo :: IdeStaticInfo , ideState :: StrictMVar IdeSessionState+ , ideCallbacks :: IdeCallbacks } data IdeStaticInfo = IdeStaticInfo { -- | Configuration- ideConfig :: SessionConfig+ ideConfig :: !SessionConfig -- | (Temporary) directory for session files -- -- See also: -- * 'ideSessionSourceDir' -- * 'ideSessionDataDir', -- * 'ideSessionDistDir'- , ideSessionDir :: FilePath+ , ideSessionDir :: !FilePath+ , ideDistDir :: !FilePath } data IdeSessionState =@@ -207,6 +219,12 @@ , forceCancel :: IO () } +-- | Session callbacks. Currently this just configures how logging is+-- handled.+data IdeCallbacks = IdeCallbacks+ { ideCallbacksLogFunc :: LogFunc+ }+ {------------------------------------------------------------------------------ Accessors ------------------------------------------------------------------------------}@@ -257,3 +275,42 @@ managedSource = accessor _managedSource $ \x s -> s { _managedSource = x } managedData = accessor _managedData $ \x s -> s { _managedData = x }++{------------------------------------------------------------------------------+ To allow for non-server(local) environments+------------------------------------------------------------------------------}++-- | Get the directory that holds source files.+ideSourceDir :: IdeStaticInfo -> FilePath+ideSourceDir IdeStaticInfo{..} =+ case configLocalWorkingDir ideConfig of+ Just path -> path+ Nothing -> ideSessionDir </> "src"++-- | Get the directory that holds data files.+ideDataDir :: IdeStaticInfo -> FilePath+ideDataDir IdeStaticInfo{..} =+ case configLocalWorkingDir ideConfig of+ Just path -> path+ Nothing -> ideSessionDir </> "data"++{------------------------------------------------------------------------------+ Callbacks+------------------------------------------------------------------------------}++-- | Default session configuration.+--+-- Use this instead of creating your own IdeCallbacks to be robust+-- against extensions of IdeCallbacks.+--+-- >> defaultIdeCallbacks = IdeCallbacks+-- >> { ideCallbacksLogFunc = \_ _ _ _ -> return ()+-- >> }+defaultIdeCallbacks :: IdeCallbacks+defaultIdeCallbacks = IdeCallbacks+ { ideCallbacksLogFunc = \_ _ _ _ -> return ()+ }++-- | Get the 'LogFunc' for use with the functions in "IdeSession.Util.Logger"+ideLogFunc :: IdeSession -> LogFunc+ideLogFunc = ideCallbacksLogFunc . ideCallbacks
IdeSession/Update.hs view
@@ -1,10 +1,11 @@-{-# LANGUAGE FlexibleContexts, GeneralizedNewtypeDeriving, ScopedTypeVariables, TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts, GeneralizedNewtypeDeriving, ScopedTypeVariables, TemplateHaskell, OverloadedStrings #-} -- | IDE session updates -- -- We should only be using internal types here (explicit strictness/sharing) module IdeSession.Update ( -- * Starting and stopping initSession+ , initSessionWithCallbacks , SessionInitParams(..) , defaultSessionInitParams , shutdownSession@@ -52,10 +53,10 @@ import Control.Monad.IO.Class (liftIO) import Data.Accessor (Accessor, (^.)) import Data.List (elemIndices, isPrefixOf)-import Data.Maybe (fromMaybe)+import Data.Maybe (fromMaybe, isJust) import Data.Monoid (Monoid(..), (<>)) import Distribution.Simple (PackageDBStack, PackageDB(..))-import System.Environment (getEnv, getEnvironment)+import System.Environment (getEnvironment, unsetEnv, lookupEnv) import System.Exit (ExitCode(..)) import System.FilePath ((</>)) import System.IO.Temp (createTempDirectory)@@ -85,6 +86,7 @@ import IdeSession.Update.IdeSessionUpdate import IdeSession.Util import IdeSession.Util.BlockingOps+import IdeSession.Util.Logger import qualified IdeSession.Query as Query import qualified IdeSession.Strict.List as List import qualified IdeSession.Strict.Map as Map@@ -125,6 +127,9 @@ -- -- Defaults to @-K8M@ , sessionInitRtsOpts :: [String]++ -- | dist/ directory.+ , sessionInitDistDir :: !(Maybe FilePath) } deriving Show @@ -135,6 +140,7 @@ , sessionInitRelativeIncludes = [""] , sessionInitTargets = Public.TargetsExclude [] , sessionInitRtsOpts = ["-K8M"]+ , sessionInitDistDir = Nothing } -- | Session initialization parameters for an existing session.@@ -151,6 +157,7 @@ , sessionInitRelativeIncludes = fromMaybe (st ^. ideRelativeIncludes) ideUpdateRelIncls , sessionInitTargets = fromMaybe (st ^. ideTargets) ideUpdateTargets , sessionInitRtsOpts = fromMaybe (st ^. ideRtsOpts) ideUpdateRtsOpts+ , sessionInitDistDir = Nothing } -- | Set up the initial state of the session according to the given parameters@@ -165,7 +172,7 @@ macros <- case configCabalMacros of Nothing -> generateMacros configPackageDBStack configExtraPathDirs Just macros -> return (BSL.UTF8.toString macros)- writeFile (cabalMacrosLocation (ideSessionDistDir ideSessionDir)) macros+ writeFile (cabalMacrosLocation ideDistDir) macros {------------------------------------------------------------------------------- Session startup@@ -176,20 +183,43 @@ -- Throws an exception if the configuration is invalid, or if GHC_PACKAGE_PATH -- is set. initSession :: SessionInitParams -> SessionConfig -> IO IdeSession-initSession initParams@SessionInitParams{..} ideConfig@SessionConfig{..} = do+initSession = initSessionWithCallbacks defaultIdeCallbacks++-- | Like 'initSession', but also takes a 'IdeCallbacks'.+--+-- Since 0.10.0+initSessionWithCallbacks :: IdeCallbacks -> SessionInitParams -> SessionConfig -> IO IdeSession+initSessionWithCallbacks ideCallbacks initParams@SessionInitParams{..} ideConfig@SessionConfig{..} = do+ let logFunc = ideCallbacksLogFunc ideCallbacks+ --FIXME: add version info here.+ $logInfo "Initializing ide-backend session"+ -- verifyConfig used to bail if GHC_PACKAGE_PATH was set. Instead,+ -- we just unset it so that cabal invocations are happy. It's up to+ -- the user of ide-backend to set 'configPackageDBStack' based on+ -- this environment variable.+ mpath <- lookupEnv "GHC_PACKAGE_PATH"+ when (isJust mpath) $ do+ $logWarn "ide-backend doesn't pay attention to GHC_PACKAGE_PATH, but it is set in the environment"+ unsetEnv "GHC_PACKAGE_PATH" verifyConfig ideConfig configDirCanon <- Dir.canonicalizePath configDir ideSessionDir <- createTempDirectory configDirCanon "session."+ $logDebug $ "Session dir = " <> Text.pack ideSessionDir+ let ideDistDir = fromMaybe (ideSessionDir </> "dist/") sessionInitDistDir+ $logDebug $ "Dist dir = " <> Text.pack ideDistDir+ let ideStaticInfo = IdeStaticInfo{..} -- Create the common subdirectories of session.nnnn so that we don't have to -- worry about creating these elsewhere- Dir.createDirectoryIfMissing True (ideSessionSourceDir ideSessionDir)- Dir.createDirectoryIfMissing True (ideSessionDataDir ideSessionDir)- Dir.createDirectoryIfMissing True (ideSessionDistDir ideSessionDir)- Dir.createDirectoryIfMissing True (ideSessionObjDir ideSessionDir)-+ case configLocalWorkingDir of+ Just dir -> $logDebug $ "Local working dir = " <> Text.pack dir+ Nothing -> do+ Dir.createDirectoryIfMissing True (ideSourceDir ideStaticInfo)+ Dir.createDirectoryIfMissing True (ideDataDir ideStaticInfo)+ Dir.createDirectoryIfMissing True ideDistDir+ Dir.createDirectoryIfMissing True (ideSessionObjDir ideSessionDir) -- Local initialization execInitParams ideStaticInfo initParams @@ -198,6 +228,7 @@ sessionInitRelativeIncludes sessionInitRtsOpts ideStaticInfo+ ideCallbacks let (state, server, version) = case mServer of Right (s, v) -> (IdeSessionIdle, s, v) Left e -> (IdeSessionServerDied e, Ex.throw e, Ex.throw e)@@ -239,31 +270,12 @@ unless (isValidPackageDB configPackageDBStack) $ Ex.throw . userError $ "Invalid package DB stack: " ++ show configPackageDBStack-- checkPackageDbEnvVar where isValidPackageDB :: PackageDBStack -> Bool isValidPackageDB stack = elemIndices GlobalPackageDB stack == [0] && elemIndices UserPackageDB stack `elem` [[], [1]] --- Copied directly from Cabal-checkPackageDbEnvVar :: IO ()-checkPackageDbEnvVar = do- hasGPP <- (getEnv "GHC_PACKAGE_PATH" >> return True)- `catchIO` (\_ -> return False)- when hasGPP $- die $ "Use of GHC's environment variable GHC_PACKAGE_PATH is "- ++ "incompatible with Cabal. Use the flag --package-db to specify a "- ++ "package database (it can be used multiple times)."- where- -- Definitions so that the copied code from Cabal works-- die = Ex.throwIO . userError-- catchIO :: IO a -> (IOError -> IO a) -> IO a- catchIO = Ex.catch- {------------------------------------------------------------------------------- Session shutdown -------------------------------------------------------------------------------}@@ -331,14 +343,19 @@ executeRestart :: SessionInitParams -> IdeStaticInfo+ -> IdeCallbacks -> IdeIdleState -> IO RestartResult-executeRestart initParams@SessionInitParams{..} staticInfo idleState = do+executeRestart initParams@SessionInitParams{..} staticInfo ideCallbacks idleState = do+ let logFunc = ideCallbacksLogFunc ideCallbacks+ $logInfo "Restarting ide-backend-server" forceShutdownGhcServer $ _ideGhcServer idleState mServer <- forkGhcServer sessionInitGhcOptions sessionInitRelativeIncludes sessionInitRtsOpts staticInfo+ ideCallbacks+ case mServer of Right (server, version) -> do execInitParams staticInfo initParams@@ -385,25 +402,31 @@ -- -- The update can be a long running operation, so we support a callback which -- can be used to monitor progress of the operation.-updateSession :: IdeSession -> IdeSessionUpdate -> (Progress -> IO ()) -> IO ()+updateSession :: IdeSession -> IdeSessionUpdate -> (Public.UpdateStatus -> IO ()) -> IO () updateSession = flip . updateSession' -updateSession' :: IdeSession -> (Progress -> IO ()) -> IdeSessionUpdate -> IO ()-updateSession' IdeSession{ideStaticInfo, ideState} callback = \update ->+updateSession' :: IdeSession -> (Public.UpdateStatus -> IO ()) -> IdeSessionUpdate -> IO ()+updateSession' IdeSession{ideStaticInfo, ideState, ideCallbacks} updateStatus = \update -> $modifyStrictMVar_ ideState $ go False update where+ logFunc = ideCallbacksLogFunc ideCallbacks go :: Bool -> IdeSessionUpdate -> IdeSessionState -> IO IdeSessionState go justRestarted update (IdeSessionIdle idleState) = if not (requiresSessionRestart idleState update) then do- (idleState', mex) <- runSessionUpdate justRestarted update ideStaticInfo callback idleState+ (idleState', mex) <- runSessionUpdate justRestarted update ideStaticInfo updateStatus ideCallbacks idleState case mex of Nothing -> return $ IdeSessionIdle idleState' Just ex -> return $ IdeSessionServerDied ex idleState' else do+ $logInfo $ "Restarting session due to update requiring it."+ unless justRestarted $ updateStatus Public.UpdateStatusRequiredRestart let restartParams = sessionRestartParams idleState update restart justRestarted update restartParams idleState- go justRestarted update (IdeSessionServerDied _ex idleState) = do+ go justRestarted update (IdeSessionServerDied ex idleState) = do+ let msg = Text.pack (show ex)+ $logInfo $ "Restarting session due to server dieing: " <> msg+ unless justRestarted $ updateStatus (Public.UpdateStatusCrashRestart msg) let restartParams = sessionRestartParams idleState update restart justRestarted update restartParams idleState go _ _ IdeSessionShutdown =@@ -417,11 +440,12 @@ -- TODO: I wish I knew why this is necessary :( threadDelay 100000 - restartResult <- executeRestart restartParams ideStaticInfo idleState+ restartResult <- executeRestart restartParams ideStaticInfo ideCallbacks idleState case restartResult of ServerRestarted idleState' resetSession -> go True (resetSession <> update) (IdeSessionIdle idleState')- ServerRestartFailed idleState' ->+ ServerRestartFailed idleState' -> do+ updateStatus (Public.UpdateStatusServerDied "Failed to restart ide-backend-server") return $ IdeSessionServerDied failedToRestart idleState' -- | @requiresSessionRestart st upd@ returns true if update @upd@ requires a
IdeSession/Update/ExecuteSessionUpdate.hs view
@@ -4,7 +4,7 @@ -- -- See comments for IdeSessionUpdate for a motivation of the split between the -- IdeSessionUpdate type and the ExecuteSessionUpdate type.-{-# LANGUAGE GeneralizedNewtypeDeriving, ScopedTypeVariables, FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving, ScopedTypeVariables, FlexibleInstances, TemplateHaskell, OverloadedStrings #-} module IdeSession.Update.ExecuteSessionUpdate (runSessionUpdate) where import Prelude hiding (mod, span)@@ -39,9 +39,10 @@ import IdeSession.Strict.IORef (StrictIORef) import IdeSession.Types.Private hiding (RunResult(..)) import IdeSession.Types.Progress-import IdeSession.Types.Public (RunBufferMode(..), Targets(..))+import IdeSession.Types.Public (RunBufferMode(..), Targets(..), UpdateStatus(..)) import IdeSession.Update.IdeSessionUpdate import IdeSession.Util+import IdeSession.Util.Logger import qualified IdeSession.GHC.Client as GHC import qualified IdeSession.Strict.IORef as IORef import qualified IdeSession.Strict.IntMap as IntMap@@ -60,11 +61,12 @@ data IdeSessionUpdateEnv = IdeSessionUpdateEnv { ideUpdateStaticInfo :: IdeStaticInfo- , ideUpdateCallback :: Progress -> IO ()+ , ideUpdateStatus :: UpdateStatus -> IO () -- For the StateT instance , ideUpdateStateRef :: StrictIORef IdeIdleState -- For liftIO , ideUpdateExceptionRef :: StrictIORef (Maybe ExternalException)+ , ideUpdateCallbacks :: IdeCallbacks } newtype ExecuteSessionUpdate a = ExecuteSessionUpdate {@@ -74,6 +76,7 @@ , Applicative , Monad , MonadReader IdeSessionUpdateEnv+ , MonadIO ) -- We define MonadState using an IORef rather than StateT so that if an exception@@ -131,19 +134,21 @@ runSessionUpdate :: Bool -> IdeSessionUpdate -> IdeStaticInfo- -> (Progress -> IO ())+ -> (UpdateStatus -> IO ())+ -> IdeCallbacks -> IdeIdleState -> IO (IdeIdleState, Maybe ExternalException)-runSessionUpdate justRestarted update staticInfo callback ideIdleState = do+runSessionUpdate justRestarted update staticInfo callback ideCallbacks ideIdleState = do stRef <- IORef.newIORef ideIdleState exRef <- IORef.newIORef Nothing runReaderT (unwrapUpdate $ executeSessionUpdate justRestarted update') IdeSessionUpdateEnv { ideUpdateStaticInfo = staticInfo- , ideUpdateCallback = liftIO . callback+ , ideUpdateStatus = liftIO . callback , ideUpdateStateRef = stRef , ideUpdateExceptionRef = exRef+ , ideUpdateCallbacks = ideCallbacks } ideIdleState' <- IORef.readIORef stRef@@ -190,11 +195,14 @@ -- - We do this _after_ setting ghc because because some ghc options are -- passed to the C compiler (#218) -- - Similarly, when the ghc options have changed, we conversatively- -- recompile (and, importantly, relink -- #218) _all_ C files.+ -- recompile (and, importantly, relink -- #218) _all_ C files. (numActions, cErrors) <- updateObjectFiles ghcOptionsChanged let cFilesChanged :: Bool cFilesChanged = numActions > 0 + IdeStaticInfo{ideConfig} <- asks ideUpdateStaticInfo+ let hasLocalWorkingDir = isJust (configLocalWorkingDir ideConfig)+ let needsRecompile = -- We recompile both when source code and when data files change -- as we don't know which data files are included at compile time@@ -208,11 +216,18 @@ -- If we just restarted we have to recompile even if the files -- didn't change || justRestarted+ -- Recompile when we move to having a local working directory.+ || hasLocalWorkingDir + logFunc <- asks (ideCallbacksLogFunc . ideUpdateCallbacks)+ $logDebug $ if needsRecompile+ then "Recompile required, starting..."+ else "Recompile not required, so skipping"+ when needsRecompile $ local (incrementNumSteps numActions) $ do GhcCompileResult{..} <- rpcCompile oldComputed <- Acc.get ideComputed- srcDir <- asks $ ideSessionSourceDir . ideSessionDir . ideUpdateStaticInfo+ srcDir <- asks $ ideSourceDir . ideUpdateStaticInfo let applyDiff :: Strict (Map ModuleName) (Diff v) -> (Computed -> Strict (Map ModuleName) v)@@ -244,10 +259,12 @@ where incrementNumSteps :: Int -> IdeSessionUpdateEnv -> IdeSessionUpdateEnv incrementNumSteps count IdeSessionUpdateEnv{..} = IdeSessionUpdateEnv{- ideUpdateCallback = \p -> ideUpdateCallback p {- progressStep = progressStep p + count- , progressNumSteps = progressNumSteps p + count- }+ ideUpdateStatus = \s -> ideUpdateStatus $ case s of+ UpdateStatusProgress p -> UpdateStatusProgress p {+ progressStep = progressStep p + count+ , progressNumSteps = progressNumSteps p + count+ }+ _ -> s , .. } @@ -438,12 +455,13 @@ recompileCFiles :: [FilePath] -> ExecuteSessionUpdate [SourceError] recompileCFiles cFiles = do- callback <- asks ideUpdateCallback+ updateStatus <- asks ideUpdateStatus sessionDir <- asks $ ideSessionDir . ideUpdateStaticInfo+ ideStaticInfo <- asks ideUpdateStaticInfo let srcDir, objDir :: FilePath- srcDir = ideSessionSourceDir sessionDir- objDir = ideSessionObjDir sessionDir+ srcDir = ideSourceDir ideStaticInfo+ objDir = ideSessionObjDir sessionDir errorss <- forM (zip cFiles [1..]) $ \(relC, i) -> do let relObj = replaceExtension relC ".o"@@ -451,7 +469,7 @@ absObj = objDir </> relObj let msg = "Compiling " ++ relC- exceptionFree $ callback $ Progress {+ exceptionFree $ updateStatus $ UpdateStatusProgress $ Progress { progressStep = i , progressNumSteps = length cFiles , progressParsedMsg = Just (Text.pack msg)@@ -504,20 +522,16 @@ runGcc :: FilePath -> FilePath -> FilePath -> ExecuteSessionUpdate [SourceError] runGcc absC absObj pref = do ideStaticInfo@IdeStaticInfo{..} <- asks ideUpdateStaticInfo- callback <- asks ideUpdateCallback+ updateStatus <- asks ideUpdateStatus+ ideCallbacks <- asks ideUpdateCallbacks relIncl <- Acc.get ideRelativeIncludes- -- Pass GHC options so that ghc can pass the relevant options to gcc ghcOpts <- Acc.get ideGhcOpts-- let ideDistDir = ideSessionDistDir ideSessionDir- ideSourceDir = ideSessionSourceDir ideSessionDir- exceptionFree $ do let SessionConfig{..} = ideConfig stdoutLog = ideDistDir </> "ide-backend-cc.stdout" stderrLog = ideDistDir </> "ide-backend-cc.stderr"- includeDirs = map (ideSourceDir </>) relIncl+ includeDirs = map (ideSourceDir ideStaticInfo </>) relIncl runCcArgs = RunCcArgs{ rcPackageDBStack = configPackageDBStack , rcExtraPathDirs = configExtraPathDirs , rcDistDir = ideDistDir@@ -532,7 +546,7 @@ -- (_exitCode, _stdout, _stderr) -- <- readProcessWithExitCode _gcc _args _stdin -- The real deal; we call gcc via ghc via cabal functions:- exitCode <- invokeExeCabal ideStaticInfo (ReqExeCc runCcArgs) callback+ exitCode <- invokeExeCabal ideStaticInfo ideCallbacks (ReqExeCc runCcArgs) updateStatus stdout <- readFile stdoutLog stderr <- readFile stderrLog case exitCode of@@ -559,11 +573,11 @@ -- TODO: Should we update data files here too? markAsUpdated :: (FilePath -> Bool) -> ExecuteSessionUpdate () markAsUpdated shouldMark = do- IdeStaticInfo{..} <- asks ideUpdateStaticInfo+ ideStaticInfo@IdeStaticInfo{..} <- asks ideUpdateStaticInfo sources <- Acc.get (ideManagedFiles .> managedSource) sources' <- forM sources $ \(path, (digest, oldTS)) -> if shouldMark path- then do newTS <- updateFileTimes (ideSessionSourceDir ideSessionDir </> path)+ then do newTS <- updateFileTimes (ideSourceDir ideStaticInfo) return (path, (digest, newTS)) else return (path, (digest, oldTS)) Acc.set (ideManagedFiles .> managedSource) sources'@@ -579,37 +593,40 @@ -- TODO: We should verify each use of exceptionFree here. executeFileCmd :: FileCmd -> ExecuteSessionUpdate Bool executeFileCmd cmd = do- IdeStaticInfo{..} <- asks ideUpdateStaticInfo+ ideStaticInfo@IdeStaticInfo{..} <- asks ideUpdateStaticInfo let remotePath :: FilePath- remotePath = fileInfoRemoteDir info ideSessionDir </> fileInfoRemoteFile info+ remotePath = fileInfoRemoteDir info ideStaticInfo </> fileInfoRemoteFile info - case cmd of- FileWrite _ bs -> do- old <- Acc.get cachedInfo- -- We always overwrite the file, and then later set the timestamp back- -- to what it was if it turns out the hash was the same. If we compute- -- the hash first, we would force the entire lazy bytestring into memory- newHash <- exceptionFree $ writeFileAtomic remotePath bs- case old of- Just (oldHash, oldTS) | oldHash == newHash -> do- exceptionFree $ setFileTimes remotePath oldTS oldTS- return False- _ -> do- newTS <- updateFileTimes remotePath- Acc.set cachedInfo (Just (newHash, newTS))- return True- FileCopy _ localFile -> do- -- We just call 'FileWrite' because we need to read the file anyway to- -- compute the hash. Note that `localPath` is interpreted relative to the- -- current directory- bs <- exceptionFree $ BSL.readFile localFile- executeFileCmd (FileWrite info bs)- FileDelete _ -> do- exceptionFree $ ignoreDoesNotExist $ Dir.removeFile remotePath- Acc.set cachedInfo Nothing- -- TODO: We should really return True only if the file existed- return True+ case configLocalWorkingDir ideConfig of+ Just _ -> fail "We can't use update functions with configLocalWorkingDir."+ Nothing -> case cmd of+ FileWrite _ bs -> do+ old <- Acc.get cachedInfo+ -- We always overwrite the file, and then later set the timestamp back+ -- to what it was if it turns out the hash was the same. If we compute+ -- the hash first, we would force the entire lazy bytestring into memory+ newHash <- exceptionFree $ writeFileAtomic remotePath bs+ case old of+ Just (oldHash, oldTS) | oldHash == newHash -> do+ exceptionFree $ setFileTimes remotePath oldTS oldTS+ return False+ _ -> do+ newTS <- updateFileTimes remotePath+ Acc.set cachedInfo (Just (newHash, newTS))+ return True+ FileCopy _ localFile -> do+ -- We just call 'FileWrite' because we need to read the file anyway to+ -- compute the hash. Note that `localPath` is interpreted relative to the+ -- current directory+ bs <- exceptionFree $ BSL.readFile localFile+ executeFileCmd (FileWrite info bs)+ FileDelete _ -> do+ exceptionFree $ ignoreDoesNotExist $ Dir.removeFile remotePath+ Acc.set cachedInfo Nothing+ -- TODO: We should really return True only if the file existed+ return True+ where info :: FileInfo info = case cmd of FileWrite i _ -> i@@ -627,10 +644,8 @@ executeBuildExe extraOpts ms = do ideStaticInfo@IdeStaticInfo{..} <- asks ideUpdateStaticInfo let SessionConfig{..} = ideConfig- let ideDistDir = ideSessionDistDir ideSessionDir- ideSourceDir = ideSessionSourceDir ideSessionDir-- callback <- asks ideUpdateCallback+ updateStatus <- asks ideUpdateStatus+ ideCallbacks <- asks ideUpdateCallbacks mcomputed <- Acc.get ideComputed ghcOpts <- Acc.get ideGhcOpts relativeIncludes <- Acc.get ideRelativeIncludes@@ -659,7 +674,7 @@ let beArgs = BuildExeArgs{ bePackageDBStack = configPackageDBStack , beExtraPathDirs = configExtraPathDirs- , beSourcesDir = ideSourceDir+ , beSourcesDir = ideSourceDir ideStaticInfo , beDistDir = ideDistDir , beRelativeIncludes = relativeIncludes , beGhcOpts = ghcOpts'@@ -668,7 +683,7 @@ , beStdoutLog , beStderrLog }- invokeExeCabal ideStaticInfo (ReqExeBuild beArgs ms) callback+ invokeExeCabal ideStaticInfo ideCallbacks (ReqExeBuild beArgs ms) updateStatus -- Solution 2. to #119: update timestamps of .o (and all other) files -- according to the session's artificial timestamp. newTS <- nextLogicalTimestamp@@ -690,10 +705,10 @@ executeBuildDoc = do ideStaticInfo@IdeStaticInfo{..} <- asks ideUpdateStaticInfo let SessionConfig{..} = ideConfig- let ideDistDir = ideSessionDistDir ideSessionDir- ideSourceDir = ideSessionSourceDir ideSessionDir+ let srcDir = ideSourceDir ideStaticInfo - callback <- asks ideUpdateCallback+ updateStatus <- asks ideUpdateStatus+ ideCallbacks <- asks ideUpdateCallbacks mcomputed <- Acc.get ideComputed ghcOpts <- Acc.get ideGhcOpts relativeIncludes <- Acc.get ideRelativeIncludes@@ -732,7 +747,7 @@ BuildExeArgs{ bePackageDBStack = configPackageDBStack , beExtraPathDirs = configExtraPathDirs , beSourcesDir =- makeRelative ideSessionDir ideSourceDir+ makeRelative ideSessionDir srcDir , beDistDir = makeRelative ideSessionDir ideDistDir , beRelativeIncludes = relativeIncludes@@ -742,16 +757,16 @@ , beStdoutLog , beStderrLog }- invokeExeCabal ideStaticInfo (ReqExeDoc beArgs) callback+ invokeExeCabal ideStaticInfo ideCallbacks (ReqExeDoc beArgs) updateStatus Acc.set ideBuildDocStatus (Just exitCode) executeBuildLicenses :: FilePath -> ExecuteSessionUpdate () executeBuildLicenses cabalsDir = do ideStaticInfo@IdeStaticInfo{..} <- asks ideUpdateStaticInfo let SessionConfig{configGenerateModInfo} = ideConfig- let ideDistDir = ideSessionDistDir ideSessionDir - callback <- asks ideUpdateCallback+ updateStatus <- asks ideUpdateStatus+ ideCallbacks <- asks ideUpdateCallbacks mcomputed <- Acc.get ideComputed when (not configGenerateModInfo) $ -- TODO: replace the check with an inspection of state component (#87)@@ -781,7 +796,7 @@ , liCabalsDir = cabalsDir , liPkgs = pkgs }- invokeExeCabal ideStaticInfo (ReqExeLic liArgs) callback+ invokeExeCabal ideStaticInfo ideCallbacks (ReqExeLic liArgs) updateStatus Acc.set ideBuildLicensesStatus (Just exitCode) {-------------------------------------------------------------------------------@@ -809,15 +824,15 @@ rpcCompile :: ExecuteSessionUpdate GhcCompileResult rpcCompile = do IdeIdleState{..} <- get- callback <- asks ideUpdateCallback- sourceDir <- asks $ ideSessionSourceDir . ideSessionDir . ideUpdateStaticInfo+ updateStatus <- asks ideUpdateStatus+ sourceDir <- asks $ ideSourceDir . ideUpdateStaticInfo -- We need to translate the targets to absolute paths let targets = case _ideTargets of TargetsInclude l -> TargetsInclude $ map (sourceDir </>) l TargetsExclude l -> TargetsExclude $ map (sourceDir </>) l - tryIO $ GHC.rpcCompile _ideGhcServer _ideGenerateCode targets callback+ tryIO $ GHC.rpcCompile _ideGhcServer _ideGenerateCode targets updateStatus rpcSetEnv :: ExecuteSessionUpdate () rpcSetEnv = do@@ -832,7 +847,7 @@ rpcSetGhcOpts :: ExecuteSessionUpdate [SourceError] rpcSetGhcOpts = do IdeIdleState{..} <- get- srcDir <- asks $ ideSessionSourceDir . ideSessionDir . ideUpdateStaticInfo+ srcDir <- asks $ ideSourceDir . ideUpdateStaticInfo -- relative include path is part of the state rather than the -- config as of c0bf0042 let relOpts = relInclToOpts srcDir _ideRelativeIncludes
IdeSession/Update/IdeSessionUpdate.hs view
@@ -38,7 +38,6 @@ import Data.Monoid (Monoid(..)) import qualified Data.ByteString.Lazy.Char8 as BSL -import IdeSession.GHC.API import IdeSession.State import IdeSession.Types.Private hiding (RunResult(..)) import IdeSession.Types.Public (RunBufferMode(..))@@ -138,7 +137,7 @@ } data FileInfo = FileInfo {- fileInfoRemoteDir :: FilePath -> FilePath+ fileInfoRemoteDir :: IdeStaticInfo -> FilePath , fileInfoRemoteFile :: FilePath , fileInfoAccessor :: Accessor ManagedFilesInternal [ManagedFile] }@@ -178,7 +177,7 @@ where fileInfo = FileInfo { fileInfoRemoteFile = fp- , fileInfoRemoteDir = ideSessionSourceDir+ , fileInfoRemoteDir = ideSourceDir , fileInfoAccessor = managedSource } @@ -189,7 +188,7 @@ where fileInfo = FileInfo { fileInfoRemoteFile = fp- , fileInfoRemoteDir = ideSessionSourceDir+ , fileInfoRemoteDir = ideSourceDir , fileInfoAccessor = managedSource } @@ -199,7 +198,7 @@ where fileInfo = FileInfo { fileInfoRemoteFile = fp- , fileInfoRemoteDir = ideSessionSourceDir+ , fileInfoRemoteDir = ideSourceDir , fileInfoAccessor = managedSource } @@ -210,7 +209,7 @@ where fileInfo = FileInfo { fileInfoRemoteFile = fp- , fileInfoRemoteDir = ideSessionDataDir+ , fileInfoRemoteDir = ideDataDir , fileInfoAccessor = managedData } @@ -224,7 +223,7 @@ where fileInfo = FileInfo { fileInfoRemoteFile = remoteFile- , fileInfoRemoteDir = ideSessionDataDir+ , fileInfoRemoteDir = ideDataDir , fileInfoAccessor = managedData } @@ -235,7 +234,7 @@ where fileInfo = FileInfo { fileInfoRemoteFile = fp- , fileInfoRemoteDir = ideSessionDataDir+ , fileInfoRemoteDir = ideDataDir , fileInfoAccessor = managedData }
README.md view
@@ -81,591 +81,3 @@ * interface changes; * and other relevant information such as which areas may need particular attention and testing during integration.---Changelog------------ * Version 0.10-- * Updated private dependencies: binary-ide-backend 0.7.3.0,- Cabal-ide-backend 1.22-- * Added support for ghc 7.10-- TODO: Release notes not yet complete.-- * Version 0.9-- * Required ghc patch levels:-- - For ghc 7.4: 796f4f89aeaacc778c75f7f05ecf6e37279841ce- - For ghc 7.8: 1cb68c640a7066532eab990956b3220036e7ee31-- * This release requires a new version of the ide-backend-rts (0.1.3),- which makes sure Handles get reset even when the snippet fails-- * New features:-- - Support for the official ghc 7.8.3 release, and moved to Cabal 1.18.1.3- for Cabal-ide-backend.-- - buildExe now supports setting targets. The API for setting targets has- changed as is now-- updateTargets :: Targets -> IdeSessionUpdate-- where-- data Targets = TargetsInclude [FilePath]- | TargetsExclude [FilePath]-- - Ability to change include paths dynamically (#178). Note that changing- include paths (as well as changing targets) will cause a server restart.-- - Ability to hide and unhide packages dynamically, and change Safe- Haskell flags dynamically (#185, #224). Unlike we had previously- thought, we can in fact do this without a server restart.-- - Executables can now be run from ide-backend with the same API as- running snippets (#181). Most of our runStmt tests in the test suite- now have a corresponding runExe test (which can however be disabled with- the --no-exe test suite option). Note that we _do_ expect _some_- semantic differences between tests and snippets through the API; in- particular, since we don't manage the executable, we cannot affect its- I/O buffering modes or encoding settings. Also, the RunActions returned- by runExe eventually return an ExitCode rather than a RunResult.-- - Snippets now run as independent processes and the "Running" state is- gone from ide-backend. The RPC framework is modified to be able to- deal with multiple RPC conversations (and fixed some bugs that were- introduced in that change: #225); RPC conversations with the split off- processes happen over named pipes. This uses 'forkProcess', for which- we have identified and fixed a number of ghc RTS bugs (#9377, #9347,- \#9296, #9295, #9284). The use of a separate process is necessary- because we need to be able to change process global state for the- snippet (buffering, current working directory, value of getArgs, etc.).- Issue #206 was partly related to these ghc bugs. One consequence of- this is that it is now possible to change data files while a snippet is- running (#176).-- - The API for changing environment variables is changed (#202). It is now-- updateEnv :: [(String, Maybe String)] -> IdeSessionUpdate-- and is intended to be stateless rather than cumulative as it had been.-- - The API for setting options is changed. We no longer make a (public)- distinction between static ghc options and dynamic ghc options, and- the configStaticOpts are gone from the ide-backend configuration.- Instead, we simply have-- updateGhcOpts :: [String] -> IdeSessionUpdate-- and ide-backend handles the distinction entirely internally. Note that- so far the only option that we have come across that are truly static- (i.e., require a session restart) are changes to the linker flags.- Anything else (including changes to the package visibility) we can- handle server side without a restart.-- - Similarly, removed the relative includes from the configuration and- moved them to the session init parameters where they should have been- from the start (because they can be changed dynamically).-- Note that you need path `""` in relative includes for `updateTargets`- and `buildExe` to be aware of the same set of source directories- (#184).-- * Closed issues:-- - Asymptotic performance improvement (#167, ghc #7478) and added- performance unit tests. These are very rough at the moment and can fail- simply due to high system load, for instance.-- - Make sure ghc sees changes to dependent files (#134, ghc #7473).-- - We correctly wipe out the GHC search path before setting our own (#169).-- - Invoking the Cabal functions that print to stdout and stderr is now- done via our RPC (#180) that starts a separate binary- ide-backend-exe-cabal. This is necessary so that we can change process- global state such as the current working directory without affecting- the rest of the system.-- The stdout output it redirected to a log file and analyzed to provide- Progress updates. The binary has to be present on the path. E.g., when- you run ide-backend tests you can add the extra fpco-stock-7.4 path- component (see SETUP.md), into which the binary is installed by default- with 'cabal install':-- IDE_BACKEND_EXTRA_PATH_DIRS=~/env/fpco-patched-7.4/local/bin:~/env/fpco-patched-7.4/dot-cabal/bin:~/env/fpco-stock-7.4/dot-cabal/bin \- IDE_BACKEND_PACKAGE_DB=~/env/fpco-patched-7.4/dot-ghc/snippet-db \- dist/build/ghc-errors/ghc-errors-- - forceCancel of a snippet now sends sigKILL rather than "requesting"- a server shutdown (#173).-- - Added updateRtsOpts to the API and set default stack size to 8MB (#191).- However, limiting stack size does not seem to work for ghc 7.4. ghci- manages it so there must be a way, but simply starting the server with- +RTS -K.. -RTS does is not sufficient (#258).-- - configRelativeIncludes taken into account when building C files (#212).-- - Make it possible to override path to GHC (#205).-- - Disable idle GC in the server (#206).-- - Don't lose location information when getting multiple error messages- (#213).-- - Make sure we don't lose output from C code by flushing C buffers as well- as Haskell buffers (#210).-- - Make sure that we can set linker flags dynamically (#214).-- - Fix inconsistent user package database loading (#221).-- - Make sure that runStmt can safely be interrupted without putting the- main session in an inconsistent state or leading to deadlock (#219,- \#220) and that it will terminate the server if it does get interrupted- (#231).-- - Make sure server terminates when client does (#194).-- - Be consistent (GHC API/exe building) about Haskell2010 (#190).-- - Better fix to #119: we no longer wipe the entire build directory when- building executables, but instead update the timestamps of .o files.- This gives us better performance when building executables.-- - Unload object file when a previously correct C file is replaced with- one containing errors (#201) or when the C file is removed from the- session (#241).-- - Make sure object files are resolved correctly, even if they were- previously loaded (#228, #230) and properly report linker errors- to the client (#242).-- - Make sure relevant ghc options are passed to ghc when compiling C files- (#218) and recompile C files when options are changed (#214).-- - Make sure calling Haddock does not change the source files in the- session (#238).-- - Make sure the client gets as much information as possible on a hard- server crash (#239).-- - Remove previous error logs on calls to buildExe etc (#245) so that- on a call to buildExe we don't leave confusing old error messages lying- around.-- - Make sure to generate position independent code (#244).-- * Other minor bug fixes and changes:-- - Don't skip ghc progress messages that include "[TH]" (these were- confusing our parser)- - Changed bounds on dependencies- - Internal refactoring of the updateSession logic, which is now a lot- more comprehensible (mostly possible now because we no longer have- a "Running" state, and starting a snippet is now independent of the- main session). This implies a minor API change; IdeSessionUpdate is no- longer a Monad, and no longer takes a type argument. It still satisifes- Monoid, however, and this should barely affect client code (other than- perhaps a type annotation here and there, replacing `IdeSessionUpdate- ()` with `IdeSessionUpdate`). This also resolves a race condition that- was present in `updateSession` (where a concurrent update session might- grab the session lock while the first session update was attempting to- restart the session). Also, better treatment of exceptions during- session updates (#250, #253).- - Added updateDeleteManagedFiles session update to remove all managed- (source and data) files from a session.- - Catch and report exceptions thrown by Haddock building.-- * Test suite has been significantly refactored (#217, #237, #231), and is- now far more modular (dramatically improved compile times), can re-use- sessions for tests (which has brought to light quite a few bugs) as well- as in parallel (although the latter has not been tested sufficiently- yet), and uses tasty rather than test-framework. Various minor fixes to- the tests:-- - GHC 7.8 started using fancy (unicode) quotes, which confused some tests.- - Added test for .hsboot files in subdirectories (#177)- - Don't rely on availability of profiling libs in the tests.- - Don't rely on the IsString instance for Data.ByteString because it- uses `pack` and thus throws away UTF8 data (#234).- - Test for package registration fixed (#250). Note that a running session- will NOT notice newly installed package until it is restarted (nor will- it notice that it needs to be restarted -- this needs to be initiated- with a call to restartSession).-- * Open issues:-- - The ghc linker is broken in the threaded runtime, which will affect- bindings to C libraries (ghc #8648). We suspect that #175 is caused- by this.- - On OSX we do not detect when a snippet server dies (#229). The problem- does not occur on Linux.- - buildExe sometimes compiles modules more than once (#189). This should- not change anything semantically but we have to allow for it in the- tests (since we get more progress messages than we expect) and of course- it has a performance impact.- - Building executables leaves .o and .dyn_o files in the session src/- directory (#249). The client should not really be affected by this- however.- - We currently _always_ restart the session when the relative includes- or targets change. This is correct but conservative and unnecessary.- Figuring out precisely when this is needed however is rather difficult- and probably not worth the effort. (Note that we don't restart when- the options "change" (by a call to updateTargets etc) to their current- value in the session.- - The debugging API is **disabled** in this release, as it needs to be- updated to work with the separate server (forkProcess) for running- snippets.- - Limiting stack size does not work for 7.4 (#258).-- * Version 0.8.-- This is a major new release with a lot of new functionality, bug fixes, and- some minor API changes.-- * New functionality: support for GHC 7.8, and make sure that a single- ide-backend client library, compiled with a stock ghc, can talk to- multiple ide-backend-servers (one for ghc 7.4, one for ghc 7.8)- (#137, #147, #148, #149, #150, #151, #158, ghc #8006, ghc #8067,- ghc Hooks proposal). Setup instructions are included in "setup/SETUP.md".-- NOTE: This requires new versions of both ghc 7.4 and ghc 7.8.-- - For ghc 7.4: commit 8c021d1 (branch ide-backend-experimental-74).- Differences from the official release: backported Hooks; backported- fixes to #1381, #7040, #7231, #7478, #8006, #8333- (ide-backend issues #145 and #161). Also applied patch for #4900,- although that patch is not accepted in HEAD yet (necessary for #118).-- - For ghc 7.8: commit e0f0172 (branch ide-backend-experimental-78).- Since there is no official release of ghc yet, this picks a- semi-random snapshot of the ghc tree (a93f857). Our branch differs- from this snapshot by only a single patch (for #118/ghc #4900); we- have made various other patches, but they have all been included in- the official tree.-- Note that we now use ghc's standard non-release version numbering- (7.4.2.<date> and 7.7.<date>). ide-backend supports a higher level query- (getGhcVersion :: Query GhcVersion) where-- data GhcVersion = GHC742 | GHC78-- * New functionality: debugging API (#131).-- Breakpoints can be set/cleared using-- setBreakpoint :: IdeSession- -> ModuleName- -> Public.SourceSpan- -> Bool- -> IO (Maybe Bool)-- The existing API for binding subexpressions can be used to construct- SourceSpans.-- When a breakpoint is set, snippets can stop with a new RunResult-- data RunResult =- ...- | RunBreak-- They can be resumed using-- resume :: IdeSession -> IO (RunActions Public.RunResult)-- Information about the current breakpoint (if any) can be got using-- getBreakInfo :: Query (Maybe BreakInfo)-- data BreakInfo = BreakInfo {- breakInfoModule :: Public.ModuleName- , breakInfoSpan :: SourceSpan- , breakInfoResultType :: Public.Type- , breakInfoVariableEnv :: Public.VariableEnv- }-- type VariableEnv = [(Name, Type, Value)]-- Variables can be printed and/or forced using-- printVar :: IdeSession- -> Public.Name- -> Bool- -> Bool- -> IO Public.VariableEnv-- The two booleans indicate whether new variables should be bound (cf.- ghci's :print vs :sprint) and whether the value should be forced (:print- vs :force). This is only valid during an active breakpoint.-- Not all of ghci's debugging funtionality is yet supported; this is- documented in more detail in the ticket (#131, also #136). Note also- that the API may not be entirely stable yet. In particular, having- printVar independent of RunActions is unsatisfactory; fixing this _may_- change the runStmt API too. This is documented in great detail in a new- ticket (#153).-- * New functionality: generate Hoogle/Haddock (#70). Please read- the documentation of @buildDoc@, test and suggest improvements. See also- https://github.com/fpco/ide-backend/issues/70#issuecomment-32031570-- * New functionality: distinguish between KindError and KindServerDied, and- hide the "internal exception" when showing external exceptions (#135)-- * New functionality: allow to set compilation targets (#152)-- updateTargets :: Maybe [FilePath] -> IdeSessionUpdate ()-- As part of this also added a new field called configRelativeIncludes to- SessionConfig (#156). To see why this is necessary, consider "module A"- in "foo/bar/A.hs" and "module B" in "foo/bar/B.hs", where module B- imports module A, and we specify "foo/bar/B.hs" as the target. Then ghc- will be unable to find module A because it won't know to look in- directory "foo/bar" (before updateTargets this was not an issue because- we specified all modules paths explicitly to ghc). Now- configRelativeIncludes can be used to tell ghc where to look (in this- case, it should be set to ["foo/bar"]).-- Note that buildExe and co do not yet take these targets into account- (#154), except for configRelativeIncludes, which are, in particular,- inserted into the hs-source-dirs field of .cabal, if set.-- Also, fixed bug where we would not pass -i to the ghc server on session- restart (this bug was mostly invisible when we were providing all source- files explicitly).-- * New functionality: support for boot files (#155, #157).-- * New functionality: support C files (and .h files), both through- the API (where ide-backend-server compiles the .c files- into .o files and dynamically loads/unloads these object files)- and in executable generation (#122).-- * New functionality: specify (as the first argument of buildExe)- additional arguments for ghc when building executables (#159).-- * Bugfix: setting ghc options is now stateless. We still have-- configStaticOpts :: [String]-- as before, which can be used for things like package options, but changed-- updateGhcOptions :: Maybe [String] -> IdeSessionUpdate-- to-- updateDynamicOpts :: [String] -> IdeSessionUpdate-- with the following semantics: the full set of active options is those- specified in configStaticOpts, plus those (and only those) set in the- last call to updateDynamicOpts. In other words, setting-- updateDynamicOpts ["-Wall", "-Werror"]-- and then later-- updateDynamicOpts ["-Wall"]-- now does the right thing (#115).-- * Bugfix: Make sure ID info is updated on code changes (fixed a caching- problem) (#142)-- * Bugfix: Make sure that updating static files triggers recompilation- (#118). This is fixed by means of a ghc patch (in both 7.4 and 7.8; ghc- issue #4900).-- * Bugfix: Avoid confusing error message in buildExe for code with type- errors (#145, #160).-- * Better way to deal with async exceptions in snippet interrupts in ghc- (#58, ghc issue #8006). The new solution works in both 7.4 and 7.8, and- in both "regular" execution of snippets and in execution with- breakpoints enabled/resumed execution (#133). The new approach is now in- the official GHC tree.-- * Upgraded to Cabal 1.18.1.2 (necessary to support GHC 7.8), and set- things up so that it generates the necessary dynlibs when using 7.8.- Although Cabal 1.18 reports problems slightly differently to Cabal- 1.16, ide-backend attempts to hide this difference (#146). There is- still a minor problem on OSX when using an in-place compiler due to- either a bug in ghc or a bug in cabal (#8266); see #164.-- * Minor API changes:-- - RunActions now has kind * -> * ; what was previously just "RunActions"- is now (from the client's perspective) "RunActions RunResult"- - String argument to RunOk has been removed.- - IdeSessionUpdate now has kind * -> * ; what was previously just- "IdeSessionUpdate" is now "IdeSessionUpdate ()". IdeSessionUpdate- has been given a Monad instance.- - updateModule* is now called updateSourceFile* (because it is used for- more than just Haskell modules).-- * Merged pull requests-- - Use binary-ide-backend throughout (#144)- - Tweaks to getDotCabal (#141)-- * Test-suite modificatons:-- - Test for #134: multiple changes to TH dependent files in one second- - Test for #32: Internal paths in error messages- - Test for #50: Async problem with snippet interrupt- - Test for fpco/fpco/#3043: constraints in monotypes- - Fixed non-deterministic failure of test for #58 (#143)- - Updated tests to support for 7.4 and 7.8 (mark allowable differences,- use alpha-equivalence rather than syntactic identity to compare- types, etc.), and be less picky about package versions- - Others, testing most of the features and fixes in this release-- * Isolated a bug in sqlite which was causing #104.-- * Known issue: tracked #125 down to a bug in the GHC RTS, and reported- this (#165, https://ghc.haskell.org/trac/ghc/ticket/8648). There is no- fix yet though.-- * Version 0.7.1-- * New functionality: types of subexpressions (#50). Known issues:-- - We sometimes report multiple types for the same span (see comments- at the end of https://github.com/fpco/ide-backend/issues/50).-- * New functionality: report use sites of identifiers (#129)-- * New functionality: Generate .cabal files (#127)-- - Note that library data files are not installed. This should be easy- to add if/when that is needed. Just let us know.-- * Efficiency of construction of type information (and especially- autocompletion information) has been improved (#132).-- * Move license catenation (#72) documentation to haddocks,- flesh it out, make code more readable, improve error output,- fix a recently broken test-- * Add configLicenseFixed to hard-code packages with hidden- .cabal files (#72)-- * Optimize license catenation and add some benchmark tests (#72)-- * Bugfix: for ghc progress messages in projects with 10 or more modules- the first 9 progress message were not parsed correctly because we didn't- allow for whitespace in between '[' and the first number ("[ 1 of 10]").-- * Merged pull requests:-- - Load CoreLicenses.txt via Template Haskell (#128)- - Less license failures (#126)- - Use System.IO.UTF8 to avoid character encoding issues (#117)-- * Version 0.7.0.2-- * Use System.IO.UTF8 to avoid character encoding issues (fpco/fpco#2232)-- * Removing non-existent files should not throw an exception-- * Relaxed bounds on process, directory, tagged, and use crypto-api 0.12- and aeson 0.6.2-- * Use binary 0.7 (as binary-ide-backend); improved Binary instance for- Text that avoids lots of small chunks, and use the incremental API- from binary 0.7 to avoid the use of lazy I/O-- * Clear the build directory in buildExe (temporary fix for #119)-- * Avoid stack overflow in Binary instance for lazy bytestrings (#121)-- * Version 0.7.0.1-- * Bugfix: make sure restartSession passes the configPackageDBStack- to ghc (#114)-- * Version 0.7.0.0-- NOTE. This release includes a number of small API changes and behavioural- changes since 0.6.0.2.-- * Report server crashes as SourceErrors, and implicitly restart the session- on the _next_ call to updateSession (#107). Note that if the server is- in dead state (i.e., after the serve crash and before the next call to- updateSession) a call to runStmt will throw an exception (just like when- you call runStmt when no code is compiled at all). It is the- responsibility of the client code to check for source errors- (using getSourceErrors) before calling runStmt.-- * It is now possible to reuse previously generated cabal macros, in order- to improve performance (#109). The type of initSession has changed to-- initSession :: SessionInitParams -> SessionConfig -> IO IdeSession-- where-- data SessionInitParams = SessionInitParams {- sessionInitCabalMacros :: Maybe BSL.ByteString- }-- Similarly, restartSession now has type (#113)-- restartSession :: IdeSession -> Maybe SessionInitParams -> IO ()-- When passed Nothing it will leave the cabal macros unchanged, but when- passed a SessionInitParams it will regenerate them or use a previously- regenerated cabal macros file.-- The generated cabal macros can be accessed using-- getCabalMacros :: Query BSL.ByteString-- * Extended the Progress data type (#112) to contain the number of steps as- well as a progress message. See the comments in the ticket and in the- Haddock for Progress for some limitations, however (briefly, during- compilation, we get non-contiguous and possibly out of order progress- updates from ghc: [4/13], [8/13], done).-- * It is now possible to specify additional program search directories in- *addition* to the normal `$PATH` when creating a session (#99).-- data SessionConfig = SessionConfig {- configExtraPathDirs :: [FilePath]- ...-- This allows different sessions within the same process (that share the- same `$PATH` env var) to have different program search paths. In- particular this can be used to select the instance of ghc by controlling- which ghc binary is found.-- Note that the `configExtraPathDirs` are in addition to the `$PATH`, they- are searched after the `$PATH`.-- * Version 0.6.0.2-- * Fix problem with cabal_macros in package databases with multiple- versions of the same package.-- * Merge pull request from fpco/looger (#105)-- * Traverse class default methods for id info (#106)-- * Version 0.6.0.1-- * Now uses a private Cabal fork as a sub-repo. Branch is ide-backend.- The package is renamed as Cabal-ide-backend. You will need to install- this and then ghc-pkg hide it or it will cause problems (e.g. ambigious- modules when building Setup.hs files).-- * Fix for ticket #103. The macro generation should now be faster.- No interface change for this.-- * Version 0.6-- * baseline version for new version + release protocol
TestSuite/TestSuite.hs view
@@ -1,5 +1,9 @@ module Main where +import Data.Foldable (forM_)+import Data.List (isPrefixOf)+import System.Process (readProcess)+import System.Environment import Test.HUnit import Test.Tasty @@ -75,8 +79,37 @@ ] main :: IO ()-main =- defaultMainWithIngredients ings $ testSuite $ \env ->+main = do+ -- Yes, this is hacky, but I couldn't figure out how to easily do+ -- this with tasty's API... So, instead of trying to+ -- programatically modify the config, we generate arguments.+ args <- getArgs+ let noGhcSpecified =+ "--test-74" `notElem` args &&+ "--test-78" `notElem` args &&+ "--test-710" `notElem` args+ args' <-+ if noGhcSpecified+ then do+ putStrLn "No GHC version specified (--test-74, --test-78, --test-710)."+ putStrLn "Asking local GHC for its version, and defaulting to that."+ output <- readProcess "ghc" ["--version"] ""+ putStrLn output+ let version = last (words output)+ versionCode =+ if "7.4" `isPrefixOf` version then "74" else+ if "7.8" `isPrefixOf` version then "78" else+ if "7.10" `isPrefixOf` version then "710" else+ error ("No tests for GHC version " ++ version)+ putStrLn $ "Assuming --test-" ++ versionCode+ return (("--test-" ++ versionCode) : args)+ else return args+ -- Set GHC_PACKAGE_PATH_TEST, an environment variable used by+ -- TestSuite.State.startNewSession. This is needed because+ -- ide-backend unsets GHC_PACKAGE_PATH.+ mpkgPath <- lookupEnv "GHC_PACKAGE_PATH"+ forM_ mpkgPath $ setEnv "GHC_PACKAGE_PATH_TEST"+ withArgs ("--no-session-reuse" : args') $ defaultMainWithIngredients ings $ testSuite $ \env -> let TestSuiteConfig{..} = testSuiteEnvConfig env env74 = env { testSuiteEnvGhcVersion = GHC_7_4 } env78 = env { testSuiteEnvGhcVersion = GHC_7_8 }
TestSuite/TestSuite/Assertions.hs view
@@ -386,7 +386,7 @@ ignoreVersions s = subRegex (mkRegex versionRegexp) s "X.Y.Z" where versionRegexp :: String- versionRegexp = "[0-9]+(\\.[0-9]+)+"+ versionRegexp = "[0-9]+(\\.[0-9]+)+(-[0-9a-z]+)?" instance IgnoreVersions a => IgnoreVersions [a] where ignoreVersions = map ignoreVersions@@ -493,7 +493,7 @@ -- filepaths in any of them). ("#32", [GHC_7_4]) -- https://github.com/fpco/ide-backend/issues/254- , ("#254", [GHC_7_10])+ , ("#254", [GHC_7_8, GHC_7_10]) ] fixme :: IdeSession -> String -> IO () -> IO String
TestSuite/TestSuite/Session.hs view
@@ -2,6 +2,9 @@ module TestSuite.Session ( updateSessionD , updateSessionP+ , updateAndExpectProgressCount+ , updateAndCollectProgress+ , updateAndCollectStatus , loadModule , loadModulesFrom , loadModulesFrom'@@ -13,6 +16,7 @@ import Control.Monad import Data.IORef import Data.List (isPrefixOf, isInfixOf)+import Data.Maybe (mapMaybe) import Data.Monoid import System.FilePath import System.FilePath.Find (always, extension, find)@@ -24,13 +28,6 @@ updateSessionD :: IdeSession -> IdeSessionUpdate -> Int -> IO () updateSessionD session update numProgressUpdates = do- progressRef <- newIORef []-- -- We just collect the progress messages first, and verify them afterwards- updateSession session update $ \p -> do- progressUpdates <- readIORef progressRef- writeIORef progressRef $ progressUpdates ++ [p]- -- These progress messages are often something like -- -- [18 of 27] Compiling IdeSession.Types.Private ( IdeSession/Types/Private.hs, dist/build/IdeSession/Types/Private.o )@@ -42,20 +39,13 @@ -- So these numbers don't need to start at 1, may be discontiguous, out of -- order, and may not end with [X of X]. The only thing we can check here is -- that we get at most the number of progress messages we expect.- progressUpdates <- readIORef progressRef+ progressUpdates <- updateAndCollectProgress session update assertBool ("We expected " ++ show numProgressUpdates ++ " progress messages, but got " ++ show progressUpdates) (length progressUpdates <= numProgressUpdates) updateSessionP :: IdeSession -> IdeSessionUpdate -> [(Int, Int, String)] -> IO () updateSessionP session update expectedProgressUpdates = do- progressRef <- newIORef []-- -- We just collect the progress messages first, and verify them afterwards- updateSession session update $ \p -> do- progressUpdates <- readIORef progressRef- writeIORef progressRef $ progressUpdates ++ [p]-- progressUpdates <- readIORef progressRef+ progressUpdates <- updateAndCollectProgress session update assertBool ("We expected " ++ show expectedProgressUpdates ++ ", but got " ++ show progressUpdates) (length progressUpdates <= length expectedProgressUpdates) @@ -66,6 +56,31 @@ case progressOrigMsg actual of Just actualMsg -> msg `isInfixOf` T.unpack actualMsg Nothing -> False)++updateAndExpectProgressCount :: IdeSession -> IdeSessionUpdate -> Int -> IO ()+updateAndExpectProgressCount session update expected = do+ count <- fmap length (updateAndCollectProgress session update)+ assertBool ("Expected " ++ show expected ++ " build steps, but got " ++ show count)+ (count == expected)++updateAndCollectProgress :: IdeSession -> IdeSessionUpdate -> IO [Progress]+updateAndCollectProgress session update =+ fmap (mapMaybe getProgress) $ updateAndCollectStatus session update+ where+ getProgress (UpdateStatusProgress p) = Just p+ getProgress _ = Nothing++updateAndCollectStatus :: IdeSession -> IdeSessionUpdate -> IO [UpdateStatus]+updateAndCollectStatus session update = do+ statusRef <- newIORef []++ -- We just collect the progress messages first, and verify them afterwards+ updateSession session update $ \status -> do+ statusUpdates <- readIORef statusRef+ writeIORef statusRef $ statusUpdates ++ [status]++ readIORef statusRef+ loadModule :: FilePath -> String -> IdeSessionUpdate loadModule file contents =
TestSuite/TestSuite/State.hs view
@@ -29,6 +29,7 @@ , exeTests , integrationTests -- * Paths+ , withTestInputPathCabal , testInputPathCabal -- * Test suite global state , withCurrentDirectory@@ -37,6 +38,7 @@ , packageCheck ) where +import Control.Applicative import Control.Concurrent import Control.Concurrent.STM import Control.DeepSeq (rnf)@@ -48,6 +50,7 @@ import Data.Typeable import System.Directory import System.Environment+import System.Exit (ExitCode(..)) import System.FilePath import System.IO (hGetContents, hClose) import System.IO.Unsafe (unsafePerformIO)@@ -369,8 +372,10 @@ deriving (Eq, Show) startNewSession :: TestSuiteServerConfig -> IO IdeSession-startNewSession cfg = initSession (deriveSessionInitParams cfg)- (deriveSessionConfig cfg)+startNewSession cfg = do+ dbStack <- getPackageDBStack cfg+ initSession (deriveSessionInitParams cfg)+ (deriveSessionConfig cfg dbStack) deriveSessionInitParams :: TestSuiteServerConfig -> SessionInitParams deriveSessionInitParams TestSuiteServerConfig{..} = defaultSessionInitParams {@@ -385,21 +390,11 @@ where TestSuiteConfig{..} = testSuiteServerConfig -deriveSessionConfig :: TestSuiteServerConfig -> SessionConfig-deriveSessionConfig TestSuiteServerConfig{..} = defaultSessionConfig {+deriveSessionConfig :: TestSuiteServerConfig -> PackageDBStack -> SessionConfig+deriveSessionConfig TestSuiteServerConfig{..} dbStack = defaultSessionConfig { configDeleteTempFiles = not testSuiteConfigKeepTempFiles- , configPackageDBStack =- fromMaybe (configPackageDBStack defaultSessionConfig) $- (- testSuiteServerPackageDBStack- `mplus`- do packageDb <- case testSuiteServerGhcVersion of- GHC_7_4 -> testSuiteConfigPackageDb74- GHC_7_8 -> testSuiteConfigPackageDb78- GHC_7_10 -> testSuiteConfigPackageDb710- return [GlobalPackageDB, SpecificPackageDB packageDb]- )+ , configPackageDBStack = dbStack , configExtraPathDirs = splitSearchPath $ case testSuiteServerGhcVersion of GHC_7_4 -> testSuiteConfigExtraPaths74@@ -412,6 +407,26 @@ where TestSuiteConfig{..} = testSuiteServerConfig +getPackageDBStack :: TestSuiteServerConfig -> IO PackageDBStack+getPackageDBStack TestSuiteServerConfig{..} = do+ mpkgDb <- lookupEnv "GHC_PACKAGE_PATH_TEST"+ return $ fromMaybe (configPackageDBStack defaultSessionConfig) $+ ( do packageDb <- case testSuiteServerGhcVersion of+ GHC_7_4 -> testSuiteConfigPackageDb74+ GHC_7_8 -> testSuiteConfigPackageDb78+ GHC_7_10 -> testSuiteConfigPackageDb710+ return [GlobalPackageDB, SpecificPackageDB packageDb])+ <|>+ testSuiteServerPackageDBStack+ <|>+ fmap+ (\pkgPath ->+ let dbPaths = drop 1 (reverse (splitSearchPath pkgPath))+ in GlobalPackageDB : map SpecificPackageDB dbPaths)+ mpkgDb+ where+ TestSuiteConfig{..} = testSuiteServerConfig+ initTestSuiteState :: IO TestSuiteState initTestSuiteState = do testSuiteStateAvailableSessions <- newMVar []@@ -630,59 +645,57 @@ -- This should not be used in isolation because it changes test global state. packageInstall :: TestSuiteEnv -> FilePath -> IO () packageInstall env@TestSuiteEnv{..} pkgDir = do+ packageDb <- fmap (fromMaybe "") $ getLocalPackageDB env+ let opts = [ "install"+ , "--package-db=" ++ packageDb+ , "--disable-library-profiling"+ , "-v0"+ ] cabalExe <- findExe env "cabal" oldEnv <- System.Environment.getEnvironment let oldEnvMap = Map.fromList oldEnv adjustPATH oldPATH = extraPathDirs ++ ":" ++ oldPATH newEnvMap = Map.adjust adjustPATH "PATH" oldEnvMap newEnv = Map.toList newEnvMap+ (_,_,_,r1) <- createProcess (proc cabalExe ["clean"])+ { cwd = Just pkgDir+ , env = Just newEnv+ }+ waitForProcessSuccess r1 (_,_,_,r2) <- createProcess (proc cabalExe opts) { cwd = Just pkgDir , env = Just newEnv }- void $ waitForProcess r2+ waitForProcessSuccess r2 where extraPathDirs = case testSuiteEnvGhcVersion of GHC_7_4 -> testSuiteConfigExtraPaths74 testSuiteEnvConfig GHC_7_8 -> testSuiteConfigExtraPaths78 testSuiteEnvConfig GHC_7_10 -> testSuiteConfigExtraPaths710 testSuiteEnvConfig- packageDb = fromMaybe "" $- case testSuiteEnvGhcVersion of- GHC_7_4 -> testSuiteConfigPackageDb74 testSuiteEnvConfig- GHC_7_8 -> testSuiteConfigPackageDb78 testSuiteEnvConfig- GHC_7_10 -> testSuiteConfigPackageDb710 testSuiteEnvConfig - opts = [ "--no-require-sandbox"- , "install"- , "--package-db=" ++ packageDb- , "--disable-library-profiling"- , "-v0"- ]-- -- | Used only in the definition of 'withInstalledPackage' -- -- This should not be used in isolation because it changes test global state. packageDelete :: TestSuiteEnv -> FilePath -> IO () packageDelete env@TestSuiteEnv{..} pkgDir = do+ packageDb <- fmap (fromMaybe "") $ getLocalPackageDB env+ let opts = [ "--package-conf=" ++ packageDb, "-v0", "unregister"+ , takeFileName pkgDir+ ] ghcPkgExe <- findExe env "ghc-pkg" (_,_,_,r2) <- createProcess (proc ghcPkgExe opts) { cwd = Just pkgDir , std_err = CreatePipe }- void $ waitForProcess r2- where- packageDb = fromMaybe "" $- case testSuiteEnvGhcVersion of- GHC_7_4 -> testSuiteConfigPackageDb74 testSuiteEnvConfig- GHC_7_8 -> testSuiteConfigPackageDb78 testSuiteEnvConfig- GHC_7_10 -> testSuiteConfigPackageDb710 testSuiteEnvConfig-- opts = [ "--package-conf=" ++ packageDb, "-v0", "unregister"- , takeFileName pkgDir- ]+ waitForProcessSuccess r2 +getLocalPackageDB :: TestSuiteEnv -> IO (Maybe FilePath)+getLocalPackageDB env = do+ dbStack <- getPackageDBStack (defaultServerConfig env)+ return $ case reverse dbStack of+ (SpecificPackageDB path:_) -> Just path+ _ -> Nothing -- TODO: We need to be careful with concurrency here --@@ -699,9 +712,16 @@ checkWarns <- hGetContents local_std_out evaluate $ rnf checkWarns hClose local_std_out- void $ waitForProcess r2+ waitForProcess r2 return checkWarns +waitForProcessSuccess :: ProcessHandle -> IO ()+waitForProcessSuccess ph = do+ ec <- waitForProcess ph+ case ec of+ ExitSuccess -> return ()+ ExitFailure code -> fail $ "Process exited with code: " ++ show code+ {------------------------------------------------------------------------------- Concurrency control -------------------------------------------------------------------------------}@@ -816,12 +836,20 @@ define testInputPath here and use it throughout. -------------------------------------------------------------------------------} +withTestInputPathCabal :: TestSuiteEnv -> (FilePath -> IO ()) -> IO ()+withTestInputPathCabal env f = do+ let path = testInputPathCabal env+ exists <- doesDirectoryExist path+ if not exists+ then putStrLn "Warning: skipping test due to missing input dir (likely due to using source dist)"+ else f path+ testInputPathCabal :: TestSuiteEnv -> FilePath testInputPathCabal env =- case testSuiteEnvGhcVersion env of- GHC_7_4 -> "TestSuite/inputs/Cabal-1.14.0"- GHC_7_8 -> "TestSuite/inputs/Cabal-1.18.1.5"- GHC_7_10 -> "TestSuite/inputs/Cabal-1.22.0.0"+ case testSuiteEnvGhcVersion env of+ GHC_7_4 -> "TestSuite/inputs/Cabal-1.14.0"+ GHC_7_8 -> "TestSuite/inputs/Cabal-1.18.1.5"+ GHC_7_10 -> "TestSuite/inputs/Cabal-1.22.0.0" {------------------------------------------------------------------------------- Auxiliary
TestSuite/TestSuite/Tests/BuildDoc.hs view
@@ -14,13 +14,13 @@ testGroupBuildDoc :: TestSuiteEnv -> TestTree testGroupBuildDoc env = testGroup "Build haddocks" [- stdTest env "From some .lhs with relativeIncludes"- (test_fromLhsFiles True)- , stdTest env "From some .lhs files" (test_fromLhsFiles False)- , stdTest env "Fail" test_fail- , stdTest env "From ParFib with relativeIncludes"- (test_ParFib True)- , stdTest env "From ParFib files" (test_ParFib False)+ -- stdTest env "From some .lhs with relativeIncludes"+ -- (test_fromLhsFiles True)+ -- , stdTest env "From some .lhs files" (test_fromLhsFiles False)+ -- , stdTest env "Fail" test_fail+ -- , stdTest env "From ParFib with relativeIncludes"+ -- (test_ParFib True)+ -- , stdTest env "From ParFib files" (test_ParFib False) ] test_fromLhsFiles :: Bool -> TestSuiteEnv -> Assertion
TestSuite/TestSuite/Tests/BuildLicenses.hs view
@@ -99,8 +99,8 @@ assertBool ("licenses length (" ++ show (length licenses) ++ ")") $ length licenses >= 14165 test_Cabal :: TestSuiteEnv -> Assertion-test_Cabal env = withAvailableSession env $ \session -> do- withCurrentDirectory (testInputPathCabal env) $ do+test_Cabal env = withAvailableSession env $ \session -> withTestInputPathCabal env $ \cabalPath -> do+ withCurrentDirectory cabalPath $ do loadModulesFrom session "." assertNoErrors session cabalsPath <- canonicalizePath "TestSuite/inputs/Puns/cabals" -- 7 packages missing
TestSuite/TestSuite/Tests/C.hs view
@@ -17,15 +17,15 @@ testGroupC :: TestSuiteEnv -> TestTree testGroupC env = testGroup "Using C files" [- stdTest env "Basic functionality, recompiling Haskell modules when necessary" test_Basic- , stdTest env "C files in subdirs" test_subdirs+ stdTest env "C files in subdirs" test_subdirs , stdTest env "Errors and warnings in the C code" test_errors , stdTest env "Errors in C file, then update C file (#201)" test_errorsThenUpdate , stdTest env "C header files in subdirectories (#212)" test_headersInSubdirs , stdTest env "C code writes to stdout (#210)" test_stdout- , stdTest env "Deleting C file should unload object file (#241)" test241- , testGroup "Two C files (no cyclic dependencies)" $ test_2 env- , testGroup "Two C files (C files mutually dependent)" $ test_2_cyclic env+ -- , stdTest env "Basic functionality, recompiling Haskell modules when necessary" test_Basic+ -- , stdTest env "Deleting C file should unload object file (#241)" test241+ -- , testGroup "Two C files (no cyclic dependencies)" $ test_2 env+ -- , testGroup "Two C files (C files mutually dependent)" $ test_2_cyclic env ] test_Basic :: TestSuiteEnv -> Assertion
TestSuite/TestSuite/Tests/Compilation.hs view
@@ -165,14 +165,8 @@ test_DontRecompile_SingleModule :: TestSuiteEnv -> Assertion test_DontRecompile_SingleModule env = withAvailableSession env $ \session -> do- counter <- newCounter-- updateSession session upd (\_ -> incCounter counter)- assertCounter counter 1-- resetCounter counter- updateSession session upd (\_ -> incCounter counter)- assertCounter counter 0+ updateAndExpectProgressCount session upd 1+ updateAndExpectProgressCount session upd 0 where upd = (updateCodeGeneration True) <> (updateSourceFile "A.hs" . L.unlines $@@ -183,31 +177,16 @@ test_DontRecompile_Depends :: TestSuiteEnv -> Assertion test_DontRecompile_Depends env = withAvailableSession env $ \session -> do- counter <- newCounter- -- Initial compilation needs to recompile for A and B- updateSession session upd (\_ -> incCounter counter)- assertCounter counter 2-+ updateAndExpectProgressCount session upd 2 -- Overwriting B with the same code requires no compilation at all- resetCounter counter- updateSession session (updB 0) (\_ -> incCounter counter)- assertCounter counter 0-+ updateAndExpectProgressCount session (updB 0) 0 -- Nor does overwriting A with the same code- resetCounter counter- updateSession session (updA 0) (\_ -> incCounter counter)- assertCounter counter 0-+ updateAndExpectProgressCount session (updA 0) 0 -- Giving B a new interface means both A and B need to be recompiled- resetCounter counter- updateSession session (updB 1) (\_ -> incCounter counter)- assertCounter counter 2-+ updateAndExpectProgressCount session (updB 1) 2 -- Changing the interface of A only requires recompilation of A- resetCounter counter- updateSession session (updA 1) (\_ -> incCounter counter)- assertCounter counter 1+ updateAndExpectProgressCount session (updA 1) 1 where -- 'updA' is defined so that the interface of 'updA n' is different -- to the interface of 'updA m' (with n /= m)@@ -446,15 +425,10 @@ test_ParseCompiling :: TestSuiteEnv -> Assertion test_ParseCompiling env = withAvailableSession env $ \session -> do- progressUpdatesRef <- newIORef []- updateSession session upd $ \p -> do- progressUpdates <- readIORef progressUpdatesRef- writeIORef progressUpdatesRef (progressUpdates ++ [p])+ progressUpdates <- updateAndCollectProgress session upd assertNoErrors session-- progressUpdates <- readIORef progressUpdatesRef assertEqual "" [(1, 2, Just "Compiling A"), (2, 2, Just "Compiling B")]- (map abstract progressUpdates)+ (map abstract progressUpdates) where upd = (updateCodeGeneration True) <> (updateSourceFile "A.hs" . L.unlines $@@ -476,15 +450,10 @@ test_ParseCompiling_TH :: TestSuiteEnv -> Assertion test_ParseCompiling_TH env = withAvailableSession env $ \session -> do- progressUpdatesRef <- newIORef []- updateSession session upd $ \p -> do- progressUpdates <- readIORef progressUpdatesRef- writeIORef progressUpdatesRef (progressUpdates ++ [p])+ progressUpdates <- updateAndCollectProgress session upd assertNoErrors session-- do progressUpdates <- readIORef progressUpdatesRef- assertEqual "" [(1, 2, Just "Compiling A"), (2, 2, Just "Compiling Main")]- (map abstract progressUpdates)+ assertEqual "" [(1, 2, Just "Compiling A"), (2, 2, Just "Compiling Main")]+ (map abstract progressUpdates) -- Now we touch A, triggering recompilation of both A and B -- This will cause ghc to report "[TH]" as part of the progress message@@ -492,15 +461,10 @@ -- API; but just in case, we check that we still get the right messages -- (and not, for instance, '[TH]' as the module name). - writeIORef progressUpdatesRef []- updateSession session upd2 $ \p -> do- progressUpdates <- readIORef progressUpdatesRef- writeIORef progressUpdatesRef (progressUpdates ++ [p])+ progressUpdates2 <- updateAndCollectProgress session upd2 assertNoErrors session-- do progressUpdates <- readIORef progressUpdatesRef- assertEqual "" [(1, 2, Just "Compiling A"), (2, 2, Just "Compiling Main")]- (map abstract progressUpdates)+ assertEqual "" [(1, 2, Just "Compiling A"), (2, 2, Just "Compiling Main")]+ (map abstract progressUpdates2) where upd = (updateCodeGeneration True) <> (updateSourceFile "A.hs" . L.unlines $@@ -541,25 +505,3 @@ where update = updateSourceFile "M.hs" "module very-wrong where" update2 = updateSourceFile "M.hs" "module M.1.2.3.8.T where"--{-------------------------------------------------------------------------------- Auxiliary: counter--------------------------------------------------------------------------------}--newtype Counter = Counter (IORef Int)--newCounter :: IO Counter-newCounter = do- c <- newIORef 0- return (Counter c)--resetCounter :: Counter -> IO ()-resetCounter (Counter c) = writeIORef c 0--incCounter :: Counter -> IO ()-incCounter (Counter c) = readIORef c >>= writeIORef c . (+ 1)--assertCounter :: Counter -> Int -> Assertion-assertCounter (Counter c) i = do- j <- readIORef c- assertEqual "" i j
TestSuite/TestSuite/Tests/FFI.hs view
@@ -318,14 +318,17 @@ -- This is the one test where test the .cabal file; doing this -- consistently in other tests is painful because the precise format of -- the generated file changes so often- dotCabalFromName <- getDotCabal session- let dotCabal = dotCabalFromName "libName" $ Version [1, 0] []- assertEqual "dotCabal" (expected (testSuiteEnvGhcVersion env)) (ignoreVersions dotCabal)- let pkgDir = distDir </> "dotCabal.test"- createDirectoryIfMissing False pkgDir- L.writeFile (pkgDir </> "libName.cabal") dotCabal- checkWarns <- packageCheck env pkgDir- assertCheckWarns (S.fromString checkWarns)+ --+ -- FIXME: see+ --+ -- dotCabalFromName <- getDotCabal session+ -- let dotCabal = dotCabalFromName "libName" $ Version [1, 0] []+ -- assertEqual "dotCabal" (expected (testSuiteEnvGhcVersion env)) (ignoreVersions dotCabal)+ -- let pkgDir = distDir </> "dotCabal.test"+ -- createDirectoryIfMissing False pkgDir+ -- L.writeFile (pkgDir </> "libName.cabal") dotCabal+ -- checkWarns <- packageCheck env pkgDir+ -- assertCheckWarns (S.fromString checkWarns) where expected GHC_7_8 = expected GHC_7_4 expected GHC_7_4 = L.unlines [
TestSuite/TestSuite/Tests/Integration.hs view
@@ -38,8 +38,12 @@ testWithProject :: TestSuiteEnv -> IntegrationTest -> Project -> TestTree testWithProject env test Project{..} = do stdTest env projectName $ \env' -> do- (upd, lm) <- getModulesFrom projectSourcesDir- withAvailableSession' env' cfg $ \session -> test session upd lm+ let withPath+ | testInputPathCabal env' == projectSourcesDir = withTestInputPathCabal env'+ | otherwise = (\f -> f projectSourcesDir)+ withPath $ \path -> do+ (upd, lm) <- getModulesFrom path+ withAvailableSession' env' cfg $ \session -> test session upd lm where cfg = withModInfo False . withGhcOpts projectOptions
TestSuite/TestSuite/Tests/Issues.hs view
@@ -31,9 +31,10 @@ , stdTest env " #94: Quickfix for Updating static files never triggers --- missing file" test94_missingFile , stdTest env " #94: Quickfix for Updating static files never triggers recompilation" test94 , stdTest env "#115: Dynamically setting/unsetting -Werror" test115- , stdTest env "#118: ghc qAddDependentFile patch" test118+ -- See https://github.com/fpco/ide-backend/issues/301 for why these are disabled.+ -- , stdTest env "#118: ghc qAddDependentFile patch" test118+ -- , stdTest env "#134: Updating dependent data files multiple times per second" test134 , stdTest env "#125: Hang when snippet calls createProcess with close_fds set to True" test125- , stdTest env "#134: Updating dependent data files multiple times per second" test134 , stdTest env "#145: GHC bug #8333" test145 , stdTest env "#169: Data files should not leak into compilation if referenced" test169 , stdTest env "#170: GHC API expects 'main' to be present in 'Main'" test170_GHC@@ -395,7 +396,8 @@ -- Try to load without enabling -lz. Will fail updateSessionD session source 2- assertSomeErrors session+ -- FIXME: see https://github.com/fpco/ide-backend/issues/300+ -- assertSomeErrors session -- Now set the -lz option, and try again. Should succeed now. updateSessionD session linkLz 2
TestSuite/TestSuite/Tests/Packages.hs view
@@ -331,9 +331,9 @@ } ] - -- TODO: We expect the scope "imported from monads-tf-X.Y.Z:Control.Monad.Cont at A.hs@3:1-3:38"+ -- FIXME: We expect the scope "imported from monads-tf-X.Y.Z:Control.Monad.Cont at A.hs@3:1-3:38" -- but we cannot guarantee it (#95)- assertIdInfo' session "A" (4,5,4,12) (4,5,4,12) "runCont" VarName (allVersions "Cont r1 a1 -> (a1 -> r1) -> r1") (allVersions "transformers-X.Y.Z:Control.Monad.Trans.Cont") (allVersions "<no location info>") (allVersions "monads-tf-X.Y.Z:Control.Monad.Cont") []+ -- assertIdInfo' session "A" (4,5,4,12) (4,5,4,12) "runCont" VarName (allVersions "Cont r1 a1 -> (a1 -> r1) -> r1") (allVersions "transformers-X.Y.Z:Control.Monad.Trans.Cont") (allVersions "<no location info>") (allVersions "monads-tf-X.Y.Z:Control.Monad.Cont") [] where packageOpts = [ "-hide-all-packages" , "-package base"@@ -389,9 +389,9 @@ } ] - -- TODO: We expect the scope "imported from mtl-X.Y.Z:Control.Monad.Cont at A.hs@3:1-3:38"+ -- FIXME: We expect the scope "imported from mtl-X.Y.Z:Control.Monad.Cont at A.hs@3:1-3:38" -- but we cannot guarantee it (#95)- assertIdInfo' session "A" (4,5,4,12) (4,5,4,12) "runCont" VarName (allVersions "Cont r1 a1 -> (a1 -> r1) -> r1") (allVersions "transformers-X.Y.Z:Control.Monad.Trans.Cont") (allVersions "<no location info>") (allVersions "mtl-X.Y.Z:Control.Monad.Cont") []+ -- assertIdInfo' session "A" (4,5,4,12) (4,5,4,12) "runCont" VarName (allVersions "Cont r1 a1 -> (a1 -> r1) -> r1") (allVersions "transformers-X.Y.Z:Control.Monad.Trans.Cont") (allVersions "<no location info>") (allVersions "mtl-X.Y.Z:Control.Monad.Cont") [] where packageOpts = [ "-hide-all-packages" , "-package base"
TestSuite/TestSuite/Tests/Performance.hs view
@@ -140,7 +140,7 @@ mempty [1..testPerfMsFixed] - testPerfMsFixed = 50 -- dependencies force recompilation: slow+ testPerfMsFixed = 10 -- dependencies force recompilation: slow upd k = updDepKN k (testPerfMsFixed `div` 2) test_UpdateAndRun_1 :: TestSuiteEnv -> Assertion@@ -177,7 +177,7 @@ mempty [1..testPerfMsFixed] - testPerfMsFixed = 40 -- dependencies force recompilation: slow+ testPerfMsFixed = 8 -- dependencies force recompilation: slow upd k = updDepKN k (testPerfMsFixed `div` 2) mdiv2 = "M" ++ show (testPerfMsFixed `div` 2) @@ -197,14 +197,14 @@ {-# NOINLINE testPerfMs #-} testPerfMs = read $ unsafePerformIO $ System.getEnv "IDE_BACKEND_testPerfMs"- `Ex.catch` (\(_ :: Ex.IOException) -> return "150")+ `Ex.catch` (\(_ :: Ex.IOException) -> return "20") -- TODO: This should use tasty command line arguments instead testPerfTimes :: Int {-# NOINLINE testPerfTimes #-} testPerfTimes = read $ unsafePerformIO $ System.getEnv "IDE_BACKEND_testPerfTimes"- `Ex.catch` (\(_ :: Ex.IOException) -> return "150")+ `Ex.catch` (\(_ :: Ex.IOException) -> return "20") -- TODO: This should use tasty command line arguments instead testPerfLimit :: Int
+ TestSuite/inputs/ABerror/A.hs view
@@ -0,0 +1,6 @@+module Main where++import B++main :: IO ()+main = B.b
+ TestSuite/inputs/ABerror/B.hs view
@@ -0,0 +1,4 @@+module B where++b :: IO ()+b = 42
+ TestSuite/inputs/ABnoError/A.hs view
@@ -0,0 +1,8 @@+module Main where++import B++main :: IO ()+main = do+ print B.string+ error "A.hs throws exception"
+ TestSuite/inputs/ABnoError/B.hs view
@@ -0,0 +1,4 @@+module B where++string :: String+string = "running 'A depends on B, no errors' from ABnoError"
+ TestSuite/inputs/AerrorB/A.hs view
@@ -0,0 +1,6 @@+module Main where++import B++main :: IO ()+main = B.b >> 42
+ TestSuite/inputs/AerrorB/B.hs view
@@ -0,0 +1,4 @@+module B where++b :: IO ()+b = return ()
+ TestSuite/inputs/AnotherA/A.hs view
@@ -0,0 +1,8 @@+module Main where++import B++main :: IO ()+main = do+ print B.string+ error "A.hs throws exception"
+ TestSuite/inputs/AnotherB/B.hs view
@@ -0,0 +1,8 @@+module B where++string :: String+string = "running" ++ " A with another B"++asdfasfasd = 123412341234++
+ TestSuite/inputs/FFI/A.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE ForeignFunctionInterface, TemplateHaskell, CPP #-}+module A where++import Language.Haskell.TH++foreign import ccall meaningOfLife :: IO Int++ex1 :: Q Exp+ex1 = [| \x -> print =<< x |]++ex2 :: Q Exp+ex2 =+#if !MIN_VERSION_base(999,0,0)+ [| meaningOfLife |]+#else+ "terrible error"+#endif
+ TestSuite/inputs/FFI/Main.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE ForeignFunctionInterface #-}+module Main where++foreign import ccall meaningOfLife :: IO Int++main :: IO ()+main = print =<< meaningOfLife
+ TestSuite/inputs/FFI/Main2.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE ForeignFunctionInterface #-}+module Main where++foreign import ccall meaningOfLife :: IO Int++main :: IO ()+main = print =<< meaningOfLife
+ TestSuite/inputs/FFI/Main3.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE ForeignFunctionInterface, TemplateHaskell, CPP #-}+module Main where++import Language.Haskell.TH++import A (ex1, ex2)++foreign import ccall meaningOfLife :: IO Int++v3 :: IO Int+v3 =+#if !MIN_VERSION_base(999,0,0)+ meaningOfLife+#else+ "terrible error"+#endif++main :: IO ()+main = do+ i2 <- $ex2+ i3 <- v3+ $ex1 (return $ i2 + i3)
+ TestSuite/inputs/FFI/ffiles/life.c view
@@ -0,0 +1,6 @@+#include "life.h"+#include "local.h"++int meaningOfLife() {+ return CONSTANT42;+}
+ TestSuite/inputs/FFI/ffiles/life.h view
@@ -0,0 +1,3 @@+// Just here to make sure we can add headers++int meaningOfLife();
+ TestSuite/inputs/FFI/ffiles/local.h view
@@ -0,0 +1,1 @@+#define CONSTANT42 42
+ TestSuite/inputs/FFI/life.c view
@@ -0,0 +1,5 @@+#include "life.h"++int meaningOfLife() {+ return 42;+}
+ TestSuite/inputs/FFI/life.h view
@@ -0,0 +1,3 @@+// Just here to make sure we can add headers++int meaningOfLife();
+ TestSuite/inputs/MainModule/ParFib.hs view
@@ -0,0 +1,4 @@++import qualified ParFib.Main as M++main = M.main
+ TestSuite/inputs/MainModule/ParFib/Main.hs view
@@ -0,0 +1,50 @@+-------------------------------------------------------------------------------+-- A parallel implementation of fib in Haskell using semi-explicit+-- parallelism expressed with `par` and `pseq`++module ParFib.Main (main) where++import Control.Parallel++-------------------------------------------------------------------------------+-- A purely sequential implementaiton of fib.++seqFib :: Int -> Integer+seqFib 0 = 1+seqFib 1 = 1+seqFib n = seqFib (n-1) + seqFib (n-2)++-------------------------------------------------------------------------------+-- A thresh-hold value below which the parallel implementation of fib+-- reverts to sequential implementation.++threshHold :: Int+threshHold = 25++-------------------------------------------------------------------------------+-- A parallel implementation of fib.++parFib :: Int -> Integer+parFib n+ = if n < threshHold then+ seqFib n+ else+ r `par` (l `pseq` l + r)+ where+ l = parFib (n-1)+ r = parFib (n-2)++-------------------------------------------------------------------------------++result :: Integer+result = parFib 24++-------------------------------------------------------------------------------++main :: IO String+main+ = do pseq result (return ())+ putStrLn $ "running 'A single file with a code to run in parallel' from MainModule/ParFib, which says fib 24 = " ++ show result+ return $ show result++-------------------------------------------------------------------------------
+ TestSuite/inputs/MainModule/cabals/base.cabal view
@@ -0,0 +1,253 @@+name: base+version: 4.5.1.0+license: BSD3+license-file: LICENSE+maintainer: libraries@haskell.org+bug-reports: http://hackage.haskell.org/trac/ghc/newticket?component=libraries/base+synopsis: Basic libraries+description:+ This package contains the Prelude and its support libraries,+ and a large collection of useful libraries ranging from data+ structures to parsing combinators and debugging utilities.+cabal-version: >=1.6+build-type: Configure+extra-tmp-files:+ config.log config.status autom4te.cache+ include/HsBaseConfig.h include/EventConfig.h+extra-source-files:+ config.guess config.sub install-sh+ aclocal.m4 configure.ac configure+ include/CTypes.h include/md5.h++source-repository head+ type: git+ location: http://darcs.haskell.org/packages/base.git/++Flag integer-simple+ Description: Use integer-simple++Library {+ if impl(ghc) {+ if flag(integer-simple)+ build-depends: integer-simple+ else+ build-depends: integer-gmp+ cpp-options: -DOPTIMISE_INTEGER_GCD_LCM+ build-depends: rts, ghc-prim+ exposed-modules:+ Foreign.Concurrent,+ GHC.Arr,+ GHC.Base,+ GHC.Conc,+ GHC.Conc.IO,+ GHC.Conc.Signal,+ GHC.Conc.Sync,+ GHC.ConsoleHandler,+ GHC.Constants,+ GHC.Desugar,+ GHC.Enum,+ GHC.Environment,+ GHC.Err,+ GHC.Exception,+ GHC.Exts,+ GHC.Fingerprint,+ GHC.Fingerprint.Type,+ GHC.Float,+ GHC.Float.ConversionUtils,+ GHC.Float.RealFracMethods,+ GHC.Foreign,+ GHC.ForeignPtr,+ GHC.Handle,+ GHC.IO,+ GHC.IO.Buffer,+ GHC.IO.BufferedIO,+ GHC.IO.Device,+ GHC.IO.Encoding,+ GHC.IO.Encoding.CodePage,+ GHC.IO.Encoding.Failure,+ GHC.IO.Encoding.Iconv,+ GHC.IO.Encoding.Latin1,+ GHC.IO.Encoding.Types,+ GHC.IO.Encoding.UTF16,+ GHC.IO.Encoding.UTF32,+ GHC.IO.Encoding.UTF8,+ GHC.IO.Exception,+ GHC.IO.FD,+ GHC.IO.Handle,+ GHC.IO.Handle.FD,+ GHC.IO.Handle.Internals,+ GHC.IO.Handle.Text,+ GHC.IO.Handle.Types,+ GHC.IO.IOMode,+ GHC.IOArray,+ GHC.IOBase,+ GHC.IORef,+ GHC.Int,+ GHC.List,+ GHC.MVar,+ GHC.Num,+ GHC.PArr,+ GHC.Pack,+ GHC.Ptr,+ GHC.Read,+ GHC.Real,+ GHC.ST,+ GHC.Stack,+ GHC.Stats,+ GHC.Show,+ GHC.Stable,+ GHC.Storable,+ GHC.STRef,+ GHC.TopHandler,+ GHC.Unicode,+ GHC.Weak,+ GHC.Word,+ System.Timeout+ if os(windows)+ exposed-modules: GHC.IO.Encoding.CodePage.Table+ GHC.Conc.Windows+ GHC.Windows+ }+ exposed-modules:+ Control.Applicative,+ Control.Arrow,+ Control.Category,+ Control.Concurrent,+ Control.Concurrent.Chan,+ Control.Concurrent.MVar,+ Control.Concurrent.QSem,+ Control.Concurrent.QSemN,+ Control.Concurrent.SampleVar,+ Control.Exception,+ Control.Exception.Base+ Control.OldException,+ Control.Monad,+ Control.Monad.Fix,+ Control.Monad.Instances,+ Control.Monad.ST,+ Control.Monad.ST.Safe,+ Control.Monad.ST.Unsafe,+ Control.Monad.ST.Lazy,+ Control.Monad.ST.Lazy.Safe,+ Control.Monad.ST.Lazy.Unsafe,+ Control.Monad.ST.Strict,+ Control.Monad.Zip+ Data.Bits,+ Data.Bool,+ Data.Char,+ Data.Complex,+ Data.Dynamic,+ Data.Either,+ Data.Eq,+ Data.Data,+ Data.Fixed,+ Data.Foldable+ Data.Function,+ Data.Functor,+ Data.HashTable,+ Data.IORef,+ Data.Int,+ Data.Ix,+ Data.List,+ Data.Maybe,+ Data.Monoid,+ Data.Ord,+ Data.Ratio,+ Data.STRef+ Data.STRef.Lazy+ Data.STRef.Strict+ Data.String,+ Data.Traversable+ Data.Tuple,+ Data.Typeable,+ Data.Typeable.Internal,+ Data.Unique,+ Data.Version,+ Data.Word,+ Debug.Trace,+ Foreign,+ Foreign.C,+ Foreign.C.Error,+ Foreign.C.String,+ Foreign.C.Types,+ Foreign.ForeignPtr,+ Foreign.ForeignPtr.Safe,+ Foreign.ForeignPtr.Unsafe,+ Foreign.Marshal,+ Foreign.Marshal.Alloc,+ Foreign.Marshal.Array,+ Foreign.Marshal.Error,+ Foreign.Marshal.Pool,+ Foreign.Marshal.Safe,+ Foreign.Marshal.Utils,+ Foreign.Marshal.Unsafe,+ Foreign.Ptr,+ Foreign.Safe,+ Foreign.StablePtr,+ Foreign.Storable,+ Numeric,+ Prelude,+ System.Console.GetOpt+ System.CPUTime,+ System.Environment,+ System.Exit,+ System.IO,+ System.IO.Error,+ System.IO.Unsafe,+ System.Info,+ System.Mem,+ System.Mem.StableName,+ System.Mem.Weak,+ System.Posix.Internals,+ System.Posix.Types,+ Text.ParserCombinators.ReadP,+ Text.ParserCombinators.ReadPrec,+ Text.Printf,+ Text.Read,+ Text.Read.Lex,+ Text.Show,+ Text.Show.Functions+ Unsafe.Coerce+ other-modules:+ Control.Monad.ST.Imp+ Control.Monad.ST.Lazy.Imp+ Foreign.ForeignPtr.Imp+ c-sources:+ cbits/PrelIOUtils.c+ cbits/WCsubst.c+ cbits/Win32Utils.c+ cbits/consUtils.c+ cbits/iconv.c+ cbits/inputReady.c+ cbits/selectUtils.c+ cbits/primFloat.c+ cbits/md5.c+ include-dirs: include+ includes: HsBase.h+ install-includes: HsBase.h HsBaseConfig.h EventConfig.h WCsubst.h consUtils.h Typeable.h+ if os(windows) {+ extra-libraries: wsock32, user32, shell32+ }+ if !os(windows) {+ exposed-modules:+ GHC.Event+ other-modules:+ GHC.Event.Array+ GHC.Event.Clock+ GHC.Event.Control+ GHC.Event.EPoll+ GHC.Event.IntMap+ GHC.Event.Internal+ GHC.Event.KQueue+ GHC.Event.Manager+ GHC.Event.PSQ+ GHC.Event.Poll+ GHC.Event.Thread+ GHC.Event.Unique+ }+ -- We need to set the package name to base (without a version number)+ -- as it's magic.+ ghc-options: -package-name base+ nhc98-options: -H4M -K3M+ extensions: CPP+}
+ TestSuite/inputs/MainModule/cabals/ghc-prim.cabal view
@@ -0,0 +1,48 @@+name: ghc-prim+version: 0.2.0.0+license: BSD3+license-file: LICENSE+maintainer: libraries@haskell.org+bug-reports: http://hackage.haskell.org/trac/ghc/newticket?component=libraries%20%28other%29+synopsis: GHC primitives+description:+ GHC primitives.+cabal-version: >=1.6+build-type: Custom++source-repository head+ type: git+ location: http://darcs.haskell.org/packages/ghc-prim.git/++flag include-ghc-prim {+ Description: Include GHC.Prim in exposed-modules+ default: False+}++Library {+ build-depends: rts+ exposed-modules:+ GHC.Classes+ GHC.CString+ GHC.Debug+ GHC.Generics+ GHC.Magic+ GHC.PrimopWrappers+ GHC.IntWord64+ GHC.Tuple+ GHC.Types++ if flag(include-ghc-prim) {+ exposed-modules: GHC.Prim+ }++ c-sources:+ cbits/debug.c+ cbits/longlong.c+ cbits/popcnt.c+ extensions: CPP, MagicHash, ForeignFunctionInterface, UnliftedFFITypes,+ UnboxedTuples, EmptyDataDecls, NoImplicitPrelude+ -- We need to set the package name to ghc-prim (without a version number)+ -- as it's magic.+ ghc-options: -package-name ghc-prim+}
+ TestSuite/inputs/MainModule/cabals/integer-gmp.cabal view
@@ -0,0 +1,36 @@+name: integer-gmp+version: 0.4.0.0+license: BSD3+license-file: LICENSE+maintainer: libraries@haskell.org+bug-reports: http://hackage.haskell.org/trac/ghc/newticket?component=libraries%20%28other%29+synopsis: Integer library based on GMP+description:+ This package contains an Integer library based on GMP.+cabal-version: >=1.6+build-type: Configure++extra-source-files:+ cbits/float.c+ cbits/alloc.c+ cbits/longlong.c++source-repository head+ type: git+ location: http://darcs.haskell.org/packages/integer-gmp.git/++Library {+ build-depends: ghc-prim+ exposed-modules: GHC.Integer+ GHC.Integer.GMP.Internals+ GHC.Integer.GMP.Prim+ GHC.Integer.Logarithms+ GHC.Integer.Logarithms.Internals+ other-modules: GHC.Integer.Type+ extensions: CPP, MagicHash, UnboxedTuples, NoImplicitPrelude,+ ForeignFunctionInterface, UnliftedFFITypes+ c-sources: cbits/cbits.c+ -- We need to set the package name to integer-gmp+ -- (without a version number) as it's magic.+ ghc-options: -package-name integer-gmp+}
+ TestSuite/inputs/MainModule/cabals/old-locale.cabal view
@@ -0,0 +1,23 @@+name: old-locale+version: 1.0.0.4+license: BSD3+license-file: LICENSE+maintainer: libraries@haskell.org+bug-reports: http://hackage.haskell.org/trac/ghc/newticket?component=libraries%20%28other%29+synopsis: locale library+category: System+description:+ This package provides the old locale library.+ For new code, the new locale library is recommended.+build-type: Simple+Cabal-Version: >= 1.6++Library+ exposed-modules:+ System.Locale+ build-depends: base >= 3 && < 5++source-repository head+ type: git+ location: http://darcs.haskell.org/packages/old-locale.git/+
+ TestSuite/inputs/MainModule/cabals/old-time.cabal view
@@ -0,0 +1,38 @@+name: old-time+version: 1.1.0.0+license: BSD3+license-file: LICENSE+maintainer: libraries@haskell.org+bug-reports: http://hackage.haskell.org/trac/ghc/newticket?component=libraries/old-time+synopsis: Time library+category: System+description:+ This package provides the old time library.+ For new code, the new time library is recommended.+build-type: Configure+extra-source-files:+ aclocal.m4+ config.guess config.sub install-sh+ configure.ac configure+ include/HsTimeConfig.h.in+extra-tmp-files:+ config.log config.status autom4te.cache+ include/HsTimeConfig.h+Cabal-Version: >= 1.6++Library+ exposed-modules:+ System.Time+ c-sources:+ cbits/timeUtils.c+ include-dirs: include+ includes: HsTime.h+ install-includes: HsTime.h HsTimeConfig.h+ extensions: CPP, ForeignFunctionInterface+ build-depends: base >= 4.4 && < 5, old-locale+ nhc98-options: -K2M++source-repository head+ type: git+ location: http://darcs.haskell.org/packages/old-time.git/+
+ TestSuite/inputs/MainModule/cabals/parallel.cabal view
@@ -0,0 +1,33 @@+name: parallel+version: 3.2.0.3+license: BSD3+license-file: LICENSE+maintainer: libraries@haskell.org+synopsis: Parallel programming library+description:+ This package provides a library for parallel programming.+category: Control+build-type: Simple+cabal-version: >=1.6++source-repository head+ type: git+ location: http://darcs.haskell.org/packages/parallel.git/++library {+ exposed-modules:+ Control.Seq+ Control.Parallel+ Control.Parallel.Strategies+ extensions: CPP BangPatterns+ build-depends: base >= 3 && < 5,+ deepseq >= 1.1 && < 1.4,+ containers >= 0.1 && < 0.6,+ array >= 0.1 && < 0.5+ ghc-options: -Wall++ if impl(ghc >= 6.11) {+ -- To improve parallel performance:+ ghc-options: -feager-blackholing+ }+}
+ TestSuite/inputs/Puns/GHC/RTS/EventLogFormat.h view
@@ -0,0 +1,282 @@+/* -----------------------------------------------------------------------------+ *+ * (c) The GHC Team, 2008-2012+ *+ * Event log format+ *+ * The log format is designed to be extensible: old tools should be+ * able to parse (but not necessarily understand all of) new versions+ * of the format, and new tools will be able to understand old log+ * files.+ *+ * Each event has a specific format. If you add new events, give them+ * new numbers: we never re-use old event numbers.+ *+ * - The format is endian-independent: all values are represented in+ * bigendian order.+ *+ * - The format is extensible:+ *+ * - The header describes each event type and its length. Tools+ * that don't recognise a particular event type can skip those events.+ *+ * - There is room for extra information in the event type+ * specification, which can be ignored by older tools.+ *+ * - Events can have extra information added, but existing fields+ * cannot be changed. Tools should ignore extra fields at the+ * end of the event record.+ *+ * - Old event type ids are never re-used; just take a new identifier.+ *+ *+ * The format+ * ----------+ *+ * log : EVENT_HEADER_BEGIN+ * EventType*+ * EVENT_HEADER_END+ * EVENT_DATA_BEGIN+ * Event*+ * EVENT_DATA_END+ *+ * EventType :+ * EVENT_ET_BEGIN+ * Word16 -- unique identifier for this event+ * Int16 -- >=0 size of the event in bytes (minus the header)+ * -- -1 variable size+ * Word32 -- length of the next field in bytes+ * Word8* -- string describing the event+ * Word32 -- length of the next field in bytes+ * Word8* -- extra info (for future extensions)+ * EVENT_ET_END+ *+ * Event :+ * Word16 -- event_type+ * Word64 -- time (nanosecs)+ * [Word16] -- length of the rest (for variable-sized events only)+ * ... extra event-specific info ...+ *+ *+ * To add a new event+ * ------------------+ *+ * - In this file:+ * - give it a new number, add a new #define EVENT_XXX below+ * - In EventLog.c+ * - add it to the EventDesc array+ * - emit the event type in initEventLogging()+ * - emit the new event in postEvent_()+ * - generate the event itself by calling postEvent() somewhere+ * - In the Haskell code to parse the event log file:+ * - add types and code to read the new event+ *+ * -------------------------------------------------------------------------- */++#ifndef RTS_EVENTLOGFORMAT_H+#define RTS_EVENTLOGFORMAT_H++/*+ * Markers for begin/end of the Header.+ */+#define EVENT_HEADER_BEGIN 0x68647262 /* 'h' 'd' 'r' 'b' */+#define EVENT_HEADER_END 0x68647265 /* 'h' 'd' 'r' 'e' */++#define EVENT_DATA_BEGIN 0x64617462 /* 'd' 'a' 't' 'b' */+#define EVENT_DATA_END 0xffff++/*+ * Markers for begin/end of the list of Event Types in the Header.+ * Header, Event Type, Begin = hetb+ * Header, Event Type, End = hete+ */+#define EVENT_HET_BEGIN 0x68657462 /* 'h' 'e' 't' 'b' */+#define EVENT_HET_END 0x68657465 /* 'h' 'e' 't' 'e' */++#define EVENT_ET_BEGIN 0x65746200 /* 'e' 't' 'b' 0 */+#define EVENT_ET_END 0x65746500 /* 'e' 't' 'e' 0 */++/*+ * Types of event+ */+#define EVENT_CREATE_THREAD 0 /* (thread) */+#define EVENT_RUN_THREAD 1 /* (thread) */+#define EVENT_STOP_THREAD 2 /* (thread, status, blockinfo) */+#define EVENT_THREAD_RUNNABLE 3 /* (thread) */+#define EVENT_MIGRATE_THREAD 4 /* (thread, new_cap) */+/* 5, 6, 7 deprecated */+#define EVENT_THREAD_WAKEUP 8 /* (thread, other_cap) */+#define EVENT_GC_START 9 /* () */+#define EVENT_GC_END 10 /* () */+#define EVENT_REQUEST_SEQ_GC 11 /* () */+#define EVENT_REQUEST_PAR_GC 12 /* () */+/* 13, 14 deprecated */+#define EVENT_CREATE_SPARK_THREAD 15 /* (spark_thread) */+#define EVENT_LOG_MSG 16 /* (message ...) */+/* EVENT_STARTUP should be deprecated at some point */+#define EVENT_STARTUP 17 /* (num_capabilities) */+#define EVENT_BLOCK_MARKER 18 /* (size, end_time, capability) */+#define EVENT_USER_MSG 19 /* (message ...) */+#define EVENT_GC_IDLE 20 /* () */+#define EVENT_GC_WORK 21 /* () */+#define EVENT_GC_DONE 22 /* () */+/* 23, 24 used by eden */+#define EVENT_CAPSET_CREATE 25 /* (capset, capset_type) */+#define EVENT_CAPSET_DELETE 26 /* (capset) */+#define EVENT_CAPSET_ASSIGN_CAP 27 /* (capset, cap) */+#define EVENT_CAPSET_REMOVE_CAP 28 /* (capset, cap) */+/* the RTS identifier is in the form of "GHC-version rts_way" */+#define EVENT_RTS_IDENTIFIER 29 /* (capset, name_version_string) */+/* the vectors in these events are null separated strings */+#define EVENT_PROGRAM_ARGS 30 /* (capset, commandline_vector) */+#define EVENT_PROGRAM_ENV 31 /* (capset, environment_vector) */+#define EVENT_OSPROCESS_PID 32 /* (capset, pid) */+#define EVENT_OSPROCESS_PPID 33 /* (capset, parent_pid) */+#define EVENT_SPARK_COUNTERS 34 /* (crt,dud,ovf,cnv,gcd,fiz,rem) */+#define EVENT_SPARK_CREATE 35 /* () */+#define EVENT_SPARK_DUD 36 /* () */+#define EVENT_SPARK_OVERFLOW 37 /* () */+#define EVENT_SPARK_RUN 38 /* () */+#define EVENT_SPARK_STEAL 39 /* (victim_cap) */+#define EVENT_SPARK_FIZZLE 40 /* () */+#define EVENT_SPARK_GC 41 /* () */+#define EVENT_INTERN_STRING 42 /* (string, id) {not used by ghc} */+#define EVENT_WALL_CLOCK_TIME 43 /* (capset, unix_epoch_seconds, nanoseconds) */+#define EVENT_THREAD_LABEL 44 /* (thread, name_string) */+#define EVENT_CAP_CREATE 45 /* (cap) */+#define EVENT_CAP_DELETE 46 /* (cap) */+#define EVENT_CAP_DISABLE 47 /* (cap) */+#define EVENT_CAP_ENABLE 48 /* (cap) */+#define EVENT_HEAP_ALLOCATED 49 /* (heap_capset, alloc_bytes) */+#define EVENT_HEAP_SIZE 50 /* (heap_capset, size_bytes) */+#define EVENT_HEAP_LIVE 51 /* (heap_capset, live_bytes) */+#define EVENT_HEAP_INFO_GHC 52 /* (heap_capset, n_generations,+ max_heap_size, alloc_area_size,+ mblock_size, block_size) */+#define EVENT_GC_STATS_GHC 53 /* (heap_capset, generation,+ copied_bytes, slop_bytes, frag_bytes,+ par_n_threads,+ par_max_copied, par_tot_copied) */+#define EVENT_GC_GLOBAL_SYNC 54 /* () */+#define EVENT_TASK_CREATE 55 /* (taskID, cap, tid) */+#define EVENT_TASK_MIGRATE 56 /* (taskID, cap, new_cap) */+#define EVENT_TASK_DELETE 57 /* (taskID) */+#define EVENT_USER_MARKER 58 /* (marker_name) */++/* Range 59 - 59 is available for new GHC and common events. */++/* Range 60 - 80 is used by eden for parallel tracing+ * see http://www.mathematik.uni-marburg.de/~eden/+ */++/* Range 100 - 139 is reserved for Mercury, see below. */++/* Range 140 - 159 is reserved for Perf events, see below. */++/*+ * The highest event code +1 that ghc itself emits. Note that some event+ * ranges higher than this are reserved but not currently emitted by ghc.+ * This must match the size of the EventDesc[] array in EventLog.c+ */+#define NUM_GHC_EVENT_TAGS 59+++/* DEPRECATED EVENTS: */+/* These two are deprecated because we don't need to record the thread, it's+ implicit. We have to keep these #defines because for tiresome reasons we+ still need to parse them, see GHC.RTS.Events.ghc6Parsers for details. */+#define EVENT_RUN_SPARK 5 /* (thread) */+#define EVENT_STEAL_SPARK 6 /* (thread, victim_cap) */+/* shutdown replaced by EVENT_CAP_DELETE */+#define EVENT_SHUTDOWN 7 /* () */+#if 0+/* ghc changed how it handles sparks so these are no longer applicable */+#define EVENT_CREATE_SPARK 13 /* (cap, thread) */+#define EVENT_SPARK_TO_THREAD 14 /* (cap, thread, spark_thread) */+/* these are used by eden but are replaced by new alternatives for ghc */+#define EVENT_VERSION 23 /* (version_string) */+#define EVENT_PROGRAM_INVOCATION 24 /* (commandline_string) */+#endif+++/*+ * These event types are Mercury specific, Mercury may use up to event number+ * 139+ */+#define EVENT_FIRST_MER_EVENT 100+#define NUM_MER_EVENTS 14++#define EVENT_MER_START_PAR_CONJUNCTION 100 /* (dyn id, static id) */+#define EVENT_MER_STOP_PAR_CONJUNCTION 101 /* (dyn id) */+#define EVENT_MER_STOP_PAR_CONJUNCT 102 /* (dyn id) */+#define EVENT_MER_CREATE_SPARK 103 /* (dyn id, spark id) */+#define EVENT_MER_FUT_CREATE 104 /* (fut id, memo'd name id) */+#define EVENT_MER_FUT_WAIT_NOSUSPEND 105 /* (fut id) */+#define EVENT_MER_FUT_WAIT_SUSPENDED 106 /* (fut id) */+#define EVENT_MER_FUT_SIGNAL 107 /* (fut id) */+#define EVENT_MER_LOOKING_FOR_GLOBAL_CONTEXT \+ 108 /* () */+#define EVENT_MER_WORK_STEALING 109 /* () */+#define EVENT_MER_LOOKING_FOR_LOCAL_SPARK \+ 112 /* () */+#define EVENT_MER_RELEASE_CONTEXT 110 /* (context id) */+#define EVENT_MER_ENGINE_SLEEPING 111 /* () */+#define EVENT_MER_CALLING_MAIN 113 /* () */+++/*+ * These event types are parsed from hardware performance counters logs,+ * such as the Linux Performance Counters data available through+ * the perf subsystem.+ */++#define EVENT_PERF_NAME 140 /* (perf_num, name) */+#define EVENT_PERF_COUNTER 141 /* (perf_num, tid, period) */+#define EVENT_PERF_TRACEPOINT 142 /* (perf_num, tid) */+++/*+ * Status values for EVENT_STOP_THREAD+ *+ * 1-5 are the StgRun return values (from includes/Constants.h):+ *+ * #define HeapOverflow 1+ * #define StackOverflow 2+ * #define ThreadYielding 3+ * #define ThreadBlocked 4+ * #define ThreadFinished 5+ * #define ForeignCall 6+ * #define BlockedOnMVar 7+ * #define BlockedOnBlackHole 8+ * #define BlockedOnRead 9+ * #define BlockedOnWrite 10+ * #define BlockedOnDelay 11+ * #define BlockedOnSTM 12+ * #define BlockedOnDoProc 13+ * #define BlockedOnCCall -- not used (see ForeignCall)+ * #define BlockedOnCCall_NoUnblockExc -- not used (see ForeignCall)+ * #define BlockedOnMsgThrowTo 16+ */+#define THREAD_SUSPENDED_FOREIGN_CALL 6++/*+ * Capset type values for EVENT_CAPSET_CREATE+ */+#define CAPSET_TYPE_CUSTOM 1 /* reserved for end-user applications */+#define CAPSET_TYPE_OSPROCESS 2 /* caps belong to the same OS process */+#define CAPSET_TYPE_CLOCKDOMAIN 3 /* caps share a local clock/time */++#ifndef EVENTLOG_CONSTANTS_ONLY++typedef StgWord16 EventTypeNum;+typedef StgWord64 EventTimestamp; /* in nanoseconds */+typedef StgWord32 EventThreadID;+typedef StgWord16 EventCapNo;+typedef StgWord16 EventPayloadSize; /* variable-size events */+typedef StgWord16 EventThreadStatus; /* status for EVENT_STOP_THREAD */+typedef StgWord32 EventCapsetID;+typedef StgWord16 EventCapsetType; /* types for EVENT_CAPSET_CREATE */++#endif++#endif /* RTS_EVENTLOGFORMAT_H */
+ TestSuite/inputs/Puns/GHC/RTS/EventParserUtils.hs view
@@ -0,0 +1,198 @@+{-# LANGUAGE CPP, FlexibleContexts #-}+{-# OPTIONS_GHC -fwarn-incomplete-patterns -fno-warn-deprecations #-}++module GHC.RTS.EventParserUtils (+ EventParser(..),+ EventParsers(..),+ GetEvents,+ GetHeader,++ getE,+ getH,+ getString,+ mkEventTypeParsers,+ simpleEvent,+ skip,+ ) where++import Control.Monad+import Control.Monad.Error+import Control.Monad.Reader+import Data.Array+import Data.Binary+import Data.Binary.Get hiding (skip)+import qualified Data.Binary.Get as G+import Data.Binary.Put+import Data.Char+import Data.Function+import Data.IntMap (IntMap)+import qualified Data.IntMap as M+import Data.List++#define EVENTLOG_CONSTANTS_ONLY+-- #include "EventLogFormat.h"++import GHC.RTS.EventTypes++-- reader/Get monad that passes around the event types+type GetEvents a = ReaderT EventParsers (ErrorT String Get) a++newtype EventParsers = EventParsers (Array Int (GetEvents EventInfo))++type GetHeader a = ErrorT String Get a++getH :: Binary a => GetHeader a+getH = lift get++getE :: Binary a => GetEvents a+getE = lift $ lift get++nBytes :: Integral a => a -> GetEvents [Word8]+nBytes n = replicateM (fromIntegral n) getE++getString :: Integral a => a -> GetEvents String+getString len = do+ bytes <- nBytes len+ return $ map (chr . fromIntegral) bytes++skip :: Integral a => a -> GetEvents ()+skip n = lift $ lift $ G.skip (fromIntegral n)++--+-- Code to build the event parser table.+--++--+-- Event parser data. Parsers are either fixed or vairable size.+--+data EventParser a+ = FixedSizeParser {+ fsp_type :: Int,+ fsp_size :: EventTypeSize,+ fsp_parser :: GetEvents a+ }+ | VariableSizeParser {+ vsp_type :: Int,+ vsp_parser :: GetEvents a+ }++get_parser (FixedSizeParser _ _ p) = p+get_parser (VariableSizeParser _ p) = p++get_type (FixedSizeParser t _ _) = t+get_type (VariableSizeParser t _) = t++isFixedSize (FixedSizeParser {}) = True+isFixedSize (VariableSizeParser {}) = False++simpleEvent :: Int -> a -> EventParser a+simpleEvent t p = FixedSizeParser t 0 (return p)++-- Our event log format allows new fields to be added to events over+-- time. This means that our parser must be able to handle:+--+-- * old versions of an event, with fewer fields than expected,+-- * new versions of an event, with more fields than expected+--+-- The event log file declares the size for each event type, so we can+-- select the correct parser for the event type based on its size. We+-- do this once after parsing the header: given the EventTypes, we build+-- an array of event parsers indexed by event type.+--+-- For each event type, we may have multiple parsers for different+-- versions of the event, indexed by size. These are listed in the+-- eventTypeParsers list below. For the given log file we select the+-- parser for the most recent version (largest size less than the size+-- declared in the header). If this is a newer version of the event+-- than we understand, there may be extra bytes that we have to read+-- and discard in the parser for this event type.+--+-- Summary:+-- if size is smaller that we expect:+-- parse the earier version, or ignore the event+-- if size is just right:+-- parse it+-- if size is too big:+-- parse the bits we understand and discard the rest++mkEventTypeParsers :: IntMap EventType+ -> [EventParser EventInfo]+ -> Array Int (GetEvents EventInfo)+mkEventTypeParsers etypes event_parsers+ = accumArray (flip const) undefined (0, max_event_num)+ [ (num, parser num) | num <- [0..max_event_num] ]+ --([ (num, undeclared_etype num) | num <- [0..max_event_num] ] +++ -- [ (num, parser num etype) | (num, etype) <- M.toList etypes ])+ where+ max_event_num = maximum (M.keys etypes)+ undeclared_etype num = throwError ("undeclared event type: " ++ show num)+ parser_map = makeParserMap event_parsers+ parser num =+ -- Get the event's size from the header,+ -- the first Maybe describes whether the event was declared in the header.+ -- the second Maybe selects between variable and fixed size events.+ let mb_mb_et_size = do et <- M.lookup num etypes+ return $ size et+ -- Find a parser for the event with the given size.+ maybe_parser mb_et_size = do possible <- M.lookup num parser_map+ best_parser <- case mb_et_size of+ Nothing -> getVariableParser possible+ Just et_size -> getFixedParser et_size possible+ return $ get_parser best_parser+ in case mb_mb_et_size of+ -- This event is declared in the log file's header+ Just mb_et_size -> case maybe_parser mb_et_size of+ -- And we have a valid parser for it.+ Just p -> p+ -- But we don't have a valid parser for it.+ Nothing -> noEventTypeParser num mb_et_size+ -- This event is not declared in the log file's header+ Nothing -> undeclared_etype num++-- Find the first variable length parser.+getVariableParser :: [EventParser a] -> Maybe (EventParser a)+getVariableParser [] = Nothing+getVariableParser (x:xs) = case x of+ FixedSizeParser _ _ _ -> getVariableParser xs+ VariableSizeParser _ _ -> Just x++-- Find the best fixed size parser, that is to say, the parser for the largest+-- event that does not exceed the size of the event as declared in the log+-- file's header.+getFixedParser :: EventTypeSize -> [EventParser a] -> Maybe (EventParser a)+getFixedParser size parsers =+ do parser <- ((filter isFixedSize) `pipe`+ (filter (\x -> (fsp_size x) <= size)) `pipe`+ (sortBy descending_size) `pipe`+ maybe_head) parsers+ return $ padParser size parser+ where pipe f g = g . f+ descending_size (FixedSizeParser _ s1 _) (FixedSizeParser _ s2 _) =+ compare s2 s1+ descending_size _ _ = undefined+ maybe_head [] = Nothing+ maybe_head (x:xs) = Just x++padParser :: EventTypeSize -> (EventParser a) -> (EventParser a)+padParser size (VariableSizeParser t p) = VariableSizeParser t p+padParser size (FixedSizeParser t orig_size orig_p) = FixedSizeParser t size p+ where p = if (size == orig_size)+ then orig_p+ else do d <- orig_p+ skip (size - orig_size)+ return d++makeParserMap :: [EventParser a] -> IntMap [EventParser a]+makeParserMap = foldl buildParserMap M.empty+ where buildParserMap map parser = M.alter (addParser parser) (get_type parser) map+ addParser p Nothing = Just [p]+ addParser p (Just ps) = Just (p:ps)++noEventTypeParser :: Int -> Maybe EventTypeSize+ -> GetEvents EventInfo+noEventTypeParser num mb_size = do+ bytes <- case mb_size of+ Just n -> return n+ Nothing -> getE :: GetEvents Word16+ skip bytes+ return UnknownEvent{ ref = fromIntegral num }
+ TestSuite/inputs/Puns/GHC/RTS/EventTypes.hs view
@@ -0,0 +1,389 @@+{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}++module GHC.RTS.EventTypes where++import Data.Word (Word8, Word16, Word32, Word64)+import Data.Binary++-- EventType.+type EventTypeNum = Word16+type EventTypeDescLen = Word32+type EventTypeDesc = String+type EventTypeSize = Word16+-- Event.+type EventDescription = String+type Timestamp = Word64+type ThreadId = Word32+type CapNo = Word16+type Marker = Word32+type BlockSize = Word32+type RawThreadStopStatus = Word16+type StringId = Word32+type Capset = Word32+type PerfEventTypeNum = Word32+type TaskId = Word64+type PID = Word32++newtype KernelThreadId = KernelThreadId { kernelThreadId :: Word64 }+ deriving (Eq, Ord, Show)+instance Binary KernelThreadId where+ put (KernelThreadId tid) = put tid+ get = fmap KernelThreadId get++-- These types are used by Mercury events.+type ParConjDynId = Word64+type ParConjStaticId = StringId+type SparkId = Word32+type FutureId = Word64++sz_event_type_num :: EventTypeSize+sz_event_type_num = 2+sz_cap :: EventTypeSize+sz_cap = 2+sz_time :: EventTypeSize+sz_time = 8+sz_tid :: EventTypeSize+sz_tid = 4+sz_old_tid :: EventTypeSize+sz_old_tid = 8 -- GHC 6.12 was using 8 for ThreadID when declaring the size+ -- of events, but was actually using 32 bits for ThreadIDs+sz_capset :: EventTypeSize+sz_capset = 4+sz_capset_type :: EventTypeSize+sz_capset_type = 2+sz_block_size :: EventTypeSize+sz_block_size = 4+sz_block_event :: EventTypeSize+sz_block_event = fromIntegral (sz_event_type_num + sz_time + sz_block_size+ + sz_time + sz_cap)+sz_pid :: EventTypeSize+sz_pid = 4+sz_taskid :: EventTypeSize+sz_taskid = 8+sz_kernel_tid :: EventTypeSize+sz_kernel_tid = 8+sz_th_stop_status :: EventTypeSize+sz_th_stop_status = 2+sz_string_id :: EventTypeSize+sz_string_id = 4+sz_perf_num :: EventTypeSize+sz_perf_num = 4++-- Sizes for Mercury event fields.+sz_par_conj_dyn_id :: EventTypeSize+sz_par_conj_dyn_id = 8+sz_par_conj_static_id :: EventTypeSize+sz_par_conj_static_id = sz_string_id+sz_spark_id :: EventTypeSize+sz_spark_id = 4+sz_future_id :: EventTypeSize+sz_future_id = 8++{-+ - Data type delcarations to build the GHC RTS data format,+ - which is a (header, data) pair.+ -+ - Header contains EventTypes.+ - Data contains Events.+ -}+data EventLog =+ EventLog {+ header :: Header,+ dat :: Data+ } deriving Show++newtype Header = Header {+ eventTypes :: [EventType]+ } deriving (Show, Eq)++data Data = Data {+ events :: [Event]+ } deriving Show++data EventType =+ EventType {+ num :: EventTypeNum,+ desc :: EventTypeDesc,+ size :: Maybe EventTypeSize -- ^ 'Nothing' indicates variable size+ } deriving (Show, Eq)++data Event =+ Event {+ time :: {-# UNPACK #-}!Timestamp,+ spec :: EventInfo+ } deriving Show++data EventInfo++ -- pseudo events+ = EventBlock { end_time :: Timestamp,+ cap :: Int,+ block_events :: [Event]+ }+ | UnknownEvent { ref :: {-# UNPACK #-}!EventTypeNum }++ -- init and shutdown+ | Startup { n_caps :: Int+ }+ -- EVENT_SHUTDOWN is replaced by EVENT_CAP_DELETE and GHC 7.6++ -- no longer generate the event; should be removed at some point+ | Shutdown { }++ -- thread scheduling+ | CreateThread { thread :: {-# UNPACK #-}!ThreadId+ }+ | RunThread { thread :: {-# UNPACK #-}!ThreadId+ }+ | StopThread { thread :: {-# UNPACK #-}!ThreadId,+ status :: ThreadStopStatus+ }+ | ThreadRunnable { thread :: {-# UNPACK #-}!ThreadId+ }+ | MigrateThread { thread :: {-# UNPACK #-}!ThreadId,+ newCap :: {-# UNPACK #-}!Int+ }+ | WakeupThread { thread :: {-# UNPACK #-}!ThreadId,+ otherCap :: {-# UNPACK #-}!Int+ }+ | ThreadLabel { thread :: {-# UNPACK #-}!ThreadId,+ threadlabel :: String+ }++ -- par sparks+ | CreateSparkThread { sparkThread :: {-# UNPACK #-}!ThreadId+ }+ | SparkCounters { sparksCreated, sparksDud, sparksOverflowed,+ sparksConverted, sparksFizzled, sparksGCd,+ sparksRemaining :: {-# UNPACK #-}! Word64+ }+ | SparkCreate { }+ | SparkDud { }+ | SparkOverflow { }+ | SparkRun { }+ | SparkSteal { victimCap :: {-# UNPACK #-}!Int }+ | SparkFizzle { }+ | SparkGC { }++ -- tasks+ | TaskCreate { taskId :: TaskId,+ cap :: {-# UNPACK #-}!Int,+ tid :: {-# UNPACK #-}!KernelThreadId+ }+ | TaskMigrate { taskId :: TaskId,+ cap :: {-# UNPACK #-}!Int,+ new_cap :: {-# UNPACK #-}!Int+ }+ | TaskDelete { taskId :: TaskId }++ -- garbage collection+ | RequestSeqGC { }+ | RequestParGC { }+ | StartGC { }+ | GCWork { }+ | GCIdle { }+ | GCDone { }+ | EndGC { }+ | GlobalSyncGC { }+ | GCStatsGHC { heapCapset :: {-# UNPACK #-}!Capset+ , gen :: {-# UNPACK #-}!Int+ , copied :: {-# UNPACK #-}!Word64+ , slop, frag :: {-# UNPACK #-}!Word64+ , parNThreads :: {-# UNPACK #-}!Int+ , parMaxCopied :: {-# UNPACK #-}!Word64+ , parTotCopied :: {-# UNPACK #-}!Word64+ }++ -- heap statistics+ | HeapAllocated { heapCapset :: {-# UNPACK #-}!Capset+ , allocBytes :: {-# UNPACK #-}!Word64+ }+ | HeapSize { heapCapset :: {-# UNPACK #-}!Capset+ , sizeBytes :: {-# UNPACK #-}!Word64+ }+ | HeapLive { heapCapset :: {-# UNPACK #-}!Capset+ , liveBytes :: {-# UNPACK #-}!Word64+ }+ | HeapInfoGHC { heapCapset :: {-# UNPACK #-}!Capset+ , gens :: {-# UNPACK #-}!Int+ , maxHeapSize :: {-# UNPACK #-}!Word64+ , allocAreaSize :: {-# UNPACK #-}!Word64+ , mblockSize :: {-# UNPACK #-}!Word64+ , blockSize :: {-# UNPACK #-}!Word64+ }++ -- adjusting the number of capabilities on the fly+ | CapCreate { cap :: {-# UNPACK #-}!Int+ }+ | CapDelete { cap :: {-# UNPACK #-}!Int+ }+ | CapDisable { cap :: {-# UNPACK #-}!Int+ }+ | CapEnable { cap :: {-# UNPACK #-}!Int+ }++ -- capability sets+ | CapsetCreate { capset :: {-# UNPACK #-}!Capset+ , capsetType :: CapsetType+ }+ | CapsetDelete { capset :: {-# UNPACK #-}!Capset+ }+ | CapsetAssignCap { capset :: {-# UNPACK #-}!Capset+ , cap :: {-# UNPACK #-}!Int+ }+ | CapsetRemoveCap { capset :: {-# UNPACK #-}!Capset+ , cap :: {-# UNPACK #-}!Int+ }++ -- program/process info+ | RtsIdentifier { capset :: {-# UNPACK #-}!Capset+ , rtsident :: String+ }+ | ProgramArgs { capset :: {-# UNPACK #-}!Capset+ , args :: [String]+ }+ | ProgramEnv { capset :: {-# UNPACK #-}!Capset+ , env :: [String]+ }+ | OsProcessPid { capset :: {-# UNPACK #-}!Capset+ , pid :: {-# UNPACK #-}!PID+ }+ | OsProcessParentPid { capset :: {-# UNPACK #-}!Capset+ , ppid :: {-# UNPACK #-}!PID+ }+ | WallClockTime { capset :: {-# UNPACK #-}!Capset+ , sec :: {-# UNPACK #-}!Word64+ , nsec :: {-# UNPACK #-}!Word32+ }++ -- messages+ | Message { msg :: String }+ | UserMessage { msg :: String }+ | UserMarker { markername :: String }++ -- These events have been added for Mercury's benifit but are generally+ -- useful.+ | InternString { str :: String, sId :: {-# UNPACK #-}!StringId }++ -- Mercury specific events.+ | MerStartParConjunction {+ dyn_id :: {-# UNPACK #-}!ParConjDynId,+ static_id :: {-# UNPACK #-}!ParConjStaticId+ }+ | MerEndParConjunction {+ dyn_id :: {-# UNPACK #-}!ParConjDynId+ }+ | MerEndParConjunct {+ dyn_id :: {-# UNPACK #-}!ParConjDynId+ }+ | MerCreateSpark {+ dyn_id :: {-# UNPACK #-}!ParConjDynId,+ spark_id :: {-# UNPACK #-}!SparkId+ }+ | MerFutureCreate {+ future_id :: {-# UNPACK #-}!FutureId,+ name_id :: {-# UNPACK #-}!StringId+ }+ | MerFutureWaitNosuspend {+ future_id :: {-# UNPACK #-}!FutureId+ }+ | MerFutureWaitSuspended {+ future_id :: {-# UNPACK #-}!FutureId+ }+ | MerFutureSignal {+ future_id :: {-# UNPACK #-}!FutureId+ }+ | MerLookingForGlobalThread+ | MerWorkStealing+ | MerLookingForLocalSpark+ | MerReleaseThread {+ thread_id :: {-# UNPACK #-}!ThreadId+ }+ | MerCapSleeping+ | MerCallingMain++ -- perf events+ | PerfName { perfNum :: {-# UNPACK #-}!PerfEventTypeNum+ , name :: String+ }+ | PerfCounter { perfNum :: {-# UNPACK #-}!PerfEventTypeNum+ , tid :: {-# UNPACK #-}!KernelThreadId+ , period :: {-# UNPACK #-}!Word64+ }+ | PerfTracepoint { perfNum :: {-# UNPACK #-}!PerfEventTypeNum+ , tid :: {-# UNPACK #-}!KernelThreadId+ }++ deriving Show++--sync with ghc/includes/Constants.h+data ThreadStopStatus+ = NoStatus+ | HeapOverflow+ | StackOverflow+ | ThreadYielding+ | ThreadBlocked+ | ThreadFinished+ | ForeignCall+ | BlockedOnMVar+ | BlockedOnBlackHole+ | BlockedOnRead+ | BlockedOnWrite+ | BlockedOnDelay+ | BlockedOnSTM+ | BlockedOnDoProc+ | BlockedOnCCall+ | BlockedOnCCall_NoUnblockExc+ | BlockedOnMsgThrowTo+ | ThreadMigrating+ | BlockedOnMsgGlobalise+ | BlockedOnBlackHoleOwnedBy {-# UNPACK #-}!ThreadId+ deriving (Show)++mkStopStatus :: RawThreadStopStatus -> ThreadStopStatus+mkStopStatus n = case n of+ 0 -> NoStatus+ 1 -> HeapOverflow+ 2 -> StackOverflow+ 3 -> ThreadYielding+ 4 -> ThreadBlocked+ 5 -> ThreadFinished+ 6 -> ForeignCall+ 7 -> BlockedOnMVar+ 8 -> BlockedOnBlackHole+ 9 -> BlockedOnRead+ 10 -> BlockedOnWrite+ 11 -> BlockedOnDelay+ 12 -> BlockedOnSTM+ 13 -> BlockedOnDoProc+ 14 -> BlockedOnCCall+ 15 -> BlockedOnCCall_NoUnblockExc+ 16 -> BlockedOnMsgThrowTo+ 17 -> ThreadMigrating+ 18 -> BlockedOnMsgGlobalise+ _ -> error "mkStat"++maxThreadStopStatus :: RawThreadStopStatus+maxThreadStopStatus = 18++data CapsetType+ = CapsetCustom+ | CapsetOsProcess+ | CapsetClockDomain+ | CapsetUnknown+ deriving Show++mkCapsetType :: Word16 -> CapsetType+mkCapsetType n = case n of+ 1 -> CapsetCustom+ 2 -> CapsetOsProcess+ 3 -> CapsetClockDomain+ _ -> CapsetUnknown++-- | An event annotated with the Capability that generated it, if any+data CapEvent+ = CapEvent { ce_cap :: Maybe Int,+ ce_event :: Event+ -- we could UNPACK ce_event, but the Event constructor+ -- might be shared, in which case we could end up+ -- increasing the space usage.+ } deriving Show
+ TestSuite/inputs/Puns/GHC/RTS/Events.hs view
@@ -0,0 +1,1367 @@+{-# LANGUAGE CPP,BangPatterns,PatternGuards #-}+{-# OPTIONS_GHC -funbox-strict-fields -fwarn-incomplete-patterns -fno-warn-deprecations #-}+{-+ - Parser functions for GHC RTS EventLog framework.+ -}++module GHC.RTS.Events (+ main,+ -- * The event log types+ EventLog(..),+ EventType(..),+ Event(..),+ EventInfo(..),+ ThreadStopStatus(..),+ Header(..),+ Data(..),+ CapsetType(..),+ Timestamp,+ ThreadId,+ TaskId,+ KernelThreadId(..),++ -- * Reading and writing event logs+ readEventLogFromFile,+ writeEventLogToFile,++ -- * Utilities+ CapEvent(..), sortEvents, groupEvents, sortGroups,+ buildEventTypeMap,++ -- * Printing+ showEventInfo, showThreadStopStatus,+ ppEventLog, ppEventType, ppEvent,++ -- * Perf events+ nEVENT_PERF_NAME, nEVENT_PERF_COUNTER, nEVENT_PERF_TRACEPOINT,+ sz_perf_num, sz_kernel_tid+ ) where++{- Libraries. -}+import Data.Binary+import Data.Binary.Get hiding (skip)+import qualified Data.Binary.Get as G+import Data.Binary.Put+import Control.Monad+import Data.IntMap (IntMap)+import qualified Data.IntMap as M+import Control.Monad.Reader+import Control.Monad.Error+import qualified Data.ByteString.Lazy as L+import Data.Function+import Data.List+import Data.Either+import Data.Maybe+import Text.Printf+import Data.Array++import GHC.RTS.EventTypes+import GHC.RTS.EventParserUtils++#define EVENTLOG_CONSTANTS_ONLY+#include "EventLogFormat.h"++main :: IO ()+main = return ()++------------------------------------------------------------------------------+-- Binary instances++getEventType :: GetHeader EventType+getEventType = do+ etNum <- getH+ size <- getH :: GetHeader EventTypeSize+ let etSize = if size == 0xffff then Nothing else Just size+ -- 0xffff indicates variable-sized event+ etDescLen <- getH :: GetHeader EventTypeDescLen+ etDesc <- getEtDesc (fromIntegral etDescLen)+ etExtraLen <- getH :: GetHeader Word32+ lift $ G.skip (fromIntegral etExtraLen)+ ete <- getH :: GetHeader Marker+ when (ete /= EVENT_ET_END) $+ throwError ("Event Type end marker not found.")+ return (EventType etNum etDesc etSize)+ where+ getEtDesc :: Int -> GetHeader [Char]+ getEtDesc s = replicateM s (getH :: GetHeader Char)++getHeader :: GetHeader Header+getHeader = do+ hdrb <- getH :: GetHeader Marker+ when (hdrb /= EVENT_HEADER_BEGIN) $+ throwError "Header begin marker not found"+ hetm <- getH :: GetHeader Marker+ when (hetm /= EVENT_HET_BEGIN) $+ throwError "Header Event Type begin marker not found"+ ets <- getEventTypes+ emark <- getH :: GetHeader Marker+ when (emark /= EVENT_HEADER_END) $+ throwError "Header end marker not found"+ return (Header ets)+ where+ getEventTypes :: GetHeader [EventType]+ getEventTypes = do+ m <- getH :: GetHeader Marker+ case () of+ _ | m == EVENT_ET_BEGIN -> do+ et <- getEventType+ nextET <- getEventTypes+ return (et : nextET)+ | m == EVENT_HET_END ->+ return []+ | otherwise ->+ throwError "Malformed list of Event Types in header"++getEvent :: EventParsers -> GetEvents (Maybe Event)+getEvent (EventParsers parsers) = do+ etRef <- getE :: GetEvents EventTypeNum+ if (etRef == EVENT_DATA_END)+ then return Nothing+ else do !ts <- getE+ -- trace ("event: " ++ show etRef) $ do+ spec <- parsers ! fromIntegral etRef+ return (Just (Event ts spec))++--+-- standardEventParsers.+--+standardParsers :: [EventParser EventInfo]+standardParsers = [+ (FixedSizeParser EVENT_STARTUP sz_cap (do -- (n_caps)+ c <- getE :: GetEvents CapNo+ return Startup{ n_caps = fromIntegral c }+ )),++ (FixedSizeParser EVENT_BLOCK_MARKER (sz_block_size + sz_time + sz_cap) (do -- (size, end_time, cap)+ block_size <- getE :: GetEvents BlockSize+ end_time <- getE :: GetEvents Timestamp+ c <- getE :: GetEvents CapNo+ lbs <- lift . lift $ getLazyByteString ((fromIntegral block_size) -+ (fromIntegral sz_block_event))+ eparsers <- ask+ let e_events = runGet (runErrorT $ runReaderT (getEventBlock eparsers) eparsers) lbs+ return EventBlock{ end_time=end_time,+ cap= fromIntegral c,+ block_events=case e_events of+ Left s -> error s+ Right es -> es }+ )),++ -- EVENT_SHUTDOWN is replaced by EVENT_CAP_DELETE and GHC 7.6++ -- no longer generate the event; should be removed at some point+ (simpleEvent EVENT_SHUTDOWN Shutdown),++ (simpleEvent EVENT_REQUEST_SEQ_GC RequestSeqGC),++ (simpleEvent EVENT_REQUEST_PAR_GC RequestParGC),++ (simpleEvent EVENT_GC_START StartGC),++ (simpleEvent EVENT_GC_WORK GCWork),++ (simpleEvent EVENT_GC_IDLE GCIdle),++ (simpleEvent EVENT_GC_DONE GCDone),++ (simpleEvent EVENT_GC_END EndGC),++ (simpleEvent EVENT_GC_GLOBAL_SYNC GlobalSyncGC),++ (FixedSizeParser EVENT_GC_STATS_GHC (sz_capset + 2 + 5*8 + 4) (do -- (heap_capset, generation, copied_bytes, slop_bytes, frag_bytes, par_n_threads, par_max_copied, par_tot_copied)+ heapCapset <- getE+ gen <- getE :: GetEvents Word16+ copied <- getE :: GetEvents Word64+ slop <- getE :: GetEvents Word64+ frag <- getE :: GetEvents Word64+ parNThreads <- getE :: GetEvents Word32+ parMaxCopied <- getE :: GetEvents Word64+ parTotCopied <- getE :: GetEvents Word64+ return GCStatsGHC{ gen = fromIntegral gen+ , parNThreads = fromIntegral parNThreads+ , ..}+ )),++ (FixedSizeParser EVENT_HEAP_ALLOCATED (sz_capset + 8) (do -- (heap_capset, alloc_bytes)+ heapCapset <- getE+ allocBytes <- getE+ return HeapAllocated{..}+ )),++ (FixedSizeParser EVENT_HEAP_SIZE (sz_capset + 8) (do -- (heap_capset, size_bytes)+ heapCapset <- getE+ sizeBytes <- getE+ return HeapSize{..}+ )),++ (FixedSizeParser EVENT_HEAP_LIVE (sz_capset + 8) (do -- (heap_capset, live_bytes)+ heapCapset <- getE+ liveBytes <- getE+ return HeapLive{..}+ )),++ (FixedSizeParser EVENT_HEAP_INFO_GHC (sz_capset + 2 + 4*8) (do -- (heap_capset, n_generations, max_heap_size, alloc_area_size, mblock_size, block_size)+ heapCapset <- getE+ gens <- getE :: GetEvents Word16+ maxHeapSize <- getE :: GetEvents Word64+ allocAreaSize <- getE :: GetEvents Word64+ mblockSize <- getE :: GetEvents Word64+ blockSize <- getE :: GetEvents Word64+ return HeapInfoGHC{gens = fromIntegral gens, ..}+ )),++ (FixedSizeParser EVENT_CAP_CREATE (sz_cap) (do -- (cap)+ cap <- getE :: GetEvents CapNo+ return CapCreate{cap = fromIntegral cap}+ )),++ (FixedSizeParser EVENT_CAP_DELETE (sz_cap) (do -- (cap)+ cap <- getE :: GetEvents CapNo+ return CapDelete{cap = fromIntegral cap}+ )),++ (FixedSizeParser EVENT_CAP_DISABLE (sz_cap) (do -- (cap)+ cap <- getE :: GetEvents CapNo+ return CapDisable{cap = fromIntegral cap}+ )),++ (FixedSizeParser EVENT_CAP_ENABLE (sz_cap) (do -- (cap)+ cap <- getE :: GetEvents CapNo+ return CapEnable{cap = fromIntegral cap}+ )),++ (FixedSizeParser EVENT_CAPSET_CREATE (sz_capset + sz_capset_type) (do -- (capset, capset_type)+ cs <- getE+ ct <- fmap mkCapsetType getE+ return CapsetCreate{capset=cs,capsetType=ct}+ )),++ (FixedSizeParser EVENT_CAPSET_DELETE sz_capset (do -- (capset)+ cs <- getE+ return CapsetDelete{capset=cs}+ )),++ (FixedSizeParser EVENT_CAPSET_ASSIGN_CAP (sz_capset + sz_cap) (do -- (capset, cap)+ cs <- getE+ cp <- getE :: GetEvents CapNo+ return CapsetAssignCap{capset=cs,cap=fromIntegral cp}+ )),++ (FixedSizeParser EVENT_CAPSET_REMOVE_CAP (sz_capset + sz_cap) (do -- (capset, cap)+ cs <- getE+ cp <- getE :: GetEvents CapNo+ return CapsetRemoveCap{capset=cs,cap=fromIntegral cp}+ )),++ (FixedSizeParser EVENT_OSPROCESS_PID (sz_capset + sz_pid) (do -- (capset, pid)+ cs <- getE+ pd <- getE+ return OsProcessPid{capset=cs,pid=pd}+ )),++ (FixedSizeParser EVENT_OSPROCESS_PPID (sz_capset + sz_pid) (do -- (capset, ppid)+ cs <- getE+ pd <- getE+ return OsProcessParentPid{capset=cs,ppid=pd}+ )),++ (FixedSizeParser EVENT_WALL_CLOCK_TIME (sz_capset + 8 + 4) (do -- (capset, unix_epoch_seconds, nanoseconds)+ cs <- getE+ s <- getE+ ns <- getE+ return WallClockTime{capset=cs,sec=s,nsec=ns}+ )),++ (VariableSizeParser EVENT_LOG_MSG (do -- (msg)+ num <- getE :: GetEvents Word16+ string <- getString num+ return Message{ msg = string }+ )),+ (VariableSizeParser EVENT_USER_MSG (do -- (msg)+ num <- getE :: GetEvents Word16+ string <- getString num+ return UserMessage{ msg = string }+ )),+ (VariableSizeParser EVENT_USER_MARKER (do -- (markername)+ num <- getE :: GetEvents Word16+ string <- getString num+ return UserMarker{ markername = string }+ )),+ (VariableSizeParser EVENT_PROGRAM_ARGS (do -- (capset, [arg])+ num <- getE :: GetEvents Word16+ cs <- getE+ string <- getString (num - sz_capset)+ return ProgramArgs{ capset = cs+ , args = splitNull string }+ )),+ (VariableSizeParser EVENT_PROGRAM_ENV (do -- (capset, [arg])+ num <- getE :: GetEvents Word16+ cs <- getE+ string <- getString (num - sz_capset)+ return ProgramEnv{ capset = cs+ , env = splitNull string }+ )),+ (VariableSizeParser EVENT_RTS_IDENTIFIER (do -- (capset, str)+ num <- getE :: GetEvents Word16+ cs <- getE+ string <- getString (num - sz_capset)+ return RtsIdentifier{ capset = cs+ , rtsident = string }+ )),++ (VariableSizeParser EVENT_INTERN_STRING (do -- (str, id)+ num <- getE :: GetEvents Word16+ string <- getString (num - sz_string_id)+ sId <- getE :: GetEvents StringId+ return (InternString string sId)+ )),++ (VariableSizeParser EVENT_THREAD_LABEL (do -- (thread, str)+ num <- getE :: GetEvents Word16+ tid <- getE+ str <- getString (num - sz_tid)+ return ThreadLabel{ thread = tid+ , threadlabel = str }+ ))+ ]++-- Parsers valid for GHC7 but not GHC6.+ghc7Parsers :: [EventParser EventInfo]+ghc7Parsers = [+ (FixedSizeParser EVENT_CREATE_THREAD sz_tid (do -- (thread)+ t <- getE+ return CreateThread{thread=t}+ )),++ (FixedSizeParser EVENT_RUN_THREAD sz_tid (do -- (thread)+ t <- getE+ return RunThread{thread=t}+ )),++ (FixedSizeParser EVENT_STOP_THREAD (sz_tid + sz_th_stop_status) (do+ -- (thread, status)+ t <- getE+ s <- getE :: GetEvents RawThreadStopStatus+ return StopThread{thread=t, status = if s > maxThreadStopStatus+ then NoStatus+ else mkStopStatus s}+ )),++ (FixedSizeParser EVENT_STOP_THREAD (sz_tid + sz_th_stop_status + sz_tid) (do+ -- (thread, status, info)+ t <- getE+ s <- getE :: GetEvents RawThreadStopStatus+ i <- getE :: GetEvents ThreadId+ return StopThread{thread = t,+ status = case () of+ _ | s > maxThreadStopStatus+ -> NoStatus+ | s == 8 {- XXX yeuch -}+ -> BlockedOnBlackHoleOwnedBy i+ | otherwise+ -> mkStopStatus s}+ )),++ (FixedSizeParser EVENT_THREAD_RUNNABLE sz_tid (do -- (thread)+ t <- getE+ return ThreadRunnable{thread=t}+ )),++ (FixedSizeParser EVENT_MIGRATE_THREAD (sz_tid + sz_cap) (do -- (thread, newCap)+ t <- getE+ nc <- getE :: GetEvents CapNo+ return MigrateThread{thread=t,newCap=fromIntegral nc}+ )),++ -- Yes, EVENT_RUN/STEAL_SPARK are deprecated, but see the explanation in the+ -- 'ghc6Parsers' section below. Since we're parsing them anyway, we might+ -- as well convert them to the new SparkRun/SparkSteal events.+ (FixedSizeParser EVENT_RUN_SPARK sz_tid (do -- (thread)+ _ <- getE :: GetEvents ThreadId+ return SparkRun+ )),++ (FixedSizeParser EVENT_STEAL_SPARK (sz_tid + sz_cap) (do -- (thread, victimCap)+ _ <- getE :: GetEvents ThreadId+ vc <- getE :: GetEvents CapNo+ return SparkSteal{victimCap=fromIntegral vc}+ )),++ (FixedSizeParser EVENT_CREATE_SPARK_THREAD sz_tid (do -- (sparkThread)+ st <- getE :: GetEvents ThreadId+ return CreateSparkThread{sparkThread=st}+ )),++ (FixedSizeParser EVENT_SPARK_COUNTERS (7*8) (do -- (crt,dud,ovf,cnv,gcd,fiz,rem)+ crt <- getE :: GetEvents Word64+ dud <- getE :: GetEvents Word64+ ovf <- getE :: GetEvents Word64+ cnv <- getE :: GetEvents Word64+ gcd <- getE :: GetEvents Word64+ fiz <- getE :: GetEvents Word64+ rem <- getE :: GetEvents Word64+ return SparkCounters{sparksCreated = crt, sparksDud = dud,+ sparksOverflowed = ovf, sparksConverted = cnv,+ -- Warning: order of fiz and gcd reversed!+ sparksFizzled = fiz, sparksGCd = gcd,+ sparksRemaining = rem}+ )),++ (simpleEvent EVENT_SPARK_CREATE SparkCreate),+ (simpleEvent EVENT_SPARK_DUD SparkDud),+ (simpleEvent EVENT_SPARK_OVERFLOW SparkOverflow),+ (simpleEvent EVENT_SPARK_RUN SparkRun),+ (FixedSizeParser EVENT_SPARK_STEAL sz_cap (do -- (victimCap)+ vc <- getE :: GetEvents CapNo+ return SparkSteal{victimCap=fromIntegral vc}+ )),+ (simpleEvent EVENT_SPARK_FIZZLE SparkFizzle),+ (simpleEvent EVENT_SPARK_GC SparkGC),++ (FixedSizeParser EVENT_TASK_CREATE (sz_taskid + sz_cap + sz_kernel_tid) (do -- (taskID, cap, tid)+ taskId <- getE :: GetEvents TaskId+ cap <- getE :: GetEvents CapNo+ tid <- getE :: GetEvents KernelThreadId+ return TaskCreate{ taskId, cap = fromIntegral cap, tid }+ )),+ (FixedSizeParser EVENT_TASK_MIGRATE (sz_taskid + sz_cap*2) (do -- (taskID, cap, new_cap)+ taskId <- getE :: GetEvents TaskId+ cap <- getE :: GetEvents CapNo+ new_cap <- getE :: GetEvents CapNo+ return TaskMigrate{ taskId, cap = fromIntegral cap+ , new_cap = fromIntegral new_cap+ }+ )),+ (FixedSizeParser EVENT_TASK_DELETE (sz_taskid) (do -- (taskID)+ taskId <- getE :: GetEvents TaskId+ return TaskDelete{ taskId }+ )),++ (FixedSizeParser EVENT_THREAD_WAKEUP (sz_tid + sz_cap) (do -- (thread, other_cap)+ t <- getE+ oc <- getE :: GetEvents CapNo+ return WakeupThread{thread=t,otherCap=fromIntegral oc}+ ))+ ]++ -----------------------+ -- GHC 6.12 compat: GHC 6.12 reported the wrong sizes for some events,+ -- so we have to recognise those wrong sizes here for backwards+ -- compatibility.+ghc6Parsers :: [EventParser EventInfo]+ghc6Parsers = [+ (FixedSizeParser EVENT_STARTUP 0 (do+ -- BUG in GHC 6.12: the startup event was incorrectly+ -- declared as size 0, so we accept it here.+ c <- getE :: GetEvents CapNo+ return Startup{ n_caps = fromIntegral c }+ )),++ (FixedSizeParser EVENT_CREATE_THREAD sz_old_tid (do -- (thread)+ t <- getE+ return CreateThread{thread=t}+ )),++ (FixedSizeParser EVENT_RUN_THREAD sz_old_tid (do -- (thread)+ t <- getE+ return RunThread{thread=t}+ )),++ (FixedSizeParser EVENT_STOP_THREAD (sz_old_tid + 2) (do -- (thread, status)+ t <- getE+ s <- getE :: GetEvents Word16+ let stat = fromIntegral s+ return StopThread{thread=t, status = if stat > maxBound+ then NoStatus+ else mkStopStatus stat}+ )),++ (FixedSizeParser EVENT_THREAD_RUNNABLE sz_old_tid (do -- (thread)+ t <- getE+ return ThreadRunnable{thread=t}+ )),++ (FixedSizeParser EVENT_MIGRATE_THREAD (sz_old_tid + sz_cap) (do -- (thread, newCap)+ t <- getE+ nc <- getE :: GetEvents CapNo+ return MigrateThread{thread=t,newCap=fromIntegral nc}+ )),++ -- Note: it is vital that these two (EVENT_RUN/STEAL_SPARK) remain here (at+ -- least in the ghc6Parsers section) even though both events are deprecated.+ -- The reason is that .eventlog files created by the buggy GHC-6.12+ -- mis-declare the size of these two events. So we have to handle them+ -- specially here otherwise we'll get the wrong size, leading to us getting+ -- out of sync and eventual parse failure. Since we're parsing them anyway,+ -- we might as well convert them to the new SparkRun/SparkSteal events.+ (FixedSizeParser EVENT_RUN_SPARK sz_old_tid (do -- (thread)+ _ <- getE :: GetEvents ThreadId+ return SparkRun+ )),++ (FixedSizeParser EVENT_STEAL_SPARK (sz_old_tid + sz_cap) (do -- (thread, victimCap)+ _ <- getE :: GetEvents ThreadId+ vc <- getE :: GetEvents CapNo+ return SparkSteal{victimCap=fromIntegral vc}+ )),++ (FixedSizeParser EVENT_CREATE_SPARK_THREAD sz_old_tid (do -- (sparkThread)+ st <- getE :: GetEvents ThreadId+ return CreateSparkThread{sparkThread=st}+ )),++ (FixedSizeParser EVENT_THREAD_WAKEUP (sz_old_tid + sz_cap) (do -- (thread, other_cap)+ t <- getE+ oc <- getE :: GetEvents CapNo+ return WakeupThread{thread=t,otherCap=fromIntegral oc}+ ))+ ]++mercuryParsers = [+ (FixedSizeParser EVENT_MER_START_PAR_CONJUNCTION+ (sz_par_conj_dyn_id + sz_par_conj_static_id)+ (do dyn_id <- getE+ static_id <- getE+ return (MerStartParConjunction dyn_id static_id))+ ),++ (FixedSizeParser EVENT_MER_STOP_PAR_CONJUNCTION sz_par_conj_dyn_id+ (do dyn_id <- getE+ return (MerEndParConjunction dyn_id))+ ),++ (FixedSizeParser EVENT_MER_STOP_PAR_CONJUNCT sz_par_conj_dyn_id+ (do dyn_id <- getE+ return (MerEndParConjunct dyn_id))+ ),++ (FixedSizeParser EVENT_MER_CREATE_SPARK (sz_par_conj_dyn_id + sz_spark_id)+ (do dyn_id <- getE+ spark_id <- getE+ return (MerCreateSpark dyn_id spark_id))+ ),++ (FixedSizeParser EVENT_MER_FUT_CREATE (sz_future_id + sz_string_id)+ (do future_id <- getE+ name_id <- getE+ return (MerFutureCreate future_id name_id))+ ),++ (FixedSizeParser EVENT_MER_FUT_WAIT_NOSUSPEND (sz_future_id)+ (do future_id <- getE+ return (MerFutureWaitNosuspend future_id))+ ),++ (FixedSizeParser EVENT_MER_FUT_WAIT_SUSPENDED (sz_future_id)+ (do future_id <- getE+ return (MerFutureWaitSuspended future_id))+ ),++ (FixedSizeParser EVENT_MER_FUT_SIGNAL (sz_future_id)+ (do future_id <- getE+ return (MerFutureSignal future_id))+ ),++ (simpleEvent EVENT_MER_LOOKING_FOR_GLOBAL_CONTEXT MerLookingForGlobalThread),+ (simpleEvent EVENT_MER_WORK_STEALING MerWorkStealing),+ (simpleEvent EVENT_MER_LOOKING_FOR_LOCAL_SPARK MerLookingForLocalSpark),++ (FixedSizeParser EVENT_MER_RELEASE_CONTEXT sz_tid+ (do thread_id <- getE+ return (MerReleaseThread thread_id))+ ),++ (simpleEvent EVENT_MER_ENGINE_SLEEPING MerCapSleeping),+ (simpleEvent EVENT_MER_CALLING_MAIN MerCallingMain)++ ]++perfParsers = [+ (VariableSizeParser EVENT_PERF_NAME (do -- (perf_num, name)+ num <- getE :: GetEvents Word16+ perfNum <- getE+ name <- getString (num - sz_perf_num)+ return PerfName{perfNum, name}+ )),++ (FixedSizeParser EVENT_PERF_COUNTER (sz_perf_num + sz_kernel_tid + 8) (do -- (perf_num, tid, period)+ perfNum <- getE+ tid <- getE+ period <- getE+ return PerfCounter{perfNum, tid, period}+ )),++ (FixedSizeParser EVENT_PERF_TRACEPOINT (sz_perf_num + sz_kernel_tid) (do -- (perf_num, tid)+ perfNum <- getE+ tid <- getE+ return PerfTracepoint{perfNum, tid}+ ))+ ]++getData :: GetEvents Data+getData = do+ db <- getE :: GetEvents Marker+ when (db /= EVENT_DATA_BEGIN) $ throwError "Data begin marker not found"+ eparsers <- ask+ let+ getEvents :: [Event] -> GetEvents Data+ getEvents events = do+ mb_e <- getEvent eparsers+ case mb_e of+ Nothing -> return (Data (reverse events))+ Just e -> getEvents (e:events)+ -- in+ getEvents []++getEventBlock :: EventParsers -> GetEvents [Event]+getEventBlock parsers = do+ b <- lift . lift $ isEmpty+ if b then return [] else do+ mb_e <- getEvent parsers+ case mb_e of+ Nothing -> return []+ Just e -> do+ es <- getEventBlock parsers+ return (e:es)++getEventLog :: ErrorT String Get EventLog+getEventLog = do+ header <- getHeader+ let imap = M.fromList [ (fromIntegral (num t),t) | t <- eventTypes header]+ -- This test is complete, no-one has extended this event yet and all future+ -- extensions will use newly allocated event IDs.+ is_ghc_6 = Just sz_old_tid == do create_et <- M.lookup EVENT_CREATE_THREAD imap+ size create_et+ {-+ -- GHC6 writes an invalid header, we handle it here by using a+ -- different set of event parsers. Note that the ghc7 event parsers+ -- are standard events, and can be used by other runtime systems that+ -- make use of threadscope.+ -}+ event_parsers = if is_ghc_6+ then standardParsers ++ ghc6Parsers+ else standardParsers ++ ghc7Parsers+ ++ mercuryParsers ++ perfParsers+ parsers = mkEventTypeParsers imap event_parsers+ dat <- runReaderT getData (EventParsers parsers)+ return (EventLog header dat)++readEventLogFromFile :: FilePath -> IO (Either String EventLog)+readEventLogFromFile f = do+ s <- L.readFile f+ return $ runGet (do v <- runErrorT $ getEventLog+ m <- isEmpty+ m `seq` return v) s++-- -----------------------------------------------------------------------------+-- Utilities++sortEvents :: [Event] -> [CapEvent]+sortEvents = sortGroups . groupEvents++-- | Sort the raw event stream by time, annotating each event with the+-- capability that generated it.+sortGroups :: [(Maybe Int, [Event])] -> [CapEvent]+sortGroups groups = mergesort' (compare `on` (time . ce_event)) $+ [ [ CapEvent cap e | e <- es ]+ | (cap, es) <- groups ]+ -- sorting is made much faster by the way that the event stream is+ -- divided into blocks of events.+ -- - All events in a block belong to a particular capability+ -- - The events in a block are ordered by time+ -- - blocks for the same capability appear in time order in the event+ -- stream and do not overlap.+ --+ -- So to sort the events we make one list of events for each+ -- capability (basically just concat . filter), and then+ -- merge the resulting lists.++groupEvents :: [Event] -> [(Maybe Int, [Event])]+groupEvents es = (Nothing, n_events) :+ [ (Just (cap (head blocks)), concatMap block_events blocks)+ | blocks <- groups ]+ where+ (blocks, anon_events) = partitionEithers (map separate es)+ where separate e | b@EventBlock{} <- spec e = Left b+ | otherwise = Right e++ (cap_blocks, gbl_blocks) = partition (is_cap . cap) blocks+ where is_cap c = fromIntegral c /= ((-1) :: Word16)++ groups = groupBy ((==) `on` cap) $ sortBy (compare `on` cap) cap_blocks++ -- There are two sources of events without a capability: events+ -- in the raw stream not inside an EventBlock, and EventBlocks+ -- with cap == -1. We have to merge those two streams.+ -- In light of merged logs, global blocks may have overlapping+ -- time spans, thus the blocks are mergesorted+ n_events = mergesort' (compare `on` time) (anon_events : map block_events gbl_blocks)++mergesort' :: (a -> a -> Ordering) -> [[a]] -> [a]+mergesort' _ [] = []+mergesort' _ [xs] = xs+mergesort' cmp xss = mergesort' cmp (merge_pairs cmp xss)++merge_pairs :: (a -> a -> Ordering) -> [[a]] -> [[a]]+merge_pairs _ [] = []+merge_pairs _ [xs] = [xs]+merge_pairs cmp (xs:ys:xss) = merge cmp xs ys : merge_pairs cmp xss++merge :: (a -> a -> Ordering) -> [a] -> [a] -> [a]+merge _ [] ys = ys+merge _ xs [] = xs+merge cmp (x:xs) (y:ys)+ = case x `cmp` y of+ GT -> y : merge cmp (x:xs) ys+ _ -> x : merge cmp xs (y:ys)+++buildEventTypeMap :: [EventType] -> IntMap EventType+buildEventTypeMap etypes = M.fromList [ (fromIntegral (num t),t) | t <- etypes ]++-----------------------------------------------------------------------------+-- Some pretty-printing support++showEventInfo :: EventInfo -> String+showEventInfo spec =+ case spec of+ EventBlock end_time cap _block_events ->+ printf "event block: cap %d, end time: %d\n" cap end_time+ Startup n_caps ->+ printf "startup: %d capabilities" n_caps+ CreateThread thread ->+ printf "creating thread %d" thread+ RunThread thread ->+ printf "running thread %d" thread+ StopThread thread status ->+ printf "stopping thread %d (%s)" thread (showThreadStopStatus status)+ ThreadRunnable thread ->+ printf "thread %d is runnable" thread+ MigrateThread thread newCap ->+ printf "migrating thread %d to cap %d" thread newCap+ CreateSparkThread sparkThread ->+ printf "creating spark thread %d" sparkThread+ SparkCounters crt dud ovf cnv fiz gcd rem ->+ printf "spark stats: %d created, %d converted, %d remaining (%d overflowed, %d dud, %d GC'd, %d fizzled)" crt cnv rem ovf dud gcd fiz+ SparkCreate ->+ printf "spark created"+ SparkDud ->+ printf "dud spark discarded"+ SparkOverflow ->+ printf "overflowed spark discarded"+ SparkRun ->+ printf "running a local spark"+ SparkSteal victimCap ->+ printf "stealing a spark from cap %d" victimCap+ SparkFizzle ->+ printf "spark fizzled"+ SparkGC ->+ printf "spark GCed"+ TaskCreate taskId cap tid ->+ printf "task 0x%x created on cap %d with OS kernel thread %d"+ taskId cap (kernelThreadId tid)+ TaskMigrate taskId cap new_cap ->+ printf "task 0x%x migrated from cap %d to cap %d"+ taskId cap new_cap+ TaskDelete taskId ->+ printf "task 0x%x deleted" taskId+ Shutdown ->+ printf "shutting down"+ WakeupThread thread otherCap ->+ printf "waking up thread %d on cap %d" thread otherCap+ ThreadLabel thread label ->+ printf "thread %d has label \"%s\"" thread label+ RequestSeqGC ->+ printf "requesting sequential GC"+ RequestParGC ->+ printf "requesting parallel GC"+ StartGC ->+ printf "starting GC"+ EndGC ->+ printf "finished GC"+ GCWork ->+ printf "GC working"+ GCIdle ->+ printf "GC idle"+ GCDone ->+ printf "GC done"+ GlobalSyncGC ->+ printf "all caps stopped for GC"+ GCStatsGHC{..} ->+ printf "GC stats for heap capset %d: generation %d, %d bytes copied, %d bytes slop, %d bytes fragmentation, %d par threads, %d bytes max par copied, %d bytes total par copied" heapCapset gen copied slop frag parNThreads parMaxCopied parTotCopied+ HeapAllocated{..} ->+ printf "allocated on heap capset %d: %d total bytes till now" heapCapset allocBytes+ HeapSize{..} ->+ printf "size of heap capset %d: %d bytes" heapCapset sizeBytes+ HeapLive{..} ->+ printf "live data in heap capset %d: %d bytes" heapCapset liveBytes+ HeapInfoGHC{..} ->+ printf "heap stats for heap capset %d: generations %d, %d bytes max heap size, %d bytes alloc area size, %d bytes mblock size, %d bytes block size" heapCapset gens maxHeapSize allocAreaSize mblockSize blockSize+ CapCreate{cap} ->+ printf "created cap %d" cap+ CapDelete{cap} ->+ printf "deleted cap %d" cap+ CapDisable{cap} ->+ printf "disabled cap %d" cap+ CapEnable{cap} ->+ printf "enabled cap %d" cap+ Message msg ->+ msg+ UserMessage msg ->+ msg+ UserMarker markername ->+ printf "marker: %s" markername+ CapsetCreate cs ct ->+ printf "created capset %d of type %s" cs (show ct)+ CapsetDelete cs ->+ printf "deleted capset %d" cs+ CapsetAssignCap cs cp ->+ printf "assigned cap %d to capset %d" cp cs+ CapsetRemoveCap cs cp ->+ printf "removed cap %d from capset %d" cp cs+ OsProcessPid cs pid ->+ printf "capset %d: pid %d" cs pid+ OsProcessParentPid cs ppid ->+ printf "capset %d: parent pid %d" cs ppid+ WallClockTime cs sec nsec ->+ printf "capset %d: wall clock time %ds %dns (unix epoch)" cs sec nsec+ RtsIdentifier cs i ->+ printf "capset %d: RTS version \"%s\"" cs i+ ProgramArgs cs args ->+ printf "capset %d: args: %s" cs (show args)+ ProgramEnv cs env ->+ printf "capset %d: env: %s" cs (show env)+ UnknownEvent n ->+ printf "Unknown event type %d" n+ InternString str sId ->+ printf "Interned string: \"%s\" with id %d" str sId+ MerStartParConjunction dyn_id static_id ->+ printf "Start a parallel conjunction 0x%x, static_id: %d" dyn_id static_id+ MerEndParConjunction dyn_id ->+ printf "End par conjunction: 0x%x" dyn_id+ MerEndParConjunct dyn_id ->+ printf "End par conjunct: 0x%x" dyn_id+ MerCreateSpark dyn_id spark_id ->+ printf "Create spark for conjunction: 0x%x spark: 0x%x" dyn_id spark_id+ MerFutureCreate future_id name_id ->+ printf "Create future 0x%x named %d" future_id name_id+ MerFutureWaitNosuspend future_id ->+ printf "Wait didn't suspend for future: 0x%x" future_id+ MerFutureWaitSuspended future_id ->+ printf "Wait suspended on future: 0x%x" future_id+ MerFutureSignal future_id ->+ printf "Signaled future 0x%x" future_id+ MerLookingForGlobalThread ->+ "Looking for global thread to resume"+ MerWorkStealing ->+ "Trying to steal a spark"+ MerLookingForLocalSpark ->+ "Looking for a local spark to execute"+ MerReleaseThread thread_id ->+ printf "Releasing thread %d to the free pool" thread_id+ MerCapSleeping ->+ "Capability going to sleep"+ MerCallingMain ->+ "About to call the program entry point"+ PerfName{perfNum, name} ->+ printf "perf event %d named \"%s\"" perfNum name+ PerfCounter{perfNum, tid, period} ->+ printf "perf event counter %d incremented by %d in OS thread %d"+ perfNum (period + 1) (kernelThreadId tid)+ PerfTracepoint{perfNum, tid} ->+ printf "perf event tracepoint %d reached in OS thread %d"+ perfNum (kernelThreadId tid)++showThreadStopStatus :: ThreadStopStatus -> String+showThreadStopStatus HeapOverflow = "heap overflow"+showThreadStopStatus StackOverflow = "stack overflow"+showThreadStopStatus ThreadYielding = "thread yielding"+showThreadStopStatus ThreadBlocked = "thread blocked"+showThreadStopStatus ThreadFinished = "thread finished"+showThreadStopStatus ForeignCall = "making a foreign call"+showThreadStopStatus BlockedOnMVar = "blocked on an MVar"+showThreadStopStatus BlockedOnBlackHole = "blocked on a black hole"+showThreadStopStatus BlockedOnRead = "blocked on I/O read"+showThreadStopStatus BlockedOnWrite = "blocked on I/O write"+showThreadStopStatus BlockedOnDelay = "blocked on threadDelay"+showThreadStopStatus BlockedOnSTM = "blocked in STM retry"+showThreadStopStatus BlockedOnDoProc = "blocked on asyncDoProc"+showThreadStopStatus BlockedOnCCall = "blocked in a foreign call"+showThreadStopStatus BlockedOnCCall_NoUnblockExc = "blocked in a foreign call"+showThreadStopStatus BlockedOnMsgThrowTo = "blocked in throwTo"+showThreadStopStatus ThreadMigrating = "thread migrating"+showThreadStopStatus BlockedOnMsgGlobalise = "waiting for data to be globalised"+showThreadStopStatus (BlockedOnBlackHoleOwnedBy target) =+ "blocked on black hole owned by thread " ++ show target+showThreadStopStatus NoStatus = "No stop thread status"++ppEventLog :: EventLog -> String+ppEventLog (EventLog (Header ets) (Data es)) = unlines $ concat (+ [ ["Event Types:"]+ , map ppEventType ets+ , [""] -- newline+ , ["Events:"]+ , map (ppEvent imap) sorted+ , [""] ]) -- extra trailing newline+ where+ imap = buildEventTypeMap ets+ sorted = sortEvents es++ppEventType :: EventType -> String+ppEventType (EventType num dsc msz) = printf "%4d: %s (size %s)" num dsc+ (case msz of Nothing -> "variable"; Just x -> show x)++ppEvent :: IntMap EventType -> CapEvent -> String+ppEvent imap (CapEvent cap (Event time spec)) =+ printf "%9d: " time +++ (case cap of+ Nothing -> ""+ Just c -> printf "cap %d: " c) +++ case spec of+ UnknownEvent{ ref=ref } ->+ printf (desc (fromJust (M.lookup (fromIntegral ref) imap)))++ other -> showEventInfo spec++type PutEvents a = PutM a++putE :: Binary a => a -> PutEvents ()+putE = put++runPutEBS :: PutEvents () -> L.ByteString+runPutEBS = runPut++writeEventLogToFile f el = L.writeFile f $ runPutEBS $ putEventLog el++putType :: EventTypeNum -> PutEvents ()+putType = putE++putCap :: Int -> PutEvents ()+putCap c = putE (fromIntegral c :: CapNo)++putMarker :: Word32 -> PutEvents ()+putMarker = putE++putEStr :: String -> PutEvents ()+putEStr = mapM_ putE++putEventLog :: EventLog -> PutEvents ()+putEventLog (EventLog hdr es) = do+ putHeader hdr+ putData es++putHeader :: Header -> PutEvents ()+putHeader (Header ets) = do+ putMarker EVENT_HEADER_BEGIN+ putMarker EVENT_HET_BEGIN+ mapM_ putEventType ets+ putMarker EVENT_HET_END+ putMarker EVENT_HEADER_END+ where+ putEventType (EventType n d msz) = do+ putMarker EVENT_ET_BEGIN+ putType n+ putE $ fromMaybe 0xffff msz+ putE (fromIntegral $ length d :: EventTypeDescLen)+ mapM_ put d+ -- the event type header allows for extra data, which we don't use:+ putE (0 :: Word32)+ putMarker EVENT_ET_END++putData :: Data -> PutEvents ()+putData (Data es) = do+ putMarker EVENT_DATA_BEGIN -- Word32+ mapM_ putEvent es+ putType EVENT_DATA_END -- Word16++eventTypeNum :: EventInfo -> EventTypeNum+eventTypeNum e = case e of+ CreateThread {} -> EVENT_CREATE_THREAD+ RunThread {} -> EVENT_RUN_THREAD+ StopThread {} -> EVENT_STOP_THREAD+ ThreadRunnable {} -> EVENT_THREAD_RUNNABLE+ MigrateThread {} -> EVENT_MIGRATE_THREAD+ Shutdown {} -> EVENT_SHUTDOWN+ WakeupThread {} -> EVENT_THREAD_WAKEUP+ ThreadLabel {} -> EVENT_THREAD_LABEL+ StartGC {} -> EVENT_GC_START+ EndGC {} -> EVENT_GC_END+ GlobalSyncGC {} -> EVENT_GC_GLOBAL_SYNC+ RequestSeqGC {} -> EVENT_REQUEST_SEQ_GC+ RequestParGC {} -> EVENT_REQUEST_PAR_GC+ CreateSparkThread {} -> EVENT_CREATE_SPARK_THREAD+ SparkCounters {} -> EVENT_SPARK_COUNTERS+ SparkCreate {} -> EVENT_SPARK_CREATE+ SparkDud {} -> EVENT_SPARK_DUD+ SparkOverflow {} -> EVENT_SPARK_OVERFLOW+ SparkRun {} -> EVENT_SPARK_RUN+ SparkSteal {} -> EVENT_SPARK_STEAL+ SparkFizzle {} -> EVENT_SPARK_FIZZLE+ SparkGC {} -> EVENT_SPARK_GC+ TaskCreate {} -> EVENT_TASK_CREATE+ TaskMigrate {} -> EVENT_TASK_MIGRATE+ TaskDelete {} -> EVENT_TASK_DELETE+ Message {} -> EVENT_LOG_MSG+ Startup {} -> EVENT_STARTUP+ EventBlock {} -> EVENT_BLOCK_MARKER+ UserMessage {} -> EVENT_USER_MSG+ UserMarker {} -> EVENT_USER_MARKER+ GCIdle {} -> EVENT_GC_IDLE+ GCWork {} -> EVENT_GC_WORK+ GCDone {} -> EVENT_GC_DONE+ GCStatsGHC{} -> EVENT_GC_STATS_GHC+ HeapAllocated{} -> EVENT_HEAP_ALLOCATED+ HeapSize{} -> EVENT_HEAP_SIZE+ HeapLive{} -> EVENT_HEAP_LIVE+ HeapInfoGHC{} -> EVENT_HEAP_INFO_GHC+ CapCreate{} -> EVENT_CAP_CREATE+ CapDelete{} -> EVENT_CAP_DELETE+ CapDisable{} -> EVENT_CAP_DISABLE+ CapEnable{} -> EVENT_CAP_ENABLE+ CapsetCreate {} -> EVENT_CAPSET_CREATE+ CapsetDelete {} -> EVENT_CAPSET_DELETE+ CapsetAssignCap {} -> EVENT_CAPSET_ASSIGN_CAP+ CapsetRemoveCap {} -> EVENT_CAPSET_REMOVE_CAP+ RtsIdentifier {} -> EVENT_RTS_IDENTIFIER+ ProgramArgs {} -> EVENT_PROGRAM_ARGS+ ProgramEnv {} -> EVENT_PROGRAM_ENV+ OsProcessPid {} -> EVENT_OSPROCESS_PID+ OsProcessParentPid{} -> EVENT_OSPROCESS_PPID+ WallClockTime{} -> EVENT_WALL_CLOCK_TIME+ UnknownEvent {} -> error "eventTypeNum UnknownEvent"+ InternString {} -> EVENT_INTERN_STRING+ MerStartParConjunction {} -> EVENT_MER_START_PAR_CONJUNCTION+ MerEndParConjunction _ -> EVENT_MER_STOP_PAR_CONJUNCTION+ MerEndParConjunct _ -> EVENT_MER_STOP_PAR_CONJUNCT+ MerCreateSpark {} -> EVENT_MER_CREATE_SPARK+ MerFutureCreate {} -> EVENT_MER_FUT_CREATE+ MerFutureWaitNosuspend _ -> EVENT_MER_FUT_WAIT_NOSUSPEND+ MerFutureWaitSuspended _ -> EVENT_MER_FUT_WAIT_SUSPENDED+ MerFutureSignal _ -> EVENT_MER_FUT_SIGNAL+ MerLookingForGlobalThread -> EVENT_MER_LOOKING_FOR_GLOBAL_CONTEXT+ MerWorkStealing -> EVENT_MER_WORK_STEALING+ MerLookingForLocalSpark -> EVENT_MER_LOOKING_FOR_LOCAL_SPARK+ MerReleaseThread _ -> EVENT_MER_RELEASE_CONTEXT+ MerCapSleeping -> EVENT_MER_ENGINE_SLEEPING+ MerCallingMain -> EVENT_MER_CALLING_MAIN+ PerfName {} -> nEVENT_PERF_NAME+ PerfCounter {} -> nEVENT_PERF_COUNTER+ PerfTracepoint {} -> nEVENT_PERF_TRACEPOINT++nEVENT_PERF_NAME, nEVENT_PERF_COUNTER, nEVENT_PERF_TRACEPOINT :: EventTypeNum+nEVENT_PERF_NAME = EVENT_PERF_NAME+nEVENT_PERF_COUNTER = EVENT_PERF_COUNTER+nEVENT_PERF_TRACEPOINT = EVENT_PERF_TRACEPOINT++putEvent :: Event -> PutEvents ()+putEvent (Event t spec) = do+ putType (eventTypeNum spec)+ put t+ putEventSpec spec++putEventSpec (Startup caps) = do+ putCap (fromIntegral caps)++putEventSpec (EventBlock end cap es) = do+ let block = runPutEBS (mapM_ putEvent es)+ put (fromIntegral (L.length block) + 24 :: Word32)+ putE end+ putE (fromIntegral cap :: CapNo)+ putLazyByteString block++putEventSpec (CreateThread t) = do+ putE t++putEventSpec (RunThread t) = do+ putE t++-- here we assume that ThreadStopStatus fromEnum matches the definitions in+-- EventLogFormat.h+putEventSpec (StopThread t s) = do+ putE t+ putE $ case s of+ NoStatus -> 0 :: Word16+ HeapOverflow -> 1+ StackOverflow -> 2+ ThreadYielding -> 3+ ThreadBlocked -> 4+ ThreadFinished -> 5+ ForeignCall -> 6+ BlockedOnMVar -> 7+ BlockedOnBlackHole -> 8+ BlockedOnBlackHoleOwnedBy _ -> 8+ BlockedOnRead -> 9+ BlockedOnWrite -> 10+ BlockedOnDelay -> 11+ BlockedOnSTM -> 12+ BlockedOnDoProc -> 13+ BlockedOnCCall -> 14+ BlockedOnCCall_NoUnblockExc -> 15+ BlockedOnMsgThrowTo -> 16+ ThreadMigrating -> 17+ BlockedOnMsgGlobalise -> 18+ putE $ case s of+ BlockedOnBlackHoleOwnedBy i -> i+ _ -> 0++putEventSpec (ThreadRunnable t) = do+ putE t++putEventSpec (MigrateThread t c) = do+ putE t+ putCap c++putEventSpec (CreateSparkThread t) = do+ putE t++putEventSpec (SparkCounters crt dud ovf cnv fiz gcd rem) = do+ putE crt+ putE dud+ putE ovf+ putE cnv+ -- Warning: order of fiz and gcd reversed!+ putE gcd+ putE fiz+ putE rem++putEventSpec SparkCreate = do+ return ()++putEventSpec SparkDud = do+ return ()++putEventSpec SparkOverflow = do+ return ()++putEventSpec SparkRun = do+ return ()++putEventSpec (SparkSteal c) = do+ putCap c++putEventSpec SparkFizzle = do+ return ()++putEventSpec SparkGC = do+ return ()++putEventSpec (WakeupThread t c) = do+ putE t+ putCap c++putEventSpec (ThreadLabel t l) = do+ putE (fromIntegral (length l) + sz_tid :: Word16)+ putE t+ putEStr l++putEventSpec Shutdown = do+ return ()++putEventSpec RequestSeqGC = do+ return ()++putEventSpec RequestParGC = do+ return ()++putEventSpec StartGC = do+ return ()++putEventSpec GCWork = do+ return ()++putEventSpec GCIdle = do+ return ()++putEventSpec GCDone = do+ return ()++putEventSpec EndGC = do+ return ()++putEventSpec GlobalSyncGC = do+ return ()++putEventSpec (TaskCreate taskId cap tid) = do+ putE taskId+ putCap cap+ putE tid++putEventSpec (TaskMigrate taskId cap new_cap) = do+ putE taskId+ putCap cap+ putCap new_cap++putEventSpec (TaskDelete taskId) = do+ putE taskId++putEventSpec GCStatsGHC{..} = do+ putE heapCapset+ putE (fromIntegral gen :: Word16)+ putE copied+ putE slop+ putE frag+ putE (fromIntegral parNThreads :: Word32)+ putE parMaxCopied+ putE parTotCopied++putEventSpec HeapAllocated{..} = do+ putE heapCapset+ putE allocBytes++putEventSpec HeapSize{..} = do+ putE heapCapset+ putE sizeBytes++putEventSpec HeapLive{..} = do+ putE heapCapset+ putE liveBytes++putEventSpec HeapInfoGHC{..} = do+ putE heapCapset+ putE (fromIntegral gens :: Word16)+ putE maxHeapSize+ putE allocAreaSize+ putE mblockSize+ putE blockSize++putEventSpec CapCreate{cap} = do+ putCap cap++putEventSpec CapDelete{cap} = do+ putCap cap++putEventSpec CapDisable{cap} = do+ putCap cap++putEventSpec CapEnable{cap} = do+ putCap cap++putEventSpec (CapsetCreate cs ct) = do+ putE cs+ putE $ case ct of+ CapsetCustom -> 1 :: Word16+ CapsetOsProcess -> 2+ CapsetClockDomain -> 3+ CapsetUnknown -> 0++putEventSpec (CapsetDelete cs) = do+ putE cs++putEventSpec (CapsetAssignCap cs cp) = do+ putE cs+ putCap cp++putEventSpec (CapsetRemoveCap cs cp) = do+ putE cs+ putCap cp++putEventSpec (RtsIdentifier cs rts) = do+ putE (fromIntegral (length rts) + sz_capset :: Word16)+ putE cs+ putEStr rts++putEventSpec (ProgramArgs cs as) = do+ let as' = unsep as+ putE (fromIntegral (length as') + sz_capset :: Word16)+ putE cs+ mapM_ putE as'++putEventSpec (ProgramEnv cs es) = do+ let es' = unsep es+ putE (fromIntegral (length es') + sz_capset :: Word16)+ putE cs+ mapM_ putE es'++putEventSpec (OsProcessPid cs pid) = do+ putE cs+ putE pid++putEventSpec (OsProcessParentPid cs ppid) = do+ putE cs+ putE ppid++putEventSpec (WallClockTime cs sec nsec) = do+ putE cs+ putE sec+ putE nsec++putEventSpec (Message s) = do+ putE (fromIntegral (length s) :: Word16)+ mapM_ putE s++putEventSpec (UserMessage s) = do+ putE (fromIntegral (length s) :: Word16)+ mapM_ putE s++putEventSpec (UserMarker s) = do+ putE (fromIntegral (length s) :: Word16)+ mapM_ putE s++putEventSpec (UnknownEvent {}) = error "putEventSpec UnknownEvent"++putEventSpec (InternString str id) = do+ putE len+ mapM_ putE str+ putE id+ where len = (fromIntegral (length str) :: Word16) + sz_string_id++putEventSpec (MerStartParConjunction dyn_id static_id) = do+ putE dyn_id+ putE static_id++putEventSpec (MerEndParConjunction dyn_id) = do+ putE dyn_id++putEventSpec (MerEndParConjunct dyn_id) = do+ putE dyn_id++putEventSpec (MerCreateSpark dyn_id spark_id) = do+ putE dyn_id+ putE spark_id++putEventSpec (MerFutureCreate future_id name_id) = do+ putE future_id+ putE name_id++putEventSpec (MerFutureWaitNosuspend future_id) = do+ putE future_id++putEventSpec (MerFutureWaitSuspended future_id) = do+ putE future_id++putEventSpec (MerFutureSignal future_id) = do+ putE future_id++putEventSpec MerLookingForGlobalThread = return ()+putEventSpec MerWorkStealing = return ()+putEventSpec MerLookingForLocalSpark = return ()++putEventSpec (MerReleaseThread thread_id) = do+ putE thread_id++putEventSpec MerCapSleeping = return ()+putEventSpec MerCallingMain = return ()++putEventSpec PerfName{..} = do+ putE (fromIntegral (length name) + sz_perf_num :: Word16)+ putE perfNum+ mapM_ putE name++putEventSpec PerfCounter{..} = do+ putE perfNum+ putE tid+ putE period++putEventSpec PerfTracepoint{..} = do+ putE perfNum+ putE tid++-- [] == []+-- [x] == x\0+-- [x, y, z] == x\0y\0+unsep :: [String] -> String+unsep = concatMap (++"\0") -- not the most efficient, but should be ok++splitNull :: String -> [String]+splitNull [] = []+splitNull xs = case span (/= '\0') xs of+ (x, xs') -> x : splitNull (drop 1 xs')
+ TestSuite/inputs/Puns/cabals/array.cabal view
@@ -0,0 +1,56 @@+name: array+version: 0.4.0.0+license: BSD3+license-file: LICENSE+maintainer: libraries@haskell.org+bug-reports: http://hackage.haskell.org/trac/ghc/newticket?component=libraries%20%28other%29+synopsis: Mutable and immutable arrays+category: Data Structures+description:+ This package defines the classes @IArray@ of immutable arrays and+ @MArray@ of arrays mutable within appropriate monads, as well as+ some instances of these classes.+cabal-version: >=1.6+build-type: Simple+extra-source-files: include/Typeable.h++source-repository head+ type: git+ location: http://darcs.haskell.org/packages/array.git/++library+ build-depends: base >= 4.2 && < 5+ exposed-modules:+ Data.Array+ extensions: CPP+ if !impl(nhc98)+ exposed-modules:+ Data.Array.Base+ Data.Array.IArray+ Data.Array.IO+ Data.Array.IO.Safe+ Data.Array.IO.Internals+ Data.Array.MArray+ Data.Array.MArray.Safe+ Data.Array.ST+ Data.Array.ST.Safe+ Data.Array.Storable+ Data.Array.Storable.Safe+ Data.Array.Storable.Internals+ Data.Array.Unboxed+ Data.Array.Unsafe+ extensions:+ MultiParamTypeClasses,+ FlexibleContexts,+ FlexibleInstances,+ TypeSynonymInstances+ if impl(ghc)+ extensions:+ DeriveDataTypeable,+ StandaloneDeriving,+ Rank2Types,+ MagicHash,+ UnboxedTuples,+ ForeignFunctionInterface,+ UnliftedFFITypes+ include-dirs: include
+ TestSuite/inputs/Puns/cabals/base.cabal view
@@ -0,0 +1,253 @@+name: base+version: 4.5.1.0+license: BSD3+license-file: LICENSE+maintainer: libraries@haskell.org+bug-reports: http://hackage.haskell.org/trac/ghc/newticket?component=libraries/base+synopsis: Basic libraries+description:+ This package contains the Prelude and its support libraries,+ and a large collection of useful libraries ranging from data+ structures to parsing combinators and debugging utilities.+cabal-version: >=1.6+build-type: Configure+extra-tmp-files:+ config.log config.status autom4te.cache+ include/HsBaseConfig.h include/EventConfig.h+extra-source-files:+ config.guess config.sub install-sh+ aclocal.m4 configure.ac configure+ include/CTypes.h include/md5.h++source-repository head+ type: git+ location: http://darcs.haskell.org/packages/base.git/++Flag integer-simple+ Description: Use integer-simple++Library {+ if impl(ghc) {+ if flag(integer-simple)+ build-depends: integer-simple+ else+ build-depends: integer-gmp+ cpp-options: -DOPTIMISE_INTEGER_GCD_LCM+ build-depends: rts, ghc-prim+ exposed-modules:+ Foreign.Concurrent,+ GHC.Arr,+ GHC.Base,+ GHC.Conc,+ GHC.Conc.IO,+ GHC.Conc.Signal,+ GHC.Conc.Sync,+ GHC.ConsoleHandler,+ GHC.Constants,+ GHC.Desugar,+ GHC.Enum,+ GHC.Environment,+ GHC.Err,+ GHC.Exception,+ GHC.Exts,+ GHC.Fingerprint,+ GHC.Fingerprint.Type,+ GHC.Float,+ GHC.Float.ConversionUtils,+ GHC.Float.RealFracMethods,+ GHC.Foreign,+ GHC.ForeignPtr,+ GHC.Handle,+ GHC.IO,+ GHC.IO.Buffer,+ GHC.IO.BufferedIO,+ GHC.IO.Device,+ GHC.IO.Encoding,+ GHC.IO.Encoding.CodePage,+ GHC.IO.Encoding.Failure,+ GHC.IO.Encoding.Iconv,+ GHC.IO.Encoding.Latin1,+ GHC.IO.Encoding.Types,+ GHC.IO.Encoding.UTF16,+ GHC.IO.Encoding.UTF32,+ GHC.IO.Encoding.UTF8,+ GHC.IO.Exception,+ GHC.IO.FD,+ GHC.IO.Handle,+ GHC.IO.Handle.FD,+ GHC.IO.Handle.Internals,+ GHC.IO.Handle.Text,+ GHC.IO.Handle.Types,+ GHC.IO.IOMode,+ GHC.IOArray,+ GHC.IOBase,+ GHC.IORef,+ GHC.Int,+ GHC.List,+ GHC.MVar,+ GHC.Num,+ GHC.PArr,+ GHC.Pack,+ GHC.Ptr,+ GHC.Read,+ GHC.Real,+ GHC.ST,+ GHC.Stack,+ GHC.Stats,+ GHC.Show,+ GHC.Stable,+ GHC.Storable,+ GHC.STRef,+ GHC.TopHandler,+ GHC.Unicode,+ GHC.Weak,+ GHC.Word,+ System.Timeout+ if os(windows)+ exposed-modules: GHC.IO.Encoding.CodePage.Table+ GHC.Conc.Windows+ GHC.Windows+ }+ exposed-modules:+ Control.Applicative,+ Control.Arrow,+ Control.Category,+ Control.Concurrent,+ Control.Concurrent.Chan,+ Control.Concurrent.MVar,+ Control.Concurrent.QSem,+ Control.Concurrent.QSemN,+ Control.Concurrent.SampleVar,+ Control.Exception,+ Control.Exception.Base+ Control.OldException,+ Control.Monad,+ Control.Monad.Fix,+ Control.Monad.Instances,+ Control.Monad.ST,+ Control.Monad.ST.Safe,+ Control.Monad.ST.Unsafe,+ Control.Monad.ST.Lazy,+ Control.Monad.ST.Lazy.Safe,+ Control.Monad.ST.Lazy.Unsafe,+ Control.Monad.ST.Strict,+ Control.Monad.Zip+ Data.Bits,+ Data.Bool,+ Data.Char,+ Data.Complex,+ Data.Dynamic,+ Data.Either,+ Data.Eq,+ Data.Data,+ Data.Fixed,+ Data.Foldable+ Data.Function,+ Data.Functor,+ Data.HashTable,+ Data.IORef,+ Data.Int,+ Data.Ix,+ Data.List,+ Data.Maybe,+ Data.Monoid,+ Data.Ord,+ Data.Ratio,+ Data.STRef+ Data.STRef.Lazy+ Data.STRef.Strict+ Data.String,+ Data.Traversable+ Data.Tuple,+ Data.Typeable,+ Data.Typeable.Internal,+ Data.Unique,+ Data.Version,+ Data.Word,+ Debug.Trace,+ Foreign,+ Foreign.C,+ Foreign.C.Error,+ Foreign.C.String,+ Foreign.C.Types,+ Foreign.ForeignPtr,+ Foreign.ForeignPtr.Safe,+ Foreign.ForeignPtr.Unsafe,+ Foreign.Marshal,+ Foreign.Marshal.Alloc,+ Foreign.Marshal.Array,+ Foreign.Marshal.Error,+ Foreign.Marshal.Pool,+ Foreign.Marshal.Safe,+ Foreign.Marshal.Utils,+ Foreign.Marshal.Unsafe,+ Foreign.Ptr,+ Foreign.Safe,+ Foreign.StablePtr,+ Foreign.Storable,+ Numeric,+ Prelude,+ System.Console.GetOpt+ System.CPUTime,+ System.Environment,+ System.Exit,+ System.IO,+ System.IO.Error,+ System.IO.Unsafe,+ System.Info,+ System.Mem,+ System.Mem.StableName,+ System.Mem.Weak,+ System.Posix.Internals,+ System.Posix.Types,+ Text.ParserCombinators.ReadP,+ Text.ParserCombinators.ReadPrec,+ Text.Printf,+ Text.Read,+ Text.Read.Lex,+ Text.Show,+ Text.Show.Functions+ Unsafe.Coerce+ other-modules:+ Control.Monad.ST.Imp+ Control.Monad.ST.Lazy.Imp+ Foreign.ForeignPtr.Imp+ c-sources:+ cbits/PrelIOUtils.c+ cbits/WCsubst.c+ cbits/Win32Utils.c+ cbits/consUtils.c+ cbits/iconv.c+ cbits/inputReady.c+ cbits/selectUtils.c+ cbits/primFloat.c+ cbits/md5.c+ include-dirs: include+ includes: HsBase.h+ install-includes: HsBase.h HsBaseConfig.h EventConfig.h WCsubst.h consUtils.h Typeable.h+ if os(windows) {+ extra-libraries: wsock32, user32, shell32+ }+ if !os(windows) {+ exposed-modules:+ GHC.Event+ other-modules:+ GHC.Event.Array+ GHC.Event.Clock+ GHC.Event.Control+ GHC.Event.EPoll+ GHC.Event.IntMap+ GHC.Event.Internal+ GHC.Event.KQueue+ GHC.Event.Manager+ GHC.Event.PSQ+ GHC.Event.Poll+ GHC.Event.Thread+ GHC.Event.Unique+ }+ -- We need to set the package name to base (without a version number)+ -- as it's magic.+ ghc-options: -package-name base+ nhc98-options: -H4M -K3M+ extensions: CPP+}
+ TestSuite/inputs/Puns/cabals/binary.cabal view
@@ -0,0 +1,60 @@+name: binary+version: 0.5.1.0+license-file: LICENSE+author: Lennart Kolmodin <kolmodin@gmail.com>+maintainer: Lennart Kolmodin, Don Stewart <dons@galois.com>+homepage: http://code.haskell.org/binary/+description: Efficient, pure binary serialisation using lazy ByteStrings.+ Haskell values may be encoded to and from binary formats, + written to disk as binary, or sent over the network.+ Serialisation speeds of over 1 G\/sec have been observed,+ so this library should be suitable for high performance+ scenarios.+synopsis: Binary serialisation for Haskell values using lazy ByteStrings+category: Data, Parsing+stability: provisional+build-type: Simple+cabal-version: >= 1.2+tested-with: GHC ==6.4.2, GHC ==6.6.1, GHC ==6.8.0, GHC ==6.10.1+extra-source-files: README index.html++flag bytestring-in-base+flag split-base+flag applicative-in-base++library+ if flag(bytestring-in-base)+ -- bytestring was in base-2.0 and 2.1.1+ build-depends: base >= 2.0 && < 2.2+ cpp-options: -DBYTESTRING_IN_BASE+ else+ -- in base 1.0 and 3.0 bytestring is a separate package+ build-depends: base < 2.0 || >= 3, bytestring >= 0.9++ if flag(split-base)+ build-depends: base >= 3.0, containers, array+ else+ build-depends: base < 3.0++ if flag(applicative-in-base)+ build-depends: base >= 2.0+ cpp-options: -DAPPLICATIVE_IN_BASE+ else+ build-depends: base < 2.0+ hs-source-dirs: src++ exposed-modules: Data.Binary,+ Data.Binary.Put,+ Data.Binary.Get,+ Data.Binary.Builder+ Data.Binary.Builder.Internal++ other-modules: Data.Binary.Builder.Base++ extensions: CPP,+ FlexibleContexts++ ghc-options: -O2 -Wall -fliberate-case-threshold=1000++-- if impl(ghc < 6.5)+-- ghc-options: -fallow-undecidable-instances
+ TestSuite/inputs/Puns/cabals/bytestring.cabal view
@@ -0,0 +1,91 @@+Name: bytestring+Version: 0.9.2.1+Synopsis: Fast, packed, strict and lazy byte arrays with a list interface+Description:+ A time and space-efficient implementation of byte vectors using+ packed Word8 arrays, suitable for high performance use, both in terms+ of large data quantities, or high speed requirements. Byte vectors+ are encoded as strict 'Word8' arrays of bytes, and lazy lists of+ strict chunks, held in a 'ForeignPtr', and can be passed between C+ and Haskell with little effort.+ .+ Test coverage data for this library is available at:+ <http://code.haskell.org/~dons/tests/bytestring/hpc_index.html>++License: BSD3+License-file: LICENSE+Category: Data+Copyright: Copyright (c) Don Stewart 2005-2009,+ (c) Duncan Coutts 2006-2009,+ (c) David Roundy 2003-2005.+Author: Don Stewart, Duncan Coutts+Maintainer: dons00@gmail.com, duncan@community.haskell.org+Homepage: http://www.cse.unsw.edu.au/~dons/fps.html+Tested-With: GHC==7.0.2, GHC==6.12.3, GHC==6.10.4, GHC ==6.8.2+Build-Type: Simple+Cabal-Version: >= 1.8+extra-source-files: README TODO++library+ build-depends: base >= 3 && < 5++ if impl(ghc >= 6.10)+ build-depends: ghc-prim, base >= 4++ exposed-modules: Data.ByteString+ Data.ByteString.Char8+ Data.ByteString.Unsafe+ Data.ByteString.Internal+ Data.ByteString.Lazy+ Data.ByteString.Lazy.Char8+ Data.ByteString.Lazy.Internal+ Data.ByteString.Fusion++ extensions: CPP, ForeignFunctionInterface++ if impl(ghc)+ extensions: UnliftedFFITypes,+ MagicHash,+ UnboxedTuples,+ DeriveDataTypeable+ ScopedTypeVariables+ if impl(ghc >= 6.11)+ extensions: NamedFieldPuns++ --TODO: eliminate orphan instances:+ ghc-options: -Wall -fno-warn-orphans+ -O2+ -funbox-strict-fields + -fmax-simplifier-iterations10+ -fdicts-cheap++ c-sources: cbits/fpstring.c+ include-dirs: include+ includes: fpstring.h+ install-includes: fpstring.h++ nhc98-options: -K4M -K3M++-- QC properties, with GHC RULES disabled+test-suite prop-compiled+ type: exitcode-stdio-1.0+ main-is: Properties.hs+ hs-source-dirs: . tests+ build-depends: base, random, directory,+ QuickCheck >= 2.3 && < 3+ if impl(ghc >= 6.10)+ build-depends: ghc-prim+ c-sources: cbits/fpstring.c+ include-dirs: include+ if impl(ghc >= 6.10)+ ghc-options: -fno-enable-rewrite-rules+ else+ ghc-options: -fno-rewrite-rules+ if impl(ghc)+ extensions: UnliftedFFITypes,+ MagicHash,+ UnboxedTuples,+ DeriveDataTypeable+ ScopedTypeVariables+ if impl(ghc >= 6.11)+ extensions: NamedFieldPuns
+ TestSuite/inputs/Puns/cabals/containers.cabal view
@@ -0,0 +1,44 @@+name: containers+version: 0.4.2.1+license: BSD3+maintainer: fox@ucw.cz+bug-reports: http://hackage.haskell.org/trac/ghc/newticket?component=libraries%20%28other%29+synopsis: Assorted concrete container types+category: Data Structures+description:+ This package contains efficient general-purpose implementations+ of various basic immutable container types. The declared cost of+ each operation is either worst-case or amortized, but remains+ valid even if structures are shared.+build-type: Simple+cabal-version: >=1.6+extra-source-files: include/Typeable.h++source-repository head+ type: git+ location: http://github.com/haskell/containers.git++Library {+ build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.4+ ghc-options: -O2+ if impl(ghc>6.10)+ Ghc-Options: -fregs-graph+ exposed-modules:+ Data.IntMap+ Data.IntSet+ Data.Map+ Data.Set+ include-dirs: include+ extensions: CPP+ if !impl(nhc98) {+ exposed-modules:+ Data.Graph+ Data.Sequence+ Data.Tree+ }+ if impl(ghc) {+ extensions: DeriveDataTypeable, StandaloneDeriving,+ MagicHash, Rank2Types+ }+}+
+ TestSuite/inputs/Puns/cabals/deepseq.cabal view
@@ -0,0 +1,35 @@+name: deepseq+version: 1.3.0.0+license: BSD3+license-file: LICENSE+maintainer: libraries@haskell.org+synopsis: Deep evaluation of data structures+category: Control+description:+ This package provides methods for fully evaluating data structures+ (\"deep evaluation\"). Deep evaluation is often used for adding+ strictness to a program, e.g. in order to force pending exceptions,+ remove space leaks, or force lazy I/O to happen. It is also useful+ in parallel programs, to ensure pending work does not migrate to the+ wrong thread.+ .+ The primary use of this package is via the 'deepseq' function, a+ \"deep\" version of 'seq'. It is implemented on top of an 'NFData'+ typeclass (\"Normal Form Data\", data structures with no unevaluated+ components) which defines strategies for fully evaluating different+ data types.+ .+build-type: Simple+cabal-version: >=1.6++source-repository head+ type: git+ location: http://darcs.haskell.org/packages/deepseq.git/++library {+ exposed-modules: Control.DeepSeq+ build-depends: base >= 3 && < 5, + array >= 0.1 && < 0.5+ ghc-options: -Wall+ extensions: CPP+}
+ TestSuite/inputs/Puns/cabals/mtl.cabal view
@@ -0,0 +1,51 @@+Name: mtl+Version: 1.1.1.1+Author: Andy Gill+Maintainer: libraries@haskell.org+Category: Control+Synopsis: Monad transformer library+Description:+ A monad transformer library, inspired by the paper /Functional+ Programming with Overloading and Higher-Order Polymorphism/,+ by Mark P Jones (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>),+ Advanced School of Functional Programming, 1995.+Build-Type: Simple+Cabal-Version: >= 1.6++Library+ Build-Depends: base < 5++ Exposed-Modules:+ Control.Monad.Cont+ Control.Monad.Cont.Class+ Control.Monad.Error+ Control.Monad.Error.Class+ Control.Monad.Identity+ Control.Monad.List+ Control.Monad.RWS+ Control.Monad.RWS.Class+ Control.Monad.RWS.Lazy+ Control.Monad.RWS.Strict+ Control.Monad.Reader+ Control.Monad.Reader.Class+ Control.Monad.State+ Control.Monad.State.Class+ Control.Monad.State.Lazy+ Control.Monad.State.Strict+ Control.Monad.Trans+ Control.Monad.Writer+ Control.Monad.Writer.Class+ Control.Monad.Writer.Lazy+ Control.Monad.Writer.Strict++ Ghc-Options: -Wall++ Extensions: MultiParamTypeClasses,+ FunctionalDependencies,+ FlexibleInstances,+ TypeSynonymInstances++ -- Compile all modules as __Safe__ modules+ if impl(ghc >= 7.2)+ Extensions: Safe+
+ TestSuite/inputs/Puns/cabals/no_text_error/array.cabal view
+ TestSuite/inputs/Puns/cabals/no_text_error/base.cabal view
+ TestSuite/inputs/Puns/cabals/no_text_error/binary.cabal view
+ TestSuite/inputs/Puns/cabals/no_text_error/bytestring.cabal view
+ TestSuite/inputs/Puns/cabals/no_text_error/containers.cabal view
+ TestSuite/inputs/Puns/cabals/no_text_error/deepseq.cabal view
+ TestSuite/inputs/Puns/cabals/no_text_error/ghc-prim.cabal view
+ TestSuite/inputs/Puns/cabals/no_text_error/integer-gmp.cabal view
+ TestSuite/inputs/Puns/cabals/no_text_error/mtl.cabal view
@@ -0,0 +1,52 @@+Name: mtl+Version: 1.1.1.1+License: PublicDomain+Author: Andy Gill+Maintainer: libraries@haskell.org+Category: Control+Synopsis: Monad transformer library+Description:+ A monad transformer library, inspired by the paper /Functional+ Programming with Overloading and Higher-Order Polymorphism/,+ by Mark P Jones (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>),+ Advanced School of Functional Programming, 1995.+Build-Type: Simple+Cabal-Version: >= 1.6++Library+ Build-Depends: base < 5++ Exposed-Modules:+ Control.Monad.Cont+ Control.Monad.Cont.Class+ Control.Monad.Error+ Control.Monad.Error.Class+ Control.Monad.Identity+ Control.Monad.List+ Control.Monad.RWS+ Control.Monad.RWS.Class+ Control.Monad.RWS.Lazy+ Control.Monad.RWS.Strict+ Control.Monad.Reader+ Control.Monad.Reader.Class+ Control.Monad.State+ Control.Monad.State.Class+ Control.Monad.State.Lazy+ Control.Monad.State.Strict+ Control.Monad.Trans+ Control.Monad.Writer+ Control.Monad.Writer.Class+ Control.Monad.Writer.Lazy+ Control.Monad.Writer.Strict++ Ghc-Options: -Wall++ Extensions: MultiParamTypeClasses,+ FunctionalDependencies,+ FlexibleInstances,+ TypeSynonymInstances++ -- Compile all modules as __Safe__ modules+ if impl(ghc >= 7.2)+ Extensions: Safe+
+ TestSuite/inputs/Puns/cabals/parse_error/array.cabal view
+ TestSuite/inputs/Puns/cabals/parse_error/base.cabal view
@@ -0,0 +1,253 @@+name: base+version: 4.5.1.0+license: BSD3 -- can't comment here+license-file: LICENSE+maintainer: libraries@haskell.org+bug-reports: http://hackage.haskell.org/trac/ghc/newticket?component=libraries/base+synopsis: Basic libraries+description:+ This package contains the Prelude and its support libraries,+ and a large collection of useful libraries ranging from data+ structures to parsing combinators and debugging utilities.+cabal-version: >=1.6+build-type: Configure+extra-tmp-files:+ config.log config.status autom4te.cache+ include/HsBaseConfig.h include/EventConfig.h+extra-source-files:+ config.guess config.sub install-sh+ aclocal.m4 configure.ac configure+ include/CTypes.h include/md5.h++source-repository head+ type: git+ location: http://darcs.haskell.org/packages/base.git/++Flag integer-simple+ Description: Use integer-simple++Library {+ if impl(ghc) {+ if flag(integer-simple)+ build-depends: integer-simple+ else+ build-depends: integer-gmp+ cpp-options: -DOPTIMISE_INTEGER_GCD_LCM+ build-depends: rts, ghc-prim+ exposed-modules:+ Foreign.Concurrent,+ GHC.Arr,+ GHC.Base,+ GHC.Conc,+ GHC.Conc.IO,+ GHC.Conc.Signal,+ GHC.Conc.Sync,+ GHC.ConsoleHandler,+ GHC.Constants,+ GHC.Desugar,+ GHC.Enum,+ GHC.Environment,+ GHC.Err,+ GHC.Exception,+ GHC.Exts,+ GHC.Fingerprint,+ GHC.Fingerprint.Type,+ GHC.Float,+ GHC.Float.ConversionUtils,+ GHC.Float.RealFracMethods,+ GHC.Foreign,+ GHC.ForeignPtr,+ GHC.Handle,+ GHC.IO,+ GHC.IO.Buffer,+ GHC.IO.BufferedIO,+ GHC.IO.Device,+ GHC.IO.Encoding,+ GHC.IO.Encoding.CodePage,+ GHC.IO.Encoding.Failure,+ GHC.IO.Encoding.Iconv,+ GHC.IO.Encoding.Latin1,+ GHC.IO.Encoding.Types,+ GHC.IO.Encoding.UTF16,+ GHC.IO.Encoding.UTF32,+ GHC.IO.Encoding.UTF8,+ GHC.IO.Exception,+ GHC.IO.FD,+ GHC.IO.Handle,+ GHC.IO.Handle.FD,+ GHC.IO.Handle.Internals,+ GHC.IO.Handle.Text,+ GHC.IO.Handle.Types,+ GHC.IO.IOMode,+ GHC.IOArray,+ GHC.IOBase,+ GHC.IORef,+ GHC.Int,+ GHC.List,+ GHC.MVar,+ GHC.Num,+ GHC.PArr,+ GHC.Pack,+ GHC.Ptr,+ GHC.Read,+ GHC.Real,+ GHC.ST,+ GHC.Stack,+ GHC.Stats,+ GHC.Show,+ GHC.Stable,+ GHC.Storable,+ GHC.STRef,+ GHC.TopHandler,+ GHC.Unicode,+ GHC.Weak,+ GHC.Word,+ System.Timeout+ if os(windows)+ exposed-modules: GHC.IO.Encoding.CodePage.Table+ GHC.Conc.Windows+ GHC.Windows+ }+ exposed-modules:+ Control.Applicative,+ Control.Arrow,+ Control.Category,+ Control.Concurrent,+ Control.Concurrent.Chan,+ Control.Concurrent.MVar,+ Control.Concurrent.QSem,+ Control.Concurrent.QSemN,+ Control.Concurrent.SampleVar,+ Control.Exception,+ Control.Exception.Base+ Control.OldException,+ Control.Monad,+ Control.Monad.Fix,+ Control.Monad.Instances,+ Control.Monad.ST,+ Control.Monad.ST.Safe,+ Control.Monad.ST.Unsafe,+ Control.Monad.ST.Lazy,+ Control.Monad.ST.Lazy.Safe,+ Control.Monad.ST.Lazy.Unsafe,+ Control.Monad.ST.Strict,+ Control.Monad.Zip+ Data.Bits,+ Data.Bool,+ Data.Char,+ Data.Complex,+ Data.Dynamic,+ Data.Either,+ Data.Eq,+ Data.Data,+ Data.Fixed,+ Data.Foldable+ Data.Function,+ Data.Functor,+ Data.HashTable,+ Data.IORef,+ Data.Int,+ Data.Ix,+ Data.List,+ Data.Maybe,+ Data.Monoid,+ Data.Ord,+ Data.Ratio,+ Data.STRef+ Data.STRef.Lazy+ Data.STRef.Strict+ Data.String,+ Data.Traversable+ Data.Tuple,+ Data.Typeable,+ Data.Typeable.Internal,+ Data.Unique,+ Data.Version,+ Data.Word,+ Debug.Trace,+ Foreign,+ Foreign.C,+ Foreign.C.Error,+ Foreign.C.String,+ Foreign.C.Types,+ Foreign.ForeignPtr,+ Foreign.ForeignPtr.Safe,+ Foreign.ForeignPtr.Unsafe,+ Foreign.Marshal,+ Foreign.Marshal.Alloc,+ Foreign.Marshal.Array,+ Foreign.Marshal.Error,+ Foreign.Marshal.Pool,+ Foreign.Marshal.Safe,+ Foreign.Marshal.Utils,+ Foreign.Marshal.Unsafe,+ Foreign.Ptr,+ Foreign.Safe,+ Foreign.StablePtr,+ Foreign.Storable,+ Numeric,+ Prelude,+ System.Console.GetOpt+ System.CPUTime,+ System.Environment,+ System.Exit,+ System.IO,+ System.IO.Error,+ System.IO.Unsafe,+ System.Info,+ System.Mem,+ System.Mem.StableName,+ System.Mem.Weak,+ System.Posix.Internals,+ System.Posix.Types,+ Text.ParserCombinators.ReadP,+ Text.ParserCombinators.ReadPrec,+ Text.Printf,+ Text.Read,+ Text.Read.Lex,+ Text.Show,+ Text.Show.Functions+ Unsafe.Coerce+ other-modules:+ Control.Monad.ST.Imp+ Control.Monad.ST.Lazy.Imp+ Foreign.ForeignPtr.Imp+ c-sources:+ cbits/PrelIOUtils.c+ cbits/WCsubst.c+ cbits/Win32Utils.c+ cbits/consUtils.c+ cbits/iconv.c+ cbits/inputReady.c+ cbits/selectUtils.c+ cbits/primFloat.c+ cbits/md5.c+ include-dirs: include+ includes: HsBase.h+ install-includes: HsBase.h HsBaseConfig.h EventConfig.h WCsubst.h consUtils.h Typeable.h+ if os(windows) {+ extra-libraries: wsock32, user32, shell32+ }+ if !os(windows) {+ exposed-modules:+ GHC.Event+ other-modules:+ GHC.Event.Array+ GHC.Event.Clock+ GHC.Event.Control+ GHC.Event.EPoll+ GHC.Event.IntMap+ GHC.Event.Internal+ GHC.Event.KQueue+ GHC.Event.Manager+ GHC.Event.PSQ+ GHC.Event.Poll+ GHC.Event.Thread+ GHC.Event.Unique+ }+ -- We need to set the package name to base (without a version number)+ -- as it's magic.+ ghc-options: -package-name base+ nhc98-options: -H4M -K3M+ extensions: CPP+}
+ TestSuite/inputs/Puns/cabals/parse_error/binary.cabal view
+ TestSuite/inputs/Puns/cabals/parse_error/bytestring.cabal view
+ TestSuite/inputs/Puns/cabals/parse_error/containers.cabal view
+ TestSuite/inputs/Puns/cabals/parse_error/deepseq.cabal view
+ TestSuite/inputs/Puns/cabals/parse_error/ghc-prim.cabal view
+ TestSuite/inputs/Puns/cabals/parse_error/integer-gmp.cabal view
+ TestSuite/inputs/Puns/cabals/parse_error/mtl.cabal view
+ TestSuite/inputs/Puns/cabals/transformers.cabal view
@@ -0,0 +1,68 @@+name: transformers+version: 0.3.0.0+license: BSD3+license-file: LICENSE+author: Andy Gill, Ross Paterson+maintainer: Ross Paterson <ross@soi.city.ac.uk>+category: Control+synopsis: Concrete functor and monad transformers+description:+ A portable library of functor and monad transformers, inspired by+ the paper \"Functional Programming with Overloading and Higher-Order+ Polymorphism\", by Mark P Jones,+ in /Advanced School of Functional Programming/, 1995+ (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>).+ .+ This package contains:+ .+ * the monad transformer class (in "Control.Monad.Trans.Class")+ .+ * concrete functor and monad transformers, each with associated+ operations and functions to lift operations associated with other+ transformers.+ .+ It can be used on its own in portable Haskell code, or with the monad+ classes in the @mtl@ or @monads-tf@ packages, which automatically+ lift operations introduced by monad transformers through other+ transformers.+build-type: Simple+cabal-version: >= 1.6++source-repository head+ type: darcs+ location: http://code.haskell.org/~ross/transformers++flag ApplicativeInBase+ description: Use the current base package, including Applicative and+ other Functor classes.++library+ if flag(ApplicativeInBase)+ build-depends: base >= 2 && < 6+ else+ build-depends: base >= 1.0 && < 2, special-functors >= 1.0 && < 1.1+ exposed-modules:+ Control.Applicative.Backwards+ Control.Applicative.Lift+ Control.Monad.IO.Class+ Control.Monad.Trans.Class+ Control.Monad.Trans.Cont+ Control.Monad.Trans.Error+ Control.Monad.Trans.Identity+ Control.Monad.Trans.List+ Control.Monad.Trans.Maybe+ Control.Monad.Trans.Reader+ Control.Monad.Trans.RWS+ Control.Monad.Trans.RWS.Lazy+ Control.Monad.Trans.RWS.Strict+ Control.Monad.Trans.State+ Control.Monad.Trans.State.Lazy+ Control.Monad.Trans.State.Strict+ Control.Monad.Trans.Writer+ Control.Monad.Trans.Writer.Lazy+ Control.Monad.Trans.Writer.Strict+ Data.Functor.Compose+ Data.Functor.Constant+ Data.Functor.Identity+ Data.Functor.Product+ Data.Functor.Reverse
+ TestSuite/inputs/README.md view
@@ -0,0 +1,4 @@+This directory contains test inputs for the test suite.++NOTE: There are some hacks in the TestSuite that rely on the structure of this+directory (for instance, see loadModule).
+ TestSuite/inputs/TH/BlockingOps.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE TemplateHaskell, NamedFieldPuns #-}+-- | Blocking operations such as+--+-- > readMVar v+--+-- may throw an exception such as+--+-- > thread blocked indefinitely in an MVar operation+--+-- Unfortunately, this exception does not give any information of _where_ in+-- the code we are blocked indefinitely. Compiling with profiling info and+-- running with +RTC -xc can address this to some extent, but (1) it requires+-- that all profiling libraries are installed and (2) when we are running+-- multithreaded code the resulting stack trace is often difficult to read+-- (and still does not include line numbers). With this module you can replace+-- the above code with+--+-- > $readMVar v+--+-- and the exception that will be thrown is+--+-- > YourModule:lineNumber: thread blocked indefinitely in an MVar operation+--+-- which is a lot more informative. When the CPP flag DEBUGGING is turned off+-- then @$readMVar@ just turns into @readMVar@.+--+-- NOTE: The type of the exception changes when using DEBUGGING mode -- in order+-- to be able to add the line number, all exceptions are turned into+-- IOExceptions.+module TH.BlockingOps (+ -- * Generic debugging utilities+ lineNumber+ , traceOnException+ , mapExceptionIO+ , mapExceptionShow+ -- * Blocking MVar ops+ , putMVar+ , takeMVar+ , modifyMVar+ , modifyMVar_+ , withMVar+ , readMVar+ -- * Blocking Chan ops+ , readChan+ ) where++import Language.Haskell.TH+import qualified Control.Concurrent as C+import System.IO (hPutStrLn, stderr)+import qualified Control.Exception as Ex++lineNumber :: ExpQ+lineNumber = do+ Loc{loc_module, loc_start=(line, _)} <- location+ [| loc_module ++ ":" ++ show (line :: Int) |]++mapExceptionIO :: (Ex.Exception e1, Ex.Exception e2)+ => (e1 -> e2) -> IO a -> IO a+mapExceptionIO f io = Ex.catch io (Ex.throwIO . f)++mapExceptionShow :: (String -> String) -> IO a -> IO a+mapExceptionShow f = mapExceptionIO (userError . f . showSomeException)+ where+ showSomeException :: Ex.SomeException -> String+ showSomeException = show++traceOnException :: String -> IO a -> IO a+traceOnException str io = Ex.catch io $ \e -> do+ hPutStrLn stderr (str ++ ": " ++ show e)+ Ex.throwIO (e :: Ex.SomeException)++rethrowWithLineNumber1 :: ExpQ -> ExpQ+rethrowWithLineNumber1 expr =+ [| \arg1 -> mapExceptionShow (\e -> $lineNumber ++ ": " ++ e)+ ($expr arg1)+ |]++rethrowWithLineNumber2 :: ExpQ -> ExpQ+rethrowWithLineNumber2 expr =+ [| \arg1 arg2 -> mapExceptionShow (\e -> $lineNumber ++ ": " ++ e)+ ($expr arg1 arg2)+ |]++takeMVar :: ExpQ+takeMVar = rethrowWithLineNumber1 [| C.takeMVar |]++putMVar :: ExpQ+putMVar = rethrowWithLineNumber2 [| C.putMVar |]++readMVar :: ExpQ+readMVar = rethrowWithLineNumber1 [| C.readMVar |]++modifyMVar :: ExpQ+modifyMVar = rethrowWithLineNumber2 [| C.modifyMVar |]++modifyMVar_ :: ExpQ+modifyMVar_ = rethrowWithLineNumber2 [| C.modifyMVar_ |]++withMVar :: ExpQ+withMVar = rethrowWithLineNumber2 [| C.withMVar |]++readChan :: ExpQ+readChan = rethrowWithLineNumber1 [| C.readChan |]
+ TestSuite/inputs/TH/TH.hs view
@@ -0,0 +1,17 @@+module TH.TH where++import Control.Concurrent.MVar (MVar, newEmptyMVar, newMVar)+import TH.BlockingOps (modifyMVar, modifyMVar_, putMVar, readMVar, takeMVar)++main = do+ mv <- newEmptyMVar+ mv2 <- newEmptyMVar+ $putMVar mv mv2+ $putMVar mv2 42+ mv3 <- $takeMVar mv+ $putMVar mv mv3+ $modifyMVar_ mv $ \mv3 -> $modifyMVar_ mv3 (\i -> return $ i + 1)+ >> return mv2+ mv4 <- $takeMVar mv+ i <- $readMVar mv3+ print $ (mv2 == mv4, i)
+ TestSuite/inputs/bootMods/A.hs view
@@ -0,0 +1,8 @@+module A where++import B( TB(..) )++newtype TA = MkTA Int+ +f :: TB -> TA+f (MkTB x) = MkTA x
+ TestSuite/inputs/bootMods/A.hs-boot view
@@ -0,0 +1,2 @@+module A where+newtype TA = MkTA Int
+ TestSuite/inputs/bootMods/B.hs view
@@ -0,0 +1,8 @@+module B where+import {-# SOURCE #-} A( TA(..) )+ +data TB = MkTB !Int++g :: TA -> TB+g (MkTA x) = MkTB x+
+ TestSuite/inputs/bootMods/C.hs view
@@ -0,0 +1,6 @@+module Main where+import B+import A -- FIX: GHC doesn't seem to figure out this dependency?!++main :: IO ()+main = let f = g in putStrLn "C"
+ TestSuite/inputs/compiler/utils/Exception.hs view
@@ -0,0 +1,109 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-deprecations #-}+module Exception+ (+ module Control.Exception,+ module Exception+ )+ where++import Prelude hiding (catch)++import Control.Exception++catchIO :: IO a -> (IOException -> IO a) -> IO a+catchIO = catch++handleIO :: (IOException -> IO a) -> IO a -> IO a+handleIO = flip catchIO++tryIO :: IO a -> IO (Either IOException a)+tryIO = try++-- | A monad that can catch exceptions. A minimal definition+-- requires a definition of 'gcatch'.+--+-- Implementations on top of 'IO' should implement 'gblock' and 'gunblock' to+-- eventually call the primitives 'Control.Exception.block' and+-- 'Control.Exception.unblock' respectively. These are used for+-- implementations that support asynchronous exceptions. The default+-- implementations of 'gbracket' and 'gfinally' use 'gblock' and 'gunblock'+-- thus rarely require overriding.+--+class Monad m => ExceptionMonad m where++ -- | Generalised version of 'Control.Exception.catch', allowing an arbitrary+ -- exception handling monad instead of just 'IO'.+ gcatch :: Exception e => m a -> (e -> m a) -> m a++ -- | Generalised version of 'Control.Exception.mask_', allowing an arbitrary+ -- exception handling monad instead of just 'IO'.+ gmask :: ((m a -> m a) -> m b) -> m b++ -- | Generalised version of 'Control.Exception.bracket', allowing an arbitrary+ -- exception handling monad instead of just 'IO'.+ gbracket :: m a -> (a -> m b) -> (a -> m c) -> m c++ -- | Generalised version of 'Control.Exception.finally', allowing an arbitrary+ -- exception handling monad instead of just 'IO'.+ gfinally :: m a -> m b -> m a++ -- | DEPRECATED, here for backwards compatibilty. Instances can+ -- define either 'gmask', or both 'block' and 'unblock'.+ gblock :: m a -> m a+ -- | DEPRECATED, here for backwards compatibilty Instances can+ -- define either 'gmask', or both 'block' and 'unblock'.+ gunblock :: m a -> m a+ -- XXX we're keeping these two methods for the time being because we+ -- have to interact with Haskeline's MonadException class which+ -- still has block/unblock; see GhciMonad.hs.++ gmask f = gblock (f gunblock)+ gblock f = gmask (\_ -> f)+ gunblock f = f -- XXX wrong; better override this if you need it++ gbracket before after thing =+ gmask $ \restore -> do+ a <- before+ r <- restore (thing a) `gonException` after a+ _ <- after a+ return r++ a `gfinally` sequel =+ gmask $ \restore -> do+ r <- restore a `gonException` sequel+ _ <- sequel+ return r++#if __GLASGOW_HASKELL__ < 613+instance ExceptionMonad IO where+ gcatch = catch+ gmask f = block $ f unblock+ gblock = block+ gunblock = unblock+#else+instance ExceptionMonad IO where+ gcatch = catch+ gmask f = mask (\x -> f x)+ gblock = undefined+ gunblock = undefined+#endif++gtry :: (ExceptionMonad m, Exception e) => m a -> m (Either e a)+gtry act = gcatch (act >>= \a -> return (Right a))+ (\e -> return (Left e))++-- | Generalised version of 'Control.Exception.handle', allowing an arbitrary+-- exception handling monad instead of just 'IO'.+ghandle :: (ExceptionMonad m, Exception e) => (e -> m a) -> m a -> m a+ghandle = flip gcatch++-- | Always executes the first argument. If this throws an exception the+-- second argument is executed and the exception is raised again.+gonException :: (ExceptionMonad m) => m a -> m b -> m a+gonException ioA cleanup = ioA `gcatch` \e ->+ do _ <- cleanup+ throw (e :: SomeException)++main :: IO ()+main = return ()
+ TestSuite/inputs/compiler/utils/Maybes.lhs view
@@ -0,0 +1,158 @@+%+% (c) The University of Glasgow 2006+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998+%++\begin{code}+{-# OPTIONS -fno-warn-tabs #-}+{-# LANGUAGE CPP #-}+#if __GLASGOW_HASKELL__ == 708+#endif+-- The above warning supression flag is a temporary kludge.+-- While working on this module you are encouraged to remove it and+-- detab the module (please do the detabbing in a separate patch). See+-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces+-- for details++module Maybes (+ module Data.Maybe,++ MaybeErr(..), -- Instance of Monad+ failME, isSuccess,++ fmapM_maybe,+ orElse,+ mapCatMaybes,+ allMaybes,+ firstJust, firstJusts,+ expectJust,+ maybeToBool,++ MaybeT(..),++ main+ ) where++import Control.Applicative+import Control.Monad+import Data.Maybe++infixr 4 `orElse`+\end{code}++%************************************************************************+%* *+\subsection[Maybe type]{The @Maybe@ type}+%* *+%************************************************************************++\begin{code}+maybeToBool :: Maybe a -> Bool+maybeToBool Nothing = False+maybeToBool (Just _) = True++-- | Collects a list of @Justs@ into a single @Just@, returning @Nothing@ if+-- there are any @Nothings@.+allMaybes :: [Maybe a] -> Maybe [a]+allMaybes [] = Just []+allMaybes (Nothing : _) = Nothing+allMaybes (Just x : ms) = case allMaybes ms of+ Nothing -> Nothing+ Just xs -> Just (x:xs)++firstJust :: Maybe a -> Maybe a -> Maybe a+firstJust (Just a) _ = Just a+firstJust Nothing b = b++-- | Takes a list of @Maybes@ and returns the first @Just@ if there is one, or+-- @Nothing@ otherwise.+firstJusts :: [Maybe a] -> Maybe a+firstJusts = foldr firstJust Nothing+\end{code}++\begin{code}+expectJust :: String -> Maybe a -> a+{-# INLINE expectJust #-}+expectJust _ (Just x) = x+expectJust err Nothing = error ("expectJust " ++ err)+\end{code}++\begin{code}+mapCatMaybes :: (a -> Maybe b) -> [a] -> [b]+mapCatMaybes _ [] = []+mapCatMaybes f (x:xs) = case f x of+ Just y -> y : mapCatMaybes f xs+ Nothing -> mapCatMaybes f xs+\end{code}++\begin{code}+-- | flipped version of @fromMaybe@.+orElse :: Maybe a -> a -> a+(Just x) `orElse` _ = x+Nothing `orElse` y = y+\end{code}++\begin{code}+fmapM_maybe :: Monad m => (a -> m b) -> Maybe a -> m (Maybe b)+fmapM_maybe _ Nothing = return Nothing+fmapM_maybe f (Just x) = do+ x' <- f x+ return $ Just x'+\end{code}++%************************************************************************+%* *+\subsection[MaybeT type]{The @MaybeT@ monad transformer}+%* *+%************************************************************************++\begin{code}++newtype MaybeT m a = MaybeT {runMaybeT :: m (Maybe a)}++instance Functor m => Functor (MaybeT m) where+ fmap f x = MaybeT $ fmap (fmap f) $ runMaybeT x++instance (Monad m, Applicative m) => Applicative (MaybeT m) where+ pure = return+ (<*>) = ap++instance Monad m => Monad (MaybeT m) where+ return = MaybeT . return . Just+ x >>= f = MaybeT $ runMaybeT x >>= maybe (return Nothing) (runMaybeT . f)+ fail _ = MaybeT $ return Nothing++\end{code}+++%************************************************************************+%* *+\subsection[MaybeErr type]{The @MaybeErr@ type}+%* *+%************************************************************************++\begin{code}+data MaybeErr err val = Succeeded val | Failed err++instance Functor (MaybeErr err) where+ fmap = liftM++instance Applicative (MaybeErr err) where+ pure = return+ (<*>) = ap++instance Monad (MaybeErr err) where+ return v = Succeeded v+ Succeeded v >>= k = k v+ Failed e >>= _ = Failed e++isSuccess :: MaybeErr err val -> Bool+isSuccess (Succeeded {}) = True+isSuccess (Failed {}) = False++failME :: err -> MaybeErr err val+failME e = Failed e++main :: IO ()+main = print $ maybeToBool Nothing+\end{code}
+ TestSuite/inputs/compiler/utils/OrdList.lhs view
@@ -0,0 +1,93 @@+%+% (c) The University of Glasgow 2006+% (c) The AQUA Project, Glasgow University, 1993-1998+%++This is useful, general stuff for the Native Code Generator.++Provide trees (of instructions), so that lists of instructions+can be appended in linear time.++\begin{code}+{-# OPTIONS -fno-warn-tabs #-}+-- The above warning supression flag is a temporary kludge.+-- While working on this module you are encouraged to remove it and+-- detab the module (please do the detabbing in a separate patch). See+-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces+-- for details++module OrdList (+ OrdList, + nilOL, isNilOL, unitOL, appOL, consOL, snocOL, concatOL,+ mapOL, fromOL, toOL, foldrOL, foldlOL+) where++infixl 5 `appOL`+infixl 5 `snocOL`+infixr 5 `consOL`++data OrdList a+ = Many [a] -- Invariant: non-empty+ | Two (OrdList a) -- Invariant: non-empty+ (OrdList a) -- Invariant: non-empty+ | One a+ | None++nilOL :: OrdList a+isNilOL :: OrdList a -> Bool++unitOL :: a -> OrdList a+snocOL :: OrdList a -> a -> OrdList a+consOL :: a -> OrdList a -> OrdList a+appOL :: OrdList a -> OrdList a -> OrdList a+concatOL :: [OrdList a] -> OrdList a++nilOL = None+unitOL as = One as+snocOL None b = One b+snocOL as b = Two as (One b)+consOL a None = One a+consOL a bs = Two (One a) bs+concatOL aas = foldr appOL None aas++isNilOL None = True+isNilOL _ = False++appOL None bs = bs+appOL as None = as+appOL as bs = Two as bs++mapOL :: (a -> b) -> OrdList a -> OrdList b+mapOL _ None = None+mapOL f (One x) = One (f x)+mapOL f (Two x y) = Two (mapOL f x) (mapOL f y)+mapOL f (Many xs) = Many (map f xs)++instance Functor OrdList where+ fmap = mapOL++foldrOL :: (a->b->b) -> b -> OrdList a -> b+foldrOL _ z None = z+foldrOL k z (One x) = k x z+foldrOL k z (Two b1 b2) = foldrOL k (foldrOL k z b2) b1+foldrOL k z (Many xs) = foldr k z xs++foldlOL :: (b->a->b) -> b -> OrdList a -> b+foldlOL _ z None = z+foldlOL k z (One x) = k z x+foldlOL k z (Two b1 b2) = foldlOL k (foldlOL k z b1) b2+foldlOL k z (Many xs) = foldl k z xs++fromOL :: OrdList a -> [a]+fromOL ol + = flat ol []+ where+ flat None rest = rest+ flat (One x) rest = x:rest+ flat (Two a b) rest = flat a (flat b rest)+ flat (Many xs) rest = xs ++ rest++toOL :: [a] -> OrdList a+toOL [] = None+toOL xs = Many xs+\end{code}
+ TestSuite/inputs/compiler/utils/Subdir/Main.lhs view
@@ -0,0 +1,90 @@+%+% (c) The University of Glasgow 2006+% (c) The AQUA Project, Glasgow University, 1993-1998+%++This is useful, general stuff for the Native Code Generator.++Provide trees (of instructions), so that lists of instructions+can be appended in linear time.++\begin{code}+{-# OPTIONS -fno-warn-tabs #-}+-- The above warning supression flag is a temporary kludge.+-- While working on this module you are encouraged to remove it and+-- detab the module (please do the detabbing in a separate patch). See+-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces+-- for details++infixl 5 `appOL`+infixl 5 `snocOL`+infixr 5 `consOL`++data OrdList a+ = Many [a] -- Invariant: non-empty+ | Two (OrdList a) -- Invariant: non-empty+ (OrdList a) -- Invariant: non-empty+ | One a+ | None++nilOL :: OrdList a+isNilOL :: OrdList a -> Bool++unitOL :: a -> OrdList a+snocOL :: OrdList a -> a -> OrdList a+consOL :: a -> OrdList a -> OrdList a+appOL :: OrdList a -> OrdList a -> OrdList a+concatOL :: [OrdList a] -> OrdList a++nilOL = None+unitOL as = One as+snocOL None b = One b+snocOL as b = Two as (One b)+consOL a None = One a+consOL a bs = Two (One a) bs+concatOL aas = foldr appOL None aas++isNilOL None = True+isNilOL _ = False++appOL None bs = bs+appOL as None = as+appOL as bs = Two as bs++mapOL :: (a -> b) -> OrdList a -> OrdList b+mapOL _ None = None+mapOL f (One x) = One (f x)+mapOL f (Two x y) = Two (mapOL f x) (mapOL f y)+mapOL f (Many xs) = Many (map f xs)++instance Functor OrdList where+ fmap = mapOL++foldrOL :: (a->b->b) -> b -> OrdList a -> b+foldrOL _ z None = z+foldrOL k z (One x) = k x z+foldrOL k z (Two b1 b2) = foldrOL k (foldrOL k z b2) b1+foldrOL k z (Many xs) = foldr k z xs++foldlOL :: (b->a->b) -> b -> OrdList a -> b+foldlOL _ z None = z+foldlOL k z (One x) = k z x+foldlOL k z (Two b1 b2) = foldlOL k (foldlOL k z b1) b2+foldlOL k z (Many xs) = foldl k z xs++fromOL :: OrdList a -> [a]+fromOL ol + = flat ol []+ where+ flat None rest = rest+ flat (One x) rest = x:rest+ flat (Two a b) rest = flat a (flat b rest)+ flat (Many xs) rest = xs ++ rest++toOL :: [a] -> OrdList a+toOL [] = None+toOL xs = Many xs++main :: IO ()+main = return ()+\end{code}
+ TestSuite/inputs/simple-lib17/LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2013, ++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 the name of nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 COPYRIGHT+OWNER OR 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.
+ TestSuite/inputs/simple-lib17/Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ TestSuite/inputs/simple-lib17/SimpleLib.hs view
@@ -0,0 +1,4 @@+module SimpleLib where++simpleLib :: Int+simpleLib = 42
+ TestSuite/inputs/simple-lib17/build.sh view
@@ -0,0 +1,2 @@+unset GHC_PACKAGE_PATH+cabal install --package-db=clear --package-db=global --package-db=../packages
+ TestSuite/inputs/simple-lib17/simple-lib17.cabal view
@@ -0,0 +1,19 @@+-- Initial simple-lib.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/++name: simple-lib17+version: 0.1.0.0+-- synopsis: +-- description: +license: BSD3+license-file: LICENSE+-- author: +-- maintainer: +-- copyright: +-- category: +build-type: Simple+cabal-version: >=1.8++library+ exposed-modules: SimpleLib+ build-depends: base
ide-backend.cabal view
@@ -1,5 +1,5 @@ name: ide-backend-version: 0.9.0.11+version: 0.10.0 synopsis: An IDE backend library description: See README.md for more details license: MIT@@ -12,10 +12,39 @@ build-type: Simple cabal-version: >=1.10 extra-source-files: README.md+ TestSuite/inputs/README.md+ TestSuite/inputs/ABerror/*.hs+ TestSuite/inputs/AnotherA/*.hs+ TestSuite/inputs/TH/*.hs+ TestSuite/inputs/simple-lib17/*.hs+ TestSuite/inputs/simple-lib17/*.sh+ TestSuite/inputs/simple-lib17/*.cabal+ TestSuite/inputs/simple-lib17/LICENSE+ TestSuite/inputs/MainModule/cabals/*.cabal+ TestSuite/inputs/MainModule/ParFib/*.hs+ TestSuite/inputs/MainModule/*.hs+ TestSuite/inputs/compiler/utils/Subdir/*.lhs+ TestSuite/inputs/compiler/utils/*.hs+ TestSuite/inputs/compiler/utils/*.lhs+ TestSuite/inputs/AnotherB/*.hs+ TestSuite/inputs/bootMods/*.hs+ TestSuite/inputs/bootMods/*.hs-boot+ TestSuite/inputs/ABnoError/*.hs+ TestSuite/inputs/AerrorB/*.hs+ TestSuite/inputs/FFI/ffiles/*.c+ TestSuite/inputs/FFI/ffiles/*.h+ TestSuite/inputs/FFI/*.hs+ TestSuite/inputs/FFI/*.h+ TestSuite/inputs/FFI/*.c+ TestSuite/inputs/Puns/cabals/parse_error/*.cabal+ TestSuite/inputs/Puns/cabals/no_text_error/*.cabal+ TestSuite/inputs/Puns/cabals/*.cabal+ TestSuite/inputs/Puns/GHC/RTS/*.h+ TestSuite/inputs/Puns/GHC/RTS/*.hs library exposed-modules: IdeSession- other-modules: IdeSession.State,+ IdeSession.State, IdeSession.Config, IdeSession.Cabal, IdeSession.ExeCabalClient,@@ -47,7 +76,7 @@ time >= 1.4 && < 1.6, attoparsec >= 0.10 && < 0.14, utf8-string >= 0.3 && < 1.1,- ide-backend-common >= 0.9.1 && < 0.10,+ ide-backend-common >= 0.10 && < 0.11, template-haskell, -- our own private fork: Cabal-ide-backend >= 1.23,@@ -174,7 +203,10 @@ random, Cabal-ide-backend, containers,- deepseq+ deepseq,+ -- Dependencies of test suite at runtime+ parallel,+ monads-tf default-language: Haskell2010 ghc-options: -Wall -threaded@@ -191,7 +223,7 @@ test-suite rpc-server type: exitcode-stdio-1.0 main-is: rpc-server.hs- hs-source-dirs: . test+ hs-source-dirs: test build-depends: base ==4.*, directory ==1.*, filemanip >= 0.3.6.2 && < 0.4,@@ -209,6 +241,7 @@ executable-path >= 0.0 && < 0.1, unix >= 2.5 && < 2.8, binary >= 0.7.1.0 && < 0.8,+ ide-backend, ide-backend-common, template-haskell