From 37d0049e7a7b55d40af6da1a884810a543fead22 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sat, 16 Aug 2025 23:56:42 +0300 Subject: lsp: add 'Resolve diagnostics' code action scoped to selection - Parse diagnostics from CodeAction context; filter to overlap with selection - Build LLM prompt from selection-only diagnostics; replace only selected range - Keep existing 'Rewrite selection' action; return both when applicable - Add Diagnostic and CodeActionContext types; make CodeActionParams.Context raw JSON - Add helpers for range overlap; unit tests for filtering/overlap - Update README to document resolve-diagnostics action --- internal/lsp/handlers_test.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'internal/lsp/handlers_test.go') diff --git a/internal/lsp/handlers_test.go b/internal/lsp/handlers_test.go index 1b5080a..613835a 100644 --- a/internal/lsp/handlers_test.go +++ b/internal/lsp/handlers_test.go @@ -1,6 +1,7 @@ package lsp import ( + "encoding/json" "strings" "testing" ) @@ -254,3 +255,32 @@ func TestStripDuplicateAssignmentPrefix(t *testing.T) { t.Fatalf("dup strip '=' failed: got %q", got2) } } + +func TestRangesOverlap(t *testing.T) { + a := Range{Start: Position{Line: 1, Character: 2}, End: Position{Line: 3, Character: 0}} + b := Range{Start: Position{Line: 2, Character: 0}, End: Position{Line: 4, Character: 1}} + if !rangesOverlap(a, b) { t.Fatalf("expected overlap") } + c := Range{Start: Position{Line: 4, Character: 1}, End: Position{Line: 5, Character: 0}} + if rangesOverlap(a, c) { t.Fatalf("expected no overlap") } +} + +func TestDiagnosticsInRange_Filtering(t *testing.T) { + s := newTestServer() + sel := Range{Start: Position{Line: 10, Character: 0}, End: Position{Line: 12, Character: 5}} + // Build a fake context payload with three diagnostics: one inside, one outside, one touching boundary + ctx := CodeActionContext{Diagnostics: []Diagnostic{ + {Range: Range{Start: Position{Line: 11, Character: 0}, End: Position{Line: 11, Character: 10}}, Message: "inside"}, + {Range: Range{Start: Position{Line: 2, Character: 0}, End: Position{Line: 3, Character: 0}}, Message: "outside"}, + {Range: Range{Start: Position{Line: 12, Character: 5}, End: Position{Line: 12, Character: 8}}, Message: "touch"}, + }} + data, _ := json.Marshal(ctx) + got := s.diagnosticsInRange(json.RawMessage(data), sel) + if len(got) != 2 { + t.Fatalf("expected 2 diagnostics in range, got %d", len(got)) + } + msgs := []string{got[0].Message, got[1].Message} + joined := strings.Join(msgs, ",") + if !strings.Contains(joined, "inside") || !strings.Contains(joined, "touch") { + t.Fatalf("unexpected diagnostics: %v", msgs) + } +} -- cgit v1.2.3