mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
cargo watch start and stop commands
This commit is contained in:
parent
0d39b1c3fa
commit
1ae6571762
5 changed files with 99 additions and 54 deletions
|
@ -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": [
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue