From d13f6ba75007816b6eae66719c4a68e27f47d44c Mon Sep 17 00:00:00 2001 From: "Alex.F" Date: Mon, 16 Aug 2021 00:19:45 +0800 Subject: [PATCH 1/4] use async version --- editors/code/src/tasks.ts | 3 ++- editors/code/src/toolchain.ts | 37 +++++++++++++++++++++-------------- editors/code/src/util.ts | 8 ++++---- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/editors/code/src/tasks.ts b/editors/code/src/tasks.ts index 947b3f2e46..1d50d03800 100644 --- a/editors/code/src/tasks.ts +++ b/editors/code/src/tasks.ts @@ -107,7 +107,8 @@ export async function buildCargoTask( // 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 cargoCommand = overrideCargo?.split(" ") ?? [toolchain.cargoPath()]; + const cargoPath = await toolchain.cargoPath(); + const cargoCommand = overrideCargo?.split(" ") ?? [cargoPath]; const fullCommand = [...cargoCommand, ...args]; diff --git a/editors/code/src/toolchain.ts b/editors/code/src/toolchain.ts index 355dd76fe5..b25ec8c062 100644 --- a/editors/code/src/toolchain.ts +++ b/editors/code/src/toolchain.ts @@ -3,7 +3,7 @@ import * as os from 'os'; import * as path from 'path'; import * as readline from 'readline'; import * as vscode from 'vscode'; -import { execute, log, memoize } from './util'; +import { execute, log, memoize, memoizeAsync } from './util'; interface CompilationArtifact { fileName: string; @@ -89,13 +89,14 @@ export class Cargo { return artifacts[0].fileName; } - private runCargo( + private async runCargo( cargoArgs: string[], onStdoutJson: (obj: any) => void, onStderrString: (data: string) => void ): Promise { - return new Promise((resolve, reject) => { - const cargo = cp.spawn(cargoPath(), cargoArgs, { + const path = await cargoPath(); + return await new Promise((resolve, reject) => { + const cargo = cp.spawn(path, cargoArgs, { stdio: ['ignore', 'pipe', 'pipe'], cwd: this.rootFolder }); @@ -121,15 +122,15 @@ export class Cargo { } /** Mirrors `project_model::sysroot::discover_sysroot_dir()` implementation*/ -export function getSysroot(dir: string): Promise { - const rustcPath = getPathForExecutable("rustc"); +export async function getSysroot(dir: string): Promise { + const rustcPath = await getPathForExecutable("rustc"); // do not memoize the result because the toolchain may change between runs - return execute(`${rustcPath} --print sysroot`, { cwd: dir }); + return await execute(`${rustcPath} --print sysroot`, { cwd: dir }); } export async function getRustcId(dir: string): Promise { - const rustcPath = getPathForExecutable("rustc"); + const rustcPath = await getPathForExecutable("rustc"); // do not memoize the result because the toolchain may change between runs const data = await execute(`${rustcPath} -V -v`, { cwd: dir }); @@ -139,27 +140,28 @@ export async function getRustcId(dir: string): Promise { } /** Mirrors `toolchain::cargo()` implementation */ -export function cargoPath(): string { +export function cargoPath(): Promise { return getPathForExecutable("cargo"); } /** Mirrors `toolchain::get_path_for_executable()` implementation */ -export const getPathForExecutable = memoize( +export const getPathForExecutable = memoizeAsync( // We apply caching to decrease file-system interactions - (executableName: "cargo" | "rustc" | "rustup"): string => { + async (executableName: "cargo" | "rustc" | "rustup"): Promise => { { const envVar = process.env[executableName.toUpperCase()]; if (envVar) return envVar; } - if (lookupInPath(executableName)) return executableName; + if (await lookupInPath(executableName)) return executableName; try { // hmm, `os.homedir()` seems to be infallible // it is not mentioned in docs and cannot be infered by the type signature... const standardPath = vscode.Uri.joinPath(vscode.Uri.file(os.homedir()), ".cargo", "bin", executableName); - if (isFileAtUri(standardPath)) return standardPath.fsPath; + const exist = await isFileAtUri(standardPath); + if (exist) return standardPath.fsPath; } catch (err) { log.error("Failed to read the fs info", err); } @@ -167,7 +169,7 @@ export const getPathForExecutable = memoize( } ); -function lookupInPath(exec: string): boolean { +async function lookupInPath(exec: string): Promise { const paths = process.env.PATH ?? "";; const candidates = paths.split(path.delimiter).flatMap(dirInPath => { @@ -177,7 +179,12 @@ function lookupInPath(exec: string): boolean { : [candidate]; }); - return candidates.some(isFileAtPath); + for await (const isFile of candidates.map(isFileAtPath)) { + if (isFile) { + return true; + } + } + return false; } async function isFileAtPath(path: string): Promise { diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts index 56e0e439e9..5eac9a227a 100644 --- a/editors/code/src/util.ts +++ b/editors/code/src/util.ts @@ -126,16 +126,16 @@ export function setContextValue(key: string, value: any): Thenable { /** * Returns a higher-order function that caches the results of invoking the - * underlying function. + * underlying async function. */ -export function memoize(func: (this: TThis, arg: Param) => Ret) { +export function memoizeAsync(func: (this: TThis, arg: Param) => Promise) { const cache = new Map(); - return function(this: TThis, arg: Param) { + return async function (this: TThis, arg: Param) { const cached = cache.get(arg); if (cached) return cached; - const result = func.call(this, arg); + const result = await func.call(this, arg); cache.set(arg, result); return result; From 6b3a6ddb39c5aa9dbc6e62631d82844c6973f6d5 Mon Sep 17 00:00:00 2001 From: "Alex.F" Date: Mon, 16 Aug 2021 00:21:12 +0800 Subject: [PATCH 2/4] fix lint --- editors/code/src/util.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts index 5eac9a227a..aa57081a5f 100644 --- a/editors/code/src/util.ts +++ b/editors/code/src/util.ts @@ -131,7 +131,7 @@ export function setContextValue(key: string, value: any): Thenable { export function memoizeAsync(func: (this: TThis, arg: Param) => Promise) { const cache = new Map(); - return async function (this: TThis, arg: Param) { + return async function(this: TThis, arg: Param) { const cached = cache.get(arg); if (cached) return cached; From 635b89fdaa687685bb482270570a48c3c0c5f84b Mon Sep 17 00:00:00 2001 From: "Alex.F" Date: Mon, 16 Aug 2021 10:35:27 +0800 Subject: [PATCH 3/4] clean imports --- editors/code/src/toolchain.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/code/src/toolchain.ts b/editors/code/src/toolchain.ts index b25ec8c062..30e79767dc 100644 --- a/editors/code/src/toolchain.ts +++ b/editors/code/src/toolchain.ts @@ -3,7 +3,7 @@ import * as os from 'os'; import * as path from 'path'; import * as readline from 'readline'; import * as vscode from 'vscode'; -import { execute, log, memoize, memoizeAsync } from './util'; +import { execute, log, memoizeAsync } from './util'; interface CompilationArtifact { fileName: string; From 8e4039c7d79cd846ddcabd6ce35eaa24813df011 Mon Sep 17 00:00:00 2001 From: "Alex.F" Date: Tue, 17 Aug 2021 15:24:13 +0800 Subject: [PATCH 4/4] inline await statement --- editors/code/src/toolchain.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/editors/code/src/toolchain.ts b/editors/code/src/toolchain.ts index 30e79767dc..52ad3e5d21 100644 --- a/editors/code/src/toolchain.ts +++ b/editors/code/src/toolchain.ts @@ -160,8 +160,7 @@ export const getPathForExecutable = memoizeAsync( // it is not mentioned in docs and cannot be infered by the type signature... const standardPath = vscode.Uri.joinPath(vscode.Uri.file(os.homedir()), ".cargo", "bin", executableName); - const exist = await isFileAtUri(standardPath); - if (exist) return standardPath.fsPath; + if (await isFileAtUri(standardPath)) return standardPath.fsPath; } catch (err) { log.error("Failed to read the fs info", err); }