Skip to content

Commit

Permalink
fix: more binary detection for windows
Browse files Browse the repository at this point in the history
related to #235
  • Loading branch information
HerringtonDarkholme committed Mar 18, 2024
1 parent 58b4eeb commit 69876ed
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 25 deletions.
44 changes: 43 additions & 1 deletion src/extension/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>(
Expand Down
4 changes: 3 additions & 1 deletion src/extension/index.ts
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
29 changes: 7 additions & 22 deletions src/extension/lsp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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<boolean> {
const workspaceFolders = workspace.workspaceFolders
if (!workspaceFolders) {
Expand Down Expand Up @@ -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.',
Expand Down Expand Up @@ -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()
}
Expand Down
2 changes: 1 addition & 1 deletion src/extension/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
})
}

Expand Down

0 comments on commit 69876ed

Please sign in to comment.