Closed rszibele closed 6 years ago
Where is the debug log located? I am experiencing the same issue with the elm compiler.
@Josef-Vonasek debug log location is configured via hie launch command. Use -d
to enable debug logging and -l
parameter to specify log file.
Example from my nvim config:
let g:LanguageClient_serverCommands.haskell = ['stack', 'exec', '--', 'hie', '--lsp', '-d', '-l', 'D:\Temp\hie.log']
Are you running against current master?
Please provide the very top line of the hie log, which gives a version, something like
2018-06-01 08:44:58.509315147 [ThreadId 4] - run entered for HIE Version 0.2.0.0, Git revision ca81c716296d7d505b80f48aa3116794a7
533934 (dirty) (1428 commits) x86_64 ghc-8.4.2
Same thing with current master.
hie-wrapper.log (from vscode extension):
Launching HIE for project located at /home/richard/Documents/stack
Using stack GHC version
The Glorious Glasgow Haskell Compilation System, version 8.2.2
Project is using GHC 8.2.2
hie-8.2.2 was found on path
Starting HIE
hie.log:
2018-06-02 13:13:57.148685286 [ThreadId 4] - run entered for HIE Version 0.2.0.0, Git revision 2aa2cf30ec693a823aea4bc8376a8ac236030a99 (1436 commits) x86_64 ghc-8.2.2
Ok, looking into this, the hover request should always return immediately.
@rszibele can you post a fresh log showing the problem, because the messages in the log file do not correlate with the version you state.
In particular, all the [ThreadId 7]
messages for the ghcDispatcher
should have a ghcDispatcher
prefix.
So it may be possible that you are somehow running some earlier version for that project.
Such as for GHC 8.0.2, I am not sure if we backported that hanging fix to it, will check.
Hmm, github is now rendering it inline. See https://github.com/haskell/haskell-ide-engine/blob/2aa2cf30ec693a823aea4bc8376a8ac236030a99/src/Haskell/Ide/Engine/Dispatcher.hs#L107 for an example that does not tie up.
And I can reproduce this with elm compiler, investigating
For elm compiler I get the following error popup with my fixed version
It seems we needed to catch "IOError" too.
@alanz sure.
2018-06-02 19:50:00.150012027 [ThreadId 4] - run entered for HIE Version 0.2.0.0, Git revision 2aa2cf30ec693a823aea4bc8376a8ac236030a99 (1436 commits) x86_64 ghc-8.2.2
2018-06-02 19:50:00.150198817 [ThreadId 4] - Current directory:/home/richard/Documents/stack
2018-06-02 19:50:00.150261656 [ThreadId 4] -
haskell-lsp:Starting up server ...
2018-06-02 19:50:00.150822743 [ThreadId 4] - ---> {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":8776,"rootPath":"/home/richard/Documents/stack","rootUri":"file:///home/richard/Documents/stack","capabilities":{"workspace":{"applyEdit":true,"workspaceEdit":{"documentChanges":true},"didChangeConfiguration":{"dynamicRegistration":true},"didChangeWatchedFiles":{"dynamicRegistration":true},"symbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}},"executeCommand":{"dynamicRegistration":true},"configuration":true,"workspaceFolders":true},"textDocument":{"publishDiagnostics":{"relatedInformation":true},"synchronization":{"dynamicRegistration":true,"willSave":true,"willSaveWaitUntil":true,"didSave":true},"completion":{"dynamicRegistration":true,"contextSupport":true,"completionItem":{"snippetSupport":true,"commitCharactersSupport":true,"documentationFormat":["markdown","plaintext"],"deprecatedSupport":true},"completionItemKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]}},"hover":{"dynamicRegistration":true,"contentFormat":["markdown","plaintext"]},"signatureHelp":{"dynamicRegistration":true,"signatureInformation":{"documentationFormat":["markdown","plaintext"]}},"definition":{"dynamicRegistration":true},"references":{"dynamicRegistration":true},"documentHighlight":{"dynamicRegistration":true},"documentSymbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}},"codeAction":{"dynamicRegistration":true},"codeLens":{"dynamicRegistration":true},"formatting":{"dynamicRegistration":true},"rangeFormatting":{"dynamicRegistration":true},"onTypeFormatting":{"dynamicRegistration":true},"rename":{"dynamicRegistration":true},"documentLink":{"dynamicRegistration":true},"typeDefinition":{"dynamicRegistration":true},"implementation":{"dynamicRegistration":true},"colorProvider":{"dynamicRegistration":true}}},"trace":"off","workspaceFolders":[{"uri":"file:///home/richard/Documents/stack","name":"stack"}]}}
2018-06-02 19:50:00.15154188 [ThreadId 4] - haskell-lsp:initializeRequestHandler: setting current dir to project root:/home/richard/Documents/stack
2018-06-02 19:50:00.152092977 [ThreadId 5] - <--2--{"result":{"capabilities":{"textDocumentSync":{"openClose":true,"change":2,"willSave":false,"willSaveWaitUntil":false,"save":{"includeText":false}},"hoverProvider":true,"completionProvider":{"resolveProvider":true,"triggerCharacters":["."]},"definitionProvider":true,"referencesProvider":true,"documentHighlightProvider":true,"documentSymbolProvider":true,"codeActionProvider":true,"documentFormattingProvider":true,"documentRangeFormattingProvider":true,"renameProvider":true,"executeCommandProvider":{"commands":["applyrefact:applyOne","hare:demote"]}}},"jsonrpc":"2.0","id":0}
2018-06-02 19:50:00.172543119 [ThreadId 4] - ---> {"jsonrpc":"2.0","method":"initialized","params":{}}
2018-06-02 19:50:00.173085986 [ThreadId 4] - ---> {"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"languageServerHaskell":{"maxNumberOfProblems":100,"hieExecutablePath":"","useHieWrapper":true,"useCustomHieWrapper":false,"useCustomHieWrapperPath":"","hlintOn":true,"showTypeForSelection":{"onHover":true,"command":{"location":"dropdown"}},"trace":{"server":"off"},"enableHIE":true}}}}
2018-06-02 19:50:00.173558294 [ThreadId 8] - ****** reactor: processing Initialized Notification
2018-06-02 19:50:00.173636183 [ThreadId 8] - reactor:didChangeConfiguration notification:NotificationMessage {_jsonrpc = "2.0", _method = WorkspaceDidChangeConfiguration, _params = DidChangeConfigurationParams {_settings = Object (fromList [("languageServerHaskell",Object (fromList [("useHieWrapper",Bool True),("useCustomHieWrapper",Bool False),("useCustomHieWrapperPath",String ""),("hlintOn",Bool True),("hieExecutablePath",String ""),("enableHIE",Bool True),("showTypeForSelection",Object (fromList [("onHover",Bool True),("command",Object (fromList [("location",String "dropdown")]))])),("maxNumberOfProblems",Number 100.0),("trace",Object (fromList [("server",String "off")]))]))])}}
2018-06-02 19:50:00.173776593 [ThreadId 4] - ---> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///home/richard/Documents/stack/src/main/Main.hs","languageId":"haskell","version":1,"text":"{-# LANGUAGE NoImplicitPrelude #-}\n{-# LANGUAGE CPP #-}\n{-# LANGUAGE DeriveDataTypeable #-}\n{-# LANGUAGE FlexibleContexts #-}\n{-# LANGUAGE GADTs #-}\n{-# LANGUAGE OverloadedStrings #-}\n{-# LANGUAGE ScopedTypeVariables #-}\n{-# LANGUAGE RecordWildCards #-}\n\n#ifdef USE_GIT_INFO\n{-# LANGUAGE TemplateHaskell #-}\n#endif\n\n-- | Main stack tool entry point.\n\nmodule Main (main) where\n\n#ifndef HIDE_DEP_VERSIONS\nimport qualified Build_stack\n#endif\nimport Stack.Prelude hiding (Display (..))\nimport Control.Monad.Reader (local)\nimport Control.Monad.Trans.Except (ExceptT)\nimport Control.Monad.Writer.Lazy (Writer)\nimport Data.Attoparsec.Args (parseArgs, EscapingMode (Escaping))\nimport Data.Attoparsec.Interpreter (getInterpreterArgs)\nimport qualified Data.ByteString.Lazy as L\nimport Data.IORef.RunOnce (runOnce)\nimport Data.List\nimport qualified Data.Map.Strict as Map\nimport qualified Data.Set as Set\nimport qualified Data.Text as T\nimport Data.Version (showVersion)\nimport RIO.Process\n#ifdef USE_GIT_INFO\nimport Development.GitRev (gitCommitCount, gitHash)\n#endif\nimport Distribution.System (buildArch)\nimport qualified Distribution.Text as Cabal (display)\nimport Distribution.Version (mkVersion')\nimport GHC.IO.Encoding (mkTextEncoding, textEncodingName)\nimport Options.Applicative\nimport Options.Applicative.Help (errorHelp, stringChunk, vcatChunks)\nimport Options.Applicative.Builder.Extra\nimport Options.Applicative.Complicated\n#ifdef USE_GIT_INFO\nimport Options.Applicative.Simple (simpleVersion)\n#endif\nimport Options.Applicative.Types (ParserHelp(..))\nimport Path\nimport Path.IO\nimport qualified Paths_stack as Meta\nimport Stack.Build\nimport Stack.Clean (CleanOpts(..), clean)\nimport Stack.Config\nimport Stack.ConfigCmd as ConfigCmd\nimport Stack.Constants\nimport Stack.Constants.Config\nimport Stack.Coverage\nimport qualified Stack.Docker as Docker\nimport Stack.Dot\nimport Stack.GhcPkg (findGhcPkgField)\nimport qualified Stack.Nix as Nix\nimport Stack.Fetch\nimport Stack.FileWatch\nimport Stack.Ghci\nimport Stack.Hoogle\nimport Stack.Ls\nimport qualified Stack.IDE as IDE\nimport qualified Stack.Image as Image\nimport Stack.Init\nimport Stack.New\nimport Stack.Options.BuildParser\nimport Stack.Options.CleanParser\nimport Stack.Options.DockerParser\nimport Stack.Options.DotParser\nimport Stack.Options.ExecParser\nimport Stack.Options.GhciParser\nimport Stack.Options.GlobalParser\n\nimport Stack.Options.HpcReportParser\nimport Stack.Options.NewParser\nimport Stack.Options.NixParser\nimport Stack.Options.ScriptParser\nimport Stack.Options.SDistParser\nimport Stack.Options.SolverParser\nimport Stack.Options.Utils\nimport qualified Stack.PackageIndex\nimport qualified Stack.Path\nimport Stack.PrettyPrint\nimport Stack.Runners\nimport Stack.Script\nimport Stack.SDist (getSDistTarball, checkSDistTarball, checkSDistTarball', SDistOpts(..))\nimport Stack.SetupCmd\nimport qualified Stack.Sig as Sig\nimport Stack.Snapshot (loadResolver)\nimport Stack.Solver (solveExtraDeps)\nimport Stack.Types.Version\nimport Stack.Types.Config\nimport Stack.Types.Compiler\nimport Stack.Types.NamedComponent\nimport Stack.Types.Nix\nimport Stack.Types.Runner\nimport Stack.Upgrade\nimport qualified Stack.Upload as Upload\nimport qualified System.Directory as D\nimport System.Environment (getProgName, getArgs, withArgs)\nimport System.Exit\nimport System.FilePath (isValid, pathSeparator)\nimport System.Console.ANSI (SGR (Reset), hSupportsANSI, setSGR)\nimport System.IO (stderr, stdin, stdout, BufferMode(..), hPutStrLn, hPrint, hGetEncoding, hSetEncoding)\n\n-- | Change the character encoding of the given Handle to transliterate\n-- on unsupported characters instead of throwing an exception\nhSetTranslit :: Handle -> IO ()\nhSetTranslit h = do\n menc <- hGetEncoding h\n case fmap textEncodingName menc of\n Just name\n | '/' `notElem` name -> do\n enc' <- mkTextEncoding $ name ++ \"//TRANSLIT\"\n hSetEncoding h enc'\n _ -> return ()\n\nversionString' :: String\n#ifdef USE_GIT_INFO\nversionString' = concat $ concat\n [ [$(simpleVersion Meta.version)]\n -- Leave out number of commits for --depth=1 clone\n -- See https://github.com/commercialhaskell/stack/issues/792\n , [\" (\" ++ commitCount ++ \" commits)\" | commitCount /= (\"1\"::String) &&\n commitCount /= (\"UNKNOWN\" :: String)]\n , [\" \", Cabal.display buildArch]\n , [depsString, warningString]\n ]\n where\n commitCount = $gitCommitCount\n#else\nversionString' =\n showVersion Meta.version\n ++ ' ' : Cabal.display buildArch\n ++ depsString\n ++ warningString\n where\n#endif\n#ifdef HIDE_DEP_VERSIONS\n depsString = \" hpack-\" ++ VERSION_hpack\n#else\n depsString = \"\\nCompiled with:\\n\" ++ unlines (map (\"- \" ++) Build_stack.deps)\n#endif\n#ifdef SUPPORTED_BUILD\n warningString = \"\"\n#else\n warningString = unlines\n [ \"\"\n , \"Warning: this is an unsupported build that may use different versions of\"\n , \"dependencies and GHC than the officially released binaries, and therefore may\"\n , \"not behave identically. If you encounter problems, please try the latest\"\n , \"official build by running 'stack upgrade --force-download'.\"\n ]\n#endif\n\nmain :: IO ()\nmain = do\n -- Line buffer the output by default, particularly for non-terminal runs.\n -- See https://github.com/commercialhaskell/stack/pull/360\n hSetBuffering stdout LineBuffering\n hSetBuffering stdin LineBuffering\n hSetBuffering stderr LineBuffering\n hSetTranslit stdout\n hSetTranslit stderr\n args <- getArgs\n progName <- getProgName\n isTerminal <- hIsTerminalDeviceOrMinTTY stdout\n execExtraHelp args\n Docker.dockerHelpOptName\n (dockerOptsParser False)\n (\"Only showing --\" ++ Docker.dockerCmdName ++ \"* options.\")\n execExtraHelp args\n Nix.nixHelpOptName\n (nixOptsParser False)\n (\"Only showing --\" ++ Nix.nixCmdName ++ \"* options.\")\n\n currentDir <- D.getCurrentDirectory\n eGlobalRun <- try $ commandLineHandler currentDir progName False\n case eGlobalRun of\n Left (exitCode :: ExitCode) ->\n throwIO exitCode\n Right (globalMonoid,run) -> do\n let global = globalOptsFromMonoid isTerminal globalMonoid\n -- If stdout is (1) recognised as a terminal supporting ANSI (for the\n -- purposes of the functions of the ansi-terminal package) and (2) a\n -- native (ConHost) terminal on Windows 10, then the setSGR function will\n -- enable the ANSI-capability for that terminal. Later uses of\n -- hSupportsANSI with the functions of the RIO package that emit ANSI\n -- codes will then have the intended outcome on native Windows 10\n -- terminals.\n when (globalColorWhen global /= ColorNever) $\n hSupportsANSI stdout >>= flip when (setSGR [Reset])\n when (globalLogLevel global == LevelDebug) $ hPutStrLn stderr versionString'\n case globalReExecVersion global of\n Just expectVersion -> do\n expectVersion' <- parseVersionFromString expectVersion\n unless (checkVersion MatchMinor expectVersion' (fromCabalVersion (mkVersion' Meta.version)))\n $ throwIO $ InvalidReExecVersion expectVersion (showVersion Meta.version)\n _ -> return ()\n run global `catch` \\e ->\n -- This special handler stops \"stack: \" from being printed before the\n -- exception\n case fromException e of\n Just ec -> exitWith ec\n Nothing -> do\n hPrint stderr e\n exitFailure\n\n-- Vertically combine only the error component of the first argument with the\n-- error component of the second.\nvcatErrorHelp :: ParserHelp -> ParserHelp -> ParserHelp\nvcatErrorHelp h1 h2 = h2 { helpError = vcatChunks [helpError h2, helpError h1] }\n\ncommandLineHandler\n :: FilePath\n -> String\n -> Bool\n -> IO (GlobalOptsMonoid, GlobalOpts -> IO ())\ncommandLineHandler currentDir progName isInterpreter = complicatedOptions\n Meta.version\n (Just versionString')\n VERSION_hpack\n \"stack - The Haskell Tool Stack\"\n \"\"\n \"stack's documentation is available at https://docs.haskellstack.org/\"\n (globalOpts OuterGlobalOpts)\n (Just failureCallback)\n addCommands\n where\n failureCallback f args =\n case stripPrefix \"Invalid argument\" (fst (renderFailure f \"\")) of\n Just _ -> if isInterpreter\n then parseResultHandler args f\n else secondaryCommandHandler args f\n >>= interpreterHandler currentDir args\n Nothing -> parseResultHandler args f\n\n parseResultHandler args f =\n if isInterpreter\n then do\n let hlp = errorHelp $ stringChunk\n (unwords [\"Error executing interpreter command:\"\n , progName\n , unwords args])\n handleParseResult (overFailure (vcatErrorHelp hlp) (Failure f))\n else handleParseResult (Failure f)\n\n addCommands = do\n unless isInterpreter (do\n addBuildCommand' \"build\"\n \"Build the package(s) in this directory/configuration\"\n buildCmd\n (buildOptsParser Build)\n addBuildCommand' \"install\"\n \"Shortcut for 'build --copy-bins'\"\n buildCmd\n (buildOptsParser Install)\n addCommand' \"uninstall\"\n \"DEPRECATED: This command performs no actions, and is present for documentation only\"\n uninstallCmd\n (many $ strArgument $ metavar \"IGNORED\")\n addBuildCommand' \"test\"\n \"Shortcut for 'build --test'\"\n buildCmd\n (buildOptsParser Test)\n addBuildCommand' \"bench\"\n \"Shortcut for 'build --bench'\"\n buildCmd\n (buildOptsParser Bench)\n addBuildCommand' \"haddock\"\n \"Shortcut for 'build --haddock'\"\n buildCmd\n (buildOptsParser Haddock)\n addCommand' \"new\"\n (unwords [ \"Create a new project from a template.\"\n , \"Run `stack templates' to see available templates.\"\n , \"Note: you can also specify a local file or a\"\n , \"remote URL as a template.\"\n ] )\n newCmd\n newOptsParser\n addCommand' \"templates\"\n (unwords [ \"List the templates available for `stack new'.\"\n , \"Templates are drawn from\"\n , \"https://github.com/commercialhaskell/stack-templates\"\n , \"Note: `stack new' can also accept a template from a\"\n , \"local file or a remote URL.\"\n ] )\n templatesCmd\n (pure ())\n addCommand' \"init\"\n \"Create stack project config from cabal or hpack package specifications\"\n initCmd\n initOptsParser\n addCommand' \"solver\"\n \"Add missing extra-deps to stack project config\"\n solverCmd\n solverOptsParser\n addCommand' \"setup\"\n \"Get the appropriate GHC for your project\"\n setupCmd\n setupParser\n addCommand' \"path\"\n \"Print out handy path information\"\n pathCmd\n Stack.Path.pathParser\n addCommand' \"ls\"\n \"List command. (Supports snapshots and dependencies)\"\n lsCmd\n lsParser\n addCommand' \"unpack\"\n \"Unpack one or more packages locally\"\n unpackCmd\n ((,) <$> some (strArgument $ metavar \"PACKAGE\")\n <*> optional (textOption $ long \"to\" <>\n help \"Optional path to unpack the package into (will unpack into subdirectory)\"))\n addCommand' \"update\"\n \"Update the package index\"\n updateCmd\n (pure ())\n addCommand' \"upgrade\"\n \"Upgrade to the latest stack\"\n upgradeCmd\n upgradeOpts\n addCommand'\n \"upload\"\n \"Upload a package to Hackage\"\n uploadCmd\n (sdistOptsParser True)\n addCommand'\n \"sdist\"\n \"Create source distribution tarballs\"\n sdistCmd\n (sdistOptsParser False)\n addCommand' \"dot\"\n \"Visualize your project's dependency graph using Graphviz dot\"\n dotCmd\n (dotOptsParser False) -- Default for --external is False.\n addCommand' \"ghc\"\n \"Run ghc\"\n execCmd\n (execOptsParser $ Just ExecGhc)\n addCommand' \"hoogle\"\n (\"Run hoogle, the Haskell API search engine. Use 'stack exec' syntax \" ++\n \"to pass Hoogle arguments, e.g. stack hoogle -- --count=20\")\n hoogleCmd\n ((,,,) <$> many (strArgument (metavar \"ARG\"))\n <*> boolFlags\n True\n \"setup\"\n \"If needed: install hoogle, build haddocks and generate a hoogle database\"\n idm\n <*> switch\n (long \"rebuild\" <>\n help \"Rebuild the hoogle database\")\n <*> switch\n (long \"server\" <>\n help \"Start local Hoogle server\"))\n )\n\n -- These are the only commands allowed in interpreter mode as well\n addCommand' \"exec\"\n \"Execute a command\"\n execCmd\n (execOptsParser Nothing)\n addCommand' \"run\"\n \"Build and run the first available executable\"\n execCmd\n (execOptsParser $ Just ExecRun)\n addGhciCommand' \"ghci\"\n \"Run ghci in the context of package(s) (experimental)\"\n ghciCmd\n ghciOptsParser\n addGhciCommand' \"repl\"\n \"Run ghci in the context of package(s) (experimental) (alias for 'ghci')\"\n ghciCmd\n ghciOptsParser\n addCommand' \"runghc\"\n \"Run runghc\"\n execCmd\n (execOptsParser $ Just ExecRunGhc)\n addCommand' \"runhaskell\"\n \"Run runghc (alias for 'runghc')\"\n execCmd\n (execOptsParser $ Just ExecRunGhc)\n addCommand' \"script\"\n \"Run a Stack Script\"\n scriptCmd\n scriptOptsParser\n\n unless isInterpreter (do\n addCommand' \"eval\"\n \"Evaluate some haskell code inline. Shortcut for 'stack exec ghc -- -e CODE'\"\n evalCmd\n (evalOptsParser \"CODE\")\n addCommand' \"clean\"\n \"Clean the local packages\"\n cleanCmd\n cleanOptsParser\n addCommand' \"list-dependencies\"\n \"List the dependencies\"\n (listDependenciesCmd True)\n listDepsOptsParser\n addCommand' \"query\"\n \"Query general build information (experimental)\"\n queryCmd\n (many $ strArgument $ metavar \"SELECTOR...\")\n addSubCommands'\n \"ide\"\n \"IDE-specific commands\"\n (do addCommand'\n \"packages\"\n \"List all available local loadable packages\"\n idePackagesCmd\n (pure ())\n addCommand'\n \"targets\"\n \"List all available stack targets\"\n ideTargetsCmd\n (pure ()))\n addSubCommands'\n Docker.dockerCmdName\n \"Subcommands specific to Docker use\"\n (do addCommand' Docker.dockerPullCmdName\n \"Pull latest version of Docker image from registry\"\n dockerPullCmd\n (pure ())\n addCommand' \"reset\"\n \"Reset the Docker sandbox\"\n dockerResetCmd\n (switch (long \"keep-home\" <>\n help \"Do not delete sandbox's home directory\"))\n addCommand' Docker.dockerCleanupCmdName\n \"Clean up Docker images and containers\"\n dockerCleanupCmd\n dockerCleanupOptsParser)\n addSubCommands'\n ConfigCmd.cfgCmdName\n \"Subcommands specific to modifying stack.yaml files\"\n (addCommand' ConfigCmd.cfgCmdSetName\n \"Sets a field in the project's stack.yaml to value\"\n cfgSetCmd\n configCmdSetParser)\n addSubCommands'\n Image.imgCmdName\n \"Subcommands specific to imaging\"\n (addCommand'\n Image.imgDockerCmdName\n \"Build a Docker image for the project\"\n imgDockerCmd\n ((,) <$>\n boolFlags\n True\n \"build\"\n \"building the project before creating the container\"\n idm <*>\n many\n (textOption\n (long \"image\" <>\n help \"A specific container image name to build\"))))\n addSubCommands'\n \"hpc\"\n \"Subcommands specific to Haskell Program Coverage\"\n (addCommand' \"report\"\n \"Generate unified HPC coverage report from tix files and project targets\"\n hpcReportCmd\n hpcReportOptsParser)\n )\n where\n -- addCommand hiding global options\n addCommand' :: String -> String -> (a -> GlobalOpts -> IO ()) -> Parser a\n -> AddCommand\n addCommand' cmd title constr =\n addCommand cmd title globalFooter constr (globalOpts OtherCmdGlobalOpts)\n\n addSubCommands' :: String -> String -> AddCommand\n -> AddCommand\n addSubCommands' cmd title =\n addSubCommands cmd title globalFooter (globalOpts OtherCmdGlobalOpts)\n\n -- Additional helper that hides global options and shows build options\n addBuildCommand' :: String -> String -> (a -> GlobalOpts -> IO ()) -> Parser a\n -> AddCommand\n addBuildCommand' cmd title constr =\n addCommand cmd title globalFooter constr (globalOpts BuildCmdGlobalOpts)\n\n -- Additional helper that hides global options and shows some ghci options\n addGhciCommand' :: String -> String -> (a -> GlobalOpts -> IO ()) -> Parser a\n -> AddCommand\n addGhciCommand' cmd title constr =\n addCommand cmd title globalFooter constr (globalOpts GhciCmdGlobalOpts)\n\n globalOpts :: GlobalOptsContext -> Parser GlobalOptsMonoid\n globalOpts kind =\n extraHelpOption hide progName (Docker.dockerCmdName ++ \"*\") Docker.dockerHelpOptName <*>\n extraHelpOption hide progName (Nix.nixCmdName ++ \"*\") Nix.nixHelpOptName <*>\n globalOptsParser currentDir kind\n (if isInterpreter\n -- Silent except when errors occur - see #2879\n then Just LevelError\n else Nothing)\n where hide = kind /= OuterGlobalOpts\n\n globalFooter = \"Run 'stack --help' for global options that apply to all subcommands.\"\n\ntype AddCommand =\n ExceptT (GlobalOpts -> IO ()) (Writer (Mod CommandFields (GlobalOpts -> IO (), GlobalOptsMonoid))) ()\n\n-- | fall-through to external executables in `git` style if they exist\n-- (i.e. `stack something` looks for `stack-something` before\n-- failing with \"Invalid argument `something'\")\nsecondaryCommandHandler\n :: [String]\n -> ParserFailure ParserHelp\n -> IO (ParserFailure ParserHelp)\nsecondaryCommandHandler args f =\n -- don't even try when the argument looks like a path or flag\n if elem pathSeparator cmd || \"-\" `isPrefixOf` head args\n then return f\n else do\n mExternalExec <- D.findExecutable cmd\n case mExternalExec of\n Just ex -> withProcessContextNoLogging $ do\n -- TODO show the command in verbose mode\n -- hPutStrLn stderr $ unwords $\n -- [\"Running\", \"[\" ++ ex, unwords (tail args) ++ \"]\"]\n _ <- exec ex (tail args)\n return f\n Nothing -> return $ fmap (vcatErrorHelp (noSuchCmd cmd)) f\n where\n -- FIXME this is broken when any options are specified before the command\n -- e.g. stack --verbosity silent cmd\n cmd = stackProgName ++ \"-\" ++ head args\n noSuchCmd name = errorHelp $ stringChunk\n (\"Auxiliary command not found in path `\" ++ name ++ \"'\")\n\ninterpreterHandler\n :: Monoid t\n => FilePath\n -> [String]\n -> ParserFailure ParserHelp\n -> IO (GlobalOptsMonoid, (GlobalOpts -> IO (), t))\ninterpreterHandler currentDir args f = do\n -- args can include top-level config such as --extra-lib-dirs=... (set by\n -- nix-shell) - we need to find the first argument which is a file, everything\n -- afterwards is an argument to the script, everything before is an argument\n -- to Stack\n (stackArgs, fileArgs) <- spanM (fmap not . D.doesFileExist) args\n case fileArgs of\n (file:fileArgs') -> runInterpreterCommand file stackArgs fileArgs'\n [] -> parseResultHandler (errorCombine (noSuchFile firstArg))\n where\n firstArg = head args\n\n spanM _ [] = return ([], [])\n spanM p xs@(x:xs') = do\n r <- p x\n if r\n then do\n (ys, zs) <- spanM p xs'\n return (x:ys, zs)\n else\n return ([], xs)\n\n -- if the first argument contains a path separator then it might be a file,\n -- or a Stack option referencing a file. In that case we only show the\n -- interpreter error message and exclude the command related error messages.\n errorCombine =\n if pathSeparator `elem` firstArg\n then overrideErrorHelp\n else vcatErrorHelp\n\n overrideErrorHelp h1 h2 = h2 { helpError = helpError h1 }\n\n parseResultHandler fn = handleParseResult (overFailure fn (Failure f))\n noSuchFile name = errorHelp $ stringChunk\n (\"File does not exist or is not a regular file `\" ++ name ++ \"'\")\n\n runInterpreterCommand path stackArgs fileArgs = do\n progName <- getProgName\n iargs <- getInterpreterArgs path\n let parseCmdLine = commandLineHandler currentDir progName True\n -- Implicit file arguments are put before other arguments that\n -- occur after \"--\". See #3658\n cmdArgs = stackArgs ++ case break (== \"--\") iargs of\n (beforeSep, []) -> beforeSep ++ [\"--\"] ++ [path] ++ fileArgs\n (beforeSep, optSep : afterSep) ->\n beforeSep ++ [optSep] ++ [path] ++ fileArgs ++ afterSep\n -- TODO show the command in verbose mode\n -- hPutStrLn stderr $ unwords $\n -- [\"Running\", \"[\" ++ progName, unwords cmdArgs ++ \"]\"]\n (a,b) <- withArgs cmdArgs parseCmdLine\n return (a,(b,mempty))\n\npathCmd :: [Text] -> GlobalOpts -> IO ()\npathCmd keys go = withBuildConfig go (Stack.Path.path keys)\n\nsetupCmd :: SetupCmdOpts -> GlobalOpts -> IO ()\nsetupCmd sco@SetupCmdOpts{..} go@GlobalOpts{..} = loadConfigWithOpts go $ \\lc -> do\n when (isJust scoUpgradeCabal && nixEnable (configNix (lcConfig lc))) $ do\n throwIO UpgradeCabalUnusable\n withUserFileLock go (view stackRootL lc) $ \\lk -> do\n let getCompilerVersion = loadCompilerVersion go lc\n runRIO (lcConfig lc) $\n Docker.reexecWithOptionalContainer\n (lcProjectRoot lc)\n Nothing\n (runRIO (lcConfig lc) $\n Nix.reexecWithOptionalShell (lcProjectRoot lc) getCompilerVersion $ do\n (wantedCompiler, compilerCheck, mstack) <-\n case scoCompilerVersion of\n Just v -> return (v, MatchMinor, Nothing)\n Nothing -> do\n bc <- liftIO $ lcLoadBuildConfig lc globalCompiler\n return ( view wantedCompilerVersionL bc\n , configCompilerCheck (lcConfig lc)\n , Just $ view stackYamlL bc\n )\n runRIO (loadMiniConfig (lcConfig lc)) $ setup sco wantedCompiler compilerCheck mstack\n )\n Nothing\n (Just $ munlockFile lk)\n\ncleanCmd :: CleanOpts -> GlobalOpts -> IO ()\ncleanCmd opts go =\n -- See issues #2010 and #3468 for why \"stack clean --full\" is not used\n -- within docker.\n case opts of\n CleanFull{} -> withBuildConfigAndLockNoDocker go (const (clean opts))\n CleanShallow{} -> withBuildConfigAndLock go (const (clean opts))\n\n-- | Helper for build and install commands\nbuildCmd :: BuildOptsCLI -> GlobalOpts -> IO ()\nbuildCmd opts go = do\n when (any ((\"-prof\" `elem`) . either (const []) id . parseArgs Escaping) (boptsCLIGhcOptions opts)) $ do\n hPutStrLn stderr \"Error: When building with stack, you should not use the -prof GHC option\"\n hPutStrLn stderr \"Instead, please use --library-profiling and --executable-profiling\"\n hPutStrLn stderr \"See: https://github.com/commercialhaskell/stack/issues/1015\"\n exitFailure\n case boptsCLIFileWatch opts of\n FileWatchPoll -> fileWatchPoll stderr inner\n FileWatch -> fileWatch stderr inner\n NoFileWatch -> inner $ const $ return ()\n where\n inner setLocalFiles = withBuildConfigAndLock go' $ \\lk ->\n Stack.Build.build setLocalFiles lk opts\n -- Read the build command from the CLI and enable it to run\n go' = case boptsCLICommand opts of\n Test -> set (globalOptsBuildOptsMonoidL.buildOptsMonoidTestsL) (Just True) go\n Haddock -> set (globalOptsBuildOptsMonoidL.buildOptsMonoidHaddockL) (Just True) go\n Bench -> set (globalOptsBuildOptsMonoidL.buildOptsMonoidBenchmarksL) (Just True) go\n Install -> set (globalOptsBuildOptsMonoidL.buildOptsMonoidInstallExesL) (Just True) go\n Build -> go -- Default case is just Build\n\nuninstallCmd :: [String] -> GlobalOpts -> IO ()\nuninstallCmd _ go = withConfigAndLock go $\n prettyErrorL\n [ flow \"stack does not manage installations in global locations.\"\n , flow \"The only global mutation stack performs is executable copying.\"\n , flow \"For the default executable destination, please run\"\n , styleShell \"stack path --local-bin\"\n ]\n\n-- | Unpack packages to the filesystem\nunpackCmd :: ([String], Maybe Text) -> GlobalOpts -> IO ()\nunpackCmd (names, Nothing) go = unpackCmd (names, Just \".\") go\nunpackCmd (names, Just dstPath) go = withConfigAndLock go $ do\n mSnapshotDef <- mapM (makeConcreteResolver Nothing >=> loadResolver) (globalResolver go)\n Stack.Fetch.unpackPackages mSnapshotDef (T.unpack dstPath) names\n\n-- | Update the package index\nupdateCmd :: () -> GlobalOpts -> IO ()\nupdateCmd () go = withConfigAndLock go Stack.PackageIndex.updateAllIndices\n\nupgradeCmd :: UpgradeOpts -> GlobalOpts -> IO ()\nupgradeCmd upgradeOpts' go = withGlobalConfigAndLock go $\n upgrade (globalConfigMonoid go)\n (globalResolver go)\n#ifdef USE_GIT_INFO\n (find (/= \"UNKNOWN\") [$gitHash])\n#else\n Nothing\n#endif\n upgradeOpts'\n\n-- | Upload to Hackage\nuploadCmd :: SDistOpts -> GlobalOpts -> IO ()\nuploadCmd (SDistOpts [] _ _ _ _ _) go =\n withConfigAndLock go . prettyErrorL $\n [ flow \"To upload the current package, please run\"\n , styleShell \"stack upload .\"\n , flow \"(with the period at the end)\"\n ]\nuploadCmd sdistOpts go = do\n let partitionM _ [] = return ([], [])\n partitionM f (x:xs) = do\n r <- f x\n (as, bs) <- partitionM f xs\n return $ if r then (x:as, bs) else (as, x:bs)\n (files, nonFiles) <- partitionM D.doesFileExist (sdoptsDirsToWorkWith sdistOpts)\n (dirs, invalid) <- partitionM D.doesDirectoryExist nonFiles\n withBuildConfigAndLock go $ \\_ -> do\n unless (null invalid) $ do\n let invalidList = bulletedList $ map (styleFile . fromString) invalid\n prettyErrorL\n [ styleShell \"stack upload\"\n , flow \"expects a list of sdist tarballs or package directories.\"\n , flow \"Can't find:\"\n , line <> invalidList\n ]\n liftIO exitFailure\n when (null files && null dirs) $ do\n prettyErrorL\n [ styleShell \"stack upload\"\n , flow \"expects a list of sdist tarballs or package directories, but none were specified.\"\n ]\n liftIO exitFailure\n config <- view configL\n getCreds <- liftIO (runOnce (Upload.loadCreds config))\n mapM_ (resolveFile' >=> checkSDistTarball sdistOpts) files\n forM_\n files\n (\\file ->\n do tarFile <- resolveFile' file\n liftIO $ do\n creds <- getCreds\n Upload.upload creds (toFilePath tarFile)\n when\n (sdoptsSign sdistOpts)\n (void $\n Sig.sign\n (sdoptsSignServerUrl sdistOpts)\n tarFile))\n unless (null dirs) $\n forM_ dirs $ \\dir -> do\n pkgDir <- resolveDir' dir\n (tarName, tarBytes, mcabalRevision) <- getSDistTarball (sdoptsPvpBounds sdistOpts) pkgDir\n checkSDistTarball' sdistOpts tarName tarBytes\n liftIO $ do\n creds <- getCreds\n Upload.uploadBytes creds tarName tarBytes\n forM_ mcabalRevision $ uncurry $ Upload.uploadRevision creds\n tarPath <- parseRelFile tarName\n when\n (sdoptsSign sdistOpts)\n (void $\n Sig.signTarBytes\n (sdoptsSignServerUrl sdistOpts)\n tarPath\n tarBytes)\n\nsdistCmd :: SDistOpts -> GlobalOpts -> IO ()\nsdistCmd sdistOpts go =\n withBuildConfig go $ do -- No locking needed.\n -- If no directories are specified, build all sdist tarballs.\n dirs' <- if null (sdoptsDirsToWorkWith sdistOpts)\n then do\n dirs <- liftM (map lpvRoot . Map.elems . lpProject) getLocalPackages\n when (null dirs) $ do\n stackYaml <- view stackYamlL\n prettyErrorL\n [ styleShell \"stack sdist\"\n , flow \"expects a list of targets, and otherwise defaults to all of the project's packages.\"\n , flow \"However, the configuration at\"\n , display stackYaml\n , flow \"contains no packages, so no sdist tarballs will be generated.\"\n ]\n liftIO exitFailure\n return dirs\n else mapM resolveDir' (sdoptsDirsToWorkWith sdistOpts)\n forM_ dirs' $ \\dir -> do\n (tarName, tarBytes, _mcabalRevision) <- getSDistTarball (sdoptsPvpBounds sdistOpts) dir\n distDir <- distDirFromDir dir\n tarPath <- (distDir </>) <$> parseRelFile tarName\n ensureDir (parent tarPath)\n liftIO $ L.writeFile (toFilePath tarPath) tarBytes\n checkSDistTarball sdistOpts tarPath\n prettyInfoL [flow \"Wrote sdist tarball to\", display tarPath]\n when (sdoptsSign sdistOpts) (void $ Sig.sign (sdoptsSignServerUrl sdistOpts) tarPath)\n\n-- | Execute a command.\nexecCmd :: ExecOpts -> GlobalOpts -> IO ()\nexecCmd ExecOpts {..} go@GlobalOpts{..} =\n case eoExtra of\n ExecOptsPlain -> do\n (cmd, args) <- case (eoCmd, eoArgs) of\n (ExecCmd cmd, args) -> return (cmd, args)\n (ExecRun, args) -> return (\"\", args)\n (ExecGhc, args) -> return (\"ghc\", args)\n (ExecRunGhc, args) -> return (\"runghc\", args)\n loadConfigWithOpts go $ \\lc ->\n withUserFileLock go (view stackRootL lc) $ \\lk -> do\n let getCompilerVersion = loadCompilerVersion go lc\n runRIO (lcConfig lc) $\n Docker.reexecWithOptionalContainer\n (lcProjectRoot lc)\n -- Unlock before transferring control away, whether using docker or not:\n (Just $ munlockFile lk)\n (runRIO (lcConfig lc) $ do\n config <- view configL\n menv <- liftIO $ configProcessContextSettings config plainEnvSettings\n withProcessContext menv $ Nix.reexecWithOptionalShell\n (lcProjectRoot lc)\n getCompilerVersion\n (runRIO (lcConfig lc) $\n exec cmd args))\n Nothing\n Nothing -- Unlocked already above.\n ExecOptsEmbellished {..} ->\n withBuildConfigAndLock go $ \\lk -> do\n let targets = concatMap words eoPackages\n unless (null targets) $\n Stack.Build.build (const $ return ()) lk defaultBuildOptsCLI\n { boptsCLITargets = map T.pack targets\n }\n\n config <- view configL\n menv <- liftIO $ configProcessContextSettings config eoEnvSettings\n withProcessContext menv $ do\n -- Add RTS options to arguments\n let argsWithRts args = if null eoRtsOptions\n then args :: [String]\n else args ++ [\"+RTS\"] ++ eoRtsOptions ++ [\"-RTS\"]\n (cmd, args) <- case (eoCmd, argsWithRts eoArgs) of\n (ExecCmd cmd, args) -> return (cmd, args)\n (ExecRun, args) -> getRunCmd args\n (ExecGhc, args) -> getGhcCmd \"\" eoPackages args\n -- NOTE: this won't currently work for GHCJS, because it doesn't have\n -- a runghcjs binary. It probably will someday, though.\n (ExecRunGhc, args) ->\n getGhcCmd \"run\" eoPackages args\n munlockFile lk -- Unlock before transferring control away.\n\n runWithPath eoCwd $ exec cmd args\n where\n -- return the package-id of the first package in GHC_PACKAGE_PATH\n getPkgId wc name = do\n mId <- findGhcPkgField wc [] name \"id\"\n case mId of\n Just i -> return (head $ words (T.unpack i))\n -- should never happen as we have already installed the packages\n _ -> liftIO $ do\n hPutStrLn stderr (\"Could not find package id of package \" ++ name)\n exitFailure\n\n getPkgOpts wc pkgs =\n map (\"-package-id=\" ++) <$> mapM (getPkgId wc) pkgs\n\n getRunCmd args = do\n pkgComponents <- liftM (map lpvComponents . Map.elems . lpProject) getLocalPackages\n let exe = find isCExe $ concatMap Set.toList pkgComponents\n case exe of\n Just (CExe exe') -> do\n Stack.Build.build (const (return ())) Nothing defaultBuildOptsCLI{boptsCLITargets = [T.concat [T.pack \":\", exe']]}\n return (T.unpack exe', args)\n _ -> liftIO $ do\n hPutStrLn stderr \"No executables found.\"\n exitFailure\n\n getGhcCmd prefix pkgs args = do\n wc <- view $ actualCompilerVersionL.whichCompilerL\n pkgopts <- getPkgOpts wc pkgs\n return (prefix ++ compilerExeName wc, pkgopts ++ args)\n\n runWithPath :: Maybe FilePath -> RIO EnvConfig () -> RIO EnvConfig ()\n runWithPath path callback = case path of\n Nothing -> callback\n Just p | not (isValid p) -> throwIO $ InvalidPathForExec p\n Just p -> withUnliftIO $ \\ul -> D.withCurrentDirectory p $ unliftIO ul callback\n\n-- | Evaluate some haskell code inline.\nevalCmd :: EvalOpts -> GlobalOpts -> IO ()\nevalCmd EvalOpts {..} go@GlobalOpts {..} = execCmd execOpts go\n where\n execOpts =\n ExecOpts { eoCmd = ExecGhc\n , eoArgs = [\"-e\", evalArg]\n , eoExtra = evalExtra\n }\n\n-- | Run GHCi in the context of a project.\nghciCmd :: GhciOpts -> GlobalOpts -> IO ()\nghciCmd ghciOpts go@GlobalOpts{..} =\n withBuildConfigAndLock go $ \\lk -> do\n munlockFile lk -- Don't hold the lock while in the GHCI.\n bopts <- view buildOptsL\n -- override env so running of tests and benchmarks is disabled\n let boptsLocal = bopts\n { boptsTestOpts = (boptsTestOpts bopts) { toDisableRun = True }\n , boptsBenchmarkOpts = (boptsBenchmarkOpts bopts) { beoDisableRun = True }\n }\n local (set buildOptsL boptsLocal)\n (ghci ghciOpts)\n\n-- | List packages in the project.\nidePackagesCmd :: () -> GlobalOpts -> IO ()\nidePackagesCmd () go =\n withBuildConfig go IDE.listPackages\n\n-- | List targets in the project.\nideTargetsCmd :: () -> GlobalOpts -> IO ()\nideTargetsCmd () go =\n withBuildConfig go IDE.listTargets\n\n-- | Pull the current Docker image.\ndockerPullCmd :: () -> GlobalOpts -> IO ()\ndockerPullCmd _ go@GlobalOpts{..} =\n loadConfigWithOpts go $ \\lc ->\n -- TODO: can we eliminate this lock if it doesn't touch ~/.stack/?\n withUserFileLock go (view stackRootL lc) $ \\_ ->\n runRIO (lcConfig lc) $\n Docker.preventInContainer Docker.pull\n\n-- | Reset the Docker sandbox.\ndockerResetCmd :: Bool -> GlobalOpts -> IO ()\ndockerResetCmd keepHome go@GlobalOpts{..} =\n loadConfigWithOpts go $ \\lc ->\n -- TODO: can we eliminate this lock if it doesn't touch ~/.stack/?\n withUserFileLock go (view stackRootL lc) $ \\_ ->\n runRIO (lcConfig lc) $\n Docker.preventInContainer $ Docker.reset (lcProjectRoot lc) keepHome\n\n-- | Cleanup Docker images and containers.\ndockerCleanupCmd :: Docker.CleanupOpts -> GlobalOpts -> IO ()\ndockerCleanupCmd cleanupOpts go@GlobalOpts{..} =\n loadConfigWithOpts go $ \\lc ->\n -- TODO: can we eliminate this lock if it doesn't touch ~/.stack/?\n withUserFileLock go (view stackRootL lc) $ \\_ ->\n runRIO (lcConfig lc) $\n Docker.preventInContainer $\n Docker.cleanup cleanupOpts\n\ncfgSetCmd :: ConfigCmd.ConfigCmdSet -> GlobalOpts -> IO ()\ncfgSetCmd co go@GlobalOpts{..} =\n withMiniConfigAndLock\n go\n (cfgCmdSet go co)\n\nimgDockerCmd :: (Bool, [Text]) -> GlobalOpts -> IO ()\nimgDockerCmd (rebuild,images) go@GlobalOpts{..} = loadConfigWithOpts go $ \\lc -> do\n let mProjectRoot = lcProjectRoot lc\n withBuildConfigExt\n False\n go\n Nothing\n (\\lk ->\n do when rebuild $\n Stack.Build.build\n (const (return ()))\n lk\n defaultBuildOptsCLI\n Image.stageContainerImageArtifacts mProjectRoot images)\n (Just $ Image.createContainerImageFromStage mProjectRoot images)\n\n-- | Project initialization\ninitCmd :: InitOpts -> GlobalOpts -> IO ()\ninitCmd initOpts go = do\n pwd <- getCurrentDir\n withMiniConfigAndLock go (initProject IsInitCmd pwd initOpts (globalResolver go))\n\n-- | Create a project directory structure and initialize the stack config.\nnewCmd :: (NewOpts,InitOpts) -> GlobalOpts -> IO ()\nnewCmd (newOpts,initOpts) go@GlobalOpts{..} =\n withMiniConfigAndLock go $ do\n dir <- new newOpts (forceOverwrite initOpts)\n exists <- doesFileExist $ dir </> stackDotYaml\n when (forceOverwrite initOpts || not exists) $\n initProject IsNewCmd dir initOpts globalResolver\n\n-- | List the available templates.\ntemplatesCmd :: () -> GlobalOpts -> IO ()\ntemplatesCmd _ go@GlobalOpts{..} = withConfigAndLock go listTemplates\n\n-- | Fix up extra-deps for a project\nsolverCmd :: Bool -- ^ modify stack.yaml automatically?\n -> GlobalOpts\n -> IO ()\nsolverCmd fixStackYaml go =\n withBuildConfigAndLock go (\\_ -> solveExtraDeps fixStackYaml)\n\n-- | Visualize dependencies\ndotCmd :: DotOpts -> GlobalOpts -> IO ()\ndotCmd dotOpts go = withBuildConfigDot dotOpts go $ dot dotOpts\n\n-- | Query build information\nqueryCmd :: [String] -> GlobalOpts -> IO ()\nqueryCmd selectors go = withBuildConfig go $ queryBuildInfo $ map T.pack selectors\n\n-- | Generate a combined HPC report\nhpcReportCmd :: HpcReportOpts -> GlobalOpts -> IO ()\nhpcReportCmd hropts go = withBuildConfig go $ generateHpcReportForTargets hropts\n\ndata MainException = InvalidReExecVersion String String\n | UpgradeCabalUnusable\n | InvalidPathForExec FilePath\n deriving (Typeable)\ninstance Exception MainException\ninstance Show MainException where\n show (InvalidReExecVersion expected actual) = concat\n [ \"When re-executing '\"\n , stackProgName\n , \"' in a container, the incorrect version was found\\nExpected: \"\n , expected\n , \"; found: \"\n , actual]\n show UpgradeCabalUnusable = \"--upgrade-cabal cannot be used when nix is activated\"\n show (InvalidPathForExec path) = concat\n [ \"Got an invalid --cwd argument for stack exec (\"\n , path\n , \")\"]\n"}}}
2018-06-02 19:50:00.173838852 [ThreadId 8] - reactor:didChangeConfiguration diagsOn:True
2018-06-02 19:50:00.177257124 [ThreadId 5] - <--2--{"jsonrpc":"2.0","method":"window/logMessage","params":{"type":4,"message":"Using hie version: Version 0.2.0.0, Git revision 2aa2cf30ec693a823aea4bc8376a8ac236030a99 (1436 commits) x86_64 ghc-8.2.2"}}
2018-06-02 19:50:00.198282204 [ThreadId 8] - ****** reactor: processing NotDidOpenTextDocument
2018-06-02 19:50:00.198512902 [ThreadId 4] - ---> {"jsonrpc":"2.0","id":1,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///home/richard/Documents/stack/src/main/Main.hs"},"range":{"start":{"line":1009,"character":18},"end":{"line":1009,"character":18}},"context":{"diagnostics":[]}}}
2018-06-02 19:50:00.198840021 [ThreadId 8] - reactor:got CodeActionRequest:RequestMessage {_jsonrpc = "2.0", _id = IdInt 1, _method = TextDocumentCodeAction, _params = CodeActionParams {_textDocument = TextDocumentIdentifier {_uri = Uri {getUri = "file:///home/richard/Documents/stack/src/main/Main.hs"}}, _range = Range {_start = Position {_line = 1009, _character = 18}, _end = Position {_line = 1009, _character = 18}}, _context = CodeActionContext {_diagnostics = List []}}}
2018-06-02 19:50:00.19899231 [ThreadId 5] - <--2--{"result":[],"jsonrpc":"2.0","id":1}
2018-06-02 19:50:00.347789997 [ThreadId 11] - ideDispatcher: top of loop
2018-06-02 19:50:00.347915816 [ThreadId 7] - ghcDispatcher: top of loop
2018-06-02 19:50:00.347970246 [ThreadId 7] - ghcDispatcher:got request with id: Nothing
2018-06-02 19:50:00.348101635 [ThreadId 7] - ghcDispatcher: top of loop
2018-06-02 19:50:00.348158785 [ThreadId 7] - ghcDispatcher:got request with id: Nothing
2018-06-02 19:50:00.349560988 [ThreadId 5] - <--2--{"jsonrpc":"2.0","method":"window/showMessage","params":{"type":2,"message":"No hoogle db found. Check the README for instructions to generate one"}}
2018-06-02 19:50:00.528231778 [ThreadId 7] - file mapping state is: fromList [("/home/richard/Documents/stack/src/main/Main.hs",FileMapping {fmPath = "/tmp/ghc-mod8884/Main8883-0.hs", fmTemp = True})]
2018-06-02 19:50:00.528374417 [ThreadId 7] - ghcDispatcher: top of loop
2018-06-02 19:50:00.528433837 [ThreadId 7] - ghcDispatcher:got request with id: Nothing
2018-06-02 19:50:00.528486557 [ThreadId 7] - ghcDispatcher:Processing request as version matches
2018-06-02 19:50:00.662354732 [ThreadId 7] - ghcDispatcher: top of loop
2018-06-02 19:50:00.662481081 [ThreadId 7] - ghcDispatcher:got request with id: Nothing
2018-06-02 19:50:00.662512091 [ThreadId 7] - ghcDispatcher:Processing request as version matches
2018-06-02 19:50:00.66266988 [ThreadId 7] - setTypecheckedModule: file mapping state is: fromList [("/home/richard/Documents/stack/src/main/Main.hs",FileMapping {fmPath = "/tmp/ghc-mod8884/Main8883-0.hs", fmTemp = True})]
2018-06-02 19:50:00.987293572 [ThreadId 5] - <--2--{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/richard/Documents/stack/src/main/Main.hs","diagnostics":[]}}
2018-06-02 19:50:20.676509983 [ThreadId 4] - ---> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///home/richard/Documents/stack/src/Hackage/Security/Client/Repository/HttpLib/HttpClient.hs","languageId":"haskell","version":1,"text":"-- Explicitly disabling due to external code {-# LANGUAGE NoImplicitPrelude #-}\n{-# LANGUAGE FlexibleContexts #-}\n{-# LANGUAGE OverloadedStrings #-}\n{-# LANGUAGE RankNTypes #-}\n{-# LANGUAGE ScopedTypeVariables #-}\n-- Taken from\n-- https://github.com/well-typed/hackage-security/tree/master/hackage-security-http-client\n-- to avoid extra dependencies\nmodule Hackage.Security.Client.Repository.HttpLib.HttpClient (\n withClient\n , makeHttpLib\n -- ** Re-exports\n , Manager -- opaque\n ) where\n\nimport Control.Exception\nimport Control.Monad (void)\nimport Data.ByteString (ByteString)\nimport Network.URI\nimport Network.HTTP.Client (Manager)\nimport qualified Data.ByteString as BS\nimport qualified Data.ByteString.Char8 as BS.C8\nimport qualified Network.HTTP.Client as HttpClient\nimport qualified Network.HTTP.Client.Internal as HttpClient\nimport qualified Network.HTTP.StackClient as StackClient\nimport qualified Network.HTTP.Types as HttpClient\n\nimport Hackage.Security.Client hiding (Header)\nimport Hackage.Security.Client.Repository.HttpLib\nimport Hackage.Security.Util.Checked\nimport qualified Hackage.Security.Util.Lens as Lens\n\n{-------------------------------------------------------------------------------\n Top-level API\n-------------------------------------------------------------------------------}\n\n-- | Initialization\n--\n-- The proxy must be specified at initialization because @http-client@ does not\n-- allow to change the proxy once the 'Manager' is created.\nwithClient :: ProxyConfig HttpClient.Proxy -> (Manager -> HttpLib -> IO a) -> IO a\nwithClient proxyConfig callback = do\n manager <- HttpClient.newManager (setProxy HttpClient.defaultManagerSettings)\n callback manager $ makeHttpLib manager\n where\n setProxy = HttpClient.managerSetProxy $\n case proxyConfig of\n ProxyConfigNone -> HttpClient.noProxy\n ProxyConfigUse p -> HttpClient.useProxy p\n ProxyConfigAuto -> HttpClient.proxyEnvironment Nothing\n\n-- | Create an 'HttpLib' value from a preexisting 'Manager'.\nmakeHttpLib :: Manager -> HttpLib\nmakeHttpLib manager = HttpLib\n { httpGet = get manager\n , httpGetRange = getRange manager\n }\n\n{-------------------------------------------------------------------------------\n Individual methods\n-------------------------------------------------------------------------------}\n\nget :: Throws SomeRemoteError\n => Manager\n -> [HttpRequestHeader] -> URI\n -> ([HttpResponseHeader] -> BodyReader -> IO a)\n -> IO a\nget manager reqHeaders uri callback = wrapCustomEx $ do\n -- TODO: setUri fails under certain circumstances; in particular, when\n -- the URI contains URL auth. Not sure if this is a concern.\n request' <- HttpClient.setUri HttpClient.defaultRequest uri\n let request = setRequestHeaders reqHeaders request'\n checkHttpException $ StackClient.withResponseByManager request manager $ \\response -> do\n let br = wrapCustomEx $ HttpClient.responseBody response\n callback (getResponseHeaders response) br\n\ngetRange :: Throws SomeRemoteError\n => Manager\n -> [HttpRequestHeader] -> URI -> (Int, Int)\n -> (HttpStatus -> [HttpResponseHeader] -> BodyReader -> IO a)\n -> IO a\ngetRange manager reqHeaders uri (from, to) callback = wrapCustomEx $ do\n request' <- HttpClient.setUri HttpClient.defaultRequest uri\n let request = setRange from to\n $ setRequestHeaders reqHeaders request'\n checkHttpException $ StackClient.withResponseByManager request manager $ \\response -> do\n let br = wrapCustomEx $ HttpClient.responseBody response\n case () of\n () | HttpClient.responseStatus response == HttpClient.partialContent206 ->\n callback HttpStatus206PartialContent (getResponseHeaders response) br\n () | HttpClient.responseStatus response == HttpClient.ok200 ->\n callback HttpStatus200OK (getResponseHeaders response) br\n _otherwise ->\n throwChecked $ HttpClient.HttpExceptionRequest request\n $ HttpClient.StatusCodeException (void response) \"\"\n\n-- | Wrap custom exceptions\n--\n-- NOTE: The only other exception defined in @http-client@ is @TimeoutTriggered@\n-- but it is currently disabled <https://github.com/snoyberg/http-client/issues/116>\nwrapCustomEx :: (Throws HttpClient.HttpException => IO a)\n -> (Throws SomeRemoteError => IO a)\nwrapCustomEx act = handleChecked (\\(ex :: HttpClient.HttpException) -> go ex) act\n where\n go ex = throwChecked (SomeRemoteError ex)\n\ncheckHttpException :: Throws HttpClient.HttpException => IO a -> IO a\ncheckHttpException = handle $ \\(ex :: HttpClient.HttpException) ->\n throwChecked ex\n\n{-------------------------------------------------------------------------------\n http-client auxiliary\n-------------------------------------------------------------------------------}\n\nhAcceptRanges :: HttpClient.HeaderName\nhAcceptRanges = \"Accept-Ranges\"\n\nhAcceptEncoding :: HttpClient.HeaderName\nhAcceptEncoding = \"Accept-Encoding\"\n\nsetRange :: Int -> Int\n -> HttpClient.Request -> HttpClient.Request\nsetRange from to req = req {\n HttpClient.requestHeaders = (HttpClient.hRange, rangeHeader)\n : HttpClient.requestHeaders req\n }\n where\n -- Content-Range header uses inclusive rather than exclusive bounds\n -- See <http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html>\n rangeHeader = BS.C8.pack $ \"bytes=\" ++ show from ++ \"-\" ++ show (to - 1)\n\n-- | Set request headers\nsetRequestHeaders :: [HttpRequestHeader]\n -> HttpClient.Request -> HttpClient.Request\nsetRequestHeaders opts req = req {\n HttpClient.requestHeaders = trOpt disallowCompressionByDefault opts\n }\n where\n trOpt :: [(HttpClient.HeaderName, [ByteString])]\n -> [HttpRequestHeader]\n -> [HttpClient.Header]\n trOpt acc [] =\n concatMap finalizeHeader acc\n trOpt acc (HttpRequestMaxAge0:os) =\n trOpt (insert HttpClient.hCacheControl [\"max-age=0\"] acc) os\n trOpt acc (HttpRequestNoTransform:os) =\n trOpt (insert HttpClient.hCacheControl [\"no-transform\"] acc) os\n\n -- disable content compression (potential security issue)\n disallowCompressionByDefault :: [(HttpClient.HeaderName, [ByteString])]\n disallowCompressionByDefault = [(hAcceptEncoding, [])]\n\n -- Some headers are comma-separated, others need multiple headers for\n -- multiple options.\n --\n -- TODO: Right we we just comma-separate all of them.\n finalizeHeader :: (HttpClient.HeaderName, [ByteString])\n -> [HttpClient.Header]\n finalizeHeader (name, strs) = [(name, BS.intercalate \", \" (reverse strs))]\n\n insert :: Eq a => a -> [b] -> [(a, [b])] -> [(a, [b])]\n insert x y = Lens.modify (Lens.lookupM x) (++ y)\n\n-- | Extract the response headers\ngetResponseHeaders :: HttpClient.Response a -> [HttpResponseHeader]\ngetResponseHeaders response = concat [\n [ HttpResponseAcceptRangesBytes\n | (hAcceptRanges, \"bytes\") `elem` headers\n ]\n ]\n where\n headers = HttpClient.responseHeaders response\n"}}}
2018-06-02 19:50:20.677597908 [ThreadId 4] - ---> {"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///home/richard/Documents/stack/src/Hackage/Security/Client/Repository/HttpLib/HttpClient.hs"},"range":{"start":{"line":0,"character":0},"end":{"line":0,"character":0}},"context":{"diagnostics":[]}}}
2018-06-02 19:50:24.337185252 [ThreadId 4] - ---> {"jsonrpc":"2.0","id":3,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///home/richard/Documents/stack/src/Hackage/Security/Client/Repository/HttpLib/HttpClient.hs"},"position":{"line":102,"character":56}}}
2018-06-02 19:50:24.523109224 [ThreadId 4] - ---> {"jsonrpc":"2.0","method":"$/cancelRequest","params":{"id":3}}
2018-06-02 19:50:25.0730657 [ThreadId 4] - ---> {"jsonrpc":"2.0","id":4,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///home/richard/Documents/stack/src/Hackage/Security/Client/Repository/HttpLib/HttpClient.hs"},"position":{"line":104,"character":4}}}
2018-06-02 19:55:00.320550334 [ThreadId 4] - ---> {"jsonrpc":"2.0","method":"$/cancelRequest","params":{"id":4}}
2018-06-02 19:55:00.470685363 [ThreadId 4] - ---> {"jsonrpc":"2.0","id":5,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///home/richard/Documents/stack/src/Hackage/Security/Client/Repository/HttpLib/HttpClient.hs"},"position":{"line":104,"character":5}}}
2018-06-02 19:55:00.590026634 [ThreadId 4] - ---> {"jsonrpc":"2.0","method":"$/cancelRequest","params":{"id":5}}
2018-06-02 19:55:00.941534951 [ThreadId 4] - ---> {"jsonrpc":"2.0","id":6,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///home/richard/Documents/stack/src/Hackage/Security/Client/Repository/HttpLib/HttpClient.hs"},"position":{"line":100,"character":18}}}
2018-06-02 19:55:00.991975145 [ThreadId 4] - ---> {"jsonrpc":"2.0","method":"$/cancelRequest","params":{"id":6}}
2018-06-02 19:55:01.14102288 [ThreadId 4] - ---> {"jsonrpc":"2.0","id":7,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///home/richard/Documents/stack/src/Hackage/Security/Client/Repository/HttpLib/HttpClient.hs"},"position":{"line":96,"character":21}}}
2018-06-02 19:55:01.382658526 [ThreadId 4] - ---> {"jsonrpc":"2.0","method":"$/cancelRequest","params":{"id":7}}
2018-06-02 19:55:03.131107091 [ThreadId 4] - ---> {"jsonrpc":"2.0","id":8,"method":"shutdown","params":null}
2018-06-02 19:55:03.131367889 [ThreadId 5] - <--2--{"result":"ok","jsonrpc":"2.0","id":8}
2018-06-02 19:55:03.132232005 [ThreadId 4] - ---> {"jsonrpc":"2.0","method":"exit","params":null}
2018-06-02 19:55:03.132326094 [ThreadId 4] - haskell-lsp:Got exit, exiting
The request is sent at 19:50:25 (id 4) and then I canceled after about 5 minutes.
I'm not sure if this is related; but HIE just seems to randomly crash on a project that's about 170 modules large:
hie-8.4.4: Data.Text.Internal.Fusion.Common.index: Index too large
CallStack (from HasCallStack):
error, called at libraries/text/Data/Text/Internal/Fusion/Common.hs:943:24 in text-1.2.3.1:Data.Text.Internal.Fusion.Common
No requests to HIE work thereafter. All requests get timed out. So as I see this, there are 2 problems:
If there's anything else I can provide to help debug this, please let me know.
I'm posting this here since the issue could be related. However, I'm not sure. I wanted to refrain from creating another issue unless I was sure.
This is definitely a bug. Some runtime exception is crashing the thread. Please open a new issue, attaching the debug log if possible. Do you have a repeatable process to trigger this exception?
HIE does not seem to be able to handle large projects for some reason and there are also no errors or warnings as to indicate why this happens. All that happens is HIE gets a request and never responds. I can let the request sit forever and still nothing happens.
The following steps can be used to reproduce this:
NB: using make to build HIE for different GHC versions produces the same problem.
I let the request do it's thing and went on about my business, hoping that an error would pop up but after around 30 minutes I cancelled it. The log also showed that the request has been received by HIE and then manually cancellled by me.
The log:
Relevant snippet from the log:
I don't believe this is an issue with the vscode extension as I debugged that and it just never gets a response. It also does not matter which hs file in stack you use to test this (big or small), the result is the same. You can also create a new file with a few functions and test it, the result is the same.