X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=editors%2Fcode%2Fsrc%2Fmain.ts;h=0e5a206410e0a4e6dcedbfb77b60b41f84b447c2;hb=5dab5e737909532e4a65390541393af6ee72f65b;hp=814ae9dc251696da24d7bf697139f6010e26f3a7;hpb=68ff71e3ab91f01039bb30121d05d0289bb1bd1f;p=rust.git diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 814ae9dc251..0e5a206410e 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -1,18 +1,18 @@ import * as vscode from 'vscode'; import * as path from "path"; import * as os from "os"; -import { promises as fs } from "fs"; +import { promises as fs, PathLike } from "fs"; import * as commands from './commands'; import { activateInlayHints } from './inlay_hints'; import { activateStatusDisplay } from './status_display'; import { Ctx } from './ctx'; -import { activateHighlighting } from './highlighting'; import { Config, NIGHTLY_TAG } from './config'; -import { log, assert } from './util'; +import { log, assert, isValidExecutable } from './util'; import { PersistentState } from './persistent_state'; import { fetchRelease, download } from './net'; -import { spawnSync } from 'child_process'; +import { activateTaskProvider } from './tasks'; +import { exec } from 'child_process'; let ctx: Ctx | undefined; @@ -41,28 +41,33 @@ export async function activate(context: vscode.ExtensionContext) { const state = new PersistentState(context.globalState); const serverPath = await bootstrap(config, state); + const workspaceFolder = vscode.workspace.workspaceFolders?.[0]; + if (workspaceFolder === undefined) { + const err = "Cannot activate rust-analyzer when no folder is opened"; + void vscode.window.showErrorMessage(err); + throw new Error(err); + } + // Note: we try to start the server before we activate type hints so that it // registers its `onDidChangeDocument` handler before us. // // This a horribly, horribly wrong way to deal with this problem. - ctx = await Ctx.create(config, context, serverPath); + ctx = await Ctx.create(config, context, serverPath, workspaceFolder.uri.fsPath); // Commands which invokes manually via command palette, shortcut, etc. - ctx.registerCommand('reload', (ctx) => { - return async () => { - vscode.window.showInformationMessage('Reloading rust-analyzer...'); - // @DanTup maneuver - // https://github.com/microsoft/vscode/issues/45774#issuecomment-373423895 - await deactivate(); - for (const sub of ctx.subscriptions) { - try { - sub.dispose(); - } catch (e) { - log.error(e); - } + + // Reloading is inspired by @DanTup maneuver: https://github.com/microsoft/vscode/issues/45774#issuecomment-373423895 + ctx.registerCommand('reload', _ => async () => { + void vscode.window.showInformationMessage('Reloading rust-analyzer...'); + await deactivate(); + while (context.subscriptions.length > 0) { + try { + context.subscriptions.pop()!.dispose(); + } catch (err) { + log.error("Dispose error:", err); } - await activate(context); - }; + } + await activate(context).catch(log.error); }); ctx.registerCommand('analyzerStatus', commands.analyzerStatus); @@ -73,30 +78,39 @@ export async function activate(context: vscode.ExtensionContext) { ctx.registerCommand('syntaxTree', commands.syntaxTree); ctx.registerCommand('expandMacro', commands.expandMacro); ctx.registerCommand('run', commands.run); + ctx.registerCommand('debug', commands.debug); + ctx.registerCommand('newDebugConfig', commands.newDebugConfig); defaultOnEnter.dispose(); ctx.registerCommand('onEnter', commands.onEnter); ctx.registerCommand('ssr', commands.ssr); ctx.registerCommand('serverVersion', commands.serverVersion); + ctx.registerCommand('toggleInlayHints', commands.toggleInlayHints); // Internal commands which are invoked by the server. ctx.registerCommand('runSingle', commands.runSingle); ctx.registerCommand('debugSingle', commands.debugSingle); ctx.registerCommand('showReferences', commands.showReferences); ctx.registerCommand('applySourceChange', commands.applySourceChange); - ctx.registerCommand('selectAndApplySourceChange', commands.selectAndApplySourceChange); + ctx.registerCommand('applySnippetWorkspaceEdit', commands.applySnippetWorkspaceEditCommand); + ctx.registerCommand('applyActionGroup', commands.applyActionGroup); + + ctx.pushCleanup(activateTaskProvider(workspaceFolder)); activateStatusDisplay(ctx); - if (!ctx.config.highlightingSemanticTokens) { - activateHighlighting(ctx); - } activateInlayHints(ctx); + + vscode.workspace.onDidChangeConfiguration( + _ => ctx?.client?.sendNotification('workspace/didChangeConfiguration', { settings: "" }), + null, + ctx.subscriptions, + ); } export async function deactivate() { - await ctx?.client?.stop(); + await ctx?.client.stop(); ctx = undefined; } @@ -167,18 +181,55 @@ async function bootstrapServer(config: Config, state: PersistentState): Promise< ); } - const res = spawnSync(path, ["--version"], { encoding: 'utf8' }); - log.debug("Checked binary availability via --version", res); - log.debug(res, "--version output:", res.output); - if (res.status !== 0) { - throw new Error( - `Failed to execute ${path} --version` - ); + log.debug("Using server binary at", path); + + if (!isValidExecutable(path)) { + throw new Error(`Failed to execute ${path} --version`); } return path; } +async function patchelf(dest: PathLike): Promise { + await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: "Patching rust-analyzer for NixOS" + }, + async (progress, _) => { + const expression = ` + {src, pkgs ? import {}}: + pkgs.stdenv.mkDerivation { + name = "rust-analyzer"; + inherit src; + phases = [ "installPhase" "fixupPhase" ]; + installPhase = "cp $src $out"; + fixupPhase = '' + chmod 755 $out + patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" $out + ''; + } + `; + const origFile = dest + "-orig"; + await fs.rename(dest, origFile); + progress.report({ message: "Patching executable", increment: 20 }); + await new Promise((resolve, reject) => { + const handle = exec(`nix-build -E - --arg src '${origFile}' -o ${dest}`, + (err, stdout, stderr) => { + if (err != null) { + reject(Error(stderr)); + } else { + resolve(stdout); + } + }); + handle.stdin?.write(expression); + handle.stdin?.end(); + }); + await fs.unlink(origFile); + } + ); +} + async function getServer(config: Config, state: PersistentState): Promise { const explicitPath = process.env.__RA_LSP_SERVER_DEBUG ?? config.serverPath; if (explicitPath) { @@ -228,6 +279,12 @@ async function getServer(config: Config, state: PersistentState): Promise true).catch(_ => false)) { + await patchelf(dest); + } + await state.updateServerVersion(config.package.version); return dest; }