1# Contributing guidelines
2
3The Haskell tooling dream is near, we need your help!
4
5- Join [our IRC channel](https://web.libera.chat/?channels=#haskell-language-server) at `#haskell-language-server` on [`libera`](https://libera.chat/).
6- Follow the [Haskell IDE team twitter account](https://twitter.com/IdeHaskell) for updates and help.
7- Join the [#haskell-tooling channel](https://discord.com/channels/280033776820813825/505370075402862594/808027763868827659) in the Functional Programming discord server. You can join the server via [this invitation](https://discord.gg/9spEdTNGrD).
8
9## Building haskell-language-server
10
11The project can be built with both `cabal build` and `stack build`.
12
13haskell-language-server can also be used with itself. We provide preset samples of `hie.yaml` for Cabal and Stack.
14
15Note: the `./install/` folder is not directly tied to the project so it has dedicated `./install/hie.yaml.[cbl|stack]`
16templates.
17
18### Using Cabal
19
20```shell
21$ cp hie-cabal.yaml hie.yaml
22$ cp install/hie-cabal.yaml install/hie.yaml
23```
24
25### Using Stack
26
27```shell
28$ cp hie-stack.yaml hie.yaml
29$ cp install/hie-stack.yaml install/hie.yaml
30$ cp ghcide/hie-stack.yaml ghcide/hie.yaml
31$ stack build --test --no-run-tests
32$ cd install
33$ stack build
34```
35
36### Using Nix
37
38The instructions below show how to set up a Cachix binary cache and open a nix shell for local development.
39
40```shell
41$ cachix use haskell-language-server
42$ nix-shell
43$ cabal update
44$ cabal build
45```
46
47#### Flakes support
48
49If you are using nix 2.4 style command (enabled by `experimental-features = nix-command`),
50you can use `nix develop` instead of `nix-shell` to enter the development shell. To enter the shell with specific GHC versions:
51
52* `nix develop` or `nix develop .#haskell-language-server-dev` - default GHC version
53* `nix develop .#haskell-language-server-8104-dev` - GHC 8.10.4
54* `nix develop .#haskell-language-server-884-dev` - GHC 8.8.4
55* `nix develop .#haskell-language-server-901-dev` - GHC 9.0.1
56
57If you are looking for a Nix expression to create haskell-language-server binaries, see https://github.com/haskell/haskell-language-server/issues/122
58
59To create binaries:
60
61* `nix build` or `nix build .#haskell-language-server` - default GHC version
62* `nix build .#haskell-language-server-8104` - GHC 8.10.4
63* `nix build .#haskell-language-server-884` - GHC 8.8.4
64* `nix build .#haskell-language-server-901` - GHC 9.0.1
65
66GHC 8.6.5 is not supported here because `nixpkgs-unstable` no longer maintains the corresponding packages set.
67
68## Testing
69
70The tests make use of the [Tasty](https://github.com/feuerbach/tasty) test framework.
71
72There are two test suites in the main haskell-language-server package, functional tests, and wrapper tests.
73Other project packages, like the core library or plugins, can have their own test suite.
74
75### Testing with Cabal
76
77Running all the tests
78
79```bash
80$ cabal test
81```
82
83Running just the functional tests
84
85```bash
86$ cabal test func-test
87```
88
89Running just the wrapper tests
90
91```bash
92$ cabal test wrapper-test
93```
94
95Running a subset of tests
96
97Tasty supports providing
98[Patterns](https://github.com/feuerbach/tasty#patterns) as command
99line arguments, to select the specific tests to run.
100
101```bash
102$ cabal test func-test --test-option "-p hlint"
103```
104
105The above recompiles everything every time you use a different test option though.
106
107An alternative, which only recompiles when tests (or dependencies) change:
108
109```bash
110$ cabal run haskell-language-server:func-test -- -p "hlint enables"
111```
112
113### Test your hacked HLS in your editor
114
115If you want to test HLS while hacking on it, follow the steps below.
116
117To do once:
118
119- Open some codebase on which you want to test your hacked HLS in your favorite editor
120- Configure this editor to use your custom HLS executable
121  - With Cabal:
122    - On Unix systems: `cabal exec which haskell-language-server`
123    - On Windows: `cabal exec where haskell-language-server`
124  - With Stack: `$(stack path --dist-dir)/build/haskell-language-server/haskell-language-server`
125
126To do every time you changed code and want to test it:
127
128- Build HLS
129  - With Cabal: `cabal build exe:haskell-language-server`
130  - With Stack: `stack build haskell-language-server:exe:haskell-language-server`
131- Restart HLS
132  - With VS Code: `Haskell: Restart Haskell LSP Server`
133
134## Style guidelines
135
136The project includes a [`.editorconfig`](https://editorconfig.org) [file](https://github.com/haskell/haskell-language-server/blob/master/.editorconfig) with the editor basic settings used by the project.
137However, most editors will need some action to honour those settings automatically.
138For example vscode needs to have installed a specific [extension](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig).
139Please, try to follow those basic settings to keep the codebase as uniform as possible.
140
141### Formatter pre-commit hook
142
143We are using [pre-commit-hook.nix](https://github.com/cachix/pre-commit-hooks.nix) to configure git pre-commit hook for formatting. Although it is possible to run formatting manually, we recommend you to use it to set pre-commit hook as our CI checks pre-commit hook is applied or not.
144
145You can configure the pre-commit-hook by running
146
147``` bash
148nix-shell
149```
150
151If you don't want to use [nix](https://nixos.org/guides/install-nix.html), you can instead use [pre-commit](https://pre-commit.com) with the following config.
152
153```json
154{
155  "repos": [
156    {
157      "hooks": [
158        {
159          "entry": "stylish-haskell --inplace",
160          "exclude": "(^Setup.hs$|test/testdata/.*$|test/data/.*$|^hie-compat/.*$|^plugins/hls-tactics-plugin/.*$)",
161          "files": "\\.l?hs$",
162          "id": "stylish-haskell",
163          "language": "system",
164          "name": "stylish-haskell",
165          "pass_filenames": true,
166          "types": [
167            "file"
168          ]
169        }
170      ],
171      "repo": "local"
172    }
173  ]
174}
175```
176
177#### Why some components are excluded from automatic formatting?
178
179- `test/testdata` and `test/data` are there as we want to test formatting plugins.
180- `hie-compat` is there as we want to keep its code as close to GHC as possible.
181- `hls-tactics-plugin` is there as the main contributor of the plugin (@isovector) does not want auto-formatting.
182
183## Introduction tutorial
184
185See the [tutorial](./plugin-tutorial.md) on writing a plugin in HLS.
186
187## Adding support for a new editor
188
189Adding support for new editors is fairly easy if the editor already has good support for generic LSP-based extensions.
190In that case, there will likely be an editor-specific support system for this (like `lsp-mode` for Emacs).
191This will typically provide instructions for how to support new languages.
192
193In some cases you may need to write a small bit of additional client support, or expose a way for the user to set the server's [configuration options](#configuring-haskell-language-server) and
194for them to configure how the server is started.
195
196## Building the docs
197
198The docs are built with [Sphinx](https://www.sphinx-doc.org/en/master/) and [ReadTheDocs](https://docs.readthedocs.io/en/stable/index.html), the documentation for both is helpful.
199
200To build the docs you need to install some Python prerequisites. You can either `pip install -r docs/requirements.txt`, or simply enter a `nix-shell`.
201
202Then to build and preview the docs:
203
204```
205cd docs
206make html
207firefox _build/html/index.html
208```
209
210Alternatively, you can build the entire thing as a Nix derivation from the flake with `nix build .#docs`.
211
212The docs are also built and previewed on every PR, so you can check them from the PR status.
213
214## Sponsorship
215
216If you want to contribute financially you can do so via [open-collective](https://opencollective.com/haskell-language-server). In the past the funding has been used to sponsor [summer student projects](https://mpickering.github.io/ide/posts/2021-07-22-summer-of-hls.html).
217