Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 39 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Haskell for Visual Studio Code

[![](https://vsmarketplacebadge.apphb.com/version/haskell.haskell.svg)](https://marketplace.visualstudio.com/items?itemName=haskell.haskell)
[![vsmarketplacebadge](https://vsmarketplacebadge.apphb.com/version/haskell.haskell.svg)](https://marketplace.visualstudio.com/items?itemName=haskell.haskell)

This extension adds language support for [Haskell](https://haskell.org), powered by the [Haskell Language Server](https://github.com/haskell/haskell-language-server).

Expand All @@ -12,27 +12,37 @@ This extension adds language support for [Haskell](https://haskell.org), powered
- Document symbols
- Highlight references in document
- Code completion
- Formatting via Brittany, Floskell, Ormolu or Stylish Haskell
- Formatting via Brittany, Floskell, Fourmolu, Ormolu or Stylish Haskell
- [Multi-root workspace](https://code.visualstudio.com/docs/editor/multi-root-workspaces) support
- Code evaluation (Haskell Language Server), see ([Tutorial](https://github.com/haskell/haskell-language-server/blob/master/plugins/hls-eval-plugin/README.md))

![Eval Demo](https://raw.githubusercontent.com/haskell/haskell-language-server/master/plugins/hls-eval-plugin/demo.gif)
![Eval Demo](https://raw.githubusercontent.com/haskell/haskell-language-server/master/plugins/hls-eval-plugin/demo.gif)

## Requirements
- Integration with [retrie](https://hackage.haskell.org/package/retrie)

- For standalone `.hs`/`.lhs` files, [ghc](https://www.haskell.org/ghc/) must be installed and on the PATH. The easiest way to install it is with [ghcup](https://www.haskell.org/ghcup/) or [Chocolatey](https://www.haskell.org/platform/windows.html) on Windows.
- For Cabal based projects, both ghc and [cabal-install](https://www.haskell.org/cabal/) must be installed and on the PATH. It can also be installed with [ghcup](https://www.haskell.org/ghcup/) or [Chocolatey](https://www.haskell.org/platform/windows.html) on Windows.
- For Stack based projects, [stack](http://haskellstack.org) must be installed and on the PATH.
![Retrie Demo](https://i.imgur.com/Ev7B87k.gif)

- Code lenses for explicit import lists

![Imports code lens Demo](https://imgur.com/pX9kvY4.gif)

## Language Servers
- Generate functions from type signatures, and intelligently complete holes using [Wingman (tactics)](https://github.com/haskell/haskell-language-server/tree/master/plugins/hls-tactics-plugin)

Whilst this extension is powered by the Haskell Language Server by default, it also supports several others which can be manually installed:
![Wingman Demo](https://user-images.githubusercontent.com/307223/92657198-3d4be400-f2a9-11ea-8ad3-f541c8eea891.gif)

- [Haskell Language Server](https://github.com/haskell/haskell-language-server#installation): This is the default language server which will automatically be downloaded, so it does not need manual installation. It builds upon ghcide by providing extra plugins and features.
- [ghcide](https://github.com/digital-asset/ghcide#install-ghcide): A fast and reliable LSP server with support for [basic features](https://github.com/digital-asset/ghcide#features).
- [Haskell IDE Engine](https://github.com/haskell/haskell-ide-engine#installation): A legacy language server, you probably shouldn't use this one. Haskell Language Server replaces it instead.
- Integration with [hlint](https://github.com/ndmitchell/hlint) to show diagnostics and apply hints via [apply-refact](https://github.com/mpickering/apply-refact)

You can choose which language server to use from the "Haskell > Language Server Variant" configuration option.
![Hlint Demo](https://user-images.githubusercontent.com/54035/110860028-8f9fa900-82bc-11eb-9fe5-6483d8bb95e6.gif)

- Module name suggestions for insertion or correction

![Module Name Demo](https://user-images.githubusercontent.com/54035/110860755-78ad8680-82bd-11eb-9845-9ea4b1cc1f76.gif)

## Requirements

- For standalone `.hs`/`.lhs` files, [ghc](https://www.haskell.org/ghc/) must be installed and on the PATH. The easiest way to install it is with [ghcup](https://www.haskell.org/ghcup/) or [Chocolatey](https://www.haskell.org/platform/windows.html) on Windows.
- For Cabal based projects, both ghc and [cabal-install](https://www.haskell.org/cabal/) must be installed and on the PATH. It can also be installed with [ghcup](https://www.haskell.org/ghcup/) or [Chocolatey](https://www.haskell.org/platform/windows.html) on Windows.
- For Stack based projects, [stack](http://haskellstack.org) must be installed and on the PATH.

## Configuration options

Expand All @@ -49,8 +59,6 @@ There are a few placeholders which will be expanded:
- `~`, `${HOME}` and `${home}` will be expanded into your users' home folder.
- `${workspaceFolder}` and `${workspaceRoot}` will expand into your current project root.

## Haskell Language Server specifics

### Local documentation

Haskell Language Server can display Haddock documentation on hover and completions if the project and
Expand All @@ -59,19 +67,23 @@ its dependencies have been built with the `-haddock` GHC flag.
- For cabal:

- Add to your global config file (e.g. `~/.cabal/config`):
```

```yaml
program-default-options
ghc-options: -haddock
```

- Or, for a single project, run `cabal configure --ghc-options=-haddock`

- For stack, add to global `$STACK_ROOT\config.yaml`, or project's `stack.yaml`:
```

```yaml
ghc-options:
"$everything": -haddock
'$everything': -haddock
```

Note that this flag will cause compilation errors if a dependency contains invalid Haddock markup,
until GHC 8.12 which [will report warnings](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/2377)
until GHC 9.0 which [will report warnings](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/2377)
instead.

### Downloaded binaries
Expand Down Expand Up @@ -101,7 +113,7 @@ These are the versions of GHC that there are binaries of `haskell-language-serve
| 8.6.5 | ✓ | ✓ | ✓ |
| 8.6.4 | ✓ | ✓ | ✓ |

The exact list of binaries can be checked in the last release of haskell-language-server: https://github.com/haskell/haskell-language-server/releases/latest
The exact list of binaries can be checked in the last release of haskell-language-server: <https://github.com/haskell/haskell-language-server/releases/latest>

## Using multi-root workspaces

Expand All @@ -111,25 +123,19 @@ The language server is now started for each workspace folder you have in your mu

## Investigating and reporting problems

1. Go to extensions and right click `Haskell Language Server` and choose `Extensions Settings`
2. Scroll down to `Language Server Haskell › Trace: Server` and set it to `messages`
3. Restart vscode and reproduce your problem
4. Go to the main menu and choose `View -> Output` (`Ctrl + Shift + U`)
5. On the new Output panel that opens on the right side in the drop down menu choose `Haskell (<your project>)`
1. Go to extensions and right click `Haskell Language Server` and choose `Extensions Settings`
2. Scroll down to `Language Server Haskell › Trace: Server` and set it to `messages`
3. Restart vscode and reproduce your problem
4. Go to the main menu and choose `View -> Output` (`Ctrl + Shift + U`)
5. On the new Output panel that opens on the right side in the drop down menu choose `Haskell (<your project>)`

Please include the output when filing any issues on the relevant language server's issue tracker.
Please include the output when filing any issues on the [haskell-language-server](https://github.com/haskell/haskell-language-server/issues/new) issue tracker.

### Troubleshooting

- Sometimes the language server might get stuck in a rut and stop responding to your latest changes.
Should this occur you can try restarting the language server with <kbd>Ctrl</kbd> <kbd>shift</kbd> <kbd>P</kbd>/<kbd>⌘</kbd> <kbd>shift</kbd> <kbd>P</kbd> > Restart Haskell LSP Server.
- Usually the error or unexpected behaviour is already reported in the haskell language server [used by the extension](#hie-variant). Finding the issue in its issue tracker could be useful to help resolve it. Sometimes even it includes a workaround for the issue.
- Haskell language servers issue trackers:
- haskell-language-server: https://github.com/haskell/haskell-language-server/issues
- ghcide: https://github.com/haskell/ghcide/issues
- _Common issues_:
- For now, the extension is not able to open a single haskell source file. You need to open a workspace or folder, configured to be built with cabal, stack or other hie-bios compatible program.
- Check you don't have other haskell extensions active, they can interfere with each other.
- Usually the error or unexpected behaviour is already reported in the [haskell language server issue tracker](https://github.com/haskell/haskell-language-server/issues). Finding the issue could be useful to help resolve it and sometimes includes a workaround for the issue.

## Contributing

Expand Down
14 changes: 2 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "haskell",
"displayName": "Haskell",
"description": "Haskell language support powered by the Haskell Language Server and ghcide",
"description": "Haskell language support powered by the Haskell Language Server",
"version": "1.3.0",
"license": "MIT",
"publisher": "haskell",
Expand Down Expand Up @@ -130,16 +130,6 @@
"default": "",
"description": "If set, redirects the logs to a file."
},
"haskell.languageServerVariant": {
"scope": "resource",
"type": "string",
"enum": [
"haskell-language-server",
"ghcide"
],
"default": "haskell-language-server",
"description": "Which language server to use."
},
"haskell.releasesURL": {
"scope": "resource",
"type": "string",
Expand All @@ -166,7 +156,7 @@
"Don't check for newer versions"
],
"default": "keep-up-to-date",
"markdownDescription": "Only applicable with `#haskell.languageServerVariant#` set to `haskell-language-server`. Determine what to do when a new version of the language server is available."
"markdownDescription": "Determine what to do when a new version of the language server is available."
},
"haskell.plugin.importLens.codeActionsOn": {
"scope": "resource",
Expand Down
58 changes: 8 additions & 50 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,21 +90,7 @@ function findManualExecutable(uri: Uri, folder?: WorkspaceFolder): string | null

/** Searches the PATH for whatever is set in serverVariant */
function findLocalServer(context: ExtensionContext, uri: Uri, folder?: WorkspaceFolder): string | null {
const serverVariant = workspace.getConfiguration('haskell', uri).languageServerVariant;

// Set the executable, based on the settings.
let exes: string[] = []; // should get set below
switch (serverVariant) {
case 'haskell-ide-engine':
exes = ['hie-wrapper', 'hie'];
break;
case 'haskell-language-server':
exes = ['haskell-language-server-wrapper', 'haskell-language-server'];
break;
case 'ghcide':
exes = ['ghcide'];
break;
}
const exes: string[] = ['haskell-language-server-wrapper', 'haskell-language-server'];

for (const exe of exes) {
if (executableExists(exe)) {
Expand Down Expand Up @@ -151,13 +137,8 @@ async function activateServerForFolder(context: ExtensionContext, uri: Uri, fold
serverExecutable = findManualExecutable(uri, folder) ?? findLocalServer(context, uri, folder);
if (serverExecutable === null) {
// If not, then try to download haskell-language-server binaries if it's selected
if (workspace.getConfiguration('haskell', uri).languageServerVariant === 'haskell-language-server') {
serverExecutable = await downloadHaskellLanguageServer(context, uri, folder);
if (!serverExecutable) {
return;
}
} else {
showNotInstalledErrorMessage(uri);
serverExecutable = await downloadHaskellLanguageServer(context, uri, folder);
if (!serverExecutable) {
return;
}
}
Expand All @@ -170,16 +151,12 @@ async function activateServerForFolder(context: ExtensionContext, uri: Uri, fold

let args: string[] = ['--lsp'];

const serverVariant = workspace.getConfiguration('haskell', uri).languageServerVariant;
// ghcide does not accept -d and -l params
if (serverVariant !== 'ghcide') {
if (logLevel === 'messages') {
args = args.concat(['-d']);
}
if (logLevel === 'messages') {
args = args.concat(['-d']);
}

if (logFile !== '') {
args = args.concat(['-l', logFile]);
}
if (logFile !== '') {
args = args.concat(['-l', logFile]);
}

// If we're operating on a standalone file (i.e. not in a folder) then we need
Expand Down Expand Up @@ -251,22 +228,3 @@ export async function deactivate() {
}
await Promise.all(promises);
}

function showNotInstalledErrorMessage(uri: Uri) {
const variant = workspace.getConfiguration('haskell', uri).languageServerVariant;
let projectUrl = '';
switch (variant) {
case 'haskell-ide-engine':
projectUrl = '/haskell/haskell-ide-engine';
break;
case 'haskell-language-server':
projectUrl = '/haskell/haskell-language-server';
break;
case 'ghcide':
projectUrl = '/digital-asset/ghcide';
break;
}
const notInstalledMsg: string =
variant + ' executable missing, please make sure it is installed, see https://github.com' + projectUrl + '.';
window.showErrorMessage(notInstalledMsg);
}