From 1ae6571762cab605a84a731e10c89d8f3f00eef8 Mon Sep 17 00:00:00 2001 From: Bernardo Date: Sat, 13 Apr 2019 22:13:21 +0200 Subject: cargo watch start and stop commands --- editors/code/package.json | 12 +++- editors/code/src/commands/cargo_watch.ts | 102 +++++++++++++++++------------- editors/code/src/commands/runnables.ts | 7 +- editors/code/src/commands/watch_status.ts | 18 ++++-- editors/code/src/extension.ts | 16 ++++- 5 files changed, 100 insertions(+), 55 deletions(-) (limited to 'editors') diff --git a/editors/code/package.json b/editors/code/package.json index a0454191a..c58171a71 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -119,6 +119,16 @@ "command": "rust-analyzer.reload", "title": "Restart server", "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": [ @@ -253,4 +263,4 @@ } ] } -} +} \ No newline at end of file diff --git a/editors/code/src/commands/cargo_watch.ts b/editors/code/src/commands/cargo_watch.ts index 32bd38a1c..1d939e28c 100644 --- a/editors/code/src/commands/cargo_watch.ts +++ b/editors/code/src/commands/cargo_watch.ts @@ -7,44 +7,55 @@ import { terminate } from '../utils/processes'; import { LineBuffer } from './line_buffer'; import { StatusDisplay } from './watch_status'; -export class CargoWatchProvider { - private diagnosticCollection?: vscode.DiagnosticCollection; - private cargoProcess?: child_process.ChildProcess; - private outBuffer: string = ''; - private statusDisplay?: StatusDisplay; - private outputChannel?: vscode.OutputChannel; - - public activate(subscriptions: vscode.Disposable[]) { - let cargoExists = false; - const cargoTomlFile = path.join( - vscode.workspace.rootPath!, - 'Cargo.toml' +export function registerCargoWatchProvider( + subscriptions: vscode.Disposable[] +): CargoWatchProvider | undefined { + let cargoExists = false; + const cargoTomlFile = path.join(vscode.workspace.rootPath!, 'Cargo.toml'); + // Check if the working directory is valid cargo root path + try { + if (fs.existsSync(cargoTomlFile)) { + cargoExists = true; + } + } catch (err) { + cargoExists = false; + } + + if (!cargoExists) { + vscode.window.showErrorMessage( + `Couldn\'t find \'Cargo.toml\' in ${cargoTomlFile}` ); - // Check if the working directory is valid cargo root path - try { - if (fs.existsSync(cargoTomlFile)) { - cargoExists = true; - } - } catch (err) { - cargoExists = false; - } + return; + } - if (!cargoExists) { - vscode.window.showErrorMessage( - `Couldn\'t find \'Cargo.toml\' in ${cargoTomlFile}` - ); - return; - } + const provider = new CargoWatchProvider(); + subscriptions.push(provider); + return provider; +} - 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( 'rustc' ); - - this.statusDisplay = new StatusDisplay(subscriptions); + this.statusDisplay = new StatusDisplay(); this.outputChannel = vscode.window.createOutputChannel( 'Cargo Watch Trace' ); + } + + public start() { + if (this.cargoProcess) { + vscode.window.showInformationMessage( + 'Cargo Watch is already running' + ); + return; + } let args = 'check --message-format json'; if (Server.config.cargoWatchOptions.checkArguments.length > 0) { @@ -95,25 +106,28 @@ export class CargoWatchProvider { this.logInfo('cargo-watch started.'); } - public dispose(): void { - if (this.diagnosticCollection) { - this.diagnosticCollection.clear(); - this.diagnosticCollection.dispose(); - } - + public stop() { if (this.cargoProcess) { this.cargoProcess.kill(); terminate(this.cargoProcess); + this.cargoProcess = undefined; + } else { + vscode.window.showInformationMessage('Cargo Watch is not running'); } + } - if (this.outputChannel) { - this.outputChannel.dispose(); - } + public dispose(): void { + this.stop(); + + this.diagnosticCollection.clear(); + this.diagnosticCollection.dispose(); + this.outputChannel.dispose(); + this.statusDisplay.dispose(); } private logInfo(line: string) { 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 === 'verbose' ) { - this.outputChannel!.append(line); + this.outputChannel.append(line); } } private parseLine(line: string) { if (line.startsWith('[Running')) { - this.diagnosticCollection!.clear(); - this.statusDisplay!.show(); + this.diagnosticCollection.clear(); + this.statusDisplay.show(); } if (line.startsWith('[Finished running')) { - this.statusDisplay!.hide(); + this.statusDisplay.hide(); } function getLevel(s: string): vscode.DiagnosticSeverity { @@ -193,7 +207,7 @@ export class CargoWatchProvider { // 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 - this.statusDisplay!.packageName = msg.package_id.split(' ')[0]; + this.statusDisplay.packageName = msg.package_id.split(' ')[0]; } else if (data.reason === 'compiler-message') { const msg = data.message as RustDiagnostic; diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/commands/runnables.ts index c4df24c79..5790252b7 100644 --- a/editors/code/src/commands/runnables.ts +++ b/editors/code/src/commands/runnables.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; import * as lc from 'vscode-languageclient'; import { Server } from '../server'; -import { CargoWatchProvider } from './cargo_watch'; +import { CargoWatchProvider, registerCargoWatchProvider } from './cargo_watch'; interface RunnablesParams { textDocument: lc.TextDocumentIdentifier; @@ -137,7 +137,7 @@ export async function handleSingle(runnable: Runnable) { */ export async function interactivelyStartCargoWatch( context: vscode.ExtensionContext -) { +): Promise { if (Server.config.cargoWatchOptions.enableOnStartup === 'disabled') { return; } @@ -197,6 +197,5 @@ export async function interactivelyStartCargoWatch( } } - const validater = new CargoWatchProvider(); - validater.activate(context.subscriptions); + return registerCargoWatchProvider(context.subscriptions); } diff --git a/editors/code/src/commands/watch_status.ts b/editors/code/src/commands/watch_status.ts index 86ae821de..a3b0178f2 100644 --- a/editors/code/src/commands/watch_status.ts +++ b/editors/code/src/commands/watch_status.ts @@ -2,19 +2,18 @@ import * as vscode from 'vscode'; const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; -export class StatusDisplay { +export class StatusDisplay implements vscode.Disposable { public packageName?: string; private i = 0; private statusBarItem: vscode.StatusBarItem; private timer?: NodeJS.Timeout; - constructor(subscriptions: vscode.Disposable[]) { + constructor() { this.statusBarItem = vscode.window.createStatusBarItem( vscode.StatusBarAlignment.Left, 10 ); - subscriptions.push(this.statusBarItem); this.statusBarItem.hide(); } @@ -33,7 +32,7 @@ export class StatusDisplay { } }, 300); - this.statusBarItem!.show(); + this.statusBarItem.show(); } public hide() { @@ -42,7 +41,16 @@ export class StatusDisplay { 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() { diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index 1073a36a0..b48ad9b29 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts @@ -2,6 +2,7 @@ import * as vscode from 'vscode'; import * as lc from 'vscode-languageclient'; import * as commands from './commands'; +import { CargoWatchProvider } from './commands/cargo_watch'; import { interactivelyStartCargoWatch } from './commands/runnables'; import { SyntaxTreeContentProvider } from './commands/syntaxTree'; import * as events from './events'; @@ -126,7 +127,20 @@ export function activate(context: vscode.ExtensionContext) { vscode.commands.registerCommand('rust-analyzer.reload', reloadCommand); // 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! startServer(); -- cgit v1.2.3