Skip to content
This repository was archived by the owner on Oct 7, 2020. It is now read-only.

Commit 8582a96

Browse files
authored
Merge pull request #1126 from mpickering/hie-bios
Implement the HIE Bios
2 parents f7e0db0 + bfedd03 commit 8582a96

File tree

105 files changed

+3658
-2471
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+3658
-2471
lines changed

.azure/linux-stack.yml

-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ jobs:
6464
source .azure/linux.bashrc
6565
stack build --stack-yaml $(YAML_FILE) --test --bench --only-dependencies
6666
stack install --stack-yaml $(YAML_FILE) # `hie` binary required for tests
67-
stack --stack-yaml $(YAML_FILE) exec hoogle generate
6867
displayName: Build Test-dependencies
6968
- bash: |
7069
sudo apt update

.azure/macos-stack.yml

-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ jobs:
6060
source .azure/macos.bashrc
6161
stack build --stack-yaml $(YAML_FILE) --test --bench --only-dependencies
6262
stack install --stack-yaml $(YAML_FILE) # `hie` binary required for tests
63-
stack --stack-yaml $(YAML_FILE) exec hoogle generate
6463
displayName: Build Test-dependencies
6564
- bash: |
6665
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

.azure/windows-stack.yml

-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ jobs:
6262
source .azure/windows.bashrc
6363
stack build --stack-yaml $(YAML_FILE) --test --bench --only-dependencies
6464
stack install --stack-yaml $(YAML_FILE) # `hie` binary required for tests
65-
stack exec --stack-yaml $(YAML_FILE) hoogle generate
6665
displayName: Build Test-dependencies
6766
- bash: |
6867
# TODO: try to install automatically (`choco install z3` fails and pacman is not installed)

.circleci/config.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ defaults: &defaults
2626
- stack-cache-{{ .Environment.HIE_CACHE }}-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "stack-build.txt" }}
2727
- stack-cache-{{ .Environment.HIE_CACHE }}-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "resolver.txt" }}
2828

29-
# - run:
30-
# name: Stack upgrade
31-
# command: stack upgrade
29+
- run:
30+
name: Stack upgrade
31+
command: stack upgrade
3232

3333
- run:
3434
name: Stack setup

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,6 @@ _build/
7474
# stack 2.1 stack.yaml lock files
7575
stack*.yaml.lock
7676
shake.yaml.lock
77+
78+
# ignore hie.yaml's for testdata
79+
test/**/*.yaml

.gitmodules

+3-11
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,12 @@
1010
# rm -rf path_to_submodule
1111

1212

13-
[submodule "submodules/HaRe"]
14-
path = submodules/HaRe
15-
# url = https://github.com/bubba/HaRe.git
16-
url = https://github.com/alanz/HaRe.git
17-
1813
[submodule "submodules/cabal-helper"]
1914
path = submodules/cabal-helper
20-
# url = https://github.com/arbor/cabal-helper.git
21-
url = https://github.com/alanz/cabal-helper.git
2215
# url = https://github.com/DanielG/cabal-helper.git
16+
# Change this back once https://github.com/DanielG/cabal-helper/pull/85/ merged
17+
url = https://github.com/bubba/cabal-helper.git
2318

2419
[submodule "submodules/ghc-mod"]
2520
path = submodules/ghc-mod
26-
# url = https://github.com/arbor/ghc-mod.git
27-
# url = https://github.com/bubba/ghc-mod.git
28-
url = https://github.com/alanz/ghc-mod.git
29-
21+
url = https://github.com/fendor/ghc-mod.git

README.md

+195-18
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,19 @@ we talk to clients.__
3030
- [Windows-specific pre-requirements](#windows-specific-pre-requirements)
3131
- [Download the source code](#download-the-source-code)
3232
- [Building](#building)
33+
- [Install via cabal](#install-via-cabal)
34+
- [Install cabal using stack](#install-cabal-using-stack)
3335
- [Install specific GHC Version](#install-specific-ghc-version)
3436
- [Multiple versions of HIE (optional)](#multiple-versions-of-hie-optional)
3537
- [Configuration](#configuration)
38+
- [Project Configuration](#project-configuration)
3639
- [Editor Integration](#editor-integration)
3740
- [Using HIE with VS Code](#using-hie-with-vs-code)
3841
- [Using VS Code with Nix](#using-vs-code-with-nix)
3942
- [Using HIE with Sublime Text](#using-hie-with-sublime-text)
4043
- [Using HIE with Vim or Neovim](#using-hie-with-vim-or-neovim)
41-
- [Coc](#Coc)
42-
- [LanguageClient-neovim](#LanguageClient-neovim)
44+
- [Coc](#coc)
45+
- [LanguageClient-neovim](#languageclient-neovim)
4346
- [vim-plug](#vim-plug)
4447
- [Clone the LanguageClient-neovim repo](#clone-the-languageclient-neovim-repo)
4548
- [Sample `~/.vimrc`](#sample-vimrc)
@@ -66,6 +69,8 @@ we talk to clients.__
6669
- [Otherwise](#otherwise)
6770
- [Nix: cabal-helper, No such file or directory](#nix-cabal-helper-no-such-file-or-directory)
6871
- [Liquid Haskell](#liquid-haskell)
72+
- [Profiling `haskell-ide-engine`.](#profiling-haskell-ide-engine)
73+
- [Using `ghc-events-analyze`](#using-ghc-events-analyze)
6974

7075
## Features
7176

@@ -104,7 +109,7 @@ we talk to clients.__
104109

105110
![Formatting](https://i.imgur.com/cqZZ8HC.gif)
106111

107-
- Renaming via HaRe
112+
- Renaming via HaRe (NOTE: HaRe is temporarily disabled)
108113

109114
![Renaming](https://i.imgur.com/z03G2a5.gif)
110115

@@ -228,17 +233,16 @@ stack ./install.hs stack-install-cabal
228233

229234
##### Install specific GHC Version
230235

231-
Install **Nightly** (and hoogle docs):
236+
Install hie for the latest available and supported GHC version (and hoogle docs):
232237

233238
```bash
234-
stack ./install.hs hie-8.6.4
235-
stack ./install.hs build-data
239+
stack ./install.hs build
236240
```
237241

238-
Install **LTS** (and hoogle docs):
242+
Install hie for a specific GHC version (and hoogle docs):
239243

240244
```bash
241-
stack ./install.hs hie-8.4.4
245+
stack ./install.hs hie-8.6.5
242246
stack ./install.hs build-data
243247
```
244248

@@ -303,6 +307,154 @@ There are some settings that can be configured via a `settings.json` file:
303307
- VS Code: These settings will show up in the settings window
304308
- LanguageClient-neovim: Create this file in `$projectdir/.vim/settings.json` or set `g:LanguageClient_settingsPath`
305309

310+
## Project Configuration
311+
312+
**For a full explanation of possible configurations, refer to [hie-bios/README](https://github.com/mpickering/hie-bios/blob/master/README.md).**
313+
314+
HIE will attempt to automatically detect your project configuration and set up
315+
the environment for GHC.
316+
317+
| `cabal.project` | `stack.yaml` | `*.cabal` | Project selected |
318+
|-----------------|--------------|-----------|------------------|
319+
|| - | - | Cabal v2 |
320+
||| - | Stack |
321+
|||| Cabal (v2 or v1) |
322+
|||| None |
323+
324+
However, you can also place a `hie.yaml` file in the root of the workspace to
325+
**explicitly** describe how to setup the environment. For example, to state that
326+
you want to use `stack` then the configuration file would look like:
327+
328+
```yaml
329+
cradle:
330+
stack:
331+
component: "haskell-ide-engine:lib"
332+
```
333+
334+
If you use `cabal` then you probably need to specify which component you want
335+
to use.
336+
337+
```yaml
338+
cradle:
339+
cabal:
340+
component: "lib:haskell-ide-engine"
341+
```
342+
343+
If you have a project with multiple components, you can use a cabal-multi
344+
cradle:
345+
346+
```yaml
347+
cradle:
348+
cabal:
349+
- path: "./test/dispatcher/"
350+
component: "test:dispatcher-test"
351+
- path: "./test/functional/"
352+
component: "test:func-test"
353+
- path: "./test/unit/"
354+
component: "test:unit-test"
355+
- path: "./hie-plugin-api/"
356+
component: "lib:hie-plugin-api"
357+
- path: "./app/MainHie.hs"
358+
component: "exe:hie"
359+
- path: "./app/HieWrapper.hs"
360+
component: "exe:hie-wrapper"
361+
- path: "./"
362+
component: "lib:haskell-ide-engine"
363+
```
364+
365+
Equivalently, you can use stack:
366+
367+
```yaml
368+
cradle:
369+
stack:
370+
- path: "./test/dispatcher/"
371+
component: "haskell-ide-engine:test:dispatcher-test"
372+
- path: "./test/functional/"
373+
component: "haskell-ide-engine:test:func-test"
374+
- path: "./test/unit/"
375+
component: "haskell-ide-engine:test:unit-test"
376+
- path: "./hie-plugin-api/"
377+
component: "hie-plugin-api:lib"
378+
- path: "./app/MainHie.hs"
379+
component: "haskell-ide-engine:exe:hie"
380+
- path: "./app/HieWrapper.hs"
381+
component: "haskell-ide-engine:exe:hie-wrapper"
382+
- path: "./"
383+
component: "haskell-ide-engine:lib"
384+
```
385+
386+
Or you can explicitly state the program which should be used to collect
387+
the options by supplying the path to the program. It is interpreted
388+
relative to the current working directory if it is not an absolute path.
389+
390+
```yaml
391+
cradle:
392+
bios:
393+
program: ".hie-bios"
394+
```
395+
396+
The complete configuration is a subset of
397+
398+
```yaml
399+
cradle:
400+
cabal:
401+
component: "optional component name"
402+
stack:
403+
component: "optional component name"
404+
bios:
405+
program: "program to run"
406+
dependency-program: "optional program to run"
407+
direct:
408+
arguments: ["list","of","ghc","arguments"]
409+
default:
410+
none:
411+
412+
dependencies:
413+
- someDep
414+
```
415+
416+
There is also support for multiple cradles in a single `hie.yaml`. An example configuration for Haskell IDE Engine:
417+
418+
```yaml
419+
cradle:
420+
multi:
421+
- path: ./test/dispatcher/
422+
config:
423+
cradle:
424+
cabal:
425+
component: "test:dispatcher-test"
426+
- path: ./test/functional/
427+
config:
428+
cradle:
429+
cabal:
430+
component: "test:func-test"
431+
- path: ./test/unit/
432+
config:
433+
cradle:
434+
cabal:
435+
component: "test:unit-test"
436+
- path: ./hie-plugin-api/
437+
config:
438+
cradle:
439+
cabal:
440+
component: "lib:hie-plugin-api"
441+
- path: ./app/MainHie.hs
442+
config:
443+
cradle:
444+
cabal:
445+
component: "exe:hie"
446+
- path: ./app/HieWrapper.hs
447+
config:
448+
cradle:
449+
cabal:
450+
component: "exe:hie-wrapper"
451+
- path: ./
452+
config:
453+
cradle:
454+
cabal:
455+
component: "lib:haskell-ide-engine"
456+
```
457+
306458
## Editor Integration
307459

308460
Note to editor integrators: there is now a `hie-wrapper` executable, which is installed alongside the `hie` executable. When this is invoked in the project root directory, it attempts to work out the GHC version used in the project, and then launch the matching `hie` executable.
@@ -545,10 +697,10 @@ Or you can set the environment variable `HIE_HOOGLE_DATABASE` to specify a speci
545697
### Planned Features
546698

547699
- [x] Multiproject support
700+
- [x] New-build support
548701
- [ ] Project wide references
549702
- [ ] Cross project find definition
550-
- [ ] New-build support
551-
- [ ] HaRe refactorings
703+
- [ ] More HaRe refactorings
552704
- [ ] More code actions
553705
- [ ] Cross project/dependency Find Definition
554706
- [ ] Case splitting, type insertion etc.
@@ -644,18 +796,43 @@ Delete any `.ghc.environment*` files in your project root and try again. (At the
644796
#### Otherwise
645797
Try running `cabal update`.
646798

647-
### Nix: cabal-helper, No such file or directory
799+
### Liquid Haskell
800+
801+
Liquid Haskell requires an SMT solver on the path. We do not take care of installing one, thus, Liquid Haskell will not run until one is installed.
802+
The recommended SMT solver is [z3](https://github.com/Z3Prover/z3). To run the tests, it is also required to have an SMT solver on the path, otherwise the tests will fail for Liquid Haskell.
803+
804+
### Profiling `haskell-ide-engine`.
648805

649-
An error on stderr like
806+
If you think `haskell-ide-engine` is using a lot of memory then the most useful
807+
thing you can do is prepare a profile of the memory usage whilst you're using
808+
the program.
809+
810+
1. Add `profiling: True` to the cabal.project file of `haskell-ide-engine`
811+
2. `cabal new-build hie`
812+
3. (IMPORTANT) Add `profiling: True` to the `cabal.project` file of the project you want to profile.
813+
4. Make a wrapper script which calls the `hie` you built in step 2 with the additional options `+RTS -hd -l-au`
814+
5. Modify your editor settings to call this wrapper script instead of looking for `hie` on the path
815+
6. Try using `h-i-e` as normal and then process the `*.eventlog` which will be created using [`eventlog2html`](http://hackage.haskell.org/package/eventlog2html).
816+
7. Repeat the process again using different profiling options if you like.
817+
818+
#### Using `ghc-events-analyze`
819+
820+
`haskell-ide-engine` contains the necessary tracing functions to work with [`ghc-events-analyze`](http://www.well-typed.com/blog/2014/02/ghc-events-analyze/). Each
821+
request which is made will emit an event to the eventlog when it starts and finishes. This way you
822+
can see if there are any requests which are taking a long time to complete or are blocking.
823+
824+
1. Make sure that `hie` is linked with the `-eventlog` option. This can be achieved by adding the flag
825+
to the `ghc-options` field in the cabal file.
826+
2. Run `hie` as normal but with the addition of `+RTS -l`. This will produce an eventlog called `hie.eventlog`.
827+
3. Run `ghc-events-analyze` on the `hie.eventlog` file to produce the rendered SVG. Warning, this might take a while and produce a big SVG file.
828+
829+
The default options for `ghc-events-analyze` will produce quite a wide chart which is difficult to view. You can try using less buckets in order
830+
to make the chart quicker to generate and faster to render.
650831

651832
```
652-
cabal-helper-wrapper: /home/<...>/.cache/cabal-helper/cabal-helper<...>: createProcess: runInteractiveProcess:
653-
exec: does not exist (No such file or directory)
833+
ghc-events-analyze hie.eventlog -b 100
654834
```
655835

656-
can happen because cabal-helper compiles and runs above executable at runtime without using nix-build, which means a Nix garbage collection can delete the paths it depends on. Delete ~/.cache/cabal-helper and restart HIE to fix this.
836+
This support is similar to the logging capabilities [built into GHC](https://www.haskell.org/ghc/blog/20190924-eventful-ghc.html).
657837

658-
### Liquid Haskell
659838

660-
Liquid Haskell requires an SMT solver on the path. We do not take care of installing one, thus, Liquid Haskell will not run until one is installed.
661-
The recommended SMT solver is [z3](https://github.com/Z3Prover/z3). To run the tests, it is also required to have an SMT solver on the path, otherwise the tests will fail for Liquid Haskell.

app/HieWrapper.hs

+7-9
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ import Data.Semigroup
99
import Data.List
1010
import Data.Foldable
1111
import Data.Version (showVersion)
12-
import qualified GhcMod.Monad as GM
13-
import qualified GhcMod.Monad.Types as GM
14-
import qualified GhcMod.Types as GM
12+
import HIE.Bios
1513
import Haskell.Ide.Engine.MonadFunctions
14+
import Haskell.Ide.Engine.Cradle (findLocalCradle)
1615
import Haskell.Ide.Engine.Options
1716
import Haskell.Ide.Engine.Plugin.Base
1817
import qualified Language.Haskell.LSP.Core as Core
@@ -23,6 +22,7 @@ import System.Environment
2322
import qualified System.Log.Logger as L
2423
import System.Process
2524
import System.Info
25+
import System.FilePath
2626

2727
-- ---------------------------------------------------------------------
2828

@@ -73,15 +73,13 @@ run opts = do
7373
logm $ "Current directory:" ++ d
7474
logm $ "Operating system:" ++ os
7575

76-
-- Get the cabal directory from the ghc-mod cradle
77-
(mcr,_) <- GM.runGhcModT GM.defaultOptions GM.cradle
78-
dir <- case mcr of
79-
Left err -> error (show err)
80-
Right cr -> return $ GM.cradleRootDir cr
76+
-- Get the cabal directory from the cradle
77+
cradle <- findLocalCradle (d </> "File.hs")
78+
let dir = cradleRootDir cradle
8179
logm $ "Cradle directory:" ++ dir
8280
setCurrentDirectory dir
8381

84-
ghcVersion <- getProjectGhcVersion
82+
ghcVersion <- getProjectGhcVersion cradle
8583
logm $ "Project GHC version:" ++ ghcVersion
8684

8785
let

0 commit comments

Comments
 (0)