Bladeren bron

fix: pass workspace symbol query to experimental LSP tool (#24576)

Luke Parker 4 maanden geleden
bovenliggende
commit
8718b98ee1

+ 5 - 2
packages/opencode/src/tool/lsp.ts

@@ -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(
@@ -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* () {
@@ -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":
                 return lsp.implementation(position)
               case "prepareCallHierarchy":

+ 6 - 1
packages/opencode/src/tool/lsp.txt

@@ -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
@@ -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.

+ 4 - 0
packages/opencode/test/tool/__snapshots__/parameters.test.ts.snap

@@ -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",

+ 25 - 1
packages/opencode/test/tool/lsp.test.ts

@@ -28,6 +28,8 @@ const ctx = {
   ask: () => Effect.void,
 }
 
+const workspaceSymbolQueries: string[] = []
+
 const lsp = Layer.succeed(
   LSP.Service,
   LSP.Service.of({
@@ -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([]),
@@ -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)
 
@@ -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 },
+      ),
+    )
   })
 })