diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-04-27 21:41:35 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-04-27 21:41:35 +0100 |
commit | fb45d2adeccfc6732b702cd8fa2911b385bc15b7 (patch) | |
tree | 41ab22e69528ccb346bc01b913f9251a24925960 /editors/code/src | |
parent | e2b87735cc4b54ca530e7a99070da585d480b1c3 (diff) | |
parent | 1b4197cb3520e4a71f118aac61a83bab1a6f5931 (diff) |
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 <[email protected]>
Diffstat (limited to 'editors/code/src')
-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 |
4 files changed, 57 insertions, 6 deletions
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 03f7d7cc3..e858f80bc 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts | |||
@@ -135,8 +135,12 @@ export class Config { | |||
135 | } | 135 | } |
136 | 136 | ||
137 | get debug() { | 137 | get debug() { |
138 | // "/rustc/<id>" used by suggestions only. | 138 | let sourceFileMap = this.get<Record<string, string> | "auto">("debug.sourceFileMap"); |
139 | const { ["/rustc/<id>"]: _, ...sourceFileMap } = this.get<Record<string, string>>("debug.sourceFileMap"); | 139 | if (sourceFileMap !== "auto") { |
140 | // "/rustc/<id>" used by suggestions only. | ||
141 | const { ["/rustc/<id>"]: _, ...trimmed } = this.get<Record<string, string>>("debug.sourceFileMap"); | ||
142 | sourceFileMap = trimmed; | ||
143 | } | ||
140 | 144 | ||
141 | return { | 145 | return { |
142 | engine: this.get<string>("debug.engine"), | 146 | engine: this.get<string>("debug.engine"), |
diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts index 3889a2773..830980f96 100644 --- a/editors/code/src/debug.ts +++ b/editors/code/src/debug.ts | |||
@@ -3,7 +3,7 @@ import * as vscode from 'vscode'; | |||
3 | import * as path from 'path'; | 3 | import * as path from 'path'; |
4 | import * as ra from './lsp_ext'; | 4 | import * as ra from './lsp_ext'; |
5 | 5 | ||
6 | import { Cargo } from './toolchain'; | 6 | import { Cargo, getRustcId, getSysroot } from './toolchain'; |
7 | import { Ctx } from "./ctx"; | 7 | import { Ctx } from "./ctx"; |
8 | import { prepareEnv } from "./run"; | 8 | import { prepareEnv } from "./run"; |
9 | 9 | ||
@@ -104,7 +104,17 @@ async function getDebugConfiguration(ctx: Ctx, runnable: ra.Runnable): Promise<v | |||
104 | 104 | ||
105 | const executable = await getDebugExecutable(runnable); | 105 | const executable = await getDebugExecutable(runnable); |
106 | const env = prepareEnv(runnable, ctx.config.runnableEnv); | 106 | const env = prepareEnv(runnable, ctx.config.runnableEnv); |
107 | const debugConfig = knownEngines[debugEngine.id](runnable, simplifyPath(executable), env, debugOptions.sourceFileMap); | 107 | let sourceFileMap = debugOptions.sourceFileMap; |
108 | if (sourceFileMap === "auto") { | ||
109 | // let's try to use the default toolchain | ||
110 | const commitHash = await getRustcId(wsFolder); | ||
111 | const sysroot = await getSysroot(wsFolder); | ||
112 | const rustlib = path.normalize(sysroot + "/lib/rustlib/src/rust"); | ||
113 | sourceFileMap = {}; | ||
114 | sourceFileMap[`/rustc/${commitHash}/`] = rustlib; | ||
115 | } | ||
116 | |||
117 | const debugConfig = knownEngines[debugEngine.id](runnable, simplifyPath(executable), env, sourceFileMap); | ||
108 | if (debugConfig.type in debugOptions.engineSettings) { | 118 | if (debugConfig.type in debugOptions.engineSettings) { |
109 | const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type]; | 119 | const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type]; |
110 | for (var key in settingsMap) { | 120 | for (var key in settingsMap) { |
diff --git a/editors/code/src/toolchain.ts b/editors/code/src/toolchain.ts index a5dc3cf0c..68826c478 100644 --- a/editors/code/src/toolchain.ts +++ b/editors/code/src/toolchain.ts | |||
@@ -4,7 +4,7 @@ import * as path from 'path'; | |||
4 | import * as fs from 'fs'; | 4 | import * as fs from 'fs'; |
5 | import * as readline from 'readline'; | 5 | import * as readline from 'readline'; |
6 | import { OutputChannel } from 'vscode'; | 6 | import { OutputChannel } from 'vscode'; |
7 | import { log, memoize } from './util'; | 7 | import { execute, log, memoize } from './util'; |
8 | 8 | ||
9 | interface CompilationArtifact { | 9 | interface CompilationArtifact { |
10 | fileName: string; | 10 | fileName: string; |
@@ -121,6 +121,24 @@ export class Cargo { | |||
121 | } | 121 | } |
122 | } | 122 | } |
123 | 123 | ||
124 | /** Mirrors `project_model::sysroot::discover_sysroot_dir()` implementation*/ | ||
125 | export function getSysroot(dir: string): Promise<string> { | ||
126 | const rustcPath = getPathForExecutable("rustc"); | ||
127 | |||
128 | // do not memoize the result because the toolchain may change between runs | ||
129 | return execute(`${rustcPath} --print sysroot`, { cwd: dir }); | ||
130 | } | ||
131 | |||
132 | export async function getRustcId(dir: string): Promise<string> { | ||
133 | const rustcPath = getPathForExecutable("rustc"); | ||
134 | |||
135 | // do not memoize the result because the toolchain may change between runs | ||
136 | const data = await execute(`${rustcPath} -V -v`, { cwd: dir }); | ||
137 | const rx = /commit-hash:\s(.*)$/m.compile(); | ||
138 | |||
139 | return rx.exec(data)![1]; | ||
140 | } | ||
141 | |||
124 | /** Mirrors `toolchain::cargo()` implementation */ | 142 | /** Mirrors `toolchain::cargo()` implementation */ |
125 | export function cargoPath(): string { | 143 | export function cargoPath(): string { |
126 | return getPathForExecutable("cargo"); | 144 | return getPathForExecutable("cargo"); |
diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts index 53492a445..56e0e439e 100644 --- a/editors/code/src/util.ts +++ b/editors/code/src/util.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import * as lc from "vscode-languageclient/node"; | 1 | import * as lc from "vscode-languageclient/node"; |
2 | import * as vscode from "vscode"; | 2 | import * as vscode from "vscode"; |
3 | import { strict as nativeAssert } from "assert"; | 3 | import { strict as nativeAssert } from "assert"; |
4 | import { spawnSync } from "child_process"; | 4 | import { exec, ExecOptions, spawnSync } from "child_process"; |
5 | import { inspect } from "util"; | 5 | import { inspect } from "util"; |
6 | 6 | ||
7 | export function assert(condition: boolean, explanation: string): asserts condition { | 7 | 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 | |||
141 | return result; | 141 | return result; |
142 | }; | 142 | }; |
143 | } | 143 | } |
144 | |||
145 | /** Awaitable wrapper around `child_process.exec` */ | ||
146 | export function execute(command: string, options: ExecOptions): Promise<string> { | ||
147 | return new Promise((resolve, reject) => { | ||
148 | exec(command, options, (err, stdout, stderr) => { | ||
149 | if (err) { | ||
150 | reject(err); | ||
151 | return; | ||
152 | } | ||
153 | |||
154 | if (stderr) { | ||
155 | reject(new Error(stderr)); | ||
156 | return; | ||
157 | } | ||
158 | |||
159 | resolve(stdout.trimEnd()); | ||
160 | }); | ||
161 | }); | ||
162 | } | ||