Skip to content

Commit 2a38710

Browse files
committed
docs(ghcide): move most of the README in hls documentation (#3639)
1 parent c5a1093 commit 2a38710

File tree

4 files changed

+338
-304
lines changed

4 files changed

+338
-304
lines changed

docs/components/ghcide.md

Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
# `ghcide`
2+
3+
[`ghcide`](https://hackage.haskell.org/package/ghcide) is a library for building Haskell IDE tooling.
4+
5+
Our vision is that you should build an IDE by combining:
6+
7+
![vscode](https://raw.githubusercontent.com/haskell/ghcide/master/img/vscode2.png)
8+
9+
* [`hie-bios`](https://github.com/mpickering/hie-bios) for determining where your files are, what are their dependencies, what extensions are enabled and so on;
10+
* `ghcide` (i.e. this library) for defining how to type check, when to type check, and producing diagnostic messages;
11+
* A bunch of plugins that haven't yet been written, e.g. [`hie-hlint`](https://github.com/ndmitchell/hlint) and [`hie-ormolu`](https://github.com/tweag/ormolu), to choose which features you want;
12+
* [`haskell-lsp`](https://github.com/alanz/haskell-lsp) for sending those messages to a [Language Server Protocol (LSP)](https://microsoft.github.io/language-server-protocol/) server;
13+
* An LSP client for your editor.
14+
15+
There are more details about our approach [in this blog post](https://4ta.uk/p/shaking-up-the-ide).
16+
17+
## Limitations to Multi-Component support
18+
19+
`ghcide` supports loading multiple components into the same session so that
20+
features such as go-to definition work across components. However, there are
21+
some limitations to this.
22+
23+
1. You will get much better results currently manually specifying the hie.yaml file.
24+
Until tools like cabal and stack provide the right interface to support multi-component
25+
projects, it is always advised to specify explicitly how your project partitions.
26+
2. Cross-component features only work if you have loaded at least one file
27+
from each component.
28+
3. There is a known issue where if you have three components, such that A depends on B which depends on C
29+
then if you load A and C into the session but not B then under certain situations you
30+
can get strange errors about a type coming from two different places. See [this repo](https://github.com/fendor/ghcide-bad-interface-files) for
31+
a simple reproduction of the bug.
32+
33+
## Using it
34+
35+
`ghcide` is not an end-user tool, [don't use `ghcide`](https://neilmitchell.blogspot.com/2020/09/dont-use-ghcide-anymore-directly.html) directly (more about the rationale [here](https://github.com/haskell/ghcide/pull/939)).
36+
37+
[`haskell-language-server`](http://github.com/haskell/haskell-language-server) is an LSP server built on top of `ghcide` with additional features and a user friendly deployment model. To get it, simply install the [Haskell extension](https://marketplace.visualstudio.com/items?itemName=haskell.haskell) in VS Code, or download prebuilt binaries from the [haskell-language-server](https://github.com/haskell/haskell-language-server) project page.
38+
39+
40+
The instructions below are meant for developers interested in setting up ghcide as an LSP server for testing purposes.
41+
42+
### Install `ghcide`
43+
44+
#### With Nix
45+
46+
Note that you need to compile `ghcide` with the same `ghc` as the project you are working on.
47+
48+
1. If the `ghc` you are using matches the version (or better is) from `nixpkgs` it‘s easiest to use the `ghcide` from `nixpkgs`. You can do so via
49+
```
50+
nix-env -iA haskellPackages.ghcide
51+
```
52+
or e.g. including `pkgs.haskellPackages.ghcide` in your projects `shell.nix`.
53+
Depending on your `nixpkgs` channel that might not be the newest `ghcide`, though.
54+
55+
2. If your `ghc` does not match nixpkgs you should try the [ghcide-nix repository](https://github.com/cachix/ghcide-nix)
56+
which provides a `ghcide` via the `haskell.nix` infrastructure.
57+
58+
#### With Cabal or Stack
59+
60+
First install the `ghcide` binary using `stack` or `cabal`, e.g.
61+
62+
1. `git clone https://github.com/haskell/ghcide.git`
63+
2. `cd ghcide`
64+
3. `cabal install` or `stack install` (and make sure `~/.local/bin` is on your `$PATH`)
65+
66+
It's important that `ghcide` is compiled with the same compiler you use to build your projects.
67+
68+
### Test `ghcide`
69+
70+
Next, check that `ghcide` is capable of loading your code. Change to the project directory and run `ghcide`, which will try and load everything using the same code as the IDE, but in a way that's much easier to understand. For example, taking the example of [`shake`](https://github.com/ndmitchell/shake), running `ghcide` gives some error messages and warnings before reporting at the end:
71+
72+
```console
73+
Files that failed:
74+
* .\model\Main.hs
75+
* .\model\Model.hs
76+
* .\model\Test.hs
77+
* .\model\Util.hs
78+
* .\output\docs\Main.hs
79+
* .\output\docs\Part_Architecture_md.hs
80+
Completed (152 worked, 6 failed)
81+
```
82+
83+
Of the 158 files in Shake, as of this moment, 152 can be loaded by the IDE, but 6 can't (error messages for the reasons they can't be loaded are given earlier). The failing files are all prototype work or test output, meaning I can confidently use Shake.
84+
85+
The `ghcide` executable mostly relies on [`hie-bios`](https://github.com/mpickering/hie-bios) to do the difficult work of setting up your GHC environment. If it doesn't work, see [the `hie-bios` manual](https://github.com/mpickering/hie-bios#readme) to get it working. My default fallback is to figure it out by hand and create a `direct` style [`hie.yaml`](https://github.com/ndmitchell/shake/blob/master/hie.yaml) listing the command line arguments to load the project.
86+
87+
If you can't get `ghcide` working outside the editor, see [this setup troubleshooting guide](https://github.com/haskell/haskell-language-server/tree/master/ghcide/docs/Setup.md). Once you have got `ghcide` working outside the editor, the next step is to pick which editor to integrate with.
88+
89+
### Optimal project setup
90+
91+
`ghcide` has been designed to handle projects with hundreds or thousands of modules. If `ghci` can handle it, then `ghcide` should be able to handle it. The only caveat is that this currently requires GHC >= 8.8, and that the first time a module is loaded in the editor will trigger generation of support files in the background if those do not already exist.
92+
93+
### Using with VS Code
94+
95+
The [Haskell](https://marketplace.visualstudio.com/items?itemName=haskell.haskell) extension has a setting for ghcide.
96+
97+
### Using with Atom
98+
99+
You can follow the [instructions](https://github.com/moodmosaic/ide-haskell-ghcide#readme) to install with `apm`.
100+
101+
### Using with Sublime Text
102+
103+
* Install [LSP](https://packagecontrol.io/packages/LSP)
104+
* Press Ctrl+Shift+P or Cmd+Shift+P in Sublime Text and search for *Preferences: LSP Settings*, then paste these settings
105+
```
106+
{
107+
"clients":
108+
{
109+
"ghcide":
110+
{
111+
"enabled" : true,
112+
"languageId": "haskell",
113+
"command" : ["ghcide", "--lsp"],
114+
"scopes" : ["source.haskell"],
115+
"syntaxes" : ["Packages/Haskell/Haskell.sublime-syntax"]
116+
}
117+
}
118+
}
119+
```
120+
121+
### Using with Emacs
122+
123+
If you don't already have [MELPA](https://melpa.org/#/) package installation configured, visit MELPA [getting started](https://melpa.org/#/getting-started) page to get set up. Then, install [`use-package`](https://melpa.org/#/use-package).
124+
125+
Now you have a choice of two different Emacs packages which can be used to communicate with the `ghcide` LSP server:
126+
127+
+ `lsp-ui`
128+
+ `eglot` (requires Emacs 26.1+)
129+
130+
In each case, you can enable support by adding the shown lines to your `.emacs`:
131+
132+
#### lsp-ui
133+
134+
```elisp
135+
;; LSP
136+
(use-package flycheck
137+
:ensure t
138+
:init
139+
(global-flycheck-mode t))
140+
(use-package yasnippet
141+
:ensure t)
142+
(use-package lsp-mode
143+
:ensure t
144+
:hook (haskell-mode . lsp)
145+
:commands lsp)
146+
(use-package lsp-ui
147+
:ensure t
148+
:commands lsp-ui-mode)
149+
(use-package lsp-haskell
150+
:ensure t
151+
:config
152+
(setq lsp-haskell-process-path-hie "ghcide")
153+
(setq lsp-haskell-process-args-hie '())
154+
;; Comment/uncomment this line to see interactions between lsp client/server.
155+
;;(setq lsp-log-io t)
156+
)
157+
```
158+
159+
#### eglot
160+
161+
````elisp
162+
(use-package eglot
163+
:ensure t
164+
:config
165+
(add-to-list 'eglot-server-programs '(haskell-mode . ("ghcide" "--lsp"))))
166+
````
167+
168+
### Using with Vim/Neovim
169+
170+
#### `LanguageClient-neovim`
171+
Install [LanguageClient-neovim](https://github.com/autozimu/LanguageClient-neovim)
172+
173+
Add this to your vim config:
174+
```vim
175+
let g:LanguageClient_rootMarkers = ['*.cabal', 'stack.yaml']
176+
let g:LanguageClient_serverCommands = {
177+
\ 'rust': ['rls'],
178+
\ 'haskell': ['ghcide', '--lsp'],
179+
\ }
180+
```
181+
182+
Refer to `:he LanguageClient` for more details on usage and configuration.
183+
184+
#### `vim-lsp`
185+
Install [vim-lsp](https://github.com/prabirshrestha/vim-lsp).
186+
187+
Add this to your vim config:
188+
189+
```vim
190+
au User lsp_setup call lsp#register_server({
191+
\ 'name': 'ghcide',
192+
\ 'cmd': {server_info->['/your/path/to/ghcide', '--lsp']},
193+
\ 'whitelist': ['haskell'],
194+
\ })
195+
```
196+
197+
To verify it works move your cursor over a symbol and run `:LspHover`.
198+
199+
### `coc.nvim`
200+
201+
Install [coc.nvim](https://github.com/neoclide/coc.nvim)
202+
203+
Add this to your coc-settings.json (which you can edit with :CocConfig):
204+
205+
```json
206+
{
207+
"languageserver": {
208+
"haskell": {
209+
"command": "ghcide",
210+
"args": [
211+
"--lsp"
212+
],
213+
"rootPatterns": [
214+
".stack.yaml",
215+
".hie-bios",
216+
"BUILD.bazel",
217+
"cabal.config",
218+
"package.yaml"
219+
],
220+
"filetypes": [
221+
"hs",
222+
"lhs",
223+
"haskell"
224+
]
225+
}
226+
}
227+
}
228+
```
229+
230+
Here's a nice article on setting up neovim and coc: [Vim and Haskell in
231+
2019](http://marco-lopes.com/articles/Vim-and-Haskell-in-2019/) (this is actually for haskell-ide, not ghcide)
232+
233+
Here is a Docker container that pins down the build and configuration for
234+
Neovim and ghcide on a minimal Debian 10 base system:
235+
[docker-ghcide-neovim](https://github.com/carlohamalainen/docker-ghcide-neovim/).
236+
237+
### SpaceVim
238+
239+
In the `autocomplete` layer, add the `autocomplete_method` option to force the use of `coc`:
240+
241+
```toml
242+
[[layers]]
243+
name = 'autocomplete'
244+
auto-completion-return-key-behavior = "complete"
245+
auto-completion-tab-key-behavior = "smart"
246+
[options]
247+
autocomplete_method = "coc"
248+
```
249+
250+
Add this to your coc-settings.json (which you can edit with :CocConfig):
251+
252+
```json
253+
{
254+
"languageserver": {
255+
"haskell": {
256+
"command": "ghcide",
257+
"args": [
258+
"--lsp"
259+
],
260+
"rootPatterns": [
261+
".stack.yaml",
262+
".hie-bios",
263+
"BUILD.bazel",
264+
"cabal.config",
265+
"package.yaml"
266+
],
267+
"filetypes": [
268+
"hs",
269+
"lhs",
270+
"haskell"
271+
]
272+
}
273+
}
274+
}
275+
```
276+
277+
This example above describes a setup in which `ghcide` is installed
278+
using `stack install ghcide` within a project.
279+
280+
### Using with Kakoune
281+
282+
Install [kak-lsp](https://github.com/ul/kak-lsp).
283+
284+
Change `kak-lsp.toml` to include this:
285+
286+
```toml
287+
[language.haskell]
288+
filetypes = ["haskell"]
289+
roots = ["Setup.hs", "stack.yaml", "*.cabal", "cabal.project", "hie.yaml"]
290+
command = "ghcide"
291+
args = ["--lsp"]
292+
```
293+
294+
## Hacking on ghcide
295+
296+
To build and work on `ghcide` itself, you should use cabal, e.g.,
297+
running `cabal test` will execute the test suite. You can use `stack test` too, but
298+
note that some tests will fail, and none of the maintainers are currently using `stack`.
299+
300+
If you are using Nix, there is a Cachix nix-shell cache for all the supported platforms: `cachix use haskell-ghcide`.
301+
302+
If you are using Windows, you should disable the `auto.crlf` setting and configure your editor to use LF line endings, directly or making it use the existing `.editor-config`.
303+
304+
If you are chasing down test failures, you can use the tasty-rerun feature by running tests as
305+
306+
cabal test --test-options"--rerun"
307+
308+
This writes a log file called `.tasty-rerun-log` of the failures, and only runs those.
309+
See the [tasty-rerun](https://hackage.haskell.org/package/tasty-rerun-1.1.17/docs/Test-Tasty-Ingredients-Rerun.html) documentation for other options.
310+
311+
If you are touching performance sensitive code, take the time to run a differential
312+
benchmark between HEAD and master using the benchHist script. This assumes that
313+
"master" points to the upstream master.
314+
315+
Run the benchmarks with `cabal bench`.
316+
317+
It should take around 15 minutes and the results will be stored in the `bench-results` folder. To interpret the results, see the comments in the `bench/hist/Main.hs` module.
318+
319+
More details in [bench/README](https://github.com/haskell/haskell-language-server/tree/master/ghcide/bench/README.md)
320+
321+
322+
## History and relationship to other Haskell IDE's
323+
324+
The teams behind this project and the [`haskell-ide-engine`](https://github.com/haskell/haskell-ide-engine#readme) have agreed to join forces under the [`haskell-language-server` project](https://github.com/haskell/haskell-language-server), see the [original announcement](https://neilmitchell.blogspot.com/2020/01/one-haskell-ide-to-rule-them-all.html). The technical work is ongoing, with the likely model being that this project serves as the core, while plugins and integrations are kept in the [`haskell-language-server` project](https://github.com/haskell/haskell-language-server).
325+
326+
The code behind `ghcide` was originally developed by [Digital Asset](https://digitalasset.com/) as part of the [DAML programming language](https://github.com/digital-asset/daml). DAML is a smart contract language targeting distributed-ledger runtimes, based on [GHC](https://www.haskell.org/ghc/) with custom language extensions. The DAML programming language has [an IDE](https://webide.daml.com/), and work was done to separate off a reusable Haskell-only IDE (what is now `ghcide`) which the [DAML IDE then builds upon](https://github.com/digital-asset/daml/tree/master/compiler/damlc). Since that time, there have been various [non-Digital Asset contributors](https://github.com/haskell/ghcide/graphs/contributors), in addition to continued investment by Digital Asset. The project has been handed over to Haskell.org as of September 2020.
327+
328+
The Haskell community [has](https://github.com/DanielG/ghc-mod) [various](https://github.com/chrisdone/intero) [IDE](https://github.com/rikvdkleij/intellij-haskell) [choices](http://leksah.org/), but the one that had been gathering momentum is [`haskell-ide-engine`](https://github.com/haskell/haskell-ide-engine#readme). Our project owes a debt of gratitude to the `haskell-ide-engine`. We reuse libraries from their ecosystem, including [`hie-bios`](https://github.com/mpickering/hie-bios#readme) (a likely future environment setup layer in `haskell-ide-engine`), [`haskell-lsp`](https://github.com/alanz/haskell-lsp#readme) and [`lsp-test`](https://github.com/bubba/lsp-test#readme) (the `haskell-ide-engine` [LSP protocol](https://microsoft.github.io/language-server-protocol/) pieces). We make heavy use of their contributions to GHC itself, in particular the work to make GHC take string buffers rather than files.
329+
330+
The best summary of the architecture of `ghcide` is available [this talk](https://www.youtube.com/watch?v=cijsaeWNf2E&list=PLxxF72uPfQVRdAsvj7THoys-nVj-oc4Ss) ([slides](https://ndmitchell.com/downloads/slides-making_a_haskell_ide-07_sep_2019.pdf)), given at [MuniHac 2019](https://munihac.de/2019.html). However, since that talk the project has renamed from `hie-core` to `ghcide`, and the repo has moved to [this location](https://github.com/haskell/ghcide/).

docs/components/index.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Components
2+
===========
3+
4+
.. toctree::
5+
:maxdepth: 2
6+
7+
ghcide

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ Official Haskell Language Server implementation. :ref:`Read more<What is the Has
1313
configuration
1414
troubleshooting
1515
contributing/index
16+
components/index

0 commit comments

Comments
 (0)