1094: Improve cargo-watch animation and refactoring r=matklad a=edwin0cheng

* Refactoring code and fixed some minor bugs.
* Add more error log and better error handling.
* Add current checking artifact name in Cargo-watch animation.

![new_status_animation](https://i.imgur.com/Zr2JLa5.gif)

Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
bors[bot] 2019-04-02 18:14:00 +00:00
commit 01a54f094b
2 changed files with 78 additions and 44 deletions

View File

@ -68,7 +68,11 @@ export class CargoWatchProvider {
this.cargoProcess.stdout.on('data', (s: string) => { this.cargoProcess.stdout.on('data', (s: string) => {
stdoutData.processOutput(s, line => { stdoutData.processOutput(s, line => {
this.logInfo(line); this.logInfo(line);
this.parseLine(line); try {
this.parseLine(line);
} catch (err) {
this.logError(`Failed to parse: ${err}, content : ${line}`);
}
}); });
}); });
@ -133,79 +137,99 @@ export class CargoWatchProvider {
if (s === 'error') { if (s === 'error') {
return vscode.DiagnosticSeverity.Error; return vscode.DiagnosticSeverity.Error;
} }
if (s.startsWith('warn')) { if (s.startsWith('warn')) {
return vscode.DiagnosticSeverity.Warning; return vscode.DiagnosticSeverity.Warning;
} }
return vscode.DiagnosticSeverity.Information; return vscode.DiagnosticSeverity.Information;
} }
interface ErrorSpan { // Reference:
// https://github.com/rust-lang/rust/blob/master/src/libsyntax/json.rs
interface RustDiagnosticSpan {
line_start: number; line_start: number;
line_end: number; line_end: number;
column_start: number; column_start: number;
column_end: number; column_end: number;
is_primary: boolean;
file_name: string;
} }
interface ErrorMessage { interface RustDiagnostic {
reason: string; spans: RustDiagnosticSpan[];
message: { rendered: string;
spans: ErrorSpan[]; level: string;
rendered: string; code?: {
level: string; code: string;
code?: {
code: string;
};
}; };
} }
interface CargoArtifact {
reason: string;
package_id: string;
}
// https://github.com/rust-lang/cargo/blob/master/src/cargo/util/machine_message.rs
interface CargoMessage {
reason: string;
package_id: string;
message: RustDiagnostic;
}
// cargo-watch itself output non json format // cargo-watch itself output non json format
// Ignore these lines // Ignore these lines
let data: ErrorMessage; let data: CargoMessage;
try { try {
data = JSON.parse(line.trim()); data = JSON.parse(line.trim());
} catch (error) { } catch (error) {
this.logError(`Fail to pass to json : { ${error} }`); this.logError(`Fail to parse to json : { ${error} }`);
return; return;
} }
// Only handle compiler-message now if (data.reason === 'compiler-artifact') {
if (data.reason !== 'compiler-message') { const msg = data as CargoArtifact;
return;
}
let spans: any[] = data.message.spans; // The format of the package_id is "{name} {version} ({source_id})",
spans = spans.filter(o => o.is_primary); // https://github.com/rust-lang/cargo/blob/37ad03f86e895bb80b474c1c088322634f4725f5/src/cargo/core/package_id.rs#L53
this.statusDisplay!.packageName = msg.package_id.split(' ')[0];
} else if (data.reason === 'compiler-message') {
const msg = data.message as RustDiagnostic;
// We only handle primary span right now. const spans = msg.spans.filter(o => o.is_primary);
if (spans.length > 0) {
const o = spans[0];
const rendered = data.message.rendered; // We only handle primary span right now.
const level = getLevel(data.message.level); if (spans.length > 0) {
const range = new vscode.Range( const o = spans[0];
new vscode.Position(o.line_start - 1, o.column_start - 1),
new vscode.Position(o.line_end - 1, o.column_end - 1)
);
const fileName = path.join(vscode.workspace.rootPath!, o.file_name); const rendered = msg.rendered;
const diagnostic = new vscode.Diagnostic(range, rendered, level); const level = getLevel(msg.level);
const range = new vscode.Range(
new vscode.Position(o.line_start - 1, o.column_start - 1),
new vscode.Position(o.line_end - 1, o.column_end - 1)
);
diagnostic.source = 'rustc'; const fileName = path.join(
diagnostic.code = data.message.code vscode.workspace.rootPath!,
? data.message.code.code o.file_name
: undefined; );
diagnostic.relatedInformation = []; const diagnostic = new vscode.Diagnostic(
range,
rendered,
level
);
const fileUrl = vscode.Uri.file(fileName!); diagnostic.source = 'rustc';
diagnostic.code = msg.code ? msg.code.code : undefined;
diagnostic.relatedInformation = [];
const diagnostics: vscode.Diagnostic[] = [ const fileUrl = vscode.Uri.file(fileName!);
...(this.diagnosticCollection!.get(fileUrl) || [])
];
diagnostics.push(diagnostic);
this.diagnosticCollection!.set(fileUrl, diagnostics); const diagnostics: vscode.Diagnostic[] = [
...(this.diagnosticCollection!.get(fileUrl) || [])
];
diagnostics.push(diagnostic);
this.diagnosticCollection!.set(fileUrl, diagnostics);
}
} }
} }
} }

View File

@ -3,6 +3,8 @@ import * as vscode from 'vscode';
const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
export class StatusDisplay { export class StatusDisplay {
public packageName?: string;
private i = 0; private i = 0;
private statusBarItem: vscode.StatusBarItem; private statusBarItem: vscode.StatusBarItem;
private timer?: NodeJS.Timeout; private timer?: NodeJS.Timeout;
@ -17,10 +19,18 @@ export class StatusDisplay {
} }
public show() { public show() {
this.packageName = undefined;
this.timer = this.timer =
this.timer || this.timer ||
setInterval(() => { setInterval(() => {
this.statusBarItem!.text = 'cargo check ' + this.frame(); if (this.packageName) {
this.statusBarItem!.text = `cargo check [${
this.packageName
}] ${this.frame()}`;
} else {
this.statusBarItem!.text = `cargo check ${this.frame()}`;
}
}, 300); }, 300);
this.statusBarItem!.show(); this.statusBarItem!.show();