mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
fix: Fix runnables being incorrectly constructed
This commit is contained in:
parent
7733403056
commit
bb9678ea3b
8 changed files with 223 additions and 113 deletions
|
@ -323,14 +323,6 @@
|
||||||
{
|
{
|
||||||
"title": "general",
|
"title": "general",
|
||||||
"properties": {
|
"properties": {
|
||||||
"rust-analyzer.cargoRunner": {
|
|
||||||
"type": [
|
|
||||||
"null",
|
|
||||||
"string"
|
|
||||||
],
|
|
||||||
"default": null,
|
|
||||||
"description": "Custom cargo runner extension ID."
|
|
||||||
},
|
|
||||||
"rust-analyzer.restartServerOnConfigChange": {
|
"rust-analyzer.restartServerOnConfigChange": {
|
||||||
"markdownDescription": "Whether to restart the server automatically when certain settings that require a restart are changed.",
|
"markdownDescription": "Whether to restart the server automatically when certain settings that require a restart are changed.",
|
||||||
"default": false,
|
"default": false,
|
||||||
|
|
|
@ -36,6 +36,12 @@ async function getServer(
|
||||||
config: Config,
|
config: Config,
|
||||||
state: PersistentState,
|
state: PersistentState,
|
||||||
): Promise<string | undefined> {
|
): Promise<string | undefined> {
|
||||||
|
const packageJson: {
|
||||||
|
version: string;
|
||||||
|
releaseTag: string | null;
|
||||||
|
enableProposedApi: boolean | undefined;
|
||||||
|
} = context.extension.packageJSON;
|
||||||
|
|
||||||
const explicitPath = process.env["__RA_LSP_SERVER_DEBUG"] ?? config.serverPath;
|
const explicitPath = process.env["__RA_LSP_SERVER_DEBUG"] ?? config.serverPath;
|
||||||
if (explicitPath) {
|
if (explicitPath) {
|
||||||
if (explicitPath.startsWith("~/")) {
|
if (explicitPath.startsWith("~/")) {
|
||||||
|
@ -43,7 +49,7 @@ async function getServer(
|
||||||
}
|
}
|
||||||
return explicitPath;
|
return explicitPath;
|
||||||
}
|
}
|
||||||
if (config.package.releaseTag === null) return "rust-analyzer";
|
if (packageJson.releaseTag === null) return "rust-analyzer";
|
||||||
|
|
||||||
const ext = process.platform === "win32" ? ".exe" : "";
|
const ext = process.platform === "win32" ? ".exe" : "";
|
||||||
const bundled = vscode.Uri.joinPath(context.extensionUri, "server", `rust-analyzer${ext}`);
|
const bundled = vscode.Uri.joinPath(context.extensionUri, "server", `rust-analyzer${ext}`);
|
||||||
|
@ -54,8 +60,15 @@ async function getServer(
|
||||||
if (bundledExists) {
|
if (bundledExists) {
|
||||||
let server = bundled;
|
let server = bundled;
|
||||||
if (await isNixOs()) {
|
if (await isNixOs()) {
|
||||||
server = await getNixOsServer(config, ext, state, bundled, server);
|
server = await getNixOsServer(
|
||||||
await state.updateServerVersion(config.package.version);
|
context.globalStorageUri,
|
||||||
|
packageJson.version,
|
||||||
|
ext,
|
||||||
|
state,
|
||||||
|
bundled,
|
||||||
|
server,
|
||||||
|
);
|
||||||
|
await state.updateServerVersion(packageJson.version);
|
||||||
}
|
}
|
||||||
return server.fsPath;
|
return server.fsPath;
|
||||||
}
|
}
|
||||||
|
@ -86,19 +99,20 @@ export function isValidExecutable(path: string, extraEnv: Env): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getNixOsServer(
|
async function getNixOsServer(
|
||||||
config: Config,
|
globalStorageUri: vscode.Uri,
|
||||||
|
version: string,
|
||||||
ext: string,
|
ext: string,
|
||||||
state: PersistentState,
|
state: PersistentState,
|
||||||
bundled: vscode.Uri,
|
bundled: vscode.Uri,
|
||||||
server: vscode.Uri,
|
server: vscode.Uri,
|
||||||
) {
|
) {
|
||||||
await vscode.workspace.fs.createDirectory(config.globalStorageUri).then();
|
await vscode.workspace.fs.createDirectory(globalStorageUri).then();
|
||||||
const dest = vscode.Uri.joinPath(config.globalStorageUri, `rust-analyzer${ext}`);
|
const dest = vscode.Uri.joinPath(globalStorageUri, `rust-analyzer${ext}`);
|
||||||
let exists = await vscode.workspace.fs.stat(dest).then(
|
let exists = await vscode.workspace.fs.stat(dest).then(
|
||||||
() => true,
|
() => true,
|
||||||
() => false,
|
() => false,
|
||||||
);
|
);
|
||||||
if (exists && config.package.version !== state.serverVersion) {
|
if (exists && version !== state.serverVersion) {
|
||||||
await vscode.workspace.fs.delete(dest);
|
await vscode.workspace.fs.delete(dest);
|
||||||
exists = false;
|
exists = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import * as path from "path";
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import { type Env, log, unwrapUndefinable, expectNotUndefined } from "./util";
|
import { type Env, log, unwrapUndefinable, expectNotUndefined } from "./util";
|
||||||
import type { JsonProject } from "./rust_project";
|
import type { JsonProject } from "./rust_project";
|
||||||
|
import type { Disposable } from "./ctx";
|
||||||
|
|
||||||
export type RunnableEnvCfgItem = {
|
export type RunnableEnvCfgItem = {
|
||||||
mask?: string;
|
mask?: string;
|
||||||
|
@ -29,22 +30,9 @@ export class Config {
|
||||||
(opt) => `${this.rootSection}.${opt}`,
|
(opt) => `${this.rootSection}.${opt}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
readonly package: {
|
constructor(disposables: Disposable[]) {
|
||||||
version: string;
|
|
||||||
releaseTag: string | null;
|
|
||||||
enableProposedApi: boolean | undefined;
|
|
||||||
} = vscode.extensions.getExtension(this.extensionId)!.packageJSON;
|
|
||||||
|
|
||||||
readonly globalStorageUri: vscode.Uri;
|
|
||||||
|
|
||||||
constructor(ctx: vscode.ExtensionContext) {
|
|
||||||
this.globalStorageUri = ctx.globalStorageUri;
|
|
||||||
this.discoveredWorkspaces = [];
|
this.discoveredWorkspaces = [];
|
||||||
vscode.workspace.onDidChangeConfiguration(
|
vscode.workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, disposables);
|
||||||
this.onDidChangeConfiguration,
|
|
||||||
this,
|
|
||||||
ctx.subscriptions,
|
|
||||||
);
|
|
||||||
this.refreshLogging();
|
this.refreshLogging();
|
||||||
this.configureLanguage();
|
this.configureLanguage();
|
||||||
}
|
}
|
||||||
|
@ -55,7 +43,10 @@ export class Config {
|
||||||
|
|
||||||
private refreshLogging() {
|
private refreshLogging() {
|
||||||
log.setEnabled(this.traceExtension ?? false);
|
log.setEnabled(this.traceExtension ?? false);
|
||||||
log.info("Extension version:", this.package.version);
|
log.info(
|
||||||
|
"Extension version:",
|
||||||
|
vscode.extensions.getExtension(this.extensionId)!.packageJSON.version,
|
||||||
|
);
|
||||||
|
|
||||||
const cfg = Object.entries(this.cfg).filter(([_, val]) => !(val instanceof Function));
|
const cfg = Object.entries(this.cfg).filter(([_, val]) => !(val instanceof Function));
|
||||||
log.info("Using configuration", Object.fromEntries(cfg));
|
log.info("Using configuration", Object.fromEntries(cfg));
|
||||||
|
@ -277,10 +268,6 @@ export class Config {
|
||||||
return this.get<string[]>("runnables.problemMatcher") || [];
|
return this.get<string[]>("runnables.problemMatcher") || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
get cargoRunner() {
|
|
||||||
return this.get<string | undefined>("cargoRunner");
|
|
||||||
}
|
|
||||||
|
|
||||||
get testExplorer() {
|
get testExplorer() {
|
||||||
return this.get<boolean | undefined>("testExplorer");
|
return this.get<boolean | undefined>("testExplorer");
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ export class Ctx implements RustAnalyzerExtensionApi {
|
||||||
extCtx.subscriptions.push(this);
|
extCtx.subscriptions.push(this);
|
||||||
this.version = extCtx.extension.packageJSON.version ?? "<unknown>";
|
this.version = extCtx.extension.packageJSON.version ?? "<unknown>";
|
||||||
this._serverVersion = "<not running>";
|
this._serverVersion = "<not running>";
|
||||||
this.config = new Config(extCtx);
|
this.config = new Config(extCtx.subscriptions);
|
||||||
this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
|
this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
|
||||||
if (this.config.testExplorer) {
|
if (this.config.testExplorer) {
|
||||||
this.testController = vscode.tests.createTestController(
|
this.testController = vscode.tests.createTestController(
|
||||||
|
|
|
@ -111,26 +111,31 @@ export async function createTaskFromRunnable(
|
||||||
runnable: ra.Runnable,
|
runnable: ra.Runnable,
|
||||||
config: Config,
|
config: Config,
|
||||||
): Promise<vscode.Task> {
|
): Promise<vscode.Task> {
|
||||||
let definition: tasks.RustTargetDefinition;
|
const target = vscode.workspace.workspaceFolders?.[0];
|
||||||
|
|
||||||
|
let definition: tasks.TaskDefinition;
|
||||||
|
let options;
|
||||||
|
let cargo;
|
||||||
if (runnable.kind === "cargo") {
|
if (runnable.kind === "cargo") {
|
||||||
const runnableArgs = runnable.args;
|
const runnableArgs = runnable.args;
|
||||||
let args = createCargoArgs(runnableArgs);
|
let args = createCargoArgs(runnableArgs);
|
||||||
|
|
||||||
let program: string;
|
|
||||||
if (runnableArgs.overrideCargo) {
|
if (runnableArgs.overrideCargo) {
|
||||||
// Split on spaces to allow overrides like "wrapper cargo".
|
// Split on spaces to allow overrides like "wrapper cargo".
|
||||||
const cargoParts = runnableArgs.overrideCargo.split(" ");
|
const cargoParts = runnableArgs.overrideCargo.split(" ");
|
||||||
|
|
||||||
program = unwrapUndefinable(cargoParts[0]);
|
cargo = unwrapUndefinable(cargoParts[0]);
|
||||||
args = [...cargoParts.slice(1), ...args];
|
args = [...cargoParts.slice(1), ...args];
|
||||||
} else {
|
} else {
|
||||||
program = await toolchain.cargoPath();
|
cargo = await toolchain.cargoPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
definition = {
|
definition = {
|
||||||
type: tasks.CARGO_TASK_TYPE,
|
type: tasks.CARGO_TASK_TYPE,
|
||||||
command: program,
|
command: unwrapUndefinable(args[0]),
|
||||||
args,
|
args: args.slice(1),
|
||||||
|
};
|
||||||
|
options = {
|
||||||
cwd: runnableArgs.workspaceRoot || ".",
|
cwd: runnableArgs.workspaceRoot || ".",
|
||||||
env: prepareEnv(runnable.label, runnableArgs, config.runnablesExtraEnv),
|
env: prepareEnv(runnable.label, runnableArgs, config.runnablesExtraEnv),
|
||||||
};
|
};
|
||||||
|
@ -140,13 +145,14 @@ export async function createTaskFromRunnable(
|
||||||
type: tasks.SHELL_TASK_TYPE,
|
type: tasks.SHELL_TASK_TYPE,
|
||||||
command: runnableArgs.program,
|
command: runnableArgs.program,
|
||||||
args: runnableArgs.args,
|
args: runnableArgs.args,
|
||||||
|
};
|
||||||
|
options = {
|
||||||
cwd: runnableArgs.cwd,
|
cwd: runnableArgs.cwd,
|
||||||
env: prepareBaseEnv(),
|
env: prepareBaseEnv(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const target = vscode.workspace.workspaceFolders?.[0];
|
const exec = await tasks.targetToExecution(definition, options, cargo);
|
||||||
const exec = await tasks.targetToExecution(definition, config.cargoRunner, true);
|
|
||||||
const task = await tasks.buildRustTask(
|
const task = await tasks.buildRustTask(
|
||||||
target,
|
target,
|
||||||
definition,
|
definition,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import type { Config } from "./config";
|
import type { Config } from "./config";
|
||||||
import { log, unwrapUndefinable } from "./util";
|
|
||||||
import * as toolchain from "./toolchain";
|
import * as toolchain from "./toolchain";
|
||||||
|
|
||||||
// This ends up as the `type` key in tasks.json. RLS also uses `cargo` and
|
// This ends up as the `type` key in tasks.json. RLS also uses `cargo` and
|
||||||
|
@ -10,21 +9,21 @@ export const SHELL_TASK_TYPE = "shell";
|
||||||
|
|
||||||
export const RUST_TASK_SOURCE = "rust";
|
export const RUST_TASK_SOURCE = "rust";
|
||||||
|
|
||||||
export type RustTargetDefinition = {
|
export type TaskDefinition = vscode.TaskDefinition & {
|
||||||
readonly type: typeof CARGO_TASK_TYPE | typeof SHELL_TASK_TYPE;
|
readonly type: typeof CARGO_TASK_TYPE | typeof SHELL_TASK_TYPE;
|
||||||
} & vscode.TaskDefinition &
|
|
||||||
RustTarget;
|
|
||||||
export type RustTarget = {
|
|
||||||
// The command to run, usually `cargo`.
|
|
||||||
command: string;
|
|
||||||
// Additional arguments passed to the command.
|
|
||||||
args?: string[];
|
args?: string[];
|
||||||
// The working directory to run the command in.
|
command: string;
|
||||||
cwd?: string;
|
|
||||||
// The shell environment.
|
|
||||||
env?: { [key: string]: string };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CargoTaskDefinition = {
|
||||||
|
env?: Record<string, string>;
|
||||||
|
type: typeof CARGO_TASK_TYPE;
|
||||||
|
} & TaskDefinition;
|
||||||
|
|
||||||
|
function isCargoTask(definition: vscode.TaskDefinition): definition is CargoTaskDefinition {
|
||||||
|
return definition.type === CARGO_TASK_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
class RustTaskProvider implements vscode.TaskProvider {
|
class RustTaskProvider implements vscode.TaskProvider {
|
||||||
private readonly config: Config;
|
private readonly config: Config;
|
||||||
|
|
||||||
|
@ -58,13 +57,13 @@ class RustTaskProvider implements vscode.TaskProvider {
|
||||||
for (const workspaceTarget of vscode.workspace.workspaceFolders) {
|
for (const workspaceTarget of vscode.workspace.workspaceFolders) {
|
||||||
for (const def of defs) {
|
for (const def of defs) {
|
||||||
const definition = {
|
const definition = {
|
||||||
command: cargo,
|
command: def.command,
|
||||||
args: [def.command],
|
type: CARGO_TASK_TYPE,
|
||||||
};
|
} as const;
|
||||||
const exec = await targetToExecution(definition, this.config.cargoRunner);
|
const exec = await targetToExecution(definition, {}, cargo);
|
||||||
const vscodeTask = await buildRustTask(
|
const vscodeTask = await buildRustTask(
|
||||||
workspaceTarget,
|
workspaceTarget,
|
||||||
{ ...definition, type: CARGO_TASK_TYPE },
|
definition,
|
||||||
`cargo ${def.command}`,
|
`cargo ${def.command}`,
|
||||||
this.config.problemMatcher,
|
this.config.problemMatcher,
|
||||||
exec,
|
exec,
|
||||||
|
@ -81,23 +80,13 @@ class RustTaskProvider implements vscode.TaskProvider {
|
||||||
// VSCode calls this for every cargo task in the user's tasks.json,
|
// VSCode calls this for every cargo task in the user's tasks.json,
|
||||||
// we need to inform VSCode how to execute that command by creating
|
// we need to inform VSCode how to execute that command by creating
|
||||||
// a ShellExecution for it.
|
// a ShellExecution for it.
|
||||||
if (task.definition.type === CARGO_TASK_TYPE) {
|
if (isCargoTask(task.definition)) {
|
||||||
const taskDefinition = task.definition as RustTargetDefinition;
|
const exec = await targetToExecution(task.definition, { env: task.definition.env });
|
||||||
const cargo = await toolchain.cargoPath();
|
return buildRustTask(
|
||||||
const exec = await targetToExecution(
|
|
||||||
{
|
|
||||||
command: cargo,
|
|
||||||
args: [taskDefinition.command].concat(taskDefinition.args || []),
|
|
||||||
cwd: taskDefinition.cwd,
|
|
||||||
env: taskDefinition.env,
|
|
||||||
},
|
|
||||||
this.config.cargoRunner,
|
|
||||||
);
|
|
||||||
return await buildRustTask(
|
|
||||||
task.scope,
|
task.scope,
|
||||||
taskDefinition,
|
task.definition,
|
||||||
task.name,
|
task.name,
|
||||||
this.config.problemMatcher,
|
task.problemMatchers,
|
||||||
exec,
|
exec,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -108,7 +97,7 @@ class RustTaskProvider implements vscode.TaskProvider {
|
||||||
|
|
||||||
export async function buildRustTask(
|
export async function buildRustTask(
|
||||||
scope: vscode.WorkspaceFolder | vscode.TaskScope | undefined,
|
scope: vscode.WorkspaceFolder | vscode.TaskScope | undefined,
|
||||||
definition: RustTargetDefinition,
|
definition: TaskDefinition,
|
||||||
name: string,
|
name: string,
|
||||||
problemMatcher: string[],
|
problemMatcher: string[],
|
||||||
exec: vscode.ProcessExecution | vscode.ShellExecution,
|
exec: vscode.ProcessExecution | vscode.ShellExecution,
|
||||||
|
@ -126,40 +115,23 @@ export async function buildRustTask(
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function targetToExecution(
|
export async function targetToExecution(
|
||||||
definition: RustTarget,
|
definition: TaskDefinition,
|
||||||
customRunner?: string,
|
options?: {
|
||||||
throwOnError: boolean = false,
|
env?: { [key: string]: string };
|
||||||
|
cwd?: string;
|
||||||
|
},
|
||||||
|
cargo?: string,
|
||||||
): Promise<vscode.ProcessExecution | vscode.ShellExecution> {
|
): Promise<vscode.ProcessExecution | vscode.ShellExecution> {
|
||||||
if (customRunner) {
|
let command, args;
|
||||||
const runnerCommand = `${customRunner}.buildShellExecution`;
|
if (isCargoTask(definition)) {
|
||||||
|
// FIXME: The server should provide cargo
|
||||||
try {
|
command = cargo || (await toolchain.cargoPath());
|
||||||
const runnerArgs = {
|
args = [definition.command].concat(definition.args || []);
|
||||||
kind: CARGO_TASK_TYPE,
|
} else {
|
||||||
args: definition.args,
|
command = definition.command;
|
||||||
cwd: definition.cwd,
|
args = definition.args || [];
|
||||||
env: definition.env,
|
|
||||||
};
|
|
||||||
const customExec = await vscode.commands.executeCommand(runnerCommand, runnerArgs);
|
|
||||||
if (customExec) {
|
|
||||||
if (customExec instanceof vscode.ShellExecution) {
|
|
||||||
return customExec;
|
|
||||||
} else {
|
|
||||||
log.debug("Invalid cargo ShellExecution", customExec);
|
|
||||||
throw "Invalid cargo ShellExecution.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// fallback to default processing
|
|
||||||
} catch (e) {
|
|
||||||
if (throwOnError) throw `Cargo runner '${customRunner}' failed! ${e}`;
|
|
||||||
// fallback to default processing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const args = unwrapUndefinable(definition.args);
|
return new vscode.ProcessExecution(command, args, options);
|
||||||
return new vscode.ProcessExecution(definition.command, args, {
|
|
||||||
cwd: definition.cwd,
|
|
||||||
env: definition.env,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function activateTaskProvider(config: Config): vscode.Disposable {
|
export function activateTaskProvider(config: Config): vscode.Disposable {
|
||||||
|
|
|
@ -13,7 +13,7 @@ export async function getTests(ctx: Context) {
|
||||||
USING_MY_VAR: "test test test",
|
USING_MY_VAR: "test test test",
|
||||||
MY_VAR: "test",
|
MY_VAR: "test",
|
||||||
};
|
};
|
||||||
const actualEnv = await substituteVariablesInEnv(envJson);
|
const actualEnv = substituteVariablesInEnv(envJson);
|
||||||
assert.deepStrictEqual(actualEnv, expectedEnv);
|
assert.deepStrictEqual(actualEnv, expectedEnv);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ export async function getTests(ctx: Context) {
|
||||||
E_IS_ISOLATED: "test",
|
E_IS_ISOLATED: "test",
|
||||||
F_USES_E: "test",
|
F_USES_E: "test",
|
||||||
};
|
};
|
||||||
const actualEnv = await substituteVariablesInEnv(envJson);
|
const actualEnv = substituteVariablesInEnv(envJson);
|
||||||
assert.deepStrictEqual(actualEnv, expectedEnv);
|
assert.deepStrictEqual(actualEnv, expectedEnv);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ export async function getTests(ctx: Context) {
|
||||||
USING_EXTERNAL_VAR: "test test test",
|
USING_EXTERNAL_VAR: "test test test",
|
||||||
};
|
};
|
||||||
|
|
||||||
const actualEnv = await substituteVariablesInEnv(envJson);
|
const actualEnv = substituteVariablesInEnv(envJson);
|
||||||
assert.deepStrictEqual(actualEnv, expectedEnv);
|
assert.deepStrictEqual(actualEnv, expectedEnv);
|
||||||
delete process.env["TEST_VARIABLE"];
|
delete process.env["TEST_VARIABLE"];
|
||||||
});
|
});
|
||||||
|
@ -56,7 +56,7 @@ export async function getTests(ctx: Context) {
|
||||||
const envJson = {
|
const envJson = {
|
||||||
USING_VSCODE_VAR: "${workspaceFolderBasename}",
|
USING_VSCODE_VAR: "${workspaceFolderBasename}",
|
||||||
};
|
};
|
||||||
const actualEnv = await substituteVariablesInEnv(envJson);
|
const actualEnv = substituteVariablesInEnv(envJson);
|
||||||
assert.deepStrictEqual(actualEnv["USING_VSCODE_VAR"], "code");
|
assert.deepStrictEqual(actualEnv["USING_VSCODE_VAR"], "code");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
139
editors/code/tests/unit/tasks.test.ts
Normal file
139
editors/code/tests/unit/tasks.test.ts
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
import type { Context } from ".";
|
||||||
|
import * as vscode from "vscode";
|
||||||
|
import * as assert from "assert";
|
||||||
|
import { targetToExecution } from "../../src/tasks";
|
||||||
|
|
||||||
|
export async function getTests(ctx: Context) {
|
||||||
|
await ctx.suite("Tasks", (suite) => {
|
||||||
|
suite.addTest("cargo targetToExecution", async () => {
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
await targetToExecution({
|
||||||
|
type: "cargo",
|
||||||
|
command: "check",
|
||||||
|
args: ["foo"],
|
||||||
|
}).then(executionToSimple),
|
||||||
|
{
|
||||||
|
process: "cargo",
|
||||||
|
args: ["check", "foo"],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
suite.addTest("shell targetToExecution", async () => {
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
await targetToExecution({
|
||||||
|
type: "shell",
|
||||||
|
command: "thing",
|
||||||
|
args: ["foo"],
|
||||||
|
}).then(executionToSimple),
|
||||||
|
{
|
||||||
|
process: "thing",
|
||||||
|
args: ["foo"],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
suite.addTest("base tasks", async () => {
|
||||||
|
const tasks = await vscode.tasks.fetchTasks({ type: "cargo" });
|
||||||
|
const expectedTasks = [
|
||||||
|
{
|
||||||
|
definition: { type: "cargo", command: "build" },
|
||||||
|
name: "cargo build",
|
||||||
|
execution: {
|
||||||
|
process: "cargo",
|
||||||
|
args: ["build"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
definition: {
|
||||||
|
type: "cargo",
|
||||||
|
command: "check",
|
||||||
|
},
|
||||||
|
name: "cargo check",
|
||||||
|
execution: {
|
||||||
|
process: "cargo",
|
||||||
|
args: ["check"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
definition: { type: "cargo", command: "clippy" },
|
||||||
|
name: "cargo clippy",
|
||||||
|
execution: {
|
||||||
|
process: "cargo",
|
||||||
|
args: ["clippy"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
definition: { type: "cargo", command: "test" },
|
||||||
|
name: "cargo test",
|
||||||
|
execution: {
|
||||||
|
process: "cargo",
|
||||||
|
args: ["test"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
definition: {
|
||||||
|
type: "cargo",
|
||||||
|
command: "clean",
|
||||||
|
},
|
||||||
|
name: "cargo clean",
|
||||||
|
execution: {
|
||||||
|
process: "cargo",
|
||||||
|
args: ["clean"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
definition: { type: "cargo", command: "run" },
|
||||||
|
name: "cargo run",
|
||||||
|
execution: {
|
||||||
|
process: "cargo",
|
||||||
|
args: ["run"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
tasks.map(f).forEach((actual, i) => {
|
||||||
|
const expected = expectedTasks[i];
|
||||||
|
assert.deepStrictEqual(actual, expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function f(task: vscode.Task): {
|
||||||
|
definition: vscode.TaskDefinition;
|
||||||
|
name: string;
|
||||||
|
execution: {
|
||||||
|
args: string[];
|
||||||
|
} & ({ command: string } | { process: string });
|
||||||
|
} {
|
||||||
|
const execution = executionToSimple(task.execution!);
|
||||||
|
|
||||||
|
return {
|
||||||
|
definition: task.definition,
|
||||||
|
name: task.name,
|
||||||
|
execution,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function executionToSimple(
|
||||||
|
taskExecution: vscode.ProcessExecution | vscode.ShellExecution | vscode.CustomExecution,
|
||||||
|
): {
|
||||||
|
args: string[];
|
||||||
|
} & ({ command: string } | { process: string }) {
|
||||||
|
const exec = taskExecution as vscode.ProcessExecution | vscode.ShellExecution;
|
||||||
|
if (exec instanceof vscode.ShellExecution) {
|
||||||
|
return {
|
||||||
|
command: typeof exec.command === "string" ? exec.command : exec.command.value,
|
||||||
|
args: exec.args.map((arg) => {
|
||||||
|
if (typeof arg === "string") {
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
return arg.value;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
process: exec.process,
|
||||||
|
args: exec.args,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue