fix: unify LSP server PATH resolution between detection and spawn (#2431)

This commit is contained in:
YeonGyu-Kim
2026-03-12 01:44:06 +09:00
parent 1c09b9869c
commit 9d0b56d375
3 changed files with 35 additions and 19 deletions

View File

@@ -1,4 +1,5 @@
import { Readable, Writable } from "node:stream"
import { delimiter } from "path"
import {
createMessageConnection,
StreamMessageReader,
@@ -7,6 +8,7 @@ import {
} from "vscode-jsonrpc/node"
import type { Diagnostic, ResolvedServer } from "./types"
import { spawnProcess, type UnifiedProcess } from "./lsp-process"
import { getLspServerAdditionalPathBases } from "./server-path-bases"
import { log } from "../../shared/logger"
export class LSPClientTransport {
protected proc: UnifiedProcess | null = null
@@ -18,12 +20,22 @@ export class LSPClientTransport {
constructor(protected root: string, protected server: ResolvedServer) {}
async start(): Promise<void> {
const env = {
...process.env,
...this.server.env,
}
const pathValue = process.platform === "win32" ? env.PATH ?? env.Path ?? "" : env.PATH ?? ""
const spawnPath = [pathValue, ...getLspServerAdditionalPathBases(this.root)]
.filter(Boolean)
.join(delimiter)
if (process.platform === "win32" && env.Path !== undefined) {
env.Path = spawnPath
}
env.PATH = spawnPath
this.proc = spawnProcess(this.server.command, {
cwd: this.root,
env: {
...process.env,
...this.server.env,
},
env,
})
if (!this.proc) {
throw new Error(`Failed to spawn LSP server: ${this.server.command.join(" ")}`)

View File

@@ -1,7 +1,7 @@
import { existsSync } from "fs"
import { join } from "path"
import { delimiter, join } from "path"
import { getOpenCodeConfigDir, getDataDir } from "../../shared"
import { getLspServerAdditionalPathBases } from "./server-path-bases"
export function isServerInstalled(command: string[]): boolean {
if (command.length === 0) return false
@@ -31,8 +31,7 @@ export function isServerInstalled(command: string[]): boolean {
pathEnv = process.env.Path || ""
}
const pathSeparator = isWindows ? ";" : ":"
const paths = pathEnv.split(pathSeparator)
const paths = pathEnv.split(delimiter)
for (const p of paths) {
for (const suffix of exts) {
@@ -42,17 +41,7 @@ export function isServerInstalled(command: string[]): boolean {
}
}
const cwd = process.cwd()
const configDir = getOpenCodeConfigDir({ binary: "opencode" })
const dataDir = join(getDataDir(), "opencode")
const additionalBases = [
join(cwd, "node_modules", ".bin"),
join(configDir, "bin"),
join(configDir, "node_modules", ".bin"),
join(dataDir, "bin"),
]
for (const base of additionalBases) {
for (const base of getLspServerAdditionalPathBases(process.cwd())) {
for (const suffix of exts) {
if (existsSync(join(base, cmd + suffix))) {
return true

View File

@@ -0,0 +1,15 @@
import { join } from "path"
import { getDataDir, getOpenCodeConfigDir } from "../../shared"
export function getLspServerAdditionalPathBases(workingDirectory: string): string[] {
const configDir = getOpenCodeConfigDir({ binary: "opencode" })
const dataDir = join(getDataDir(), "opencode")
return [
join(workingDirectory, "node_modules", ".bin"),
join(configDir, "bin"),
join(configDir, "node_modules", ".bin"),
join(dataDir, "bin"),
]
}