mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +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",
|
||||
"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 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
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;
|
||||
}
|
||||
|
||||
public activate(subscriptions: vscode.Disposable[]) {
|
||||
let cargoExists = false;
|
||||
const cargoTomlFile = path.join(
|
||||
vscode.workspace.rootPath!,
|
||||
'Cargo.toml'
|
||||
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;
|
||||
|
||||
|
|
|
@ -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<CargoWatchProvider | undefined> {
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue