fix(windows): use cross-spawn for shim-backed commands (#18010)
This commit is contained in:
@@ -5,6 +5,7 @@ import { pathToFileURL, fileURLToPath } from "url"
|
||||
import { createMessageConnection, StreamMessageReader, StreamMessageWriter } from "vscode-jsonrpc/node"
|
||||
import type { Diagnostic as VSCodeDiagnostic } from "vscode-languageserver-types"
|
||||
import { Log } from "../util/log"
|
||||
import { Process } from "../util/process"
|
||||
import { LANGUAGE_EXTENSIONS } from "./language"
|
||||
import z from "zod"
|
||||
import type { LSPServer } from "./server"
|
||||
@@ -239,7 +240,7 @@ export namespace LSPClient {
|
||||
l.info("shutting down")
|
||||
connection.end()
|
||||
connection.dispose()
|
||||
input.server.process.kill()
|
||||
await Process.stop(input.server.process)
|
||||
l.info("shutdown")
|
||||
},
|
||||
}
|
||||
|
||||
@@ -7,9 +7,10 @@ import { pathToFileURL, fileURLToPath } from "url"
|
||||
import { LSPServer } from "./server"
|
||||
import z from "zod"
|
||||
import { Config } from "../config/config"
|
||||
import { spawn } from "child_process"
|
||||
import { Instance } from "../project/instance"
|
||||
import { Flag } from "@/flag/flag"
|
||||
import { Process } from "../util/process"
|
||||
import { spawn as lspspawn } from "./launch"
|
||||
|
||||
export namespace LSP {
|
||||
const log = Log.create({ service: "lsp" })
|
||||
@@ -112,9 +113,8 @@ export namespace LSP {
|
||||
extensions: item.extensions ?? existing?.extensions ?? [],
|
||||
spawn: async (root) => {
|
||||
return {
|
||||
process: spawn(item.command[0], item.command.slice(1), {
|
||||
process: lspspawn(item.command[0], item.command.slice(1), {
|
||||
cwd: root,
|
||||
windowsHide: true,
|
||||
env: {
|
||||
...process.env,
|
||||
...item.env,
|
||||
@@ -200,21 +200,20 @@ export namespace LSP {
|
||||
serverID: server.id,
|
||||
server: handle,
|
||||
root,
|
||||
}).catch((err) => {
|
||||
}).catch(async (err) => {
|
||||
s.broken.add(key)
|
||||
handle.process.kill()
|
||||
await Process.stop(handle.process)
|
||||
log.error(`Failed to initialize LSP client ${server.id}`, { error: err })
|
||||
return undefined
|
||||
})
|
||||
|
||||
if (!client) {
|
||||
handle.process.kill()
|
||||
return undefined
|
||||
}
|
||||
|
||||
const existing = s.clients.find((x) => x.root === root && x.serverID === server.id)
|
||||
if (existing) {
|
||||
handle.process.kill()
|
||||
await Process.stop(handle.process)
|
||||
return existing
|
||||
}
|
||||
|
||||
|
||||
21
packages/opencode/src/lsp/launch.ts
Normal file
21
packages/opencode/src/lsp/launch.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import type { ChildProcessWithoutNullStreams } from "child_process"
|
||||
import { Process } from "../util/process"
|
||||
|
||||
type Child = Process.Child & ChildProcessWithoutNullStreams
|
||||
|
||||
export function spawn(cmd: string, args: string[], opts?: Process.Options): Child
|
||||
export function spawn(cmd: string, opts?: Process.Options): Child
|
||||
export function spawn(cmd: string, argsOrOpts?: string[] | Process.Options, opts?: Process.Options) {
|
||||
const args = Array.isArray(argsOrOpts) ? [...argsOrOpts] : []
|
||||
const cfg = Array.isArray(argsOrOpts) ? opts : argsOrOpts
|
||||
const proc = Process.spawn([cmd, ...args], {
|
||||
...(cfg ?? {}),
|
||||
stdin: "pipe",
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
}) as Child
|
||||
|
||||
if (!proc.stdin || !proc.stdout || !proc.stderr) throw new Error("Process output not available")
|
||||
|
||||
return proc
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn as launch, type ChildProcessWithoutNullStreams } from "child_process"
|
||||
import type { ChildProcessWithoutNullStreams } from "child_process"
|
||||
import path from "path"
|
||||
import os from "os"
|
||||
import { Global } from "../global"
|
||||
@@ -13,11 +13,7 @@ import { Archive } from "../util/archive"
|
||||
import { Process } from "../util/process"
|
||||
import { which } from "../util/which"
|
||||
import { Module } from "@opencode-ai/util/module"
|
||||
|
||||
const spawn = ((cmd, args, opts) => {
|
||||
if (Array.isArray(args)) return launch(cmd, [...args], { ...(opts ?? {}), windowsHide: true })
|
||||
return launch(cmd, { ...(args ?? {}), windowsHide: true })
|
||||
}) as typeof launch
|
||||
import { spawn } from "./launch"
|
||||
|
||||
export namespace LSPServer {
|
||||
const log = Log.create({ service: "lsp.server" })
|
||||
@@ -273,7 +269,7 @@ export namespace LSPServer {
|
||||
}
|
||||
|
||||
if (lintBin) {
|
||||
const proc = Process.spawn([lintBin, "--help"], { stdout: "pipe" })
|
||||
const proc = spawn(lintBin, ["--help"])
|
||||
await proc.exited
|
||||
if (proc.stdout) {
|
||||
const help = await text(proc.stdout)
|
||||
|
||||
Reference in New Issue
Block a user