From 768aa4259fce15f313042892739ed4d8b7e518b4 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 30 Mar 2020 18:12:22 +0100 Subject: Add basic task support This adds basic support for running `cargo build`, `cargo run`, etc. --- editors/code/src/client.ts | 5 ++-- editors/code/src/ctx.ts | 9 +++++-- editors/code/src/main.ts | 9 ++++++- editors/code/src/tasks.ts | 60 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 editors/code/src/tasks.ts (limited to 'editors') diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index d72ecc58f..c9819e457 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -30,15 +30,14 @@ export function configToServerOptions(config: Config) { }; } -export async function createClient(config: Config, serverPath: string): Promise { +export async function createClient(config: Config, serverPath: string, workspaceFolder: vscode.WorkspaceFolder | null): Promise { // '.' Is the fallback if no folder is open // TODO?: Workspace folders support Uri's (eg: file://test.txt). // It might be a good idea to test if the uri points to a file. - const workspaceFolderPath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? '.'; const run: lc.Executable = { command: serverPath, - options: { cwd: workspaceFolderPath }, + options: { cwd: workspaceFolder?.uri.fsPath ?? '.' }, }; const serverOptions: lc.ServerOptions = { run, diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index d2f49cd23..0e705bc84 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -15,8 +15,13 @@ export class Ctx { } - static async create(config: Config, extCtx: vscode.ExtensionContext, serverPath: string): Promise { - const client = await createClient(config, serverPath); + static async create( + config: Config, + extCtx: vscode.ExtensionContext, + serverPath: string, + workspaceFolder: vscode.WorkspaceFolder | null, + ): Promise { + const client = await createClient(config, serverPath, workspaceFolder); const res = new Ctx(config, extCtx, client, serverPath); res.pushCleanup(client.start()); await client.onReady(); diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index a46dbde33..40701e4f5 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -13,6 +13,7 @@ import { log, assert } from './util'; import { PersistentState } from './persistent_state'; import { fetchRelease, download } from './net'; import { spawnSync } from 'child_process'; +import { activateTaskProvider } from './tasks'; let ctx: Ctx | undefined; @@ -41,11 +42,13 @@ export async function activate(context: vscode.ExtensionContext) { const state = new PersistentState(context.globalState); const serverPath = await bootstrap(config, state); + const workspaceFolder = vscode.workspace.workspaceFolders?.[0] ?? null; + // Note: we try to start the server before we activate type hints so that it // registers its `onDidChangeDocument` handler before us. // // This a horribly, horribly wrong way to deal with this problem. - ctx = await Ctx.create(config, context, serverPath); + ctx = await Ctx.create(config, context, serverPath, workspaceFolder); // Commands which invokes manually via command palette, shortcut, etc. @@ -85,6 +88,10 @@ export async function activate(context: vscode.ExtensionContext) { ctx.registerCommand('applySourceChange', commands.applySourceChange); ctx.registerCommand('selectAndApplySourceChange', commands.selectAndApplySourceChange); + if (workspaceFolder !== null) { + ctx.pushCleanup(activateTaskProvider(workspaceFolder)); + } + activateStatusDisplay(ctx); if (!ctx.config.highlightingSemanticTokens) { diff --git a/editors/code/src/tasks.ts b/editors/code/src/tasks.ts new file mode 100644 index 000000000..be036b872 --- /dev/null +++ b/editors/code/src/tasks.ts @@ -0,0 +1,60 @@ +import { + Disposable, + ShellExecution, + Task, + TaskGroup, + TaskProvider, + tasks, + WorkspaceFolder, +} from 'vscode'; + +// This ends up as the `type` key in tasks.json. RLS also uses `cargo` and +// our configuration should be compatible with it so use the same key. +const TASK_TYPE = 'cargo'; + +export function activateTaskProvider(target: WorkspaceFolder): Disposable { + const provider: TaskProvider = { + // Detect Rust tasks. Currently we do not do any actual detection + // of tasks (e.g. aliases in .cargo/config) and just return a fixed + // set of tasks that always exist. These tasks cannot be removed in + // tasks.json - only tweaked. + provideTasks: () => getStandardCargoTasks(target), + + // We don't need to implement this. + resolveTask: () => undefined, + }; + + return tasks.registerTaskProvider(TASK_TYPE, provider); +} + +function getStandardCargoTasks(target: WorkspaceFolder): Task[] { + return [ + { command: 'build', group: TaskGroup.Build }, + { command: 'check', group: TaskGroup.Build }, + { command: 'test', group: TaskGroup.Test }, + { command: 'clean', group: TaskGroup.Clean }, + { command: 'run', group: undefined }, + ] + .map(({ command, group }) => { + const vscodeTask = new Task( + // The contents of this object end up in the tasks.json entries. + { + type: TASK_TYPE, + command, + }, + // The scope of the task - workspace or specific folder (global + // is not supported). + target, + // The task name, and task source. These are shown in the UI as + // `${source}: ${name}`, e.g. `rust: cargo build`. + `cargo ${command}`, + 'rust', + // What to do when this command is executed. + new ShellExecution('cargo', [command]), + // Problem matchers. + ['$rustc'], + ); + vscodeTask.group = group; + return vscodeTask; + }); +} -- cgit v1.2.3 From 6e535915bda524de34f011f75067132e88a3a3cc Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 31 Mar 2020 09:01:41 +0100 Subject: Use namespace import --- editors/code/src/tasks.ts | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'editors') diff --git a/editors/code/src/tasks.ts b/editors/code/src/tasks.ts index be036b872..fa1c4a951 100644 --- a/editors/code/src/tasks.ts +++ b/editors/code/src/tasks.ts @@ -1,19 +1,11 @@ -import { - Disposable, - ShellExecution, - Task, - TaskGroup, - TaskProvider, - tasks, - WorkspaceFolder, -} from 'vscode'; +import * as vscode from 'vscode'; // This ends up as the `type` key in tasks.json. RLS also uses `cargo` and // our configuration should be compatible with it so use the same key. const TASK_TYPE = 'cargo'; -export function activateTaskProvider(target: WorkspaceFolder): Disposable { - const provider: TaskProvider = { +export function activateTaskProvider(target: vscode.WorkspaceFolder): vscode.Disposable { + const provider: vscode.TaskProvider = { // Detect Rust tasks. Currently we do not do any actual detection // of tasks (e.g. aliases in .cargo/config) and just return a fixed // set of tasks that always exist. These tasks cannot be removed in @@ -24,19 +16,19 @@ export function activateTaskProvider(target: WorkspaceFolder): Disposable { resolveTask: () => undefined, }; - return tasks.registerTaskProvider(TASK_TYPE, provider); + return vscode.tasks.registerTaskProvider(TASK_TYPE, provider); } -function getStandardCargoTasks(target: WorkspaceFolder): Task[] { +function getStandardCargoTasks(target: vscode.WorkspaceFolder): vscode.Task[] { return [ - { command: 'build', group: TaskGroup.Build }, - { command: 'check', group: TaskGroup.Build }, - { command: 'test', group: TaskGroup.Test }, - { command: 'clean', group: TaskGroup.Clean }, + { command: 'build', group: vscode.TaskGroup.Build }, + { command: 'check', group: vscode.TaskGroup.Build }, + { command: 'test', group: vscode.TaskGroup.Test }, + { command: 'clean', group: vscode.TaskGroup.Clean }, { command: 'run', group: undefined }, ] .map(({ command, group }) => { - const vscodeTask = new Task( + const vscodeTask = new vscode.Task( // The contents of this object end up in the tasks.json entries. { type: TASK_TYPE, @@ -50,7 +42,7 @@ function getStandardCargoTasks(target: WorkspaceFolder): Task[] { `cargo ${command}`, 'rust', // What to do when this command is executed. - new ShellExecution('cargo', [command]), + new vscode.ShellExecution('cargo', [command]), // Problem matchers. ['$rustc'], ); -- cgit v1.2.3 From a781a58fe2cefefbf9bf505247df78fd750a8f13 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 31 Mar 2020 09:05:22 +0100 Subject: Throw error if no folder is opened --- editors/code/src/client.ts | 4 ++-- editors/code/src/ctx.ts | 2 +- editors/code/src/main.ts | 7 ++++++- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'editors') diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index c9819e457..0de45bb30 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -30,14 +30,14 @@ export function configToServerOptions(config: Config) { }; } -export async function createClient(config: Config, serverPath: string, workspaceFolder: vscode.WorkspaceFolder | null): Promise { +export async function createClient(config: Config, serverPath: string, workspaceFolder: vscode.WorkspaceFolder): Promise { // '.' Is the fallback if no folder is open // TODO?: Workspace folders support Uri's (eg: file://test.txt). // It might be a good idea to test if the uri points to a file. const run: lc.Executable = { command: serverPath, - options: { cwd: workspaceFolder?.uri.fsPath ?? '.' }, + options: { cwd: workspaceFolder.uri.fsPath }, }; const serverOptions: lc.ServerOptions = { run, diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 0e705bc84..255d57f5e 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -19,7 +19,7 @@ export class Ctx { config: Config, extCtx: vscode.ExtensionContext, serverPath: string, - workspaceFolder: vscode.WorkspaceFolder | null, + workspaceFolder: vscode.WorkspaceFolder, ): Promise { const client = await createClient(config, serverPath, workspaceFolder); const res = new Ctx(config, extCtx, client, serverPath); diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 40701e4f5..ee6e712a4 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -42,7 +42,12 @@ export async function activate(context: vscode.ExtensionContext) { const state = new PersistentState(context.globalState); const serverPath = await bootstrap(config, state); - const workspaceFolder = vscode.workspace.workspaceFolders?.[0] ?? null; + const workspaceFolder = vscode.workspace.workspaceFolders?.[0]; + if (workspaceFolder === undefined) { + const err = "Cannot activate rust-analyzer when no folder is opened"; + void vscode.window.showErrorMessage(err); + throw new Error(err); + } // Note: we try to start the server before we activate type hints so that it // registers its `onDidChangeDocument` handler before us. -- cgit v1.2.3 From 9ef1e9efc6039c9299cbb866118ff92cb4467202 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 31 Mar 2020 09:11:22 +0100 Subject: Remove unnecessary null check --- editors/code/src/main.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'editors') diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index ee6e712a4..c1e2b97c3 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -93,9 +93,7 @@ export async function activate(context: vscode.ExtensionContext) { ctx.registerCommand('applySourceChange', commands.applySourceChange); ctx.registerCommand('selectAndApplySourceChange', commands.selectAndApplySourceChange); - if (workspaceFolder !== null) { - ctx.pushCleanup(activateTaskProvider(workspaceFolder)); - } + ctx.pushCleanup(activateTaskProvider(workspaceFolder)); activateStatusDisplay(ctx); -- cgit v1.2.3 From 3eb45b99223ae6a708d82c52d656c697bc993c3b Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 31 Mar 2020 10:23:18 +0100 Subject: Pass string instread of WorkspaceFolder --- editors/code/src/client.ts | 4 ++-- editors/code/src/ctx.ts | 4 ++-- editors/code/src/main.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'editors') diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index 0de45bb30..f909f8db2 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -30,14 +30,14 @@ export function configToServerOptions(config: Config) { }; } -export async function createClient(config: Config, serverPath: string, workspaceFolder: vscode.WorkspaceFolder): Promise { +export async function createClient(config: Config, serverPath: string, cwd: string): Promise { // '.' Is the fallback if no folder is open // TODO?: Workspace folders support Uri's (eg: file://test.txt). // It might be a good idea to test if the uri points to a file. const run: lc.Executable = { command: serverPath, - options: { cwd: workspaceFolder.uri.fsPath }, + options: { cwd }, }; const serverOptions: lc.ServerOptions = { run, diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 255d57f5e..86b5f3629 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -19,9 +19,9 @@ export class Ctx { config: Config, extCtx: vscode.ExtensionContext, serverPath: string, - workspaceFolder: vscode.WorkspaceFolder, + cwd: string, ): Promise { - const client = await createClient(config, serverPath, workspaceFolder); + const client = await createClient(config, serverPath, cwd); const res = new Ctx(config, extCtx, client, serverPath); res.pushCleanup(client.start()); await client.onReady(); diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index c1e2b97c3..7ba16120c 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -53,7 +53,7 @@ export async function activate(context: vscode.ExtensionContext) { // registers its `onDidChangeDocument` handler before us. // // This a horribly, horribly wrong way to deal with this problem. - ctx = await Ctx.create(config, context, serverPath, workspaceFolder); + ctx = await Ctx.create(config, context, serverPath, workspaceFolder.uri.fsPath); // Commands which invokes manually via command palette, shortcut, etc. -- cgit v1.2.3