From 2dd1393340410530d1b4b7fd61e540ffcf1dffe4 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 9 Jan 2025 08:41:22 -0800 Subject: [PATCH] Use terminal shell env when resolving commands in path Fixes #237587 --- extensions/terminal-suggest/package.json | 3 +- .../src/terminalSuggestMain.ts | 31 ++++++++++++++----- extensions/terminal-suggest/tsconfig.json | 3 +- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/extensions/terminal-suggest/package.json b/extensions/terminal-suggest/package.json index 611ef00ed4ceb..981112636bcbe 100644 --- a/extensions/terminal-suggest/package.json +++ b/extensions/terminal-suggest/package.json @@ -14,7 +14,8 @@ "Other" ], "enabledApiProposals": [ - "terminalCompletionProvider" + "terminalCompletionProvider", + "terminalShellEnv" ], "scripts": { "compile": "npx gulp compile-extension:terminal-suggest", diff --git a/extensions/terminal-suggest/src/terminalSuggestMain.ts b/extensions/terminal-suggest/src/terminalSuggestMain.ts index 13ff032037ac7..6ca011720f397 100644 --- a/extensions/terminal-suggest/src/terminalSuggestMain.ts +++ b/extensions/terminal-suggest/src/terminalSuggestMain.ts @@ -11,6 +11,7 @@ import codeInsidersCompletionSpec from './completions/code-insiders'; import codeCompletionSpec from './completions/code'; import cdSpec from './completions/cd'; +let cachedAvailableCommandsPath: string | undefined; let cachedAvailableCommands: Set | undefined; const cachedBuiltinCommands: Map = new Map(); @@ -80,7 +81,7 @@ export async function activate(context: vscode.ExtensionContext) { return; } - const commandsInPath = await getCommandsInPath(); + const commandsInPath = await getCommandsInPath(terminal.shellIntegration?.env); const builtinCommands = getBuiltinCommands(shellPath); if (!commandsInPath || !builtinCommands) { return; @@ -129,6 +130,7 @@ export async function resolveCwdFromPrefix(prefix: string, currentCwd?: vscode.U // Resolve the absolute path of the prefix const resolvedPath = path.resolve(currentCwd?.fsPath, relativeFolder); + const stat = await fs.stat(resolvedPath); // Check if the resolved path exists and is a directory @@ -187,15 +189,30 @@ async function isExecutable(filePath: string): Promise { } } -async function getCommandsInPath(): Promise | undefined> { - if (cachedAvailableCommands) { - return cachedAvailableCommands; +async function getCommandsInPath(env: { [key: string]: string | undefined } = process.env): Promise | undefined> { + // Get PATH value + let pathValue: string | undefined; + if (osIsWindows()) { + const caseSensitivePathKey = Object.keys(env).find(key => key.toLowerCase() === 'path'); + if (caseSensitivePathKey) { + pathValue = env[caseSensitivePathKey]; + } + } else { + pathValue = env.PATH; } - const paths = osIsWindows() ? process.env.PATH?.split(';') : process.env.PATH?.split(':'); - if (!paths) { + if (pathValue === undefined) { return; } - const pathSeparator = osIsWindows() ? '\\' : '/'; + + // Check cache + if (cachedAvailableCommands && cachedAvailableCommandsPath === pathValue) { + return cachedAvailableCommands; + } + + // Extract executables from PATH + const isWindows = osIsWindows(); + const paths = pathValue.split(isWindows ? ';' : ':'); + const pathSeparator = isWindows ? '\\' : '/'; const executables = new Set(); for (const path of paths) { try { diff --git a/extensions/terminal-suggest/tsconfig.json b/extensions/terminal-suggest/tsconfig.json index 151a29616bb23..df4e9764caf13 100644 --- a/extensions/terminal-suggest/tsconfig.json +++ b/extensions/terminal-suggest/tsconfig.json @@ -16,6 +16,7 @@ "src/**/*", "src/completions/index.d.ts", "../../src/vscode-dts/vscode.d.ts", - "../../src/vscode-dts/vscode.proposed.terminalCompletionProvider.d.ts" + "../../src/vscode-dts/vscode.proposed.terminalCompletionProvider.d.ts", + "../../src/vscode-dts/vscode.proposed.terminalShellEnv.d.ts" ] }