diff --git a/README.md b/README.md index 74c971c0d3..979e4ef88a 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,8 @@ $ cargo xtask install $ cargo xtask install --server ``` -For non-standard setup of VS Code and other editors, see [./docs/user](./docs/user). +For non-standard setup of VS Code and other editors, or if the language server +cannot start, see [./docs/user](./docs/user). ## Documentation diff --git a/docs/user/README.md b/docs/user/README.md index 5ec8fb25d1..04c3493426 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -204,4 +204,19 @@ Installation: * You can now invoke the command palette and type LSP enable to locally/globally enable the rust-analyzer LSP (type LSP enable, then choose either locally or globally, then select rust-analyzer) -* Note that `ra_lsp_server` binary must be in `$PATH` for this to work. If it's not the case, you can specify full path to the binary, which is typically `.cargo/bin/ra_lsp_server`. +### Setting up the `PATH` variable + +On Unix systems, `rustup` adds `~/.cargo/bin` to `PATH` by modifying the shell's +startup file. Depending on your configuration, your Desktop Environment might not +actually load it. If you find that `rust-analyzer` only runs when starting the +editor from the terminal, you will have to set up your `PATH` variable manually. + +There are a couple of ways to do that: + +- for Code, set `rust-analyzer.raLspServerPath` to `~/.cargo/bin` (the `~` is + automatically resolved by the extension) +- copy the binary to a location that is already in `PATH`, e.g. `/usr/local/bin` +- on Linux, use PAM to configure the `PATH` variable, by e.g. putting + `PATH DEFAULT=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:@{HOME}/.cargo/bin:@{HOME}/.local/bin` + in your `~/.pam_environment` file; note that this might interfere with other + defaults set by the system administrator via `/etc/environment`. diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 2ceac60a09..099aaaaa2a 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -763,6 +763,11 @@ "chalk": "^2.0.1" } }, + "lookpath": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/lookpath/-/lookpath-1.0.3.tgz", + "integrity": "sha512-XIdgzlX26g10XnzyZdO/4obybEmfGnZyWQZ2DgmmEfVB79X+n3lhUoIzMe501C6s7RmCpAo66OPegWc+CsxYMg==" + }, "magic-string": { "version": "0.25.3", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", diff --git a/editors/code/package.json b/editors/code/package.json index 94887674ba..5dea8fac0a 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -31,6 +31,7 @@ "singleQuote": true }, "dependencies": { + "lookpath": "^1.0.3", "seedrandom": "^3.0.1", "vscode-languageclient": "^5.3.0-next.4" }, diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index 683497dfd4..6637c3bf0b 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts @@ -14,7 +14,7 @@ import * as events from './events'; import * as notifications from './notifications'; import { Server } from './server'; -export function activate(context: vscode.ExtensionContext) { +export async function activate(context: vscode.ExtensionContext) { function disposeOnDeactivation(disposable: vscode.Disposable) { context.subscriptions.push(disposable); } @@ -159,7 +159,11 @@ export function activate(context: vscode.ExtensionContext) { }); // Start the language server, finally! - startServer(); + try { + await startServer(); + } catch (e) { + vscode.window.showErrorMessage(e.message); + } if (Server.config.displayInlayHints) { const hintsUpdater = new HintsUpdater(); @@ -204,10 +208,10 @@ export function deactivate(): Thenable { return Server.client.stop(); } -async function reloadServer(startServer: () => void) { +async function reloadServer(startServer: () => Promise) { if (Server.client != null) { vscode.window.showInformationMessage('Reloading rust-analyzer...'); await Server.client.stop(); - startServer(); + await startServer(); } } diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts index 7907b70bc5..e717ab294d 100644 --- a/editors/code/src/server.ts +++ b/editors/code/src/server.ts @@ -1,3 +1,4 @@ +import { lookpath } from 'lookpath'; import { homedir } from 'os'; import * as lc from 'vscode-languageclient'; @@ -17,7 +18,7 @@ export class Server { public static config = new Config(); public static client: lc.LanguageClient; - public static start( + public static async start( notificationHandlers: Iterable<[string, lc.GenericNotificationHandler]> ) { // '.' Is the fallback if no folder is open @@ -27,8 +28,14 @@ export class Server { folder = workspace.workspaceFolders[0].uri.fsPath.toString(); } + const command = expandPathResolving(this.config.raLspServerPath); + if (!(await lookpath(command))) { + throw new Error( + `Cannot find rust-analyzer server \`${command}\` in PATH.` + ); + } const run: lc.Executable = { - command: expandPathResolving(this.config.raLspServerPath), + command, options: { cwd: folder } }; const serverOptions: lc.ServerOptions = {