From 69876edaf7f428c12034df66660601d40c79aedb Mon Sep 17 00:00:00 2001 From: HerringtonDarkholme <2883231+HerringtonDarkholme@users.noreply.github.com> Date: Sun, 17 Mar 2024 18:05:02 -0700 Subject: [PATCH] fix: more binary detection for windows related to #235 --- src/extension/common.ts | 44 ++++++++++++++++++++++++++++++++++++++++- src/extension/index.ts | 4 +++- src/extension/lsp.ts | 29 +++++++-------------------- src/extension/search.ts | 2 +- 4 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/extension/common.ts b/src/extension/common.ts index 9e5d53d1..4a17ad0f 100644 --- a/src/extension/common.ts +++ b/src/extension/common.ts @@ -2,13 +2,55 @@ import type { ParentPort } from '../types' import { Unport } from 'unport' import { workspace } from 'vscode' import type { ChildProcessWithoutNullStreams } from 'node:child_process' +import { execFile } from 'node:child_process' -const defaultBinary = process.platform === 'win32' ? 'ast-grep.exe' : 'ast-grep' +let defaultBinary: string + +export async function detectDefaultBinaryAtStart() { + if (defaultBinary) { + return + } + if (process.platform !== 'win32') { + defaultBinary = 'ast-grep' + return + } + // on windows, binary command is confusing like sh*t + // different installation method and different shell will + // resolve totally different binary + // See: + // https://zenn.dev/hd_nvim/articles/e49ef2c812ae8d#comment-0b861171ac40cb + // https://github.com/ast-grep/ast-grep-vscode/issues/235 + // https://github.com/nodejs/node/issues/29532#issue-492569087 + for (const cmd of ['ast-grep', 'ast-grep.exe', 'ast-grep.cmd']) { + if (await testBinaryExist(cmd)) { + defaultBinary = cmd + return + } + } + // every possible command tried, fallback to ast-grep + defaultBinary = 'ast-grep' +} export function resolveBinary() { return workspace.getConfiguration('astGrep').get('serverPath', defaultBinary) } +export async function testBinaryExist(command: string) { + return new Promise(r => { + execFile( + command, + ['-h'], + { + // for windows + shell: process.platform === 'win32', + }, + err => { + r(!err) + }, + ) + }) +} + export const parentPort: ParentPort = new Unport() export function streamedPromise( diff --git a/src/extension/index.ts b/src/extension/index.ts index c5641741..cf73a1d5 100644 --- a/src/extension/index.ts +++ b/src/extension/index.ts @@ -1,10 +1,12 @@ import type { ExtensionContext } from 'vscode' +import { detectDefaultBinaryAtStart } from './common' import { activatePreview } from './preview' import { activateWebview } from './webview' import { activateLsp } from './lsp' import { activateSearch } from './search' -export function activate(context: ExtensionContext) { +export async function activate(context: ExtensionContext) { + await detectDefaultBinaryAtStart() activateLsp(context) activateWebview(context) activateSearch(context) diff --git a/src/extension/lsp.ts b/src/extension/lsp.ts index 7f690fe4..1c7006ee 100644 --- a/src/extension/lsp.ts +++ b/src/extension/lsp.ts @@ -5,8 +5,7 @@ import { type ServerOptions, type Executable, } from 'vscode-languageclient/node' -import { resolveBinary } from './common' -import { execFile } from 'node:child_process' +import { resolveBinary, testBinaryExist } from './common' let client: LanguageClient const diagnosticCollectionName = 'ast-grep-diagnostics' @@ -25,28 +24,11 @@ function getExecutable(isDebug: boolean): Executable { ...(isDebug ? { RUST_LOG: 'debug' } : {}), }, // shell is required for Windows cmd to pick up global npm binary - shell: true, + shell: process.platform === 'win32', }, } } -async function testBinaryExist() { - const command = resolveBinary() - return new Promise(r => { - execFile( - command, - ['-h'], - { - // for windows - shell: true, - }, - err => { - r(!err) - }, - ) - }) -} - async function fileExists(pathFromRoot: string): Promise { const workspaceFolders = workspace.workspaceFolders if (!workspaceFolders) { @@ -82,7 +64,7 @@ export async function activateLsp(context: ExtensionContext) { }), ) - if (!(await testBinaryExist())) { + if (!(await testBinaryExist(resolveBinary()))) { window .showErrorMessage( 'ast-grep cannot be started. Make sure it is installed.', @@ -124,7 +106,10 @@ export async function activateLsp(context: ExtensionContext) { ) // Automatically start the client only if we can find a config file - if (await fileExists('sgconfig.yml')) { + if ( + (await fileExists('sgconfig.yml')) || + (await fileExists('sgconfig.yaml')) + ) { // Start the client. This will also launch the server client.start() } diff --git a/src/extension/search.ts b/src/extension/search.ts index c9f2ef98..dcf2dcf1 100644 --- a/src/extension/search.ts +++ b/src/extension/search.ts @@ -128,7 +128,7 @@ export function buildCommand(query: CommandArgs) { // TODO: multi-workspaces support return spawn(command, args, { cwd: uris[0], - // shell: true, // it is safe because it is end user input + shell: process.platform === 'win32', // it is safe because it is end user input }) }