diff options
Diffstat (limited to 'editors/code/src')
-rw-r--r-- | editors/code/src/client.ts | 11 | ||||
-rw-r--r-- | editors/code/src/commands.ts | 8 | ||||
-rw-r--r-- | editors/code/src/config.ts | 3 | ||||
-rw-r--r-- | editors/code/src/ctx.ts | 2 | ||||
-rw-r--r-- | editors/code/src/main.ts | 50 |
5 files changed, 56 insertions, 18 deletions
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index 63ab82dde..539e487ec 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts | |||
@@ -6,6 +6,10 @@ import { DocumentSemanticsTokensSignature, DocumentSemanticsTokensEditsSignature | |||
6 | import { assert } from './util'; | 6 | import { assert } from './util'; |
7 | import { WorkspaceEdit } from 'vscode'; | 7 | import { WorkspaceEdit } from 'vscode'; |
8 | 8 | ||
9 | export interface Env { | ||
10 | [name: string]: string; | ||
11 | } | ||
12 | |||
9 | function renderCommand(cmd: ra.CommandLink) { | 13 | function renderCommand(cmd: ra.CommandLink) { |
10 | return `[${cmd.title}](command:${cmd.command}?${encodeURIComponent(JSON.stringify(cmd.arguments))} '${cmd.tooltip!}')`; | 14 | return `[${cmd.title}](command:${cmd.command}?${encodeURIComponent(JSON.stringify(cmd.arguments))} '${cmd.tooltip!}')`; |
11 | } | 15 | } |
@@ -27,14 +31,17 @@ async function semanticHighlightingWorkaround<R, F extends (...args: any[]) => v | |||
27 | return res; | 31 | return res; |
28 | } | 32 | } |
29 | 33 | ||
30 | export function createClient(serverPath: string, cwd: string): lc.LanguageClient { | 34 | export function createClient(serverPath: string, cwd: string, extraEnv: Env): lc.LanguageClient { |
31 | // '.' Is the fallback if no folder is open | 35 | // '.' Is the fallback if no folder is open |
32 | // TODO?: Workspace folders support Uri's (eg: file://test.txt). | 36 | // TODO?: Workspace folders support Uri's (eg: file://test.txt). |
33 | // It might be a good idea to test if the uri points to a file. | 37 | // It might be a good idea to test if the uri points to a file. |
34 | 38 | ||
39 | const newEnv = Object.assign({}, process.env); | ||
40 | Object.assign(newEnv, extraEnv); | ||
41 | |||
35 | const run: lc.Executable = { | 42 | const run: lc.Executable = { |
36 | command: serverPath, | 43 | command: serverPath, |
37 | options: { cwd }, | 44 | options: { cwd, env: newEnv }, |
38 | }; | 45 | }; |
39 | const serverOptions: lc.ServerOptions = { | 46 | const serverOptions: lc.ServerOptions = { |
40 | run, | 47 | run, |
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index 92bc4d7f7..b12e134ca 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts | |||
@@ -469,8 +469,14 @@ export function resolveCodeAction(ctx: Ctx): Cmd { | |||
469 | if (!item.edit) { | 469 | if (!item.edit) { |
470 | return; | 470 | return; |
471 | } | 471 | } |
472 | const edit = client.protocol2CodeConverter.asWorkspaceEdit(item.edit); | 472 | const itemEdit = item.edit; |
473 | const edit = client.protocol2CodeConverter.asWorkspaceEdit(itemEdit); | ||
474 | // filter out all text edits and recreate the WorkspaceEdit without them so we can apply | ||
475 | // snippet edits on our own | ||
476 | const itemEditWithoutTextEdits = { ...item, documentChanges: itemEdit.documentChanges?.filter(change => "kind" in change) }; | ||
477 | const editWithoutTextEdits = client.protocol2CodeConverter.asWorkspaceEdit(itemEditWithoutTextEdits); | ||
473 | await applySnippetWorkspaceEdit(edit); | 478 | await applySnippetWorkspaceEdit(edit); |
479 | await vscode.workspace.applyEdit(editWithoutTextEdits); | ||
474 | }; | 480 | }; |
475 | } | 481 | } |
476 | 482 | ||
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 848e92af9..fe9f3b4a8 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import * as vscode from 'vscode'; | 1 | import * as vscode from 'vscode'; |
2 | import { Env } from './client'; | ||
2 | import { log } from "./util"; | 3 | import { log } from "./util"; |
3 | 4 | ||
4 | export type UpdatesChannel = "stable" | "nightly"; | 5 | export type UpdatesChannel = "stable" | "nightly"; |
@@ -13,6 +14,7 @@ export class Config { | |||
13 | readonly rootSection = "rust-analyzer"; | 14 | readonly rootSection = "rust-analyzer"; |
14 | private readonly requiresReloadOpts = [ | 15 | private readonly requiresReloadOpts = [ |
15 | "serverPath", | 16 | "serverPath", |
17 | "server", | ||
16 | "cargo", | 18 | "cargo", |
17 | "procMacro", | 19 | "procMacro", |
18 | "files", | 20 | "files", |
@@ -92,6 +94,7 @@ export class Config { | |||
92 | } | 94 | } |
93 | 95 | ||
94 | get serverPath() { return this.get<null | string>("serverPath"); } | 96 | get serverPath() { return this.get<null | string>("serverPath"); } |
97 | get serverExtraEnv() { return this.get<Env | null>("server.extraEnv") ?? {}; } | ||
95 | get channel() { return this.get<UpdatesChannel>("updates.channel"); } | 98 | get channel() { return this.get<UpdatesChannel>("updates.channel"); } |
96 | get askBeforeDownload() { return this.get<boolean>("updates.askBeforeDownload"); } | 99 | get askBeforeDownload() { return this.get<boolean>("updates.askBeforeDownload"); } |
97 | get traceExtension() { return this.get<boolean>("trace.extension"); } | 100 | get traceExtension() { return this.get<boolean>("trace.extension"); } |
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index d39864d33..e7585184b 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts | |||
@@ -24,7 +24,7 @@ export class Ctx { | |||
24 | serverPath: string, | 24 | serverPath: string, |
25 | cwd: string, | 25 | cwd: string, |
26 | ): Promise<Ctx> { | 26 | ): Promise<Ctx> { |
27 | const client = createClient(serverPath, cwd); | 27 | const client = createClient(serverPath, cwd, config.serverExtraEnv); |
28 | 28 | ||
29 | const statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); | 29 | const statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); |
30 | extCtx.subscriptions.push(statusBar); | 30 | extCtx.subscriptions.push(statusBar); |
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 191960960..282240d84 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts | |||
@@ -19,9 +19,8 @@ let ctx: Ctx | undefined; | |||
19 | const RUST_PROJECT_CONTEXT_NAME = "inRustProject"; | 19 | const RUST_PROJECT_CONTEXT_NAME = "inRustProject"; |
20 | 20 | ||
21 | export async function activate(context: vscode.ExtensionContext) { | 21 | export async function activate(context: vscode.ExtensionContext) { |
22 | // For some reason vscode not always shows pop-up error notifications | 22 | // VS Code doesn't show a notification when an extension fails to activate |
23 | // when an extension fails to activate, so we do it explicitly by ourselves. | 23 | // so we do it ourselves. |
24 | // FIXME: remove this bit of code once vscode fixes this issue: https://github.com/microsoft/vscode/issues/101242 | ||
25 | await tryActivate(context).catch(err => { | 24 | await tryActivate(context).catch(err => { |
26 | void vscode.window.showErrorMessage(`Cannot activate rust-analyzer: ${err.message}`); | 25 | void vscode.window.showErrorMessage(`Cannot activate rust-analyzer: ${err.message}`); |
27 | throw err; | 26 | throw err; |
@@ -132,7 +131,7 @@ async function tryActivate(context: vscode.ExtensionContext) { | |||
132 | ctx.pushCleanup(activateTaskProvider(workspaceFolder, ctx.config)); | 131 | ctx.pushCleanup(activateTaskProvider(workspaceFolder, ctx.config)); |
133 | 132 | ||
134 | activateInlayHints(ctx); | 133 | activateInlayHints(ctx); |
135 | warnAboutRustLangExtensionConflict(); | 134 | warnAboutExtensionConflicts(); |
136 | 135 | ||
137 | vscode.workspace.onDidChangeConfiguration( | 136 | vscode.workspace.onDidChangeConfiguration( |
138 | _ => ctx?.client?.sendNotification('workspace/didChangeConfiguration', { settings: "" }), | 137 | _ => ctx?.client?.sendNotification('workspace/didChangeConfiguration', { settings: "" }), |
@@ -288,10 +287,14 @@ async function getServer(config: Config, state: PersistentState): Promise<string | |||
288 | if (config.package.releaseTag === null) return "rust-analyzer"; | 287 | if (config.package.releaseTag === null) return "rust-analyzer"; |
289 | 288 | ||
290 | let platform: string | undefined; | 289 | let platform: string | undefined; |
291 | if (process.arch === "x64" || process.arch === "ia32") { | 290 | if ((process.arch === "x64" || process.arch === "ia32") && process.platform === "win32") { |
292 | if (process.platform === "linux") platform = "linux"; | 291 | platform = "x86_64-pc-windows-msvc"; |
293 | if (process.platform === "darwin") platform = "mac"; | 292 | } else if (process.arch === "x64" && process.platform === "linux") { |
294 | if (process.platform === "win32") platform = "windows"; | 293 | platform = "x86_64-unknown-linux-gnu"; |
294 | } else if (process.arch === "x64" && process.platform === "darwin") { | ||
295 | platform = "x86_64-apple-darwin"; | ||
296 | } else if (process.arch === "arm64" && process.platform === "darwin") { | ||
297 | platform = "aarch64-apple-darwin"; | ||
295 | } | 298 | } |
296 | if (platform === undefined) { | 299 | if (platform === undefined) { |
297 | vscode.window.showErrorMessage( | 300 | vscode.window.showErrorMessage( |
@@ -304,7 +307,7 @@ async function getServer(config: Config, state: PersistentState): Promise<string | |||
304 | ); | 307 | ); |
305 | return undefined; | 308 | return undefined; |
306 | } | 309 | } |
307 | const ext = platform === "windows" ? ".exe" : ""; | 310 | const ext = platform.indexOf("-windows-") !== -1 ? ".exe" : ""; |
308 | const dest = path.join(config.globalStoragePath, `rust-analyzer-${platform}${ext}`); | 311 | const dest = path.join(config.globalStoragePath, `rust-analyzer-${platform}${ext}`); |
309 | const exists = await fs.stat(dest).then(() => true, () => false); | 312 | const exists = await fs.stat(dest).then(() => true, () => false); |
310 | if (!exists) { | 313 | if (!exists) { |
@@ -340,7 +343,7 @@ async function getServer(config: Config, state: PersistentState): Promise<string | |||
340 | }); | 343 | }); |
341 | 344 | ||
342 | // Patching executable if that's NixOS. | 345 | // Patching executable if that's NixOS. |
343 | if (await fs.stat("/etc/nixos").then(_ => true).catch(_ => false)) { | 346 | if (await isNixOs()) { |
344 | await patchelf(dest); | 347 | await patchelf(dest); |
345 | } | 348 | } |
346 | 349 | ||
@@ -348,6 +351,15 @@ async function getServer(config: Config, state: PersistentState): Promise<string | |||
348 | return dest; | 351 | return dest; |
349 | } | 352 | } |
350 | 353 | ||
354 | async function isNixOs(): Promise<boolean> { | ||
355 | try { | ||
356 | const contents = await fs.readFile("/etc/os-release"); | ||
357 | return contents.indexOf("ID=nixos") !== -1; | ||
358 | } catch (e) { | ||
359 | return false; | ||
360 | } | ||
361 | } | ||
362 | |||
351 | async function downloadWithRetryDialog<T>(state: PersistentState, downloadFunc: () => Promise<T>): Promise<T> { | 363 | async function downloadWithRetryDialog<T>(state: PersistentState, downloadFunc: () => Promise<T>): Promise<T> { |
352 | while (true) { | 364 | while (true) { |
353 | try { | 365 | try { |
@@ -401,11 +413,21 @@ async function queryForGithubToken(state: PersistentState): Promise<void> { | |||
401 | } | 413 | } |
402 | } | 414 | } |
403 | 415 | ||
404 | function warnAboutRustLangExtensionConflict() { | 416 | function warnAboutExtensionConflicts() { |
405 | const rustLangExt = vscode.extensions.getExtension("rust-lang.rust"); | 417 | const conflicting = [ |
406 | if (rustLangExt !== undefined) { | 418 | ["rust-analyzer", "matklad.rust-analyzer"], |
419 | ["Rust", "rust-lang.rust"], | ||
420 | ["Rust", "kalitaalexey.vscode-rust"], | ||
421 | ]; | ||
422 | |||
423 | const found = conflicting.filter( | ||
424 | nameId => vscode.extensions.getExtension(nameId[1]) !== undefined); | ||
425 | |||
426 | if (found.length > 1) { | ||
427 | const fst = found[0]; | ||
428 | const sec = found[1]; | ||
407 | vscode.window.showWarningMessage( | 429 | vscode.window.showWarningMessage( |
408 | "You have both rust-analyzer (matklad.rust-analyzer) and Rust (rust-lang.rust) " + | 430 | `You have both the ${fst[0]} (${fst[1]}) and ${sec[0]} (${sec[1]}) ` + |
409 | "plugins enabled. These are known to conflict and cause various functions of " + | 431 | "plugins enabled. These are known to conflict and cause various functions of " + |
410 | "both plugins to not work correctly. You should disable one of them.", "Got it"); | 432 | "both plugins to not work correctly. You should disable one of them.", "Got it"); |
411 | }; | 433 | }; |