fix: unify LSP server PATH resolution between detection and spawn (#2431)
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { Readable, Writable } from "node:stream"
|
import { Readable, Writable } from "node:stream"
|
||||||
|
import { delimiter } from "path"
|
||||||
import {
|
import {
|
||||||
createMessageConnection,
|
createMessageConnection,
|
||||||
StreamMessageReader,
|
StreamMessageReader,
|
||||||
@@ -7,6 +8,7 @@ import {
|
|||||||
} from "vscode-jsonrpc/node"
|
} from "vscode-jsonrpc/node"
|
||||||
import type { Diagnostic, ResolvedServer } from "./types"
|
import type { Diagnostic, ResolvedServer } from "./types"
|
||||||
import { spawnProcess, type UnifiedProcess } from "./lsp-process"
|
import { spawnProcess, type UnifiedProcess } from "./lsp-process"
|
||||||
|
import { getLspServerAdditionalPathBases } from "./server-path-bases"
|
||||||
import { log } from "../../shared/logger"
|
import { log } from "../../shared/logger"
|
||||||
export class LSPClientTransport {
|
export class LSPClientTransport {
|
||||||
protected proc: UnifiedProcess | null = null
|
protected proc: UnifiedProcess | null = null
|
||||||
@@ -18,12 +20,22 @@ export class LSPClientTransport {
|
|||||||
|
|
||||||
constructor(protected root: string, protected server: ResolvedServer) {}
|
constructor(protected root: string, protected server: ResolvedServer) {}
|
||||||
async start(): Promise<void> {
|
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, {
|
this.proc = spawnProcess(this.server.command, {
|
||||||
cwd: this.root,
|
cwd: this.root,
|
||||||
env: {
|
env,
|
||||||
...process.env,
|
|
||||||
...this.server.env,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
if (!this.proc) {
|
if (!this.proc) {
|
||||||
throw new Error(`Failed to spawn LSP server: ${this.server.command.join(" ")}`)
|
throw new Error(`Failed to spawn LSP server: ${this.server.command.join(" ")}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { existsSync } from "fs"
|
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 {
|
export function isServerInstalled(command: string[]): boolean {
|
||||||
if (command.length === 0) return false
|
if (command.length === 0) return false
|
||||||
@@ -31,8 +31,7 @@ export function isServerInstalled(command: string[]): boolean {
|
|||||||
pathEnv = process.env.Path || ""
|
pathEnv = process.env.Path || ""
|
||||||
}
|
}
|
||||||
|
|
||||||
const pathSeparator = isWindows ? ";" : ":"
|
const paths = pathEnv.split(delimiter)
|
||||||
const paths = pathEnv.split(pathSeparator)
|
|
||||||
|
|
||||||
for (const p of paths) {
|
for (const p of paths) {
|
||||||
for (const suffix of exts) {
|
for (const suffix of exts) {
|
||||||
@@ -42,17 +41,7 @@ export function isServerInstalled(command: string[]): boolean {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const cwd = process.cwd()
|
for (const base of getLspServerAdditionalPathBases(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 suffix of exts) {
|
for (const suffix of exts) {
|
||||||
if (existsSync(join(base, cmd + suffix))) {
|
if (existsSync(join(base, cmd + suffix))) {
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -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"),
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user