Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manage all the Haskell things #547

Merged
merged 27 commits into from
Mar 23, 2022
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ on:
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [macos-11, ubuntu-latest, windows-latest]
ghc: [9.0.1, 8.10.4]
Expand All @@ -20,6 +21,9 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: 17
- name: Upgrade ghcup
run: ghcup upgrade -i -f
shell: bash
# Setup the environment for the tests
- name: Ensure there is a supported ghc versions
uses: haskell/actions/setup@v1
Expand Down
23 changes: 17 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ You can watch demos for some of these features [here](https://haskell-language-s
- 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.
- If you are installing from an offline VSIX file, you need to install [language-haskell](https://github.com/JustusAdam/language-haskell) too after installation (either from the marketplace or offline).
- Alternatively, you can let the extension manage your entire toolchain automatically (you'll be asked on first startup) via
[ghcup](https://www.haskell.org/ghcup/), which should be pre-installed

## Configuration options

Expand Down Expand Up @@ -71,17 +73,26 @@ The environment _only will be visible for the lsp server_, not for other extensi

### Downloaded binaries

This extension will download `haskell-language-server` binaries either via an internal ghcup (it will download it automaticlaly)
or via a system ghcup (which must be present), unless you set the config option `haskell.manageHLS` to `PATH` (the extension
will ask you on first start).
This extension will download `haskell-language-server` binaries and the rest of the toolchain if you selected to use GHCup during
first start. Check the `haskell.manageHLS` setting.
hasufell marked this conversation as resolved.
Show resolved Hide resolved

It will then download the newest version of haskell-language-server which has support for the required ghc.
That means it could use an older version than the latest one, without the last features and bug fixes.
For example, if a project needs ghc-8.10.4 the extension will download and use haskell-language-server-1.4.0, the lastest version which supported ghc-8.10.4. Even if the lastest global haskell language-server version is 1.5.1.

If you have disk space issues and use system ghcup, check `ghcup gc --help`.
If you have disk space issues and use the internal ghcup, check the following directories, depending on your platform
and possible delete them:
If you have disk space issues, check `ghcup gc --help`.

You can also instruct the extension to use a different installation directory for the toolchain,
e.g. to not interfere with system GHCup installation. Depending on your platform, add the full
resolved path like so:

```json
"haskell.serverEnvironment": {
"GHCUP_INSTALL_BASE_PREFIX": "/home/foo/.config/Code/User/globalStorage/haskell.haskell/"
}
```

The internal storage paths for the extension depend on the platform:

| Platform | Path |
| -------- | ------------------------------------------------------------------------------- |
Expand Down
40 changes: 31 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
"scope": "resource",
"type": "string",
"default": "",
"markdownDescription": "An optional path where downloaded binaries will be stored. Check the default value [here](https://github.com/haskell/vscode-haskell#downloaded-binaries)"
"markdownDescription": "An optional path where downloaded metadata will be stored. Check the default value [here](https://github.com/haskell/vscode-haskell#downloaded-binaries)"
},
"haskell.serverExecutablePath": {
"scope": "resource",
Expand All @@ -151,6 +151,12 @@
"default": "",
"markdownDescription": "Pass additional arguments to the language server."
},
"haskell.ghcupExecutablePath": {
"scope": "resource",
"type": "string",
"default": "",
"markdownDescription": "Manually set a ghcup executable path."
},
"haskell.serverEnvironment": {
"scope": "resource",
"type": "object",
Expand All @@ -163,21 +169,37 @@
"default": null,
"description": "How to manage/find HLS installations.",
"enum": [
"system-ghcup",
"internal-ghcup",
"GHCup",
"PATH"
],
"enumDescriptions": [
"Will use a user-wide installation of ghcup (usually in '~/.ghcup') to manage HLS automatically",
"Will use an internal installation of ghcup to manage HLS automatically, to avoid interfering with system ghcup",
"Discovers HLS executables in system PATH"
"Will use ghcup and manage Haskell toolchain in the default location (usually '~/.ghcup')",
"Discovers HLS and other executables in system PATH"
]
},
"haskell.useSystemGHCup": {
"haskell.installStack": {
"scope": "resource",
"type": "boolean",
"default": null,
"description": "Whether to use the system ghcup or an internal one for installing HLS."
"default": true,
"description": "Whether to also install/manage stack when 'manageHLS' is set to 'GHCup'."
},
"haskell.installCabal": {
"scope": "resource",
"type": "boolean",
"default": true,
"description": "Whether to also install/manage cabal when 'manageHLS' is set to 'GHCup'."
},
"haskell.installGHC": {
"scope": "resource",
"type": "boolean",
"default": true,
"description": "Whether to also install/manage GHC when 'manageHLS' is set to 'GHCup'."
},
"haskell.upgradeGHCup": {
"scope": "resource",
"type": "boolean",
"default": true,
"description": "Whether to upgrade GHCup automatically when 'manageHLS' is set to 'GHCup'."
},
"haskell.checkProject": {
"scope": "resource",
Expand Down
14 changes: 7 additions & 7 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use strict';
import * as path from 'path';
import {
env,
commands,
env,
ExtensionContext,
OutputChannel,
TextDocument,
Expand All @@ -23,8 +23,8 @@ import {
import { CommandNames } from './commands/constants';
import { ImportIdentifier } from './commands/importIdentifier';
import { DocsBrowser } from './docsBrowser';
import { MissingToolError, addPathToProcessPath, findHaskellLanguageServer, IEnvVars } from './hlsBinaries';
import { expandHomeDir, ExtensionLogger } from './utils';
import { findHaskellLanguageServer, IEnvVars, MissingToolError } from './hlsBinaries';
import { addPathToProcessPath, expandHomeDir, ExtensionLogger } from './utils';

// The current map of documents & folders to language servers.
// It may be null to indicate that we are in the process of launching a server,
Expand Down Expand Up @@ -196,17 +196,17 @@ async function activateServerForFolder(context: ExtensionContext, uri: Uri, fold
}
logger.info(cwdMsg);

let serverEnvironment: IEnvVars = workspace.getConfiguration('haskell', uri).serverEnvironment;
let serverEnvironment: IEnvVars = await workspace.getConfiguration('haskell', uri).serverEnvironment;
if (addInternalServerPath !== undefined) {
const newPath = addPathToProcessPath(addInternalServerPath);
const newPath = await addPathToProcessPath(addInternalServerPath, logger);
serverEnvironment = {
PATH: newPath,
...serverEnvironment,
...{ PATH: newPath },
};
}
const exeOptions: ExecutableOptions = {
cwd: folder ? undefined : path.dirname(uri.fsPath),
env: Object.assign(process.env, serverEnvironment),
env: { ...process.env, ...serverEnvironment },
};

// We don't want empty strings in our args
Expand Down
Loading