-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor extension to support arbitrary shell command runnables #16839
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,22 +2,20 @@ import * as vscode from "vscode"; | |
import * as toolchain from "./toolchain"; | ||
import type { Config } from "./config"; | ||
import { log } from "./util"; | ||
import { unwrapUndefinable } from "./undefinable"; | ||
|
||
// 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. | ||
export const TASK_TYPE = "cargo"; | ||
export const TASK_SOURCE = "rust"; | ||
|
||
export interface CargoTaskDefinition extends vscode.TaskDefinition { | ||
command?: string; | ||
args?: string[]; | ||
export interface RustTargetDefinition extends vscode.TaskDefinition { | ||
program: string; | ||
args: string[]; | ||
cwd?: string; | ||
env?: { [key: string]: string }; | ||
overrideCargo?: string; | ||
} | ||
|
||
class CargoTaskProvider implements vscode.TaskProvider { | ||
class RustTaskProvider implements vscode.TaskProvider { | ||
private readonly config: Config; | ||
|
||
constructor(config: Config) { | ||
|
@@ -39,14 +37,15 @@ class CargoTaskProvider implements vscode.TaskProvider { | |
{ command: "run", group: undefined }, | ||
]; | ||
|
||
const cargoPath = await toolchain.cargoPath(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know if this should happen in this PR, but I wonder whether if we're to switch over, i think it's worth considering keeping the old and new versions of runnables around before removing the older version. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This PR (especially with #16840 being a larger change) is probably better as a small focused PR, but I agree it would be nice to follow up on how toolchains are handled :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we should ideally replicate the toolchain discovery here / allow clients to query the server for the correct toolchain stuff. Not doing that can cause recompilations and random failures. (Agree that that can go into a separate PR though) |
||
|
||
const tasks: vscode.Task[] = []; | ||
for (const workspaceTarget of vscode.workspace.workspaceFolders || []) { | ||
for (const def of defs) { | ||
const vscodeTask = await buildCargoTask( | ||
const vscodeTask = await buildRustTask( | ||
workspaceTarget, | ||
{ type: TASK_TYPE, command: def.command }, | ||
{ type: TASK_TYPE, program: cargoPath, args: [def.command] }, | ||
`cargo ${def.command}`, | ||
[def.command], | ||
this.config.problemMatcher, | ||
this.config.cargoRunner, | ||
); | ||
|
@@ -63,15 +62,13 @@ class CargoTaskProvider implements vscode.TaskProvider { | |
// we need to inform VSCode how to execute that command by creating | ||
// a ShellExecution for it. | ||
|
||
const definition = task.definition as CargoTaskDefinition; | ||
const definition = task.definition as RustTargetDefinition; | ||
|
||
if (definition.type === TASK_TYPE && definition.command) { | ||
const args = [definition.command].concat(definition.args ?? []); | ||
return await buildCargoTask( | ||
if (definition.type === TASK_TYPE) { | ||
return await buildRustTask( | ||
task.scope, | ||
definition, | ||
task.name, | ||
args, | ||
this.config.problemMatcher, | ||
this.config.cargoRunner, | ||
); | ||
|
@@ -81,11 +78,10 @@ class CargoTaskProvider implements vscode.TaskProvider { | |
} | ||
} | ||
|
||
export async function buildCargoTask( | ||
export async function buildRustTask( | ||
scope: vscode.WorkspaceFolder | vscode.TaskScope | undefined, | ||
definition: CargoTaskDefinition, | ||
definition: RustTargetDefinition, | ||
name: string, | ||
args: string[], | ||
problemMatcher: string[], | ||
customRunner?: string, | ||
throwOnError: boolean = false, | ||
|
@@ -95,7 +91,12 @@ export async function buildCargoTask( | |
if (customRunner) { | ||
const runnerCommand = `${customRunner}.buildShellExecution`; | ||
try { | ||
const runnerArgs = { kind: TASK_TYPE, args, cwd: definition.cwd, env: definition.env }; | ||
const runnerArgs = { | ||
kind: TASK_TYPE, | ||
args: definition.args, | ||
cwd: definition.cwd, | ||
env: definition.env, | ||
}; | ||
const customExec = await vscode.commands.executeCommand(runnerCommand, runnerArgs); | ||
if (customExec) { | ||
if (customExec instanceof vscode.ShellExecution) { | ||
|
@@ -113,16 +114,7 @@ export async function buildCargoTask( | |
} | ||
|
||
if (!exec) { | ||
// Check whether we must use a user-defined substitute for cargo. | ||
// Split on spaces to allow overrides like "wrapper cargo". | ||
const overrideCargo = definition.overrideCargo ?? definition.overrideCargo; | ||
const cargoPath = await toolchain.cargoPath(); | ||
const cargoCommand = overrideCargo?.split(" ") ?? [cargoPath]; | ||
|
||
const fullCommand = [...cargoCommand, ...args]; | ||
|
||
const processName = unwrapUndefinable(fullCommand[0]); | ||
exec = new vscode.ProcessExecution(processName, fullCommand.slice(1), definition); | ||
exec = new vscode.ProcessExecution(definition.program, definition.args, definition); | ||
} | ||
|
||
return new vscode.Task( | ||
|
@@ -138,6 +130,6 @@ export async function buildCargoTask( | |
} | ||
|
||
export function activateTaskProvider(config: Config): vscode.Disposable { | ||
const provider = new CargoTaskProvider(config); | ||
const provider = new RustTaskProvider(config); | ||
return vscode.tasks.registerTaskProvider(TASK_TYPE, provider); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I'm not sure there will be any other kind of Task run by rust-analyzer, so I wouldn't qualify with
Rust
, but I also don't feel too strongly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it needs some name,
class TaskProvider implements vscode.TaskProvider
would be confusing. I don't feel strongly about the name though. Do you have any suggestions?RustAnalyzerTaskProvider
is maybe a little long.