mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-18 10:07:58 +00:00
fix(lsp): preserve instance ref for update events (#28016)
This commit is contained in:
@@ -13,8 +13,11 @@ import { InstanceState } from "@/effect/instance-state"
|
||||
import { containsPath } from "@/project/instance-context"
|
||||
import { NonNegativeInt } from "@opencode-ai/core/schema"
|
||||
import { RuntimeFlags } from "@/effect/runtime-flags"
|
||||
import { InstanceRef } from "@/effect/instance-ref"
|
||||
import { makeRuntime } from "@/effect/run-service"
|
||||
|
||||
const log = Log.create({ service: "lsp" })
|
||||
const busRuntime = makeRuntime(Bus.Service, Bus.layer)
|
||||
|
||||
export const Event = {
|
||||
Updated: BusEvent.define("lsp.updated", Schema.Struct({})),
|
||||
@@ -291,7 +294,9 @@ export const layer = Layer.effect(
|
||||
if (!client) continue
|
||||
|
||||
result.push(client)
|
||||
Bus.publish(Event.Updated, {})
|
||||
void busRuntime.runPromise((bus) =>
|
||||
bus.publish(Event.Updated, {}).pipe(Effect.provideService(InstanceRef, ctx)),
|
||||
)
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { describe, expect, spyOn } from "bun:test"
|
||||
import path from "path"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { Deferred, Effect, Layer } from "effect"
|
||||
import { Bus } from "@/bus"
|
||||
import { Config } from "@/config/config"
|
||||
import { RuntimeFlags } from "@/effect/runtime-flags"
|
||||
import { LSP } from "@/lsp/lsp"
|
||||
import * as LSPServer from "@/lsp/server"
|
||||
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
||||
import { provideTmpdirInstance } from "../fixture/fixture"
|
||||
import { testEffect } from "../lib/effect"
|
||||
import { awaitWithTimeout, testEffect } from "../lib/effect"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(LSP.defaultLayer, CrossSpawnSpawner.defaultLayer))
|
||||
const experimentalTyIt = testEffect(
|
||||
@@ -16,6 +17,7 @@ const experimentalTyIt = testEffect(
|
||||
CrossSpawnSpawner.defaultLayer,
|
||||
),
|
||||
)
|
||||
const fakeServerPath = path.join(__dirname, "../fixture/lsp/fake-lsp-server.js")
|
||||
const disabledDownloadIt = testEffect(
|
||||
Layer.mergeAll(
|
||||
LSP.layer.pipe(Layer.provide(Config.defaultLayer), Layer.provide(RuntimeFlags.layer({ disableLspDownload: true }))),
|
||||
@@ -92,6 +94,35 @@ describe("lsp.spawn", () => {
|
||||
),
|
||||
)
|
||||
|
||||
it.live("publishes lsp.updated after custom LSP initialization", () =>
|
||||
provideTmpdirInstance(
|
||||
(dir) =>
|
||||
Effect.gen(function* () {
|
||||
const lsp = yield* LSP.Service
|
||||
const updated = yield* Deferred.make<void>()
|
||||
const unsubscribe = Bus.subscribe(LSP.Event.Updated, () =>
|
||||
Effect.runSync(Deferred.succeed(updated, undefined)),
|
||||
)
|
||||
yield* Effect.addFinalizer(() => Effect.sync(unsubscribe))
|
||||
|
||||
const file = path.join(dir, "sample.repro")
|
||||
yield* Effect.promise(() => Bun.write(file, "sample\n"))
|
||||
yield* lsp.touchFile(file)
|
||||
yield* awaitWithTimeout(Deferred.await(updated), "lsp.updated event was not published")
|
||||
}),
|
||||
{
|
||||
config: {
|
||||
lsp: {
|
||||
fake: {
|
||||
command: [process.execPath, fakeServerPath],
|
||||
extensions: [".repro"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
it.live("would spawn builtin LSP for files inside instance when config object is provided", () =>
|
||||
provideTmpdirInstance(
|
||||
(dir) =>
|
||||
|
||||
Reference in New Issue
Block a user