From f0a344a76e237f185a3e94e9f1bb015ce1fa7a3c Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 13 Apr 2021 19:34:43 +0200 Subject: [PATCH] npm: use which (#121209) --- .../npm/extension-browser.webpack.config.js | 3 ++- extensions/npm/package.json | 4 +++- .../npm/src/features/jsonContributions.ts | 4 ++-- .../npm/src/features/packageJSONContribution.ts | 12 ++++++------ extensions/npm/src/npmBrowserMain.ts | 2 +- extensions/npm/src/npmMain.ts | 16 ++++++++++++++-- extensions/npm/yarn.lock | 17 +++++++++++++++++ 7 files changed, 45 insertions(+), 13 deletions(-) diff --git a/extensions/npm/extension-browser.webpack.config.js b/extensions/npm/extension-browser.webpack.config.js index b0c70c96d48..b9f00ed50bd 100644 --- a/extensions/npm/extension-browser.webpack.config.js +++ b/extensions/npm/extension-browser.webpack.config.js @@ -18,6 +18,7 @@ module.exports = withBrowserDefaults({ filename: 'npmBrowserMain.js' }, node: { - 'child_process': 'empty' + 'child_process': 'empty', + 'which': 'empty' } }); diff --git a/extensions/npm/package.json b/extensions/npm/package.json index d93d80ad30f..3a8a73eddfa 100644 --- a/extensions/npm/package.json +++ b/extensions/npm/package.json @@ -24,11 +24,13 @@ "minimatch": "^3.0.4", "request-light": "^0.4.0", "vscode-nls": "^4.1.1", + "which": "^2.0.2", "which-pm": "^2.0.0" }, "devDependencies": { "@types/minimatch": "^3.0.3", - "@types/node": "^12.19.9" + "@types/node": "^12.19.9", + "@types/which": "^2.0.0" }, "resolutions": { "which-pm/load-yaml-file/**/argparse": "1.0.9" diff --git a/extensions/npm/src/features/jsonContributions.ts b/extensions/npm/src/features/jsonContributions.ts index d542c4e0db8..bae32a5c6a9 100644 --- a/extensions/npm/src/features/jsonContributions.ts +++ b/extensions/npm/src/features/jsonContributions.ts @@ -29,8 +29,8 @@ export interface IJSONContribution { resolveSuggestion?(resourceUri: Uri | undefined, item: CompletionItem): Thenable | null; } -export function addJSONProviders(xhr: XHRRequest, canRunNPM: boolean): Disposable { - const contributions = [new PackageJSONContribution(xhr, canRunNPM), new BowerJSONContribution(xhr)]; +export function addJSONProviders(xhr: XHRRequest, npmCommandPath: string | undefined): Disposable { + const contributions = [new PackageJSONContribution(xhr, npmCommandPath), new BowerJSONContribution(xhr)]; const subscriptions: Disposable[] = []; contributions.forEach(contribution => { const selector = contribution.getDocumentSelector(); diff --git a/extensions/npm/src/features/packageJSONContribution.ts b/extensions/npm/src/features/packageJSONContribution.ts index 10cbac8558b..3afbf98259b 100644 --- a/extensions/npm/src/features/packageJSONContribution.ts +++ b/extensions/npm/src/features/packageJSONContribution.ts @@ -32,7 +32,7 @@ export class PackageJSONContribution implements IJSONContribution { return [{ language: 'json', scheme: '*', pattern: '**/package.json' }]; } - public constructor(private xhr: XHRRequest, private canRunNPM: boolean) { + public constructor(private xhr: XHRRequest, private npmCommandPath: string | undefined) { } public collectDefaultSuggestions(_resource: Uri, result: ISuggestionsCollector): Thenable { @@ -52,7 +52,7 @@ export class PackageJSONContribution implements IJSONContribution { } private isEnabled() { - return this.canRunNPM || this.onlineEnabled(); + return this.npmCommandPath || this.onlineEnabled(); } private onlineEnabled() { @@ -268,8 +268,8 @@ export class PackageJSONContribution implements IJSONContribution { return undefined; // avoid unnecessary lookups } let info: ViewPackageInfo | undefined; - if (this.canRunNPM) { - info = await this.npmView(pack, resource); + if (this.npmCommandPath) { + info = await this.npmView(this.npmCommandPath, pack, resource); } if (!info && this.onlineEnabled()) { info = await this.npmjsView(pack); @@ -277,11 +277,11 @@ export class PackageJSONContribution implements IJSONContribution { return info; } - private npmView(pack: string, resource: Uri | undefined): Promise { + private npmView(npmCommandPath: string, pack: string, resource: Uri | undefined): Promise { return new Promise((resolve, _reject) => { const args = ['view', '--json', pack, 'description', 'dist-tags.latest', 'homepage', 'version']; let cwd = resource && resource.scheme === 'file' ? dirname(resource.fsPath) : undefined; - cp.execFile(process.platform === 'win32' ? 'npm.cmd' : 'npm', args, { cwd }, (error, stdout) => { + cp.execFile(npmCommandPath, args, { cwd }, (error, stdout) => { if (!error) { try { const content = JSON.parse(stdout); diff --git a/extensions/npm/src/npmBrowserMain.ts b/extensions/npm/src/npmBrowserMain.ts index 96cfe579505..c562b5a4a32 100644 --- a/extensions/npm/src/npmBrowserMain.ts +++ b/extensions/npm/src/npmBrowserMain.ts @@ -8,7 +8,7 @@ import * as vscode from 'vscode'; import { addJSONProviders } from './features/jsonContributions'; export async function activate(context: vscode.ExtensionContext): Promise { - context.subscriptions.push(addJSONProviders(httpRequest.xhr, false)); + context.subscriptions.push(addJSONProviders(httpRequest.xhr, undefined)); } export function deactivate(): void { diff --git a/extensions/npm/src/npmMain.ts b/extensions/npm/src/npmMain.ts index c5d442a4ddb..6969b7d63a6 100644 --- a/extensions/npm/src/npmMain.ts +++ b/extensions/npm/src/npmMain.ts @@ -11,6 +11,7 @@ import { NpmScriptsTreeDataProvider } from './npmView'; import { getPackageManager, invalidateTasksCache, NpmTaskProvider, hasPackageJson } from './tasks'; import { invalidateHoverScriptsCache, NpmScriptHoverProvider } from './scriptHover'; import { NpmScriptLensProvider } from './npmScriptLens'; +import * as which from 'which'; let treeDataProvider: NpmScriptsTreeDataProvider | undefined; @@ -30,8 +31,8 @@ export async function activate(context: vscode.ExtensionContext): Promise } })); - const canRunNPM = canRunNpmInCurrentWorkspace(); - context.subscriptions.push(addJSONProviders(httpRequest.xhr, canRunNPM)); + const npmCommandPath = await getNPMCommandPath(); + context.subscriptions.push(addJSONProviders(httpRequest.xhr, npmCommandPath)); registerTaskProvider(context); treeDataProvider = registerExplorer(context); @@ -71,6 +72,17 @@ export async function activate(context: vscode.ExtensionContext): Promise context.subscriptions.push(new NpmScriptLensProvider()); } +async function getNPMCommandPath(): Promise { + if (canRunNpmInCurrentWorkspace()) { + try { + return await which(process.platform === 'win32' ? 'npm.cmd' : 'npm'); + } catch (e) { + return undefined; + } + } + return undefined; +} + function canRunNpmInCurrentWorkspace() { if (vscode.workspace.workspaceFolders) { return vscode.workspace.workspaceFolders.some(f => f.uri.scheme === 'file'); diff --git a/extensions/npm/yarn.lock b/extensions/npm/yarn.lock index c8ca31e3343..6b653dec9d9 100644 --- a/extensions/npm/yarn.lock +++ b/extensions/npm/yarn.lock @@ -12,6 +12,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/which@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/which/-/which-2.0.0.tgz#446d35586611dee657120de8e0457382a658fc25" + integrity sha512-JHTNOEpZnACQdsTojWggn+SQ8IucfqEhtz7g8Z0G67WdSj4x3F0X5I2c/CVcl8z/QukGrIHeQ/N49v1au74XFQ== + agent-base@4: version "4.2.0" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce" @@ -130,6 +135,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + js-yaml@^3.13.0: version "3.14.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" @@ -257,3 +267,10 @@ which-pm@^2.0.0: dependencies: load-yaml-file "^0.2.0" path-exists "^4.0.0" + +which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0"