aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/commands
diff options
context:
space:
mode:
Diffstat (limited to 'editors/code/src/commands')
-rw-r--r--editors/code/src/commands/cargo_watch.ts117
-rw-r--r--editors/code/src/commands/watch_status.ts12
2 files changed, 83 insertions, 46 deletions
diff --git a/editors/code/src/commands/cargo_watch.ts b/editors/code/src/commands/cargo_watch.ts
index 6d8e4d885..32bd38a1c 100644
--- a/editors/code/src/commands/cargo_watch.ts
+++ b/editors/code/src/commands/cargo_watch.ts
@@ -46,12 +46,15 @@ export class CargoWatchProvider {
46 'Cargo Watch Trace' 46 'Cargo Watch Trace'
47 ); 47 );
48 48
49 let args = '"check --message-format json'; 49 let args = 'check --message-format json';
50 if (Server.config.cargoWatchOptions.checkArguments.length > 0) { 50 if (Server.config.cargoWatchOptions.checkArguments.length > 0) {
51 // Excape the double quote string: 51 // Excape the double quote string:
52 args += ' ' + Server.config.cargoWatchOptions.checkArguments; 52 args += ' ' + Server.config.cargoWatchOptions.checkArguments;
53 } 53 }
54 args += '"'; 54 // Windows handles arguments differently than the unix-likes, so we need to wrap the args in double quotes
55 if (process.platform === 'win32') {
56 args = '"' + args + '"';
57 }
55 58
56 // Start the cargo watch with json message 59 // Start the cargo watch with json message
57 this.cargoProcess = child_process.spawn( 60 this.cargoProcess = child_process.spawn(
@@ -68,7 +71,11 @@ export class CargoWatchProvider {
68 this.cargoProcess.stdout.on('data', (s: string) => { 71 this.cargoProcess.stdout.on('data', (s: string) => {
69 stdoutData.processOutput(s, line => { 72 stdoutData.processOutput(s, line => {
70 this.logInfo(line); 73 this.logInfo(line);
71 this.parseLine(line); 74 try {
75 this.parseLine(line);
76 } catch (err) {
77 this.logError(`Failed to parse: ${err}, content : ${line}`);
78 }
72 }); 79 });
73 }); 80 });
74 81
@@ -133,79 +140,99 @@ export class CargoWatchProvider {
133 if (s === 'error') { 140 if (s === 'error') {
134 return vscode.DiagnosticSeverity.Error; 141 return vscode.DiagnosticSeverity.Error;
135 } 142 }
136
137 if (s.startsWith('warn')) { 143 if (s.startsWith('warn')) {
138 return vscode.DiagnosticSeverity.Warning; 144 return vscode.DiagnosticSeverity.Warning;
139 } 145 }
140
141 return vscode.DiagnosticSeverity.Information; 146 return vscode.DiagnosticSeverity.Information;
142 } 147 }
143 148
144 interface ErrorSpan { 149 // Reference:
150 // https://github.com/rust-lang/rust/blob/master/src/libsyntax/json.rs
151 interface RustDiagnosticSpan {
145 line_start: number; 152 line_start: number;
146 line_end: number; 153 line_end: number;
147 column_start: number; 154 column_start: number;
148 column_end: number; 155 column_end: number;
156 is_primary: boolean;
157 file_name: string;
149 } 158 }
150 159
151 interface ErrorMessage { 160 interface RustDiagnostic {
152 reason: string; 161 spans: RustDiagnosticSpan[];
153 message: { 162 rendered: string;
154 spans: ErrorSpan[]; 163 level: string;
155 rendered: string; 164 code?: {
156 level: string; 165 code: string;
157 code?: {
158 code: string;
159 };
160 }; 166 };
161 } 167 }
162 168
169 interface CargoArtifact {
170 reason: string;
171 package_id: string;
172 }
173
174 // https://github.com/rust-lang/cargo/blob/master/src/cargo/util/machine_message.rs
175 interface CargoMessage {
176 reason: string;
177 package_id: string;
178 message: RustDiagnostic;
179 }
180
163 // cargo-watch itself output non json format 181 // cargo-watch itself output non json format
164 // Ignore these lines 182 // Ignore these lines
165 let data: ErrorMessage; 183 let data: CargoMessage;
166 try { 184 try {
167 data = JSON.parse(line.trim()); 185 data = JSON.parse(line.trim());
168 } catch (error) { 186 } catch (error) {
169 this.logError(`Fail to pass to json : { ${error} }`); 187 this.logError(`Fail to parse to json : { ${error} }`);
170 return; 188 return;
171 } 189 }
172 190
173 // Only handle compiler-message now 191 if (data.reason === 'compiler-artifact') {
174 if (data.reason !== 'compiler-message') { 192 const msg = data as CargoArtifact;
175 return;
176 }
177 193
178 let spans: any[] = data.message.spans; 194 // The format of the package_id is "{name} {version} ({source_id})",
179 spans = spans.filter(o => o.is_primary); 195 // https://github.com/rust-lang/cargo/blob/37ad03f86e895bb80b474c1c088322634f4725f5/src/cargo/core/package_id.rs#L53
196 this.statusDisplay!.packageName = msg.package_id.split(' ')[0];
197 } else if (data.reason === 'compiler-message') {
198 const msg = data.message as RustDiagnostic;
180 199
181 // We only handle primary span right now. 200 const spans = msg.spans.filter(o => o.is_primary);
182 if (spans.length > 0) {
183 const o = spans[0];
184 201
185 const rendered = data.message.rendered; 202 // We only handle primary span right now.
186 const level = getLevel(data.message.level); 203 if (spans.length > 0) {
187 const range = new vscode.Range( 204 const o = spans[0];
188 new vscode.Position(o.line_start - 1, o.column_start - 1), 205
189 new vscode.Position(o.line_end - 1, o.column_end - 1) 206 const rendered = msg.rendered;
190 ); 207 const level = getLevel(msg.level);
208 const range = new vscode.Range(
209 new vscode.Position(o.line_start - 1, o.column_start - 1),
210 new vscode.Position(o.line_end - 1, o.column_end - 1)
211 );
191 212
192 const fileName = path.join(vscode.workspace.rootPath!, o.file_name); 213 const fileName = path.join(
193 const diagnostic = new vscode.Diagnostic(range, rendered, level); 214 vscode.workspace.rootPath!,
215 o.file_name
216 );
217 const diagnostic = new vscode.Diagnostic(
218 range,
219 rendered,
220 level
221 );
194 222
195 diagnostic.source = 'rustc'; 223 diagnostic.source = 'rustc';
196 diagnostic.code = data.message.code 224 diagnostic.code = msg.code ? msg.code.code : undefined;
197 ? data.message.code.code 225 diagnostic.relatedInformation = [];
198 : undefined;
199 diagnostic.relatedInformation = [];
200 226
201 const fileUrl = vscode.Uri.file(fileName!); 227 const fileUrl = vscode.Uri.file(fileName!);
202 228
203 const diagnostics: vscode.Diagnostic[] = [ 229 const diagnostics: vscode.Diagnostic[] = [
204 ...(this.diagnosticCollection!.get(fileUrl) || []) 230 ...(this.diagnosticCollection!.get(fileUrl) || [])
205 ]; 231 ];
206 diagnostics.push(diagnostic); 232 diagnostics.push(diagnostic);
207 233
208 this.diagnosticCollection!.set(fileUrl, diagnostics); 234 this.diagnosticCollection!.set(fileUrl, diagnostics);
235 }
209 } 236 }
210 } 237 }
211} 238}
diff --git a/editors/code/src/commands/watch_status.ts b/editors/code/src/commands/watch_status.ts
index f027d7bbc..86ae821de 100644
--- a/editors/code/src/commands/watch_status.ts
+++ b/editors/code/src/commands/watch_status.ts
@@ -3,6 +3,8 @@ import * as vscode from 'vscode';
3const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; 3const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
4 4
5export class StatusDisplay { 5export class StatusDisplay {
6 public packageName?: string;
7
6 private i = 0; 8 private i = 0;
7 private statusBarItem: vscode.StatusBarItem; 9 private statusBarItem: vscode.StatusBarItem;
8 private timer?: NodeJS.Timeout; 10 private timer?: NodeJS.Timeout;
@@ -17,10 +19,18 @@ export class StatusDisplay {
17 } 19 }
18 20
19 public show() { 21 public show() {
22 this.packageName = undefined;
23
20 this.timer = 24 this.timer =
21 this.timer || 25 this.timer ||
22 setInterval(() => { 26 setInterval(() => {
23 this.statusBarItem!.text = 'cargo check ' + this.frame(); 27 if (this.packageName) {
28 this.statusBarItem!.text = `cargo check [${
29 this.packageName
30 }] ${this.frame()}`;
31 } else {
32 this.statusBarItem!.text = `cargo check ${this.frame()}`;
33 }
24 }, 300); 34 }, 300);
25 35
26 this.statusBarItem!.show(); 36 this.statusBarItem!.show();