diff options
Diffstat (limited to 'internal/lsp/codeaction_more_test.go')
| -rw-r--r-- | internal/lsp/codeaction_more_test.go | 151 |
1 files changed, 87 insertions, 64 deletions
diff --git a/internal/lsp/codeaction_more_test.go b/internal/lsp/codeaction_more_test.go index 412d988..82972d8 100644 --- a/internal/lsp/codeaction_more_test.go +++ b/internal/lsp/codeaction_more_test.go @@ -1,86 +1,109 @@ package lsp import ( - "encoding/json" - "path/filepath" - "strings" - "testing" - tut "codeberg.org/snonux/hexai/internal/testutil" + "encoding/json" + "path/filepath" + "strings" + "testing" + + tut "codeberg.org/snonux/hexai/internal/testutil" ) func TestBuildDocumentCodeAction_AndResolve(t *testing.T) { - s := newTestServer() - s.llmClient = fakeLLM{resp: tut.MultilineDocBlock()+"\n"+"func add(a,b int) int { return a+b }"} - uri := "file:///doc.go" - s.setDocument(uri, "package x\nfunc add(a,b int) int {return a+b}") - p := CodeActionParams{TextDocument: TextDocumentIdentifier{URI: uri}, Range: Range{Start: Position{Line:1, Character:0}, End: Position{Line:1, Character:10}}} - sel := "func add(a,b int) int {return a+b}" - ca := s.buildDocumentCodeAction(p, sel) - if ca == nil { t.Fatalf("expected document code action") } - resolved, ok := s.resolveCodeAction(*ca) - if !ok || resolved.Edit == nil { t.Fatalf("expected resolved edit") } - edits := resolved.Edit.Changes[uri] - if len(edits) != 1 || strings.TrimSpace(edits[0].NewText) == "" { t.Fatalf("expected replacement text") } + s := newTestServer() + s.llmClient = fakeLLM{resp: tut.MultilineDocBlock() + "\n" + "func add(a,b int) int { return a+b }"} + uri := "file:///doc.go" + s.setDocument(uri, "package x\nfunc add(a,b int) int {return a+b}") + p := CodeActionParams{TextDocument: TextDocumentIdentifier{URI: uri}, Range: Range{Start: Position{Line: 1, Character: 0}, End: Position{Line: 1, Character: 10}}} + sel := "func add(a,b int) int {return a+b}" + ca := s.buildDocumentCodeAction(p, sel) + if ca == nil { + t.Fatalf("expected document code action") + } + resolved, ok := s.resolveCodeAction(*ca) + if !ok || resolved.Edit == nil { + t.Fatalf("expected resolved edit") + } + edits := resolved.Edit.Changes[uri] + if len(edits) != 1 || strings.TrimSpace(edits[0].NewText) == "" { + t.Fatalf("expected replacement text") + } } func TestResolveCodeAction_Rewrite(t *testing.T) { - s := newTestServer() - s.llmClient = fakeLLM{resp: "rewritten"} - uri := "file:///x.go" - s.setDocument(uri, "package p\nvar a=1\n") - payload := struct { - Type string `json:"type"` - URI string `json:"uri"` - Range Range `json:"range"` - Instruction string `json:"instruction"` - Selection string `json:"selection"` - }{Type: "rewrite", URI: uri, Range: Range{Start: Position{Line:1}, End: Position{Line:1, Character: 5}}, Instruction: "do it", Selection: "var a"} - raw, _ := json.Marshal(payload) - ca := CodeAction{Title: "Hexai: rewrite selection", Data: raw} - if resolved, ok := s.resolveCodeAction(ca); !ok || resolved.Edit == nil { t.Fatalf("expected resolved rewrite edit") } + s := newTestServer() + s.llmClient = fakeLLM{resp: "rewritten"} + uri := "file:///x.go" + s.setDocument(uri, "package p\nvar a=1\n") + payload := struct { + Type string `json:"type"` + URI string `json:"uri"` + Range Range `json:"range"` + Instruction string `json:"instruction"` + Selection string `json:"selection"` + }{Type: "rewrite", URI: uri, Range: Range{Start: Position{Line: 1}, End: Position{Line: 1, Character: 5}}, Instruction: "do it", Selection: "var a"} + raw, _ := json.Marshal(payload) + ca := CodeAction{Title: "Hexai: rewrite selection", Data: raw} + if resolved, ok := s.resolveCodeAction(ca); !ok || resolved.Edit == nil { + t.Fatalf("expected resolved rewrite edit") + } } func TestBuildGoUnitTestCodeAction_AndResolveCreate(t *testing.T) { - s := newTestServer() - // place files under a temp dir to avoid collisions - dir := t.TempDir() - srcPath := filepath.Join(dir, "calc.go") - uri := "file://" + srcPath - src := "package calc\n\nfunc Sum(a, b int) int { return a+b }\n" - s.setDocument(uri, src) - // Offer action (not a _test.go) - p := CodeActionParams{TextDocument: TextDocumentIdentifier{URI: uri}, Range: Range{Start: Position{Line:2}}} - if a := s.buildGoUnitTestCodeAction(p); a == nil { t.Fatalf("expected go unit test action") } - // Resolve should create new test file with package+import and a test function - we, testURI, _, ok := s.resolveGoTest(uri, Position{Line:2}) - if !ok { t.Fatalf("resolveGoTest failed") } - if len(we.DocumentChanges) != 2 { t.Fatalf("expected create + edits, got %d", len(we.DocumentChanges)) } - if !strings.HasSuffix(testURI, "_test.go") { t.Fatalf("unexpected test URI: %s", testURI) } + s := newTestServer() + // place files under a temp dir to avoid collisions + dir := t.TempDir() + srcPath := filepath.Join(dir, "calc.go") + uri := "file://" + srcPath + src := "package calc\n\nfunc Sum(a, b int) int { return a+b }\n" + s.setDocument(uri, src) + // Offer action (not a _test.go) + p := CodeActionParams{TextDocument: TextDocumentIdentifier{URI: uri}, Range: Range{Start: Position{Line: 2}}} + if a := s.buildGoUnitTestCodeAction(p); a == nil { + t.Fatalf("expected go unit test action") + } + // Resolve should create new test file with package+import and a test function + we, testURI, _, ok := s.resolveGoTest(uri, Position{Line: 2}) + if !ok { + t.Fatalf("resolveGoTest failed") + } + if len(we.DocumentChanges) != 2 { + t.Fatalf("expected create + edits, got %d", len(we.DocumentChanges)) + } + if !strings.HasSuffix(testURI, "_test.go") { + t.Fatalf("unexpected test URI: %s", testURI) + } } func TestBuildGoUnitTestCodeAction_SkipOnTestFile(t *testing.T) { - s := newTestServer() - uri := "file:///tmp/x_test.go" - s.setDocument(uri, "package p\nfunc T(){}") - p := CodeActionParams{TextDocument: TextDocumentIdentifier{URI: uri}} - if a := s.buildGoUnitTestCodeAction(p); a != nil { t.Fatalf("expected no action on _test.go") } + s := newTestServer() + uri := "file:///tmp/x_test.go" + s.setDocument(uri, "package p\nfunc T(){}") + p := CodeActionParams{TextDocument: TextDocumentIdentifier{URI: uri}} + if a := s.buildGoUnitTestCodeAction(p); a != nil { + t.Fatalf("expected no action on _test.go") + } } func TestDiagnosticsInRange(t *testing.T) { - s := newTestServer() - ctx := CodeActionContext{Diagnostics: []Diagnostic{ - {Range: Range{Start: Position{Line: 3}, End: Position{Line: 3, Character: 5}}, Message: "in"}, - {Range: Range{Start: Position{Line: 10}, End: Position{Line: 11}}, Message: "out"}, - }} - raw, _ := json.Marshal(ctx) - got := s.diagnosticsInRange(json.RawMessage(raw), Range{Start: Position{Line:2}, End: Position{Line:4}}) - if len(got) != 1 || got[0].Message != "in" { t.Fatalf("unexpected diags: %+v", got) } + s := newTestServer() + ctx := CodeActionContext{Diagnostics: []Diagnostic{ + {Range: Range{Start: Position{Line: 3}, End: Position{Line: 3, Character: 5}}, Message: "in"}, + {Range: Range{Start: Position{Line: 10}, End: Position{Line: 11}}, Message: "out"}, + }} + raw, _ := json.Marshal(ctx) + got := s.diagnosticsInRange(json.RawMessage(raw), Range{Start: Position{Line: 2}, End: Position{Line: 4}}) + if len(got) != 1 || got[0].Message != "in" { + t.Fatalf("unexpected diags: %+v", got) + } } func TestDocBeforeAfter(t *testing.T) { - s := newTestServer() - uri := "file:///d.go" - s.setDocument(uri, "ab\ncd\nef") - before, after := s.docBeforeAfter(uri, Position{Line:1, Character:1}) - if before != "ab\nc" || after != "d\nef" { t.Fatalf("before=%q after=%q", before, after) } + s := newTestServer() + uri := "file:///d.go" + s.setDocument(uri, "ab\ncd\nef") + before, after := s.docBeforeAfter(uri, Position{Line: 1, Character: 1}) + if before != "ab\nc" || after != "d\nef" { + t.Fatalf("before=%q after=%q", before, after) + } } |
