diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-04-27 20:41:35 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-04-27 20:41:35 +0000 |
| commit | fb45d2adeccfc6732b702cd8fa2911b385bc15b7 (patch) | |
| tree | 41ab22e69528ccb346bc01b913f9251a24925960 | |
| parent | e2b87735cc4b54ca530e7a99070da585d480b1c3 (diff) | |
| parent | 1b4197cb3520e4a71f118aac61a83bab1a6f5931 (diff) | |
| download | rust-fb45d2adeccfc6732b702cd8fa2911b385bc15b7.tar.gz rust-fb45d2adeccfc6732b702cd8fa2911b385bc15b7.zip | |
Merge #8624
8624: Automatically detect rust library source file map r=vsrs a=vsrs
This PR adds a new possible `rust-analyzer.debug.sourceFileMap` value:
```json
{
"rust-analyzer.debug.sourceFileMap": "auto"
}
```
I did not make it the default because it uses two shell calls (`rustc --print sysroot` and `rustc -V -v`). First one can be slow (https://github.com/rust-lang/rustup/issues/783)
Fixes #8619
Co-authored-by: vsrs <vit@conrlab.com>
| -rw-r--r-- | editors/code/package.json | 5 | ||||
| -rw-r--r-- | editors/code/src/config.ts | 8 | ||||
| -rw-r--r-- | editors/code/src/debug.ts | 14 | ||||
| -rw-r--r-- | editors/code/src/toolchain.ts | 20 | ||||
| -rw-r--r-- | editors/code/src/util.ts | 21 |
5 files changed, 60 insertions, 8 deletions
diff --git a/editors/code/package.json b/editors/code/package.json index 97d92e43c82..35b50e669d3 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -353,8 +353,9 @@ "Use [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)" ] }, - "rust-analyzer.debug.sourceFileMap": { - "type": "object", + "rust-analyzer.debug.sourceFileMap": { + "type": ["object", "string"], + "const": "auto", "description": "Optional source file mappings passed to the debug engine.", "default": { "/rustc/<id>": "${env:USERPROFILE}/.rustup/toolchains/<toolchain-id>/lib/rustlib/src/rust" diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 03f7d7cc348..e858f80bcc4 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -135,8 +135,12 @@ export class Config { } get debug() { - // "/rustc/<id>" used by suggestions only. - const { ["/rustc/<id>"]: _, ...sourceFileMap } = this.get<Record<string, string>>("debug.sourceFileMap"); + let sourceFileMap = this.get<Record<string, string> | "auto">("debug.sourceFileMap"); + if (sourceFileMap !== "auto") { + // "/rustc/<id>" used by suggestions only. + const { ["/rustc/<id>"]: _, ...trimmed } = this.get<Record<string, string>>("debug.sourceFileMap"); + sourceFileMap = trimmed; + } return { engine: this.get<string>("debug.engine"), diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts index 3889a277304..830980f968c 100644 --- a/editors/code/src/debug.ts +++ b/editors/code/src/debug.ts @@ -3,7 +3,7 @@ import * as vscode from 'vscode'; import * as path from 'path'; import * as ra from './lsp_ext'; -import { Cargo } from './toolchain'; +import { Cargo, getRustcId, getSysroot } from './toolchain'; import { Ctx } from "./ctx"; import { prepareEnv } from "./run"; @@ -104,7 +104,17 @@ async function getDebugConfiguration(ctx: Ctx, runnable: ra.Runnable): Promise<v const executable = await getDebugExecutable(runnable); const env = prepareEnv(runnable, ctx.config.runnableEnv); - const debugConfig = knownEngines[debugEngine.id](runnable, simplifyPath(executable), env, debugOptions.sourceFileMap); + let sourceFileMap = debugOptions.sourceFileMap; + if (sourceFileMap === "auto") { + // let's try to use the default toolchain + const commitHash = await getRustcId(wsFolder); + const sysroot = await getSysroot(wsFolder); + const rustlib = path.normalize(sysroot + "/lib/rustlib/src/rust"); + sourceFileMap = {}; + sourceFileMap[`/rustc/${commitHash}/`] = rustlib; + } + + const debugConfig = knownEngines[debugEngine.id](runnable, simplifyPath(executable), env, sourceFileMap); if (debugConfig.type in debugOptions.engineSettings) { const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type]; for (var key in settingsMap) { diff --git a/editors/code/src/toolchain.ts b/editors/code/src/toolchain.ts index a5dc3cf0ccf..68826c478d3 100644 --- a/editors/code/src/toolchain.ts +++ b/editors/code/src/toolchain.ts @@ -4,7 +4,7 @@ import * as path from 'path'; import * as fs from 'fs'; import * as readline from 'readline'; import { OutputChannel } from 'vscode'; -import { log, memoize } from './util'; +import { execute, log, memoize } from './util'; interface CompilationArtifact { fileName: string; @@ -121,6 +121,24 @@ export class Cargo { } } +/** Mirrors `project_model::sysroot::discover_sysroot_dir()` implementation*/ +export function getSysroot(dir: string): Promise<string> { + const rustcPath = getPathForExecutable("rustc"); + + // do not memoize the result because the toolchain may change between runs + return execute(`${rustcPath} --print sysroot`, { cwd: dir }); +} + +export async function getRustcId(dir: string): Promise<string> { + const rustcPath = getPathForExecutable("rustc"); + + // do not memoize the result because the toolchain may change between runs + const data = await execute(`${rustcPath} -V -v`, { cwd: dir }); + const rx = /commit-hash:\s(.*)$/m.compile(); + + return rx.exec(data)![1]; +} + /** Mirrors `toolchain::cargo()` implementation */ export function cargoPath(): string { return getPathForExecutable("cargo"); diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts index 53492a445c4..56e0e439e98 100644 --- a/editors/code/src/util.ts +++ b/editors/code/src/util.ts @@ -1,7 +1,7 @@ import * as lc from "vscode-languageclient/node"; import * as vscode from "vscode"; import { strict as nativeAssert } from "assert"; -import { spawnSync } from "child_process"; +import { exec, ExecOptions, spawnSync } from "child_process"; import { inspect } from "util"; export function assert(condition: boolean, explanation: string): asserts condition { @@ -141,3 +141,22 @@ export function memoize<Ret, TThis, Param extends string>(func: (this: TThis, ar return result; }; } + +/** Awaitable wrapper around `child_process.exec` */ +export function execute(command: string, options: ExecOptions): Promise<string> { + return new Promise((resolve, reject) => { + exec(command, options, (err, stdout, stderr) => { + if (err) { + reject(err); + return; + } + + if (stderr) { + reject(new Error(stderr)); + return; + } + + resolve(stdout.trimEnd()); + }); + }); +} |
