Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…age-server into hlint-tests
  • Loading branch information
jneira committed Nov 5, 2021
2 parents ebd9445 + 132d1c0 commit 5ef5777
Show file tree
Hide file tree
Showing 45 changed files with 712 additions and 433 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/hackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
"hls-splice-plugin", "hls-tactics-plugin",
"hls-call-hierarchy-plugin",
"haskell-language-server"]
ghc: ["8.10.7", "8.8.4", "8.6.5"]
ghc: ["9.0.1", "8.10.7", "8.8.4", "8.6.5"]

steps:

Expand Down Expand Up @@ -119,6 +119,7 @@ jobs:
path: ${{ steps.generate-dist-tarball.outputs.path }}

upload-candidate:
if: ${{ !contains(github.head_ref, 'check') }}
needs: check-and-upload-tarballs
runs-on: ubuntu-latest
steps:
Expand Down
18 changes: 9 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ defaults:
run:
shell: bash

# See: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#concurrency.
concurrency:
group: ${{ github.head_ref }}-${{ github.workflow }}
cancel-in-progress: true

on:
pull_request:
branches:
Expand All @@ -19,19 +24,14 @@ jobs:
- id: skip_check
uses: fkirc/[email protected]
with:
cancel_others: true
paths_ignore: '["**/docs/**", "**.md", "**/LICENSE", "install/**", "**.nix", "flake.lock", "**/README.md", "FUNDING.yml"]'
cancel_others: false
paths_ignore: '["**/docs/**", "**.md", "**/LICENSE", "install/**", "**.nix", "flake.lock", "**/README.md", "FUNDING.yml", ".circleci/**"]'
# If we only change ghcide downstream packages we have not test ghcide itself
- id: skip_ghcide_check
uses: fkirc/[email protected]
with:
cancel_others: false
paths_ignore: '["hls-test-utils/**", "plugins/**", "src/**", "exe/**", "test/**", "shake-bench/**"]'
- if: steps.skip_check.outputs.should_skip == 'true'
name: Skip circleci
uses: marocchino/sticky-pull-request-comment@v2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
message: We are gonna [skip circleci]

test:
if: needs.pre_job.outputs.should_skip != 'true'
Expand Down Expand Up @@ -148,7 +148,7 @@ jobs:
# run the tests without parallelism to avoid running out of memory
run: cabal test ghcide --test-options="-j1 --rerun-update" || cabal test ghcide --test-options="-j1 --rerun" || LSP_TEST_LOG_COLOR=0 LSP_TEST_LOG_MESSAGES=true LSP_TEST_LOG_STDERR=true cabal test ghcide --test-options="-j1 --rerun"

- if: matrix.test && !(matrix.os == 'windows-latest' && matrix.ghc == '9.0.1')
- if: matrix.test
name: Test func-test suite
env:
HLS_TEST_EXE: hls
Expand Down
4 changes: 2 additions & 2 deletions cabal-ghc901.project
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ write-ghc-environment-files: never
index-state: 2021-10-04T02:41:06Z

constraints:
-- These plugins don't work on GHC9 yet
haskell-language-server -brittany -class -stylishhaskell -tactic
-- These plugins don't work on GHC9 yet
haskell-language-server +ignore-plugins-ghc-bounds -brittany -class -stylishhaskell -tactic

allow-newer:
floskell:base,
Expand Down
5 changes: 2 additions & 3 deletions cabal-ghc921.project
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ write-ghc-environment-files: never
index-state: 2021-09-29T21:38:47Z

constraints:
-- These plugins doesn't work on GHC9 yet
haskell-language-server -brittany -class -fourmolu -splice -stylishhaskell -tactic -refineImports -callhierarchy -retrie

-- These plugins doesn't work on GHC92 yet
haskell-language-server +ignore-plugins-ghc-bounds -brittany -class -fourmolu -splice -stylishhaskell -tactic -refineImports -callhierarchy -retrie

allow-newer:
Cabal,
Expand Down
20 changes: 10 additions & 10 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ For example, there are protocol methods for highlighting matching identifiers th
This is a capability which any server can implement, so the client can decide generically whether to ask the server to do it or not.
So your editor can provide a setting to turn this on or off globally, for any language server you might use.

Settings like this are typically provided by the generic LSP client support for your editor, for example in Emacs by [`lsp-mode`](https://github.com/emacs-lsp/lsp-mode).
Settings like this are typically provided by the generic LSP client support for your editor, for example in Emacs by [lsp-mode](https://github.com/emacs-lsp/lsp-mode).

### Generic editor options

Your editor may provide some settings that affect how the information from the language server is used.
For example, whether popups are shown, or whether code lenses appear by default.

Settings like this are typically provided by the generic LSP client support for your editor, for example in Emacs by [`lsp-mode`](https://github.com/emacs-lsp/lsp-mode).
Settings like this are typically provided by the generic LSP client support for your editor, for example in Emacs by [lsp-mode](https://github.com/emacs-lsp/lsp-mode).

### Language-specific server options

Expand All @@ -48,7 +48,7 @@ Here is a list of the additional settings currently supported by `haskell-langua
- Hlint (`haskell.hlintOn`, default true): whether to enable Hlint support. *Deprecated* as it is equivalen to `haskell.plugin.hlint.globalOn`
- Max completions (`haskell.maxCompletions`, default 40): maximum number of completions sent to the LSP client.
- Check project (`haskell.checkProject`, default true): whether to typecheck the entire project on load. As it is activated by default could drive to bad perfomance in large projects.
- Check parents (`haskell.checkParents`, default `CheckOnSaveAndClose`): when to typecheck reverse dependencies of a file; one of `NeverCheck`, `CheckOnClose`, `CheckOnSaveAndClose`, or `AlwaysCheck`.
- Check parents (`haskell.checkParents`, default `CheckOnSaveAndClose`): when to typecheck reverse dependencies of a file; one of `NeverCheck`, `CheckOnClose`, `CheckOnSaveAndClose`, or `AlwaysCheck`.

#### Generic plugin configuration

Expand All @@ -57,7 +57,7 @@ Plugins have a generic config to control their behaviour. The schema of such con
- `haskell.plugin.${pluginName}.globalOn`: usually with default true. Whether the plugin is enabled at runtime or it is not. That is the option you might use if you want to disable completely a plugin.
- Actual plugin names are: `ghcide-code-actions-fill-holes`, `ghcide-completions`, `ghcide-hover-and-symbols`, `ghcide-type-lenses`, `ghcide-code-actions-type-signatures`, `ghcide-code-actions-bindings`, `ghcide-code-actions-imports-exports`, `eval`, `moduleName`, `pragmas`, `refineImports`, `importLens`, `class`, `tactics` (aka wingman), `hlint`, `haddockComments`, `retrie`, `splice`.
- So to disable the import lens with an explicit list of module definitions you could set `haskell.plugin.importLens.globalOn: false`
- `haskell.plugin.${pluginName}.${lspCapability}On`: usually with default true. Whether a concrete plugin capability is enabled.
- `haskell.plugin.${pluginName}.${lspCapability}On`: usually with default true. Whether a concrete plugin capability is enabled.
- Capabilities are the different ways a lsp server can interact with the editor. The current available capabilities of the server are: `callHierarchy`, `codeActions`, `codeLens`, `diagnostics`, `hover`, `symbols`, `completion`, `rename`.
- Note that usually plugins don't provide all capabilities but some of them or even only one.
- So to disable code changes suggestions from the `hlint` plugin (but no diagnostics) you could set `haskell.plugin.hlint.codeActionsOn: false`
Expand All @@ -78,7 +78,7 @@ Plugins have a generic config to control their behaviour. The schema of such con
This reference of configuration can be outdated at any time but we can query the `haskell-server-executable` about what configuration is effectively used:
- `haskell-language-server generate-default-config`: will print the json configuration with all default values. It can be used as template to modify it.
- `haskell-language-server vscode-extension-schema`: will print a json schema used to setup the haskell vscode extension. But it is useful to see what range of values can an option take and a description about it.

Settings like this are typically provided by the language-specific LSP client support for your editor, for example in Emacs by `lsp-haskell`.

### Client options
Expand All @@ -90,11 +90,11 @@ 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 by the [hie-bios](https://github.com/mpickering/hie-bios) 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).**
**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).**

At the moment, `haskell-language-server` has support to automatically detect your project build configuration to handle most use cases.
At the moment, `haskell-language-server` has support to automatically detect your project build configuration to handle most use cases.

*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`

Expand All @@ -104,7 +104,7 @@ For that you need to know what *components* your project has, and the path assoc
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.

You also can use [this utility](https://github.com/Avi-D-coder/implicit-hie) to automatically generate `hie.yaml` files for
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

For example, to state that you want to use `stack` then the configuration file
Expand Down Expand Up @@ -351,7 +351,7 @@ it may also be helpful to also specify root markers:
let g:LanguageClient_rootMarkers = ['*.cabal', 'stack.yaml']
```

Further configuration can be done by pointing the [`g:LanguageClient_settingsPath`](https://github.com/autozimu/LanguageClient-neovim/blob/0e5c9546bfddbaa2b01e5056389c25aefc8bf989/doc/LanguageClient.txt#L221)
Further configuration can be done by pointing the `g:LanguageClient_settingsPath` [option](https://github.com/autozimu/LanguageClient-neovim/blob/0e5c9546bfddbaa2b01e5056389c25aefc8bf989/doc/LanguageClient.txt#L221)
variable to the file in which you want to keep your LSP settings.

### Atom
Expand Down
37 changes: 21 additions & 16 deletions docs/contributing/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The Haskell tooling dream is near, we need your help!
- Join the [haskell-tooling channel](https://matrix.to/#/#haskell-tooling:matrix.org) in [matrix](https://matrix.org/).
- Visit [the project GitHub repo](https://github.com/haskell/haskell-language-server) to view the source code, or open issues or pull requests.

## Building haskell-language-server
## Building

Clone the repository:
```shell
Expand All @@ -19,26 +19,18 @@ $ git clone https://github.com/haskell/haskell-language-server

The project can then be built with both `cabal build` and `stack build`.

haskell-language-server can also be used with itself. We provide preset samples of `hie.yaml` for Cabal and Stack.

Note: the `./install/` folder is not directly tied to the project so it has dedicated `./install/hie.yaml.[cbl|stack]`
templates.

### Using Cabal

```shell
$ cp hie-cabal.yaml hie.yaml
$ cp install/hie-cabal.yaml install/hie.yaml
# If you have not run `cabal update` in a while
$ cabal update
# Then
$ cabal build
```

### Using Stack

```shell
$ cp hie-stack.yaml hie.yaml
$ cp install/hie-stack.yaml install/hie.yaml
$ cp ghcide/hie-stack.yaml ghcide/hie.yaml
$ stack build --test --no-run-tests
$ cd install
$ stack build
```

Expand Down Expand Up @@ -119,26 +111,39 @@ An alternative, which only recompiles when tests (or dependencies) change:
$ cabal run haskell-language-server:func-test -- -p "hlint enables"
```

### Test your hacked HLS in your editor
## Using HLS on HLS code

[HLS project configuration guidelines](../configuration.md#configuring-your-project-build) also apply to the HLS project itself.

Note: HLS implicitly detects HLS codebase as a Stack project (see [hie-bios implicit configuration documentation](https://github.com/haskell/hie-bios/blob/master/README.md#implicit-configuration)).
If you want HLS to use Cabal, you need to create an `hie.yaml` file:
```yaml
cradle:
cabal:
```
Also note that the `install/` subdirectory is a different project, so if you want to work on this part of the code, you may also have to create an `install/hie.yaml` file.

### Manually testing your hacked HLS
If you want to test HLS while hacking on it, follow the steps below.

To do once:

- Open some codebase on which you want to test your hacked HLS in your favorite editor
- Open some codebase on which you want to test your hacked HLS in your favorite editor (it can also be HLS codebase itself: see previous section for configuration)
- Configure this editor to use your custom HLS executable
- With Cabal:
- On Unix systems: `cabal exec which haskell-language-server`
- On Windows: `cabal exec where haskell-language-server`
- With Stack: `$(stack path --dist-dir)/build/haskell-language-server/haskell-language-server`

To do every time you changed code and want to test it:
To do every time you change HLS code and want to test it:

- Build HLS
- With Cabal: `cabal build exe:haskell-language-server`
- With Stack: `stack build haskell-language-server:exe:haskell-language-server`
- Restart HLS
- With VS Code: `Haskell: Restart Haskell LSP Server`
- With Emacs: `lsp-workspace-restart`

## Style guidelines

Expand Down
33 changes: 25 additions & 8 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,30 @@ Example with `tasty-discover`:

This returns an error in HLS if 'tasty-discover' is not in the path: `could not execute: tasty-discover`.

## Common issues

### Difficulties with Stack and `Paths_` modules
### Problems with multi component (tests suites, executables, benchmarks) support using stack

These are known to be somewhat buggy at the moment: <https://github.com/haskell/haskell-language-server/issues/478>.
This issue should be fixed in Stack versions >= 2.5.
Due to some limitations in the interaction between HLS and stack, there are some issues in projects with a main library and executables, test suites or benchmarks:
- The stack project has to be built succesfully *before* loading it with HLS to get components other than the library work.
- Changes in the library are not automatically propagated to other components, especially in the presence of errors in the library, so you have to restart HLS to get those components correctly loaded. The usual symptom is the editor showing errors like `Could not load module ...` or `Cannot satisfy -package ...`
- See https://github.com/haskell/haskell-language-server/issues/366 for more info about.
## Common issues

### Problems with dynamic linking

As haskell-language-server prebuilt binaries are statically linked, they don't play well with projects using dynamic linking.
An usual symptom is the presence of errors containing `unknown symbol` and it is typical in arch linux, where a dynamically linked version of ghc is used.

The workaround is to use a version of haskell-language-server compiled from source with `-dynamic` enabled`. See more details [here](https://github.com/haskell/haskell-language-server/issues/1160#issuecomment-756566273).
The workaround is to use a version of haskell-language-server compiled from source with the ghc option `-dynamic` enabled. See more details [here](https://github.com/haskell/haskell-language-server/issues/1160#issuecomment-756566273).

### Problems with Template Haskell

Due to how Template Haskell code is evaluated at compile time and some limitations in the interaction between HLS and GHC, the loading of modules using TH can be problematic.

The errors thrown are usually related to linking and usually make HLS crash: `Segmentation fault`, `GHC runtime linker: fatal error`, etc

A workaround which has helped in some cases is to compile HLS from source with the ghc option `-dynamic` enabled, as in the previous issue.

We have a [dedicated label](https://github.com/haskell/haskell-language-server/issues?q=is%3Aissue+is%3Aopen+label%3A%22type%3A+template+haskell+related%22) in the issue tracker and an [general issue](https://github.com/haskell/haskell-language-server/issues/1431) tracking support for TH.

## Troubleshooting the server

Expand All @@ -56,11 +67,17 @@ sent, or if there are any errors.

To get a more verbose, also pass `--debug` to the executable.

### Identify which plugin could be the cause of the issue.

Sometimes the issue is produced by one of the plugins included in HLS. To diagnose that and help to trace the final cause one possible strategy is simple disable all plugins, check if the issue is gone and then enable them selectively until the issue is reproduced again.

There is a configuration json snippet which disables all plugins [here](https://github.com/haskell/haskell-language-server/issues/2151#issuecomment-911397030).

## Troubleshooting the client

Many clients provide diagnostic information about a LSP session.
In particular, look for a way to get the status of the server, the server stderr, or a log of the messages that the client has sent to the server.
For example, `lsp-mode` provides all of these (see its [troubleshooting page](https://emacs-lsp.github.io/lsp-mode/page/troubleshooting/) for details).
For vscode you can read how to access the lsp session log [here])https://github.com/haskell/vscode-haskell#investigating-and-reporting-problems).

The most common client-related problem is the client simply not finding the server executable, so make sure that you have the right `PATH` and you have configured
it to look for the right executable.
The most common client-related problem is the client simply not finding the server executable or the tools needed to load Haskell code (`ghc`, `cabal`, or `stack`). So make sure that you have the right `PATH` and you have configured the client to look for the right executables.
2 changes: 1 addition & 1 deletion ghcide/.hlint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
# Things that are unsafe in Haskell base library
- {name: unsafeInterleaveIO, within: [Development.IDE.LSP.LanguageServer]}
- {name: unsafeDupablePerformIO, within: []}
- {name: unsafeCoerce, within: [Ide.Plugin.Eval.Code]}
- {name: unsafeCoerce, within: [Ide.Plugin.Eval.Code, Development.IDE.Types.Shake]}
# Things that are a bit dangerous in the GHC API
- {name: nameModule, within: []}

Expand Down
4 changes: 3 additions & 1 deletion ghcide/exe/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Development.IDE (Priority (Debug, Info),
action)
import Development.IDE.Core.OfInterest (kick)
import Development.IDE.Core.Rules (mainRule)
import Development.IDE.Core.Tracing (withTelemetryLogger)
import Development.IDE.Graph (ShakeOptions (shakeThreads))
import qualified Development.IDE.Main as Main
import qualified Development.IDE.Plugin.HLS.GhcIde as GhcIde
Expand All @@ -39,7 +40,7 @@ ghcideVersion = do
<> gitHashSection

main :: IO ()
main = do
main = withTelemetryLogger $ \telemetryLogger -> do
let hlsPlugins = pluginDescToIdePlugins GhcIde.descriptors
-- WARNING: If you write to stdout before runLanguageServer
-- then the language server will not work
Expand All @@ -55,6 +56,7 @@ main = do

Main.defaultMain arguments
{Main.argCommand = argsCommand
,Main.argsLogger = Main.argsLogger arguments <> pure telemetryLogger

,Main.argsRules = do
-- install the main and ghcide-plugin rules
Expand Down
2 changes: 1 addition & 1 deletion ghcide/ghcide.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ library
rope-utf16-splay,
safe,
safe-exceptions,
hls-graph ^>= 1.5,
hls-graph ^>= 1.5.1,
sorted-list,
sqlite-simple,
stm,
Expand Down
Loading

0 comments on commit 5ef5777

Please sign in to comment.