cargo watch start and stop commands

This commit is contained in:
Bernardo 2019-04-13 22:13:21 +02:00
parent 0d39b1c3fa
commit 1ae6571762
5 changed files with 99 additions and 54 deletions

View file

@ -119,6 +119,16 @@
"command": "rust-analyzer.reload", "command": "rust-analyzer.reload",
"title": "Restart server", "title": "Restart server",
"category": "Rust Analyzer" "category": "Rust Analyzer"
},
{
"command": "rust-analyzer.startCargoWatch",
"title": "Start Cargo Watch",
"category": "Rust Analyzer"
},
{
"command": "rust-analyzer.stopCargoWatch",
"title": "Stop Cargo Watch",
"category": "Rust Analyzer"
} }
], ],
"keybindings": [ "keybindings": [

View file

@ -7,44 +7,55 @@ import { terminate } from '../utils/processes';
import { LineBuffer } from './line_buffer'; import { LineBuffer } from './line_buffer';
import { StatusDisplay } from './watch_status'; import { StatusDisplay } from './watch_status';
export class CargoWatchProvider { export function registerCargoWatchProvider(
private diagnosticCollection?: vscode.DiagnosticCollection; subscriptions: vscode.Disposable[]
private cargoProcess?: child_process.ChildProcess; ): CargoWatchProvider | undefined {
private outBuffer: string = ''; let cargoExists = false;
private statusDisplay?: StatusDisplay; const cargoTomlFile = path.join(vscode.workspace.rootPath!, 'Cargo.toml');
private outputChannel?: vscode.OutputChannel; // Check if the working directory is valid cargo root path
try {
if (fs.existsSync(cargoTomlFile)) {
cargoExists = true;
}
} catch (err) {
cargoExists = false;
}
public activate(subscriptions: vscode.Disposable[]) { if (!cargoExists) {
let cargoExists = false; vscode.window.showErrorMessage(
const cargoTomlFile = path.join( `Couldn\'t find \'Cargo.toml\' in ${cargoTomlFile}`
vscode.workspace.rootPath!,
'Cargo.toml'
); );
// Check if the working directory is valid cargo root path return;
try { }
if (fs.existsSync(cargoTomlFile)) {
cargoExists = true;
}
} catch (err) {
cargoExists = false;
}
if (!cargoExists) { const provider = new CargoWatchProvider();
vscode.window.showErrorMessage( subscriptions.push(provider);
`Couldn\'t find \'Cargo.toml\' in ${cargoTomlFile}` return provider;
); }
return;
}
subscriptions.push(this); export class CargoWatchProvider implements vscode.Disposable {
private readonly diagnosticCollection: vscode.DiagnosticCollection;
private readonly statusDisplay: StatusDisplay;
private readonly outputChannel: vscode.OutputChannel;
private cargoProcess?: child_process.ChildProcess;
constructor() {
this.diagnosticCollection = vscode.languages.createDiagnosticCollection( this.diagnosticCollection = vscode.languages.createDiagnosticCollection(
'rustc' 'rustc'
); );
this.statusDisplay = new StatusDisplay();
this.statusDisplay = new StatusDisplay(subscriptions);
this.outputChannel = vscode.window.createOutputChannel( this.outputChannel = vscode.window.createOutputChannel(
'Cargo Watch Trace' 'Cargo Watch Trace'
); );
}
public start() {
if (this.cargoProcess) {
vscode.window.showInformationMessage(
'Cargo Watch is already running'
);
return;
}
let args = 'check --message-format json'; let args = 'check --message-format json';
if (Server.config.cargoWatchOptions.checkArguments.length > 0) { if (Server.config.cargoWatchOptions.checkArguments.length > 0) {
@ -95,25 +106,28 @@ export class CargoWatchProvider {
this.logInfo('cargo-watch started.'); this.logInfo('cargo-watch started.');
} }
public dispose(): void { public stop() {
if (this.diagnosticCollection) {
this.diagnosticCollection.clear();
this.diagnosticCollection.dispose();
}
if (this.cargoProcess) { if (this.cargoProcess) {
this.cargoProcess.kill(); this.cargoProcess.kill();
terminate(this.cargoProcess); terminate(this.cargoProcess);
this.cargoProcess = undefined;
} else {
vscode.window.showInformationMessage('Cargo Watch is not running');
} }
}
if (this.outputChannel) { public dispose(): void {
this.outputChannel.dispose(); this.stop();
}
this.diagnosticCollection.clear();
this.diagnosticCollection.dispose();
this.outputChannel.dispose();
this.statusDisplay.dispose();
} }
private logInfo(line: string) { private logInfo(line: string) {
if (Server.config.cargoWatchOptions.trace === 'verbose') { if (Server.config.cargoWatchOptions.trace === 'verbose') {
this.outputChannel!.append(line); this.outputChannel.append(line);
} }
} }
@ -122,18 +136,18 @@ export class CargoWatchProvider {
Server.config.cargoWatchOptions.trace === 'error' || Server.config.cargoWatchOptions.trace === 'error' ||
Server.config.cargoWatchOptions.trace === 'verbose' Server.config.cargoWatchOptions.trace === 'verbose'
) { ) {
this.outputChannel!.append(line); this.outputChannel.append(line);
} }
} }
private parseLine(line: string) { private parseLine(line: string) {
if (line.startsWith('[Running')) { if (line.startsWith('[Running')) {
this.diagnosticCollection!.clear(); this.diagnosticCollection.clear();
this.statusDisplay!.show(); this.statusDisplay.show();
} }
if (line.startsWith('[Finished running')) { if (line.startsWith('[Finished running')) {
this.statusDisplay!.hide(); this.statusDisplay.hide();
} }
function getLevel(s: string): vscode.DiagnosticSeverity { function getLevel(s: string): vscode.DiagnosticSeverity {
@ -193,7 +207,7 @@ export class CargoWatchProvider {
// The format of the package_id is "{name} {version} ({source_id})", // The format of the package_id is "{name} {version} ({source_id})",
// https://github.com/rust-lang/cargo/blob/37ad03f86e895bb80b474c1c088322634f4725f5/src/cargo/core/package_id.rs#L53 // https://github.com/rust-lang/cargo/blob/37ad03f86e895bb80b474c1c088322634f4725f5/src/cargo/core/package_id.rs#L53
this.statusDisplay!.packageName = msg.package_id.split(' ')[0]; this.statusDisplay.packageName = msg.package_id.split(' ')[0];
} else if (data.reason === 'compiler-message') { } else if (data.reason === 'compiler-message') {
const msg = data.message as RustDiagnostic; const msg = data.message as RustDiagnostic;

View file

@ -5,7 +5,7 @@ import * as vscode from 'vscode';
import * as lc from 'vscode-languageclient'; import * as lc from 'vscode-languageclient';
import { Server } from '../server'; import { Server } from '../server';
import { CargoWatchProvider } from './cargo_watch'; import { CargoWatchProvider, registerCargoWatchProvider } from './cargo_watch';
interface RunnablesParams { interface RunnablesParams {
textDocument: lc.TextDocumentIdentifier; textDocument: lc.TextDocumentIdentifier;
@ -137,7 +137,7 @@ export async function handleSingle(runnable: Runnable) {
*/ */
export async function interactivelyStartCargoWatch( export async function interactivelyStartCargoWatch(
context: vscode.ExtensionContext context: vscode.ExtensionContext
) { ): Promise<CargoWatchProvider | undefined> {
if (Server.config.cargoWatchOptions.enableOnStartup === 'disabled') { if (Server.config.cargoWatchOptions.enableOnStartup === 'disabled') {
return; return;
} }
@ -197,6 +197,5 @@ export async function interactivelyStartCargoWatch(
} }
} }
const validater = new CargoWatchProvider(); return registerCargoWatchProvider(context.subscriptions);
validater.activate(context.subscriptions);
} }

View file

@ -2,19 +2,18 @@ import * as vscode from 'vscode';
const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
export class StatusDisplay { export class StatusDisplay implements vscode.Disposable {
public packageName?: string; 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;
constructor(subscriptions: vscode.Disposable[]) { constructor() {
this.statusBarItem = vscode.window.createStatusBarItem( this.statusBarItem = vscode.window.createStatusBarItem(
vscode.StatusBarAlignment.Left, vscode.StatusBarAlignment.Left,
10 10
); );
subscriptions.push(this.statusBarItem);
this.statusBarItem.hide(); this.statusBarItem.hide();
} }
@ -33,7 +32,7 @@ export class StatusDisplay {
} }
}, 300); }, 300);
this.statusBarItem!.show(); this.statusBarItem.show();
} }
public hide() { public hide() {
@ -42,7 +41,16 @@ export class StatusDisplay {
this.timer = undefined; this.timer = undefined;
} }
this.statusBarItem!.hide(); this.statusBarItem.hide();
}
public dispose() {
if (this.timer) {
clearInterval(this.timer);
this.timer = undefined;
}
this.statusBarItem.dispose();
} }
private frame() { private frame() {

View file

@ -2,6 +2,7 @@ import * as vscode from 'vscode';
import * as lc from 'vscode-languageclient'; import * as lc from 'vscode-languageclient';
import * as commands from './commands'; import * as commands from './commands';
import { CargoWatchProvider } from './commands/cargo_watch';
import { interactivelyStartCargoWatch } from './commands/runnables'; import { interactivelyStartCargoWatch } from './commands/runnables';
import { SyntaxTreeContentProvider } from './commands/syntaxTree'; import { SyntaxTreeContentProvider } from './commands/syntaxTree';
import * as events from './events'; import * as events from './events';
@ -126,7 +127,20 @@ export function activate(context: vscode.ExtensionContext) {
vscode.commands.registerCommand('rust-analyzer.reload', reloadCommand); vscode.commands.registerCommand('rust-analyzer.reload', reloadCommand);
// Executing `cargo watch` provides us with inline diagnostics on save // Executing `cargo watch` provides us with inline diagnostics on save
interactivelyStartCargoWatch(context); let provider: CargoWatchProvider | undefined;
interactivelyStartCargoWatch(context).then(p => {
provider = p;
});
registerCommand('rust-analyzer.startCargoWatch', () => {
if (provider) {
provider.start();
}
});
registerCommand('rust-analyzer.stopCargoWatch', () => {
if (provider) {
provider.stop();
}
});
// Start the language server, finally! // Start the language server, finally!
startServer(); startServer();