diff options
| author | Kujtim Hoxha <[email protected]> | 2025-04-04 15:03:50 +0200 |
|---|---|---|
| committer | Kujtim Hoxha <[email protected]> | 2025-04-04 15:03:50 +0200 |
| commit | 3aef4dedcfd1ad408c6cb6c06e5e731feb528a1e (patch) | |
| tree | 20e018a73754880e78c0e7f569828b415c66b6a2 /internal | |
| parent | a1f6147506af1f98e5dfa670fc83fa45c2249842 (diff) | |
| download | opencode-3aef4dedcfd1ad408c6cb6c06e5e731feb528a1e.tar.gz opencode-3aef4dedcfd1ad408c6cb6c06e5e731feb528a1e.zip | |
Improve LSP diagnostics handling for file operations
- Split LSP file notification into separate functions
- Add waitForLspDiagnostics function to wait for diagnostics after file changes
- Move LSP diagnostics to after file operations in edit and write tools
- Fix string splitting in diff generation
- Reduce diagnostics timeout from 10 to 5 seconds
🤖 Generated with termai
Co-Authored-By: termai <[email protected]>
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/llm/tools/diagnostics.go | 36 | ||||
| -rw-r--r-- | internal/llm/tools/edit.go | 11 | ||||
| -rw-r--r-- | internal/llm/tools/write.go | 3 |
3 files changed, 38 insertions, 12 deletions
diff --git a/internal/llm/tools/diagnostics.go b/internal/llm/tools/diagnostics.go index 3eb72eafc..ce76ae12f 100644 --- a/internal/llm/tools/diagnostics.go +++ b/internal/llm/tools/diagnostics.go @@ -53,6 +53,7 @@ func (b *diagnosticsTool) Run(ctx context.Context, call ToolCall) (ToolResponse, if params.FilePath != "" { notifyLspOpenFile(ctx, params.FilePath, lsps) + waitForLspDiagnostics(ctx, params.FilePath, lsps) } output := appendDiagnostics(params.FilePath, lsps) @@ -61,6 +62,22 @@ func (b *diagnosticsTool) Run(ctx context.Context, call ToolCall) (ToolResponse, } func notifyLspOpenFile(ctx context.Context, filePath string, lsps map[string]*lsp.Client) { + for _, client := range lsps { + // Open the file + err := client.OpenFile(ctx, filePath) + if err != nil { + // If there's an error opening the file, continue to the next client + continue + } + } +} + +// waitForLspDiagnostics opens a file in LSP clients and waits for diagnostics to be published +func waitForLspDiagnostics(ctx context.Context, filePath string, lsps map[string]*lsp.Client) { + if len(lsps) == 0 { + return + } + // Create a channel to receive diagnostic notifications diagChan := make(chan struct{}, 1) @@ -92,11 +109,18 @@ func notifyLspOpenFile(ctx context.Context, filePath string, lsps map[string]*ls // Register our temporary handler client.RegisterNotificationHandler("textDocument/publishDiagnostics", handler) - // Open the file - err := client.OpenFile(ctx, filePath) - if err != nil { - // If there's an error opening the file, continue to the next client - continue + // Notify change if the file is already open + if client.IsFileOpen(filePath) { + err := client.NotifyChange(ctx, filePath) + if err != nil { + continue + } + } else { + // Open the file if it's not already open + err := client.OpenFile(ctx, filePath) + if err != nil { + continue + } } } @@ -104,7 +128,7 @@ func notifyLspOpenFile(ctx context.Context, filePath string, lsps map[string]*ls select { case <-diagChan: // Diagnostics received - case <-time.After(10 * time.Second): + case <-time.After(5 * time.Second): // Timeout after 5 seconds - this is a fallback in case no diagnostics are published case <-ctx.Done(): // Context cancelled diff --git a/internal/llm/tools/edit.go b/internal/llm/tools/edit.go index 394ce13b9..f158401b8 100644 --- a/internal/llm/tools/edit.go +++ b/internal/llm/tools/edit.go @@ -74,7 +74,6 @@ func (e *editTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error) params.FilePath = filepath.Join(wd, params.FilePath) } - notifyLspOpenFile(ctx, params.FilePath, e.lspClients) if params.OldString == "" { result, err := createNewFile(params.FilePath, params.NewString) if err != nil { @@ -96,6 +95,8 @@ func (e *editTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error) return NewTextErrorResponse(fmt.Sprintf("error replacing content: %s", err)), nil } + // Wait for LSP diagnostics after editing the file + waitForLspDiagnostics(ctx, params.FilePath, e.lspClients) result = fmt.Sprintf("<result>\n%s\n</result>\n", result) result += appendDiagnostics(params.FilePath, e.lspClients) return NewTextResponse(result), nil @@ -303,23 +304,23 @@ func GenerateDiff(oldContent, newContent string) string { diffs = dmp.DiffCharsToLines(diffs, dmpStrings) diffs = dmp.DiffCleanupSemantic(diffs) buff := strings.Builder{} - + // Add a header to make the diff more readable buff.WriteString("Changes:\n") - + for _, diff := range diffs { text := diff.Text switch diff.Type { case diffmatchpatch.DiffInsert: - for _, line := range strings.Split(text, "\n") { + for line := range strings.SplitSeq(text, "\n") { if line == "" { continue } _, _ = buff.WriteString("+ " + line + "\n") } case diffmatchpatch.DiffDelete: - for _, line := range strings.Split(text, "\n") { + for line := range strings.SplitSeq(text, "\n") { if line == "" { continue } diff --git a/internal/llm/tools/write.go b/internal/llm/tools/write.go index 1c32410f7..86c9be37e 100644 --- a/internal/llm/tools/write.go +++ b/internal/llm/tools/write.go @@ -100,7 +100,6 @@ func (w *writeTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error return NewTextErrorResponse(fmt.Sprintf("Failed to create parent directories: %s", err)), nil } - notifyLspOpenFile(ctx, filePath, w.lspClients) // Get old content for diff if file exists oldContent := "" if fileInfo != nil && !fileInfo.IsDir() { @@ -135,6 +134,8 @@ func (w *writeTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error // Record the file write recordFileWrite(filePath) recordFileRead(filePath) + // Wait for LSP diagnostics after writing the file + waitForLspDiagnostics(ctx, filePath, w.lspClients) result := fmt.Sprintf("File successfully written: %s", filePath) result = fmt.Sprintf("<result>\n%s\n</result>", result) |
