diff options
Diffstat (limited to 'editors/code/src/main.ts')
-rw-r--r-- | editors/code/src/main.ts | 59 |
1 files changed, 56 insertions, 3 deletions
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 8b0a9d870..b7337621c 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import * as vscode from 'vscode'; | 1 | import * as vscode from 'vscode'; |
2 | import * as path from "path"; | 2 | import * as path from "path"; |
3 | import * as os from "os"; | 3 | import * as os from "os"; |
4 | import { promises as fs } from "fs"; | 4 | import { promises as fs, PathLike } from "fs"; |
5 | 5 | ||
6 | import * as commands from './commands'; | 6 | import * as commands from './commands'; |
7 | import { activateInlayHints } from './inlay_hints'; | 7 | import { activateInlayHints } from './inlay_hints'; |
@@ -12,9 +12,13 @@ import { log, assert, isValidExecutable } from './util'; | |||
12 | import { PersistentState } from './persistent_state'; | 12 | import { PersistentState } from './persistent_state'; |
13 | import { fetchRelease, download } from './net'; | 13 | import { fetchRelease, download } from './net'; |
14 | import { activateTaskProvider } from './tasks'; | 14 | import { activateTaskProvider } from './tasks'; |
15 | import { setContextValue } from './util'; | ||
16 | import { exec } from 'child_process'; | ||
15 | 17 | ||
16 | let ctx: Ctx | undefined; | 18 | let ctx: Ctx | undefined; |
17 | 19 | ||
20 | const RUST_PROJECT_CONTEXT_NAME = "inRustProject"; | ||
21 | |||
18 | export async function activate(context: vscode.ExtensionContext) { | 22 | export async function activate(context: vscode.ExtensionContext) { |
19 | // Register a "dumb" onEnter command for the case where server fails to | 23 | // Register a "dumb" onEnter command for the case where server fails to |
20 | // start. | 24 | // start. |
@@ -53,6 +57,8 @@ export async function activate(context: vscode.ExtensionContext) { | |||
53 | // This a horribly, horribly wrong way to deal with this problem. | 57 | // This a horribly, horribly wrong way to deal with this problem. |
54 | ctx = await Ctx.create(config, context, serverPath, workspaceFolder.uri.fsPath); | 58 | ctx = await Ctx.create(config, context, serverPath, workspaceFolder.uri.fsPath); |
55 | 59 | ||
60 | setContextValue(RUST_PROJECT_CONTEXT_NAME, true); | ||
61 | |||
56 | // Commands which invokes manually via command palette, shortcut, etc. | 62 | // Commands which invokes manually via command palette, shortcut, etc. |
57 | 63 | ||
58 | // Reloading is inspired by @DanTup maneuver: https://github.com/microsoft/vscode/issues/45774#issuecomment-373423895 | 64 | // Reloading is inspired by @DanTup maneuver: https://github.com/microsoft/vscode/issues/45774#issuecomment-373423895 |
@@ -85,14 +91,14 @@ export async function activate(context: vscode.ExtensionContext) { | |||
85 | 91 | ||
86 | ctx.registerCommand('ssr', commands.ssr); | 92 | ctx.registerCommand('ssr', commands.ssr); |
87 | ctx.registerCommand('serverVersion', commands.serverVersion); | 93 | ctx.registerCommand('serverVersion', commands.serverVersion); |
94 | ctx.registerCommand('toggleInlayHints', commands.toggleInlayHints); | ||
88 | 95 | ||
89 | // Internal commands which are invoked by the server. | 96 | // Internal commands which are invoked by the server. |
90 | ctx.registerCommand('runSingle', commands.runSingle); | 97 | ctx.registerCommand('runSingle', commands.runSingle); |
91 | ctx.registerCommand('debugSingle', commands.debugSingle); | 98 | ctx.registerCommand('debugSingle', commands.debugSingle); |
92 | ctx.registerCommand('showReferences', commands.showReferences); | 99 | ctx.registerCommand('showReferences', commands.showReferences); |
93 | ctx.registerCommand('applySourceChange', commands.applySourceChange); | ||
94 | ctx.registerCommand('applySnippetWorkspaceEdit', commands.applySnippetWorkspaceEditCommand); | 100 | ctx.registerCommand('applySnippetWorkspaceEdit', commands.applySnippetWorkspaceEditCommand); |
95 | ctx.registerCommand('selectAndApplySourceChange', commands.selectAndApplySourceChange); | 101 | ctx.registerCommand('applyActionGroup', commands.applyActionGroup); |
96 | 102 | ||
97 | ctx.pushCleanup(activateTaskProvider(workspaceFolder)); | 103 | ctx.pushCleanup(activateTaskProvider(workspaceFolder)); |
98 | 104 | ||
@@ -108,6 +114,7 @@ export async function activate(context: vscode.ExtensionContext) { | |||
108 | } | 114 | } |
109 | 115 | ||
110 | export async function deactivate() { | 116 | export async function deactivate() { |
117 | setContextValue(RUST_PROJECT_CONTEXT_NAME, undefined); | ||
111 | await ctx?.client.stop(); | 118 | await ctx?.client.stop(); |
112 | ctx = undefined; | 119 | ctx = undefined; |
113 | } | 120 | } |
@@ -188,6 +195,46 @@ async function bootstrapServer(config: Config, state: PersistentState): Promise< | |||
188 | return path; | 195 | return path; |
189 | } | 196 | } |
190 | 197 | ||
198 | async function patchelf(dest: PathLike): Promise<void> { | ||
199 | await vscode.window.withProgress( | ||
200 | { | ||
201 | location: vscode.ProgressLocation.Notification, | ||
202 | title: "Patching rust-analyzer for NixOS" | ||
203 | }, | ||
204 | async (progress, _) => { | ||
205 | const expression = ` | ||
206 | {src, pkgs ? import <nixpkgs> {}}: | ||
207 | pkgs.stdenv.mkDerivation { | ||
208 | name = "rust-analyzer"; | ||
209 | inherit src; | ||
210 | phases = [ "installPhase" "fixupPhase" ]; | ||
211 | installPhase = "cp $src $out"; | ||
212 | fixupPhase = '' | ||
213 | chmod 755 $out | ||
214 | patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" $out | ||
215 | ''; | ||
216 | } | ||
217 | `; | ||
218 | const origFile = dest + "-orig"; | ||
219 | await fs.rename(dest, origFile); | ||
220 | progress.report({ message: "Patching executable", increment: 20 }); | ||
221 | await new Promise((resolve, reject) => { | ||
222 | const handle = exec(`nix-build -E - --arg src '${origFile}' -o ${dest}`, | ||
223 | (err, stdout, stderr) => { | ||
224 | if (err != null) { | ||
225 | reject(Error(stderr)); | ||
226 | } else { | ||
227 | resolve(stdout); | ||
228 | } | ||
229 | }); | ||
230 | handle.stdin?.write(expression); | ||
231 | handle.stdin?.end(); | ||
232 | }); | ||
233 | await fs.unlink(origFile); | ||
234 | } | ||
235 | ); | ||
236 | } | ||
237 | |||
191 | async function getServer(config: Config, state: PersistentState): Promise<string | undefined> { | 238 | async function getServer(config: Config, state: PersistentState): Promise<string | undefined> { |
192 | const explicitPath = process.env.__RA_LSP_SERVER_DEBUG ?? config.serverPath; | 239 | const explicitPath = process.env.__RA_LSP_SERVER_DEBUG ?? config.serverPath; |
193 | if (explicitPath) { | 240 | if (explicitPath) { |
@@ -237,6 +284,12 @@ async function getServer(config: Config, state: PersistentState): Promise<string | |||
237 | assert(!!artifact, `Bad release: ${JSON.stringify(release)}`); | 284 | assert(!!artifact, `Bad release: ${JSON.stringify(release)}`); |
238 | 285 | ||
239 | await download(artifact.browser_download_url, dest, "Downloading rust-analyzer server", { mode: 0o755 }); | 286 | await download(artifact.browser_download_url, dest, "Downloading rust-analyzer server", { mode: 0o755 }); |
287 | |||
288 | // Patching executable if that's NixOS. | ||
289 | if (await fs.stat("/etc/nixos").then(_ => true).catch(_ => false)) { | ||
290 | await patchelf(dest); | ||
291 | } | ||
292 | |||
240 | await state.updateServerVersion(config.package.version); | 293 | await state.updateServerVersion(config.package.version); |
241 | return dest; | 294 | return dest; |
242 | } | 295 | } |