Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions packages/opencode/src/tool/lsp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export const Parameters = Schema.Struct({
character: Schema.Number.check(Schema.isInt())
.check(Schema.isGreaterThanOrEqualTo(1))
.annotate({ description: "The character offset (1-based, as shown in editors)" }),
query: Schema.optional(Schema.String).annotate({
description: "Search query for workspaceSymbol. Empty string requests all symbols.",
}),
})

export const LspTool = Tool.define(
Expand All @@ -40,7 +43,7 @@ export const LspTool = Tool.define(
description: DESCRIPTION,
parameters: Parameters,
execute: (
args: { operation: (typeof operations)[number]; filePath: string; line: number; character: number },
args: Schema.Schema.Type<typeof Parameters>,
ctx: Tool.Context,
) =>
Effect.gen(function* () {
Expand Down Expand Up @@ -89,7 +92,7 @@ export const LspTool = Tool.define(
case "documentSymbol":
return lsp.documentSymbol(uri)
case "workspaceSymbol":
return lsp.workspaceSymbol("")
return lsp.workspaceSymbol(args.query ?? "")
case "goToImplementation":
Comment thread
Hona marked this conversation as resolved.
return lsp.implementation(position)
case "prepareCallHierarchy":
Expand Down
7 changes: 6 additions & 1 deletion packages/opencode/src/tool/lsp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Supported operations:
- findReferences: Find all references to a symbol
- hover: Get hover information (documentation, type info) for a symbol
- documentSymbol: Get all symbols (functions, classes, variables) in a document
- workspaceSymbol: Search for symbols across the entire workspace
- workspaceSymbol: List project-wide symbols matching a query string
- goToImplementation: Find implementations of an interface or abstract method
- prepareCallHierarchy: Get call hierarchy item at a position (functions/methods)
- incomingCalls: Find all functions/methods that call the function at a position
Expand All @@ -16,4 +16,9 @@ All operations require:
- line: The line number (1-based, as shown in editors)
- character: The character offset (1-based, as shown in editors)

workspaceSymbol also accepts:
- query: A query string to filter symbols by. Empty string requests all symbols.

For workspaceSymbol, filePath is not sent in the LSP workspace/symbol request. It is used by opencode to select and start the matching LSP server.

Note: LSP servers must be configured for the file type. If no server is available, an error will be returned.
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ exports[`tool parameters JSON Schema (wire shape) lsp 1`] = `
],
"type": "string",
},
"query": {
"description": "Search query for workspaceSymbol. Empty string requests all symbols.",
"type": "string",
},
},
"required": [
"operation",
Expand Down
26 changes: 25 additions & 1 deletion packages/opencode/test/tool/lsp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const ctx = {
ask: () => Effect.void,
}

const workspaceSymbolQueries: string[] = []

const lsp = Layer.succeed(
LSP.Service,
LSP.Service.of({
Expand All @@ -41,7 +43,11 @@ const lsp = Layer.succeed(
references: () => Effect.succeed([]),
implementation: () => Effect.succeed([]),
documentSymbol: () => Effect.succeed([]),
workspaceSymbol: () => Effect.succeed([]),
workspaceSymbol: (query) =>
Effect.sync(() => {
workspaceSymbolQueries.push(query)
return []
}),
prepareCallHierarchy: () => Effect.succeed([]),
incomingCalls: () => Effect.succeed([]),
outgoingCalls: () => Effect.succeed([]),
Expand Down Expand Up @@ -142,6 +148,7 @@ describe("tool.lsp", () => {
provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
workspaceSymbolQueries.length = 0
const file = path.join(dir, "test.ts")
yield* put(file)

Expand All @@ -158,5 +165,22 @@ describe("tool.lsp", () => {
{ git: true },
),
)

it.live("passes workspaceSymbol query to LSP", () =>
provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
workspaceSymbolQueries.length = 0
const file = path.join(dir, "test.ts")
yield* put(file)

yield* run({ operation: "workspaceSymbol", filePath: file, line: 3, character: 7, query: "TestSymbol" })
yield* run({ operation: "workspaceSymbol", filePath: file, line: 3, character: 7 })

expect(workspaceSymbolQueries).toEqual(["TestSymbol", ""])
}),
{ git: true },
),
)
})
})
Loading