aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorveetaha <[email protected]>2020-05-31 03:13:08 +0100
committerveetaha <[email protected]>2020-05-31 03:21:45 +0100
commitd605ec9c321392d9c7ee4b440c560e1e405d92e6 (patch)
tree58d16996d1d1a05733dcc85ae4efddc563b3d3b1
parenta419cedb1cc661349a022262c8b03993e063252f (diff)
Change Runnable.bin -> Runnable.kind
As per matklad, we now pass the responsibility for finding the binary to the frontend. Also, added caching for finding the binary path to reduce the amount of filesystem interactions.
-rw-r--r--Cargo.lock1
-rw-r--r--crates/rust-analyzer/Cargo.toml1
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs11
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs14
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/main.rs14
-rw-r--r--docs/dev/lsp-extensions.md2
-rw-r--r--editors/code/src/debug.ts2
-rw-r--r--editors/code/src/lsp_ext.ts5
-rw-r--r--editors/code/src/run.ts3
-rw-r--r--editors/code/src/tasks.ts4
-rw-r--r--editors/code/src/toolchain.ts (renamed from editors/code/src/cargo.ts)117
-rw-r--r--editors/code/src/util.ts18
-rw-r--r--editors/code/tests/unit/launch_config.test.ts14
13 files changed, 123 insertions, 83 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e1da335f5..07f18c760 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1365,7 +1365,6 @@ dependencies = [
1365 "ra_syntax", 1365 "ra_syntax",
1366 "ra_text_edit", 1366 "ra_text_edit",
1367 "ra_tt", 1367 "ra_tt",
1368 "ra_toolchain",
1369 "ra_vfs", 1368 "ra_vfs",
1370 "rand", 1369 "rand",
1371 "relative-path", 1370 "relative-path",
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 2e49448cc..65b487db3 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -48,7 +48,6 @@ hir = { path = "../ra_hir", package = "ra_hir" }
48hir_def = { path = "../ra_hir_def", package = "ra_hir_def" } 48hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
49hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" } 49hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" }
50ra_proc_macro_srv = { path = "../ra_proc_macro_srv" } 50ra_proc_macro_srv = { path = "../ra_proc_macro_srv" }
51ra_toolchain = { path = "../ra_toolchain" }
52 51
53[target.'cfg(windows)'.dependencies] 52[target.'cfg(windows)'.dependencies]
54winapi = "0.3.8" 53winapi = "0.3.8"
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index acb1dacb6..173c23b9e 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -121,12 +121,21 @@ pub struct RunnablesParams {
121 pub position: Option<Position>, 121 pub position: Option<Position>,
122} 122}
123 123
124// Must strictly correspond to the executable name
125#[derive(Serialize, Deserialize, Debug)]
126#[serde(rename_all = "lowercase")]
127pub enum RunnableKind {
128 Cargo,
129 Rustc,
130 Rustup,
131}
132
124#[derive(Deserialize, Serialize, Debug)] 133#[derive(Deserialize, Serialize, Debug)]
125#[serde(rename_all = "camelCase")] 134#[serde(rename_all = "camelCase")]
126pub struct Runnable { 135pub struct Runnable {
127 pub range: Range, 136 pub range: Range,
128 pub label: String, 137 pub label: String,
129 pub bin: String, 138 pub kind: RunnableKind,
130 pub args: Vec<String>, 139 pub args: Vec<String>,
131 pub extra_args: Vec<String>, 140 pub extra_args: Vec<String>,
132 pub env: FxHashMap<String, String>, 141 pub env: FxHashMap<String, String>,
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index d42cfa300..bc7c7f1ef 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -40,7 +40,6 @@ use crate::{
40 world::WorldSnapshot, 40 world::WorldSnapshot,
41 LspError, Result, 41 LspError, Result,
42}; 42};
43use anyhow::Context;
44 43
45pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> { 44pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> {
46 let _p = profile("handle_analyzer_status"); 45 let _p = profile("handle_analyzer_status");
@@ -427,7 +426,7 @@ pub fn handle_runnables(
427 res.push(lsp_ext::Runnable { 426 res.push(lsp_ext::Runnable {
428 range: Default::default(), 427 range: Default::default(),
429 label: format!("cargo {} -p {}", cmd, spec.package), 428 label: format!("cargo {} -p {}", cmd, spec.package),
430 bin: cargo_path()?, 429 kind: lsp_ext::RunnableKind::Cargo,
431 args: vec![cmd.to_string(), "--package".to_string(), spec.package.clone()], 430 args: vec![cmd.to_string(), "--package".to_string(), spec.package.clone()],
432 extra_args: Vec::new(), 431 extra_args: Vec::new(),
433 env: FxHashMap::default(), 432 env: FxHashMap::default(),
@@ -439,7 +438,7 @@ pub fn handle_runnables(
439 res.push(lsp_ext::Runnable { 438 res.push(lsp_ext::Runnable {
440 range: Default::default(), 439 range: Default::default(),
441 label: "cargo check --workspace".to_string(), 440 label: "cargo check --workspace".to_string(),
442 bin: cargo_path()?, 441 kind: lsp_ext::RunnableKind::Cargo,
443 args: vec!["check".to_string(), "--workspace".to_string()], 442 args: vec!["check".to_string(), "--workspace".to_string()],
444 extra_args: Vec::new(), 443 extra_args: Vec::new(),
445 env: FxHashMap::default(), 444 env: FxHashMap::default(),
@@ -450,13 +449,6 @@ pub fn handle_runnables(
450 Ok(res) 449 Ok(res)
451} 450}
452 451
453fn cargo_path() -> Result<String> {
454 Ok(ra_toolchain::cargo()
455 .to_str()
456 .context("Path to `cargo` executable contains invalid UTF8 characters")?
457 .to_owned())
458}
459
460pub fn handle_completion( 452pub fn handle_completion(
461 world: WorldSnapshot, 453 world: WorldSnapshot,
462 params: lsp_types::CompletionParams, 454 params: lsp_types::CompletionParams,
@@ -994,7 +986,7 @@ fn to_lsp_runnable(
994 Ok(lsp_ext::Runnable { 986 Ok(lsp_ext::Runnable {
995 range: to_proto::range(&line_index, runnable.range), 987 range: to_proto::range(&line_index, runnable.range),
996 label, 988 label,
997 bin: cargo_path()?, 989 kind: lsp_ext::RunnableKind::Cargo,
998 args, 990 args,
999 extra_args, 991 extra_args,
1000 env: { 992 env: {
diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs
index a31580c86..8b473ff74 100644
--- a/crates/rust-analyzer/tests/heavy_tests/main.rs
+++ b/crates/rust-analyzer/tests/heavy_tests/main.rs
@@ -58,10 +58,6 @@ use std::collections::Spam;
58 eprintln!("completion took {:?}", completion_start.elapsed()); 58 eprintln!("completion took {:?}", completion_start.elapsed());
59} 59}
60 60
61fn cargo_path() -> String {
62 ra_toolchain::cargo().to_str().unwrap().to_owned()
63}
64
65#[test] 61#[test]
66fn test_runnables_no_project() { 62fn test_runnables_no_project() {
67 if skip_slow_tests() { 63 if skip_slow_tests() {
@@ -83,7 +79,7 @@ fn foo() {
83 { 79 {
84 "args": [ "test" ], 80 "args": [ "test" ],
85 "extraArgs": [ "foo", "--nocapture" ], 81 "extraArgs": [ "foo", "--nocapture" ],
86 "bin": cargo_path(), 82 "kind": "cargo",
87 "env": { "RUST_BACKTRACE": "short" }, 83 "env": { "RUST_BACKTRACE": "short" },
88 "cwd": null, 84 "cwd": null,
89 "label": "test foo", 85 "label": "test foo",
@@ -95,7 +91,7 @@ fn foo() {
95 { 91 {
96 "args": ["check", "--workspace"], 92 "args": ["check", "--workspace"],
97 "extraArgs": [], 93 "extraArgs": [],
98 "bin": cargo_path(), 94 "kind": "cargo",
99 "env": {}, 95 "env": {},
100 "cwd": null, 96 "cwd": null,
101 "label": "cargo check --workspace", 97 "label": "cargo check --workspace",
@@ -145,7 +141,7 @@ fn main() {}
145 { 141 {
146 "args": [ "test", "--package", "foo", "--test", "spam" ], 142 "args": [ "test", "--package", "foo", "--test", "spam" ],
147 "extraArgs": [ "test_eggs", "--exact", "--nocapture" ], 143 "extraArgs": [ "test_eggs", "--exact", "--nocapture" ],
148 "bin": cargo_path(), 144 "kind": "cargo",
149 "env": { "RUST_BACKTRACE": "short" }, 145 "env": { "RUST_BACKTRACE": "short" },
150 "label": "test test_eggs", 146 "label": "test test_eggs",
151 "range": { 147 "range": {
@@ -157,7 +153,7 @@ fn main() {}
157 { 153 {
158 "args": [ "check", "--package", "foo" ], 154 "args": [ "check", "--package", "foo" ],
159 "extraArgs": [], 155 "extraArgs": [],
160 "bin": cargo_path(), 156 "kind": "cargo",
161 "env": {}, 157 "env": {},
162 "label": "cargo check -p foo", 158 "label": "cargo check -p foo",
163 "range": { 159 "range": {
@@ -169,7 +165,7 @@ fn main() {}
169 { 165 {
170 "args": [ "test", "--package", "foo" ], 166 "args": [ "test", "--package", "foo" ],
171 "extraArgs": [], 167 "extraArgs": [],
172 "bin": cargo_path(), 168 "kind": "cargo",
173 "env": {}, 169 "env": {},
174 "label": "cargo test -p foo", 170 "label": "cargo test -p foo",
175 "range": { 171 "range": {
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index dbc95be38..d06da355d 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -417,7 +417,7 @@ interface Runnable {
417 /// The label to show in the UI. 417 /// The label to show in the UI.
418 label: string; 418 label: string;
419 /// The following fields describe a process to spawn. 419 /// The following fields describe a process to spawn.
420 bin: string; 420 kind: "cargo" | "rustc" | "rustup";
421 args: string[]; 421 args: string[];
422 /// Args for cargo after `--`. 422 /// Args for cargo after `--`.
423 extraArgs: string[]; 423 extraArgs: string[];
diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts
index 027504ecd..bdec5b735 100644
--- a/editors/code/src/debug.ts
+++ b/editors/code/src/debug.ts
@@ -3,7 +3,7 @@ import * as vscode from 'vscode';
3import * as path from 'path'; 3import * as path from 'path';
4import * as ra from './lsp_ext'; 4import * as ra from './lsp_ext';
5 5
6import { Cargo } from './cargo'; 6import { Cargo } from './toolchain';
7import { Ctx } from "./ctx"; 7import { Ctx } from "./ctx";
8 8
9const debugOutput = vscode.window.createOutputChannel("Debug"); 9const debugOutput = vscode.window.createOutputChannel("Debug");
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index 4da12eb30..3e0b60699 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -45,10 +45,13 @@ export interface RunnablesParams {
45 textDocument: lc.TextDocumentIdentifier; 45 textDocument: lc.TextDocumentIdentifier;
46 position: lc.Position | null; 46 position: lc.Position | null;
47} 47}
48
49export type RunnableKind = "cargo" | "rustc" | "rustup";
50
48export interface Runnable { 51export interface Runnable {
49 range: lc.Range; 52 range: lc.Range;
50 label: string; 53 label: string;
51 bin: string; 54 kind: RunnableKind;
52 args: string[]; 55 args: string[];
53 extraArgs: string[]; 56 extraArgs: string[];
54 env: { [key: string]: string }; 57 env: { [key: string]: string };
diff --git a/editors/code/src/run.ts b/editors/code/src/run.ts
index 2a7a429cf..401cb76af 100644
--- a/editors/code/src/run.ts
+++ b/editors/code/src/run.ts
@@ -1,6 +1,7 @@
1import * as vscode from 'vscode'; 1import * as vscode from 'vscode';
2import * as lc from 'vscode-languageclient'; 2import * as lc from 'vscode-languageclient';
3import * as ra from './lsp_ext'; 3import * as ra from './lsp_ext';
4import * as toolchain from "./toolchain";
4 5
5import { Ctx, Cmd } from './ctx'; 6import { Ctx, Cmd } from './ctx';
6import { startDebugSession, getDebugConfiguration } from './debug'; 7import { startDebugSession, getDebugConfiguration } from './debug';
@@ -175,7 +176,7 @@ export function createTask(spec: ra.Runnable): vscode.Task {
175 const definition: CargoTaskDefinition = { 176 const definition: CargoTaskDefinition = {
176 type: 'cargo', 177 type: 'cargo',
177 label: spec.label, 178 label: spec.label,
178 command: spec.bin, 179 command: toolchain.getPathForExecutable(spec.kind),
179 args: spec.extraArgs ? [...spec.args, '--', ...spec.extraArgs] : spec.args, 180 args: spec.extraArgs ? [...spec.args, '--', ...spec.extraArgs] : spec.args,
180 env: spec.env, 181 env: spec.env,
181 }; 182 };
diff --git a/editors/code/src/tasks.ts b/editors/code/src/tasks.ts
index c22d69362..9748824df 100644
--- a/editors/code/src/tasks.ts
+++ b/editors/code/src/tasks.ts
@@ -1,5 +1,5 @@
1import * as vscode from 'vscode'; 1import * as vscode from 'vscode';
2import { getCargoPathOrFail } from "./cargo"; 2import * as toolchain from "./toolchain";
3 3
4// This ends up as the `type` key in tasks.json. RLS also uses `cargo` and 4// This ends up as the `type` key in tasks.json. RLS also uses `cargo` and
5// our configuration should be compatible with it so use the same key. 5// our configuration should be compatible with it so use the same key.
@@ -25,7 +25,7 @@ class CargoTaskProvider implements vscode.TaskProvider {
25 // set of tasks that always exist. These tasks cannot be removed in 25 // set of tasks that always exist. These tasks cannot be removed in
26 // tasks.json - only tweaked. 26 // tasks.json - only tweaked.
27 27
28 const cargoPath = getCargoPathOrFail(); 28 const cargoPath = toolchain.cargoPath();
29 29
30 return [ 30 return [
31 { command: 'build', group: vscode.TaskGroup.Build }, 31 { command: 'build', group: vscode.TaskGroup.Build },
diff --git a/editors/code/src/cargo.ts b/editors/code/src/toolchain.ts
index 46cd3d777..80a7915e9 100644
--- a/editors/code/src/cargo.ts
+++ b/editors/code/src/toolchain.ts
@@ -1,9 +1,10 @@
1import * as cp from 'child_process'; 1import * as cp from 'child_process';
2import * as os from 'os'; 2import * as os from 'os';
3import * as path from 'path'; 3import * as path from 'path';
4import * as fs from 'fs';
4import * as readline from 'readline'; 5import * as readline from 'readline';
5import { OutputChannel } from 'vscode'; 6import { OutputChannel } from 'vscode';
6import { isValidExecutable } from './util'; 7import { log, memoize } from './util';
7 8
8interface CompilationArtifact { 9interface CompilationArtifact {
9 fileName: string; 10 fileName: string;
@@ -17,33 +18,34 @@ export interface ArtifactSpec {
17 filter?: (artifacts: CompilationArtifact[]) => CompilationArtifact[]; 18 filter?: (artifacts: CompilationArtifact[]) => CompilationArtifact[];
18} 19}
19 20
20export function artifactSpec(args: readonly string[]): ArtifactSpec { 21export class Cargo {
21 const cargoArgs = [...args, "--message-format=json"]; 22 constructor(readonly rootFolder: string, readonly output: OutputChannel) { }
22 23
23 // arguments for a runnable from the quick pick should be updated. 24 // Made public for testing purposes
24 // see crates\rust-analyzer\src\main_loop\handlers.rs, handle_code_lens 25 static artifactSpec(args: readonly string[]): ArtifactSpec {
25 switch (cargoArgs[0]) { 26 const cargoArgs = [...args, "--message-format=json"];
26 case "run": cargoArgs[0] = "build"; break; 27
27 case "test": { 28 // arguments for a runnable from the quick pick should be updated.
28 if (!cargoArgs.includes("--no-run")) { 29 // see crates\rust-analyzer\src\main_loop\handlers.rs, handle_code_lens
29 cargoArgs.push("--no-run"); 30 switch (cargoArgs[0]) {
31 case "run": cargoArgs[0] = "build"; break;
32 case "test": {
33 if (!cargoArgs.includes("--no-run")) {
34 cargoArgs.push("--no-run");
35 }
36 break;
30 } 37 }
31 break;
32 } 38 }
33 }
34 39
35 const result: ArtifactSpec = { cargoArgs: cargoArgs }; 40 const result: ArtifactSpec = { cargoArgs: cargoArgs };
36 if (cargoArgs[0] === "test") { 41 if (cargoArgs[0] === "test") {
37 // for instance, `crates\rust-analyzer\tests\heavy_tests\main.rs` tests 42 // for instance, `crates\rust-analyzer\tests\heavy_tests\main.rs` tests
38 // produce 2 artifacts: {"kind": "bin"} and {"kind": "test"} 43 // produce 2 artifacts: {"kind": "bin"} and {"kind": "test"}
39 result.filter = (artifacts) => artifacts.filter(it => it.isTest); 44 result.filter = (artifacts) => artifacts.filter(it => it.isTest);
40 } 45 }
41
42 return result;
43}
44 46
45export class Cargo { 47 return result;
46 constructor(readonly rootFolder: string, readonly output: OutputChannel) { } 48 }
47 49
48 private async getArtifacts(spec: ArtifactSpec): Promise<CompilationArtifact[]> { 50 private async getArtifacts(spec: ArtifactSpec): Promise<CompilationArtifact[]> {
49 const artifacts: CompilationArtifact[] = []; 51 const artifacts: CompilationArtifact[] = [];
@@ -77,7 +79,7 @@ export class Cargo {
77 } 79 }
78 80
79 async executableFromArgs(args: readonly string[]): Promise<string> { 81 async executableFromArgs(args: readonly string[]): Promise<string> {
80 const artifacts = await this.getArtifacts(artifactSpec(args)); 82 const artifacts = await this.getArtifacts(Cargo.artifactSpec(args));
81 83
82 if (artifacts.length === 0) { 84 if (artifacts.length === 0) {
83 throw new Error('No compilation artifacts'); 85 throw new Error('No compilation artifacts');
@@ -94,14 +96,7 @@ export class Cargo {
94 onStderrString: (data: string) => void 96 onStderrString: (data: string) => void
95 ): Promise<number> { 97 ): Promise<number> {
96 return new Promise((resolve, reject) => { 98 return new Promise((resolve, reject) => {
97 let cargoPath; 99 const cargo = cp.spawn(cargoPath(), cargoArgs, {
98 try {
99 cargoPath = getCargoPathOrFail();
100 } catch (err) {
101 return reject(err);
102 }
103
104 const cargo = cp.spawn(cargoPath, cargoArgs, {
105 stdio: ['ignore', 'pipe', 'pipe'], 100 stdio: ['ignore', 'pipe', 'pipe'],
106 cwd: this.rootFolder 101 cwd: this.rootFolder
107 }); 102 });
@@ -126,26 +121,54 @@ export class Cargo {
126 } 121 }
127} 122}
128 123
129// Mirrors `ra_toolchain::cargo()` implementation 124/** Mirrors `ra_toolchain::cargo()` implementation */
130export function getCargoPathOrFail(): string { 125export function cargoPath(): string {
131 const envVar = process.env.CARGO; 126 return getPathForExecutable("cargo");
132 const executableName = "cargo"; 127}
128
129/** Mirrors `ra_toolchain::get_path_for_executable()` implementation */
130export const getPathForExecutable = memoize(
131 // We apply caching to decrease file-system interactions
132 (executableName: "cargo" | "rustc" | "rustup"): string => {
133 {
134 const envVar = process.env[executableName.toUpperCase()];
135 if (envVar) return envVar;
136 }
137
138 if (lookupInPath(executableName)) return executableName;
133 139
134 if (envVar) { 140 try {
135 if (isValidExecutable(envVar)) return envVar; 141 // hmm, `os.homedir()` seems to be infallible
142 // it is not mentioned in docs and cannot be infered by the type signature...
143 const standardPath = path.join(os.homedir(), ".cargo", "bin", executableName);
136 144
137 throw new Error(`\`${envVar}\` environment variable points to something that's not a valid executable`); 145 if (isFile(standardPath)) return standardPath;
146 } catch (err) {
147 log.error("Failed to read the fs info", err);
148 }
149 return executableName;
138 } 150 }
151);
139 152
140 if (isValidExecutable(executableName)) return executableName; 153function lookupInPath(exec: string): boolean {
154 const paths = process.env.PATH ?? "";;
141 155
142 const standardLocation = path.join(os.homedir(), '.cargo', 'bin', executableName); 156 const candidates = paths.split(path.delimiter).flatMap(dirInPath => {
157 const candidate = path.join(dirInPath, exec);
158 return os.type() === "Windows_NT"
159 ? [candidate, `${candidate}.exe`]
160 : [candidate];
161 });
143 162
144 if (isValidExecutable(standardLocation)) return standardLocation; 163 return candidates.some(isFile);
164}
145 165
146 throw new Error( 166function isFile(suspectPath: string): boolean {
147 `Failed to find \`${executableName}\` executable. ` + 167 // It is not mentionned in docs, but `statSync()` throws an error when
148 `Make sure \`${executableName}\` is in \`$PATH\`, ` + 168 // the path doesn't exist
149 `or set \`${envVar}\` to point to a valid executable.` 169 try {
150 ); 170 return fs.statSync(suspectPath).isFile();
171 } catch {
172 return false;
173 }
151} 174}
diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts
index 352ef9162..fe3fb71cd 100644
--- a/editors/code/src/util.ts
+++ b/editors/code/src/util.ts
@@ -99,3 +99,21 @@ export function isValidExecutable(path: string): boolean {
99export function setContextValue(key: string, value: any): Thenable<void> { 99export function setContextValue(key: string, value: any): Thenable<void> {
100 return vscode.commands.executeCommand('setContext', key, value); 100 return vscode.commands.executeCommand('setContext', key, value);
101} 101}
102
103/**
104 * Returns a higher-order function that caches the results of invoking the
105 * underlying function.
106 */
107export function memoize<Ret, TThis, Param extends string>(func: (this: TThis, arg: Param) => Ret) {
108 const cache = new Map<string, Ret>();
109
110 return function(this: TThis, arg: Param) {
111 const cached = cache.get(arg);
112 if (cached) return cached;
113
114 const result = func.call(this, arg);
115 cache.set(arg, result);
116
117 return result;
118 };
119}
diff --git a/editors/code/tests/unit/launch_config.test.ts b/editors/code/tests/unit/launch_config.test.ts
index d5cf1b74e..68794d53e 100644
--- a/editors/code/tests/unit/launch_config.test.ts
+++ b/editors/code/tests/unit/launch_config.test.ts
@@ -1,25 +1,25 @@
1import * as assert from 'assert'; 1import * as assert from 'assert';
2import * as cargo from '../../src/cargo'; 2import { Cargo } from '../../src/toolchain';
3 3
4suite('Launch configuration', () => { 4suite('Launch configuration', () => {
5 5
6 suite('Lens', () => { 6 suite('Lens', () => {
7 test('A binary', async () => { 7 test('A binary', async () => {
8 const args = cargo.artifactSpec(["build", "--package", "pkg_name", "--bin", "pkg_name"]); 8 const args = Cargo.artifactSpec(["build", "--package", "pkg_name", "--bin", "pkg_name"]);
9 9
10 assert.deepEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "pkg_name", "--message-format=json"]); 10 assert.deepEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "pkg_name", "--message-format=json"]);
11 assert.deepEqual(args.filter, undefined); 11 assert.deepEqual(args.filter, undefined);
12 }); 12 });
13 13
14 test('One of Multiple Binaries', async () => { 14 test('One of Multiple Binaries', async () => {
15 const args = cargo.artifactSpec(["build", "--package", "pkg_name", "--bin", "bin1"]); 15 const args = Cargo.artifactSpec(["build", "--package", "pkg_name", "--bin", "bin1"]);
16 16
17 assert.deepEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "bin1", "--message-format=json"]); 17 assert.deepEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "bin1", "--message-format=json"]);
18 assert.deepEqual(args.filter, undefined); 18 assert.deepEqual(args.filter, undefined);
19 }); 19 });
20 20
21 test('A test', async () => { 21 test('A test', async () => {
22 const args = cargo.artifactSpec(["test", "--package", "pkg_name", "--lib", "--no-run"]); 22 const args = Cargo.artifactSpec(["test", "--package", "pkg_name", "--lib", "--no-run"]);
23 23
24 assert.deepEqual(args.cargoArgs, ["test", "--package", "pkg_name", "--lib", "--no-run", "--message-format=json"]); 24 assert.deepEqual(args.cargoArgs, ["test", "--package", "pkg_name", "--lib", "--no-run", "--message-format=json"]);
25 assert.notDeepEqual(args.filter, undefined); 25 assert.notDeepEqual(args.filter, undefined);
@@ -28,7 +28,7 @@ suite('Launch configuration', () => {
28 28
29 suite('QuickPick', () => { 29 suite('QuickPick', () => {
30 test('A binary', async () => { 30 test('A binary', async () => {
31 const args = cargo.artifactSpec(["run", "--package", "pkg_name", "--bin", "pkg_name"]); 31 const args = Cargo.artifactSpec(["run", "--package", "pkg_name", "--bin", "pkg_name"]);
32 32
33 assert.deepEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "pkg_name", "--message-format=json"]); 33 assert.deepEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "pkg_name", "--message-format=json"]);
34 assert.deepEqual(args.filter, undefined); 34 assert.deepEqual(args.filter, undefined);
@@ -36,14 +36,14 @@ suite('Launch configuration', () => {
36 36
37 37
38 test('One of Multiple Binaries', async () => { 38 test('One of Multiple Binaries', async () => {
39 const args = cargo.artifactSpec(["run", "--package", "pkg_name", "--bin", "bin2"]); 39 const args = Cargo.artifactSpec(["run", "--package", "pkg_name", "--bin", "bin2"]);
40 40
41 assert.deepEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "bin2", "--message-format=json"]); 41 assert.deepEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "bin2", "--message-format=json"]);
42 assert.deepEqual(args.filter, undefined); 42 assert.deepEqual(args.filter, undefined);
43 }); 43 });
44 44
45 test('A test', async () => { 45 test('A test', async () => {
46 const args = cargo.artifactSpec(["test", "--package", "pkg_name", "--lib"]); 46 const args = Cargo.artifactSpec(["test", "--package", "pkg_name", "--lib"]);
47 47
48 assert.deepEqual(args.cargoArgs, ["test", "--package", "pkg_name", "--lib", "--message-format=json", "--no-run"]); 48 assert.deepEqual(args.cargoArgs, ["test", "--package", "pkg_name", "--lib", "--message-format=json", "--no-run"]);
49 assert.notDeepEqual(args.filter, undefined); 49 assert.notDeepEqual(args.filter, undefined);