summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-06-30 16:45:13 -0400
committerDax Raad <[email protected]>2025-06-30 16:45:26 -0400
commit9ad1687f04a50ac3f38459a4be412343d7fbce90 (patch)
tree864cafb193b1a67f5c2ef4e3b026bf4e90a83bcc /packages
parentc573270e66843c7b34d1f3a4f446d5c4438e3b27 (diff)
downloadopencode-9ad1687f04a50ac3f38459a4be412343d7fbce90.tar.gz
opencode-9ad1687f04a50ac3f38459a4be412343d7fbce90.zip
optimistically boot lsp servers
Diffstat (limited to 'packages')
-rw-r--r--packages/opencode/src/cli/bootstrap.ts2
-rw-r--r--packages/opencode/src/cli/cmd/debug.ts56
-rw-r--r--packages/opencode/src/lsp/client.ts2
-rw-r--r--packages/opencode/src/lsp/index.ts34
4 files changed, 85 insertions, 9 deletions
diff --git a/packages/opencode/src/cli/bootstrap.ts b/packages/opencode/src/cli/bootstrap.ts
index 66c8a7570..e2b96f23d 100644
--- a/packages/opencode/src/cli/bootstrap.ts
+++ b/packages/opencode/src/cli/bootstrap.ts
@@ -1,6 +1,7 @@
import { App } from "../app/app"
import { ConfigHooks } from "../config/hooks"
import { Format } from "../format"
+import { LSP } from "../lsp"
import { Share } from "../share/share"
export async function bootstrap<T>(
@@ -11,6 +12,7 @@ export async function bootstrap<T>(
Share.init()
Format.init()
ConfigHooks.init()
+ LSP.init()
return cb(app)
})
diff --git a/packages/opencode/src/cli/cmd/debug.ts b/packages/opencode/src/cli/cmd/debug.ts
index ed81c1186..0924467e4 100644
--- a/packages/opencode/src/cli/cmd/debug.ts
+++ b/packages/opencode/src/cli/cmd/debug.ts
@@ -1,12 +1,18 @@
import { App } from "../../app/app"
import { Ripgrep } from "../../file/ripgrep"
import { LSP } from "../../lsp"
+import { bootstrap } from "../bootstrap"
import { cmd } from "./cmd"
export const DebugCommand = cmd({
command: "debug",
builder: (yargs) =>
- yargs.command(DiagnosticsCommand).command(TreeCommand).demandCommand(),
+ yargs
+ .command(DiagnosticsCommand)
+ .command(TreeCommand)
+ .command(SymbolsCommand)
+ .command(FilesCommand)
+ .demandCommand(),
async handler() {},
})
@@ -15,7 +21,7 @@ const DiagnosticsCommand = cmd({
builder: (yargs) =>
yargs.positional("file", { type: "string", demandOption: true }),
async handler(args) {
- await App.provide({ cwd: process.cwd() }, async () => {
+ await bootstrap({ cwd: process.cwd() }, async () => {
await LSP.touchFile(args.file, true)
console.log(await LSP.diagnostics())
})
@@ -29,9 +35,53 @@ const TreeCommand = cmd({
type: "number",
}),
async handler(args) {
- await App.provide({ cwd: process.cwd() }, async () => {
+ await bootstrap({ cwd: process.cwd() }, async () => {
const app = App.info()
console.log(await Ripgrep.tree({ cwd: app.path.cwd, limit: args.limit }))
})
},
})
+
+const SymbolsCommand = cmd({
+ command: "symbols <query>",
+ builder: (yargs) =>
+ yargs.positional("query", { type: "string", demandOption: true }),
+ async handler(args) {
+ await bootstrap({ cwd: process.cwd() }, async () => {
+ await LSP.touchFile("./src/index.ts", true)
+ await new Promise((resolve) => setTimeout(resolve, 3000))
+ const results = await LSP.workspaceSymbol(args.query)
+ console.log(JSON.stringify(results, null, 2))
+ })
+ },
+})
+
+const FilesCommand = cmd({
+ command: "files",
+ builder: (yargs) =>
+ yargs
+ .option("query", {
+ type: "string",
+ description: "Filter files by query",
+ })
+ .option("glob", {
+ type: "string",
+ description: "Glob pattern to match files",
+ })
+ .option("limit", {
+ type: "number",
+ description: "Limit number of results",
+ }),
+ async handler(args) {
+ await bootstrap({ cwd: process.cwd() }, async () => {
+ const app = App.info()
+ const files = await Ripgrep.files({
+ cwd: app.path.cwd,
+ query: args.query,
+ glob: args.glob,
+ limit: args.limit,
+ })
+ console.log(files.join("\n"))
+ })
+ },
+})
diff --git a/packages/opencode/src/lsp/client.ts b/packages/opencode/src/lsp/client.ts
index 628ccd5af..38d8b3505 100644
--- a/packages/opencode/src/lsp/client.ts
+++ b/packages/opencode/src/lsp/client.ts
@@ -185,7 +185,7 @@ export namespace LSPClient {
log.info("shutting down")
connection.end()
connection.dispose()
- server.process.kill("SIGKILL")
+ server.process.kill("SIGTERM")
},
}
diff --git a/packages/opencode/src/lsp/index.ts b/packages/opencode/src/lsp/index.ts
index d29cd83a9..35224edfb 100644
--- a/packages/opencode/src/lsp/index.ts
+++ b/packages/opencode/src/lsp/index.ts
@@ -3,6 +3,7 @@ import { Log } from "../util/log"
import { LSPClient } from "./client"
import path from "path"
import { LSPServer } from "./server"
+import { Ripgrep } from "../file/ripgrep"
export namespace LSP {
const log = Log.create({ service: "lsp" })
@@ -25,6 +26,23 @@ export namespace LSP {
},
)
+ export async function init() {
+ log.info("init")
+ const app = App.info()
+ const result = Object.values(LSPServer).map(async (x) => {
+ for (const extension of x.extensions) {
+ const [file] = await Ripgrep.files({
+ cwd: app.path.cwd,
+ glob: "*" + extension,
+ })
+ if (!file) continue
+ await LSP.touchFile(file, true)
+ break
+ }
+ })
+ return Promise.all(result)
+ }
+
export async function touchFile(input: string, waitForDiagnostics?: boolean) {
const extension = path.parse(input).ext
const s = await state()
@@ -32,14 +50,12 @@ export namespace LSP {
x.extensions.includes(extension),
)
for (const match of matches) {
- if (s.skip.has(match.id)) continue
const existing = s.clients.get(match.id)
if (existing) continue
+ if (s.skip.has(match.id)) continue
+ s.skip.add(match.id)
const handle = await match.spawn(App.info())
- if (!handle) {
- s.skip.add(match.id)
- continue
- }
+ if (!handle) continue
const client = await LSPClient.create(match.id, handle).catch(() => {})
if (!client) {
s.skip.add(match.id)
@@ -86,6 +102,14 @@ export namespace LSP {
})
}
+ export async function workspaceSymbol(query: string) {
+ return run((client) =>
+ client.connection.sendRequest("workspace/symbol", {
+ query,
+ }),
+ )
+ }
+
async function run<T>(
input: (client: LSPClient.Info) => Promise<T>,
): Promise<T[]> {