diff --git a/docs/configuration.md b/docs/configuration.md index 1a74d688f2..18aa4717eb 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -90,25 +90,46 @@ Settings like this are typically be provided by the language-specific LSP client ## Configuring your project build `haskell-language-server` has to compile your project in order to give you diagnostics, which means that it needs to know how to do so. -This is handled by the [hie-bios](https://github.com/mpickering/hie-bios) project. +This is handled under the hood by the [hie-bios](https://github.com/mpickering/hie-bios) application. +In turn, `hie-bios` needs some configuration to identify all files, GHC options, etc., needed to compile a project. -**For a full explanation of how `hie-bios` determines the project build configuration, and how to configure it manually, refer to the [hie-bios README](https://github.com/mpickering/hie-bios/blob/master/README.md).** +There are several ways to provide this configuration to `hie-bios`, detailed below. -At the moment, `haskell-language-server` has support to automatically detect your project build configuration to handle most use cases. +### Implicit configuration +If no `hie.yaml` file is present, `haskell-language-server` automatically detects your `hie-bios` configuration using [implicit-hie](https://github.com/Avi-D-coder/implicit-hie). +**For most cases, this works just fine, and is the recommended way.** -*So using a explicit `hie.yaml` file will not likely fix your ide setup*. It will do it almost only if you see an error like `Multi Cradle: No prefixes matched` +### Explicit, generated configuration +Maybe using the implicit configuration does not suit you. +E.g., it does not work, or you prefer to have explicit configuration in your project. +In that case, you can automatically generate a `hie.yaml` file, using [implicit-hie](https://github.com/Avi-D-coder/implicit-hie): -If the automatic detection fails with that error you can configure `hie-bios` using a `hie.yaml` file in the root of the workspace. -A `hie.yaml` file **explicitly** describes how to setup the environment to compile the various parts of your project. -For that you need to know what *components* your project has, and the path associated with each one. -So you will need some knowledge about -[stack](https://docs.haskellstack.org/en/stable/build_command/#components) or [cabal](https://cabal.readthedocs.io/en/latest/cabal-commands.html?#cabal-v2-build) components. +```shell +gen-hie > hie.yaml # In the root directory of your project +``` + +### Explicit, manual configuration +Maybe using the generated `hie.yaml` file does not suit you. +E.g., it still does not work, or you want to fine-tune the configuration. + +In that case, refer to the [hie-bios explicit configuration documentation](https://github.com/haskell/hie-bios#explicit-configuration). +Keep in mind that you can start from the `hie.yaml` file generated by `implicit-hie` (see previous section) and modify it to your liking. + +#### Examples of explicit `hie-yaml` configurations -You also can use [implicit-hie](https://github.com/Avi-D-coder/implicit-hie) to automatically generate `hie.yaml` files for -the most common stack and cabal configurations +##### Basic Stack +```yaml +cradle: + stack: +``` + +##### Basic Cabal +```yaml +cradle: + cabal: +``` -For example, to state that you want to use `stack` then the configuration file -would look like: +##### Single Stack component ```yaml cradle: @@ -116,8 +137,7 @@ cradle: component: "haskell-language-server:lib" ``` -If you use `cabal` then you probably need to specify which component you want -to use. +##### Single Cabal component ```yaml cradle: @@ -125,48 +145,48 @@ cradle: component: "lib:haskell-language-server" ``` -If you have a project with multiple components, you can use a cabal-multi -cradle: +##### Multiple Stack components ```yaml cradle: - cabal: + stack: - path: "./test/functional/" component: "haskell-language-server:func-test" - - path: "./test/utils/" - component: "haskell-language-server:hls-test-utils" - path: "./exe/Main.hs" component: "haskell-language-server:exe:haskell-language-server" - path: "./exe/Wrapper.hs" component: "haskell-language-server:exe:haskell-language-server-wrapper" - path: "./src" - component: "lib:haskell-language-server" + component: "haskell-language-server:lib" - path: "./ghcide/src" component: "ghcide:lib:ghcide" - path: "./ghcide/exe" component: "ghcide:exe:ghcide" ``` -Equivalently, you can use stack: +##### Multiple Cabal components ```yaml cradle: - stack: + cabal: - path: "./test/functional/" component: "haskell-language-server:func-test" + - path: "./test/utils/" + component: "haskell-language-server:hls-test-utils" - path: "./exe/Main.hs" component: "haskell-language-server:exe:haskell-language-server" - path: "./exe/Wrapper.hs" component: "haskell-language-server:exe:haskell-language-server-wrapper" - path: "./src" - component: "haskell-language-server:lib" + component: "lib:haskell-language-server" - path: "./ghcide/src" component: "ghcide:lib:ghcide" - path: "./ghcide/exe" component: "ghcide:exe:ghcide" ``` -Or you can explicitly state the program which should be used to collect +##### Custom program +You can explicitly state the program which should be used to collect the options by supplying the path to the program. It is interpreted relative to the current working directory if it is not an absolute path. diff --git a/docs/contributing/contributing.md b/docs/contributing/contributing.md index 2ac39b3780..1eae381892 100644 --- a/docs/contributing/contributing.md +++ b/docs/contributing/contributing.md @@ -108,79 +108,73 @@ $ cabal run haskell-language-server:func-test -- -p "hlint enables" ## Using HLS on HLS code -Project source code should load without `hie.yaml` setup. +Refer to the [HLS project configuration guidelines](../configuration.md#configuring-your-project-build) as they also apply to the HLS project itself. -In other cases: - -1. Check if `hie.yaml` (& `hie.yml`) files left from previous configurations. - -2. If the main project needs special configuration, note that other internal subprojects probably also would need configuration. - -To create an explicit configuration for all projects - use [implicit-hie](https://github.com/Avi-D-coder/implicit-hie) generator directly: - -```shell -gen-hie > hie.yaml # into the main HLS directory -``` - -that configuration should help. - -3. Inspect & tune configuration explicitly. - -[Configuring project build](../configuration.md#configuring-your-project-build) applies to HLS project source code loading just as to any other. - -Note: HLS may implicitly detect codebase as a Stack project (see [hie-bios implicit configuration documentation](https://github.com/haskell/hie-bios/blob/master/README.md#implicit-configuration)). To use Cabal, try creating an `hie.yaml` file: +Note: HLS implicitly detects the HLS codebase as a Stack project (since there is a `stack.yaml` file). +If you want HLS to use Cabal, create this `hie.yaml` file at the root of the project: ```yaml cradle: cabal: ``` -### Manually testing your hacked HLS -If you want to test HLS while hacking on it, follow the steps below. - -#### Using Cabal +## Manually testing your hacked HLS +If you want to test HLS while hacking on it (you can even test it on HLS codebase itself, see previous section), you need to: -- Whenever you want to build HLS, call `cabal install exe:haskell-language-server --overwrite-policy=always`. - At the end of the output you will find the path the HLS executable was installed to, i.e.: +1. (Once) Find the path to the hacked HLS you build +2. (Once) Configure your editor to use it +3. (Every time you change the HLS code) Rebuild HLS +4. (Every time you change the HLS code) Restart the LSP workspace - ``` - ... - Resolving dependencies... - Symlinking 'haskell-language-server' to - '/home/user/.cabal/bin/haskell-language-server' - Symlinking 'haskell-language-server-wrapper' to - '/home/user/.cabal/bin/haskell-language-server-wrapper' - ``` +### Find the path to the hacked HLS you build +Note that unless you change the GHC version or the HLS version between builds, the path should remain the same, this is why you need to set it only once. - In this example output, the path would be `/home/user/.cabal/bin/haskell-language-server`. +#### Using Cabal +Run: +```shell +$ cabal build exe:haskell-language-server && cabal list-bin exe:haskell-language-server +[..] +/haskell-language-server +``` -- Open some codebase on which you want to test your local HLS in your favorite editor (it can also be the HLS codebase itself: see previous section for configuration) - - Configure this editor to use your custom HLS executable by using the path you obtained previously. -- Restart HLS in your project: - - With VS Code: Press `CTRL + Shift + P` and type `Haskell: Restart Haskell LSP Server` - - With Emacs: `lsp-workspace-restart` +#### Using Stack +Run: +```shell +$ echo $(pwd)/$(stack path --dist-dir)/build/haskell-language-server/haskell-language-server +[..] +/haskell-language-server +``` -##### VS Code +### Configure your editor to use it -When using VS Code you can set up a test project to use a specific HLS executable: +#### VS Code +When using VS Code you can set up each project to use a specific HLS executable: - If it doesn't already exist in your project directory, create a directory called `.vscode`. -- In the `.vscode` directory create a file called `settings.json` with the below contents. The path used here is the one obtained by using the `cabal` install command. - +- In the `.vscode` directory create a file called `settings.json` with the below contents. ```json { - "haskell.serverExecutablePath": "/home/user/.cabal/bin/haskell-language-server" + "haskell.serverExecutablePath": "/path/to/your/hacked/haskell-language-server" } ``` -#### Using Stack +#### Emacs +There are several ways to configure the HLS server path: +- `M-x customize-grouplsp-haskellLsp Haskell Server Path` +- Evaluate `(setq lsp-haskell-server-path "/path/to/your/hacked/haskell-language-server")` +- Create a file `.dir-locals.el` with the following content: +```lisp +((haskell-mode . ((lsp-haskell-server-path . "/path/to/your/hacked/haskell-language-server")))) +``` + +### Rebuild HLS +- With Stack: `stack build haskell-language-server:exe:haskell-language-server` +- With Cabal: `cabal build exe:haskell-language-server` -- Open some codebase on which you want to test your local HLS in your favorite editor (it can also be the HLS codebase itself: see previous section for configuration) -- Configure this editor to use your custom HLS executable - - To obtain the path to your local HLS executable: `$(stack path --dist-dir)/build/haskell-language-server/haskell-language-server` +### Restart the LSP workspace -- Build HLS - - `stack build haskell-language-server:exe:haskell-language-server` +- With VS Code: Press `Ctrl + Shift + p` and type `Haskell: Restart Haskell LSP Server` +- With Emacs: `M-x lsp-workspace-restart` ## Style guidelines diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 7160816b96..8947fd8eb7 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -165,6 +165,10 @@ The server log will show which cradle is being chosen. Using an explicit `hie.yaml` to configure the cradle can resolve the problem, see the [configuration page](./configuration.md#configuring-your-project-build). +### Multi Cradle: No prefixes matched +The error message `Multi Cradle: No prefixes matched` usually means that implicit configuration failed. +In that case, you must use [explicit configuration](./configuration.md#configuring-your-project-build). + ### Static binaries Static binaries use the GHC linker for dynamically loading dependencies when typechecking Template Haskell code, and this can run into issues when loading shared objects linked against mismatching system libraries, or into GHC linker bugs (mainly the Mach linker used in Mac OS, but also potentially the ELF linker).