فهرست منبع

refactor: extract LSP diagnostic report formatter (#21964)

Kit Langton 4 ماه پیش
والد
کامیت
a17ac02061

+ 11 - 0
packages/opencode/src/lsp/index.ts

@@ -540,6 +540,8 @@ export namespace LSP {
   export const outgoingCalls = async (input: LocInput) => runPromise((svc) => svc.outgoingCalls(input))
 
   export namespace Diagnostic {
+    const MAX_PER_FILE = 20
+
     export function pretty(diagnostic: LSPClient.Diagnostic) {
       const severityMap = {
         1: "ERROR",
@@ -554,5 +556,14 @@ export namespace LSP {
 
       return `${severity} [${line}:${col}] ${diagnostic.message}`
     }
+
+    export function report(file: string, issues: LSPClient.Diagnostic[]) {
+      const errors = issues.filter((item) => item.severity === 1)
+      if (errors.length === 0) return ""
+      const limited = errors.slice(0, MAX_PER_FILE)
+      const more = errors.length - MAX_PER_FILE
+      const suffix = more > 0 ? `\n... and ${more} more` : ""
+      return `<diagnostics file="${file}">\n${limited.map(pretty).join("\n")}${suffix}\n</diagnostics>`
+    }
   }
 }

+ 4 - 11
packages/opencode/src/tool/apply_patch.ts

@@ -258,20 +258,13 @@ export const ApplyPatchTool = Tool.defineEffect(
       })
       let output = `Success. Updated the following files:\n${summaryLines.join("\n")}`
 
-      // Report LSP errors for changed files
-      const MAX_DIAGNOSTICS_PER_FILE = 20
       for (const change of fileChanges) {
         if (change.type === "delete") continue
         const target = change.movePath ?? change.filePath
-        const normalized = AppFileSystem.normalizePath(target)
-        const issues = diagnostics[normalized] ?? []
-        const errors = issues.filter((item) => item.severity === 1)
-        if (errors.length > 0) {
-          const limited = errors.slice(0, MAX_DIAGNOSTICS_PER_FILE)
-          const suffix =
-            errors.length > MAX_DIAGNOSTICS_PER_FILE ? `\n... and ${errors.length - MAX_DIAGNOSTICS_PER_FILE} more` : ""
-          output += `\n\nLSP errors detected in ${path.relative(Instance.worktree, target).replaceAll("\\", "/")}, please fix:\n<diagnostics file="${target}">\n${limited.map(LSP.Diagnostic.pretty).join("\n")}${suffix}\n</diagnostics>`
-        }
+        const block = LSP.Diagnostic.report(target, diagnostics[AppFileSystem.normalizePath(target)] ?? [])
+        if (!block) continue
+        const rel = path.relative(Instance.worktree, target).replaceAll("\\", "/")
+        output += `\n\nLSP errors detected in ${rel}, please fix:\n${block}`
       }
 
       return {

+ 2 - 12
packages/opencode/src/tool/edit.ts

@@ -20,8 +20,6 @@ import { Instance } from "../project/instance"
 import { Snapshot } from "@/snapshot"
 import { assertExternalDirectoryEffect } from "./external-directory"
 
-const MAX_DIAGNOSTICS_PER_FILE = 20
-
 function normalizeLineEndings(text: string): string {
   return text.replaceAll("\r\n", "\n")
 }
@@ -166,16 +164,8 @@ export const EditTool = Tool.defineEffect(
           yield* lsp.touchFile(filePath, true)
           const diagnostics = yield* lsp.diagnostics()
           const normalizedFilePath = Filesystem.normalizePath(filePath)
-          const issues = diagnostics[normalizedFilePath] ?? []
-          const errors = issues.filter((item) => item.severity === 1)
-          if (errors.length > 0) {
-            const limited = errors.slice(0, MAX_DIAGNOSTICS_PER_FILE)
-            const suffix =
-              errors.length > MAX_DIAGNOSTICS_PER_FILE
-                ? `\n... and ${errors.length - MAX_DIAGNOSTICS_PER_FILE} more`
-                : ""
-            output += `\n\nLSP errors detected in this file, please fix:\n<diagnostics file="${filePath}">\n${limited.map(LSP.Diagnostic.pretty).join("\n")}${suffix}\n</diagnostics>`
-          }
+          const block = LSP.Diagnostic.report(filePath, diagnostics[normalizedFilePath] ?? [])
+          if (block) output += `\n\nLSP errors detected in this file, please fix:\n${block}`
 
           return {
             metadata: {

+ 7 - 12
packages/opencode/src/tool/write.ts

@@ -15,7 +15,6 @@ import { Instance } from "../project/instance"
 import { trimDiff } from "./edit"
 import { assertExternalDirectoryEffect } from "./external-directory"
 
-const MAX_DIAGNOSTICS_PER_FILE = 20
 const MAX_PROJECT_DIAGNOSTICS_FILES = 5
 
 export const WriteTool = Tool.defineEffect(
@@ -72,20 +71,16 @@ export const WriteTool = Tool.defineEffect(
           const normalizedFilepath = AppFileSystem.normalizePath(filepath)
           let projectDiagnosticsCount = 0
           for (const [file, issues] of Object.entries(diagnostics)) {
-            const errors = issues.filter((item) => item.severity === 1)
-            if (errors.length === 0) continue
-            const limited = errors.slice(0, MAX_DIAGNOSTICS_PER_FILE)
-            const suffix =
-              errors.length > MAX_DIAGNOSTICS_PER_FILE
-                ? `\n... and ${errors.length - MAX_DIAGNOSTICS_PER_FILE} more`
-                : ""
-            if (file === normalizedFilepath) {
-              output += `\n\nLSP errors detected in this file, please fix:\n<diagnostics file="${filepath}">\n${limited.map(LSP.Diagnostic.pretty).join("\n")}${suffix}\n</diagnostics>`
+            const current = file === normalizedFilepath
+            if (!current && projectDiagnosticsCount >= MAX_PROJECT_DIAGNOSTICS_FILES) continue
+            const block = LSP.Diagnostic.report(current ? filepath : file, issues)
+            if (!block) continue
+            if (current) {
+              output += `\n\nLSP errors detected in this file, please fix:\n${block}`
               continue
             }
-            if (projectDiagnosticsCount >= MAX_PROJECT_DIAGNOSTICS_FILES) continue
             projectDiagnosticsCount++
-            output += `\n\nLSP errors detected in other files:\n<diagnostics file="${file}">\n${limited.map(LSP.Diagnostic.pretty).join("\n")}${suffix}\n</diagnostics>`
+            output += `\n\nLSP errors detected in other files:\n${block}`
           }
 
           return {