995: Install and run `cargo watch` if user agrees r=matklad a=Xanewok

This isn't a glorious patch but hopefully is useful 👍 This introduces a default background `cargo watch` task and (separately from that) asks the user on every startup if they want to run `cargo watch` (installs it if it's not available).

r? @matklad does it fit the what you've been thinking about?

Co-authored-by: Igor Matuszewski <xanewok@gmail.com>
This commit is contained in:
bors[bot] 2019-03-18 21:52:27 +00:00
commit 91576afc7e
4 changed files with 106 additions and 2 deletions

View File

@ -168,6 +168,11 @@
"default": "ra_lsp_server",
"description": "Path to ra_lsp_server executable"
},
"rust-analyzer.enableCargoWatchOnStartup": {
"type": "boolean",
"default": "true",
"description": "When enabled, ask the user whether to run `cargo watch` on startup"
},
"rust-analyzer.trace.server": {
"type": "string",
"scope": "window",

View File

@ -1,5 +1,8 @@
import * as child_process from 'child_process';
import * as util from 'util';
import * as vscode from 'vscode';
import * as lc from 'vscode-languageclient';
import { Server } from '../server';
interface RunnablesParams {
@ -8,7 +11,6 @@ interface RunnablesParams {
}
interface Runnable {
range: lc.Range;
label: string;
bin: string;
args: string[];
@ -38,7 +40,7 @@ function createTask(spec: Runnable): vscode.Task {
const TASK_SOURCE = 'Rust';
const definition: CargoTaskDefinition = {
type: 'cargo',
label: 'cargo',
label: spec.label,
command: spec.bin,
args: spec.args,
env: spec.env
@ -124,3 +126,88 @@ export async function handleSingle(runnable: Runnable) {
return vscode.tasks.executeTask(task);
}
export const autoCargoWatchTask: vscode.Task = {
name: 'cargo watch',
source: 'rust-analyzer',
definition: {
type: 'watch'
},
execution: new vscode.ShellExecution('cargo', ['watch'], { cwd: '.' }),
isBackground: true,
problemMatchers: ['$rustc-watch'],
presentationOptions: {
clear: true
},
// Not yet exposed in the vscode.d.ts
// https://github.com/Microsoft/vscode/blob/ea7c31d770e04b51d586b0d3944f3a7feb03afb9/src/vs/workbench/contrib/tasks/common/tasks.ts#L444-L456
runOptions: ({
runOn: 2 // RunOnOptions.folderOpen
} as unknown) as vscode.RunOptions
};
/**
* Interactively asks the user whether we should run `cargo check` in order to
* provide inline diagnostics; the user is met with a series of dialog boxes
* that, when accepted, allow us to `cargo install cargo-watch` and then run it.
*/
export async function interactivelyStartCargoWatch() {
if (!Server.config.enableCargoWatchOnStartup) {
return;
}
const execPromise = util.promisify(child_process.exec);
const watch = await vscode.window.showInformationMessage(
'Start watching changes with cargo? (Executes `cargo watch`, provides inline diagnostics)',
'yes',
'no'
);
if (watch === 'no') {
return;
}
const { stderr } = await execPromise('cargo watch --version').catch(e => e);
if (stderr.includes('no such subcommand: `watch`')) {
const msg =
'The `cargo-watch` subcommand is not installed. Install? (takes ~1-2 minutes)';
const install = await vscode.window.showInformationMessage(
msg,
'yes',
'no'
);
if (install === 'no') {
return;
}
const label = 'install-cargo-watch';
const taskFinished = new Promise((resolve, reject) => {
const disposable = vscode.tasks.onDidEndTask(({ execution }) => {
if (execution.task.name === label) {
disposable.dispose();
resolve();
}
});
});
vscode.tasks.executeTask(
createTask({
label,
bin: 'cargo',
args: ['install', 'cargo-watch'],
env: {}
})
);
await taskFinished;
const output = await execPromise('cargo watch --version').catch(e => e);
if (output.stderr !== '') {
vscode.window.showErrorMessage(
`Couldn't install \`cargo-\`watch: ${output.stderr}`
);
return;
}
}
vscode.tasks.executeTask(autoCargoWatchTask);
}

View File

@ -9,6 +9,7 @@ export class Config {
public enableEnhancedTyping = true;
public raLspServerPath = RA_LSP_DEBUG || 'ra_lsp_server';
public showWorkspaceLoadedNotification = true;
public enableCargoWatchOnStartup = true;
private prevEnhancedTyping: null | boolean = null;
@ -68,5 +69,12 @@ export class Config {
this.raLspServerPath =
RA_LSP_DEBUG || (config.get('raLspServerPath') as string);
}
if (config.has('enableCargoWatchOnStartup')) {
this.enableCargoWatchOnStartup = config.get<boolean>(
'enableCargoWatchOnStartup',
true
);
}
}
}

View File

@ -2,6 +2,7 @@ import * as vscode from 'vscode';
import * as lc from 'vscode-languageclient';
import * as commands from './commands';
import { interactivelyStartCargoWatch } from './commands/runnables';
import { SyntaxTreeContentProvider } from './commands/syntaxTree';
import * as events from './events';
import * as notifications from './notifications';
@ -119,6 +120,9 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions
);
// Executing `cargo watch` provides us with inline diagnostics on save
interactivelyStartCargoWatch();
// Start the language server, finally!
Server.start(allNotifications);
}