aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/cargo.ts
diff options
context:
space:
mode:
Diffstat (limited to 'editors/code/src/cargo.ts')
-rw-r--r--editors/code/src/cargo.ts63
1 files changed, 40 insertions, 23 deletions
diff --git a/editors/code/src/cargo.ts b/editors/code/src/cargo.ts
index 6a41873d0..c3e2e5c05 100644
--- a/editors/code/src/cargo.ts
+++ b/editors/code/src/cargo.ts
@@ -12,14 +12,46 @@ interface CompilationArtifact {
12 isTest: boolean; 12 isTest: boolean;
13} 13}
14 14
15export interface ArtifactSpec {
16 cargoArgs: string[];
17 filter?: (artifacts: CompilationArtifact[]) => CompilationArtifact[];
18}
19
20export function artifactSpec(args: readonly string[]): ArtifactSpec {
21 const cargoArgs = [...args, "--message-format=json"];
22
23 // arguments for a runnable from the quick pick should be updated.
24 // see crates\rust-analyzer\src\main_loop\handlers.rs, handle_code_lens
25 switch (cargoArgs[0]) {
26 case "run": cargoArgs[0] = "build"; break;
27 case "test": {
28 if (cargoArgs.indexOf("--no-run") === -1) {
29 cargoArgs.push("--no-run");
30 }
31 break;
32 }
33 }
34
35 const result: ArtifactSpec = { cargoArgs: cargoArgs };
36 if (cargoArgs[0] === "test") {
37 // for instance, `crates\rust-analyzer\tests\heavy_tests\main.rs` tests
38 // produce 2 artifacts: {"kind": "bin"} and {"kind": "test"}
39 result.filter = (artifacts) => {
40 return artifacts.filter(a => a.isTest);
41 };
42 }
43
44 return result;
45}
46
15export class Cargo { 47export class Cargo {
16 constructor(readonly rootFolder: string, readonly output: OutputChannel) { } 48 constructor(readonly rootFolder: string, readonly output: OutputChannel) { }
17 49
18 private async artifactsFromArgs(cargoArgs: string[]): Promise<CompilationArtifact[]> { 50 private async getArtifacts(spec: ArtifactSpec): Promise<CompilationArtifact[]> {
19 const artifacts: CompilationArtifact[] = []; 51 let artifacts: CompilationArtifact[] = [];
20 52
21 try { 53 try {
22 await this.runCargo(cargoArgs, 54 await this.runCargo(spec.cargoArgs,
23 message => { 55 message => {
24 if (message.reason === 'compiler-artifact' && message.executable) { 56 if (message.reason === 'compiler-artifact' && message.executable) {
25 const isBinary = message.target.crate_types.includes('bin'); 57 const isBinary = message.target.crate_types.includes('bin');
@@ -43,30 +75,15 @@ export class Cargo {
43 throw new Error(`Cargo invocation has failed: ${err}`); 75 throw new Error(`Cargo invocation has failed: ${err}`);
44 } 76 }
45 77
78 if (spec.filter) {
79 artifacts = spec.filter(artifacts);
80 }
81
46 return artifacts; 82 return artifacts;
47 } 83 }
48 84
49 async executableFromArgs(args: readonly string[]): Promise<string> { 85 async executableFromArgs(args: readonly string[]): Promise<string> {
50 const cargoArgs = [...args, "--message-format=json"]; 86 const artifacts = await this.getArtifacts(artifactSpec(args));
51
52 // arguments for a runnable from the quick pick should be updated.
53 // see crates\rust-analyzer\src\main_loop\handlers.rs, handle_code_lens
54 switch (cargoArgs[0]) {
55 case "run": cargoArgs[0] = "build"; break;
56 case "test": {
57 if (cargoArgs.indexOf("--no-run") === -1) {
58 cargoArgs.push("--no-run");
59 }
60 break;
61 }
62 }
63
64 let artifacts = await this.artifactsFromArgs(cargoArgs);
65 if (cargoArgs[0] === "test") {
66 // for instance, `crates\rust-analyzer\tests\heavy_tests\main.rs` tests
67 // produce 2 artifacts: {"kind": "bin"} and {"kind": "test"}
68 artifacts = artifacts.filter(a => a.isTest);
69 }
70 87
71 if (artifacts.length === 0) { 88 if (artifacts.length === 0) {
72 throw new Error('No compilation artifacts'); 89 throw new Error('No compilation artifacts');