// Summary: Tests for instruction extraction helpers in handlers.go package lsp import "testing" func TestFindFirstInstructionInLine_NoMarker(t *testing.T) { line := "fmt.Println(\"hello\")" s := newTestServer() instr, cleaned, ok := s.findFirstInstructionInLine(line) if ok { t.Fatalf("expected ok=false; got ok=true with instr=%q cleaned=%q", instr, cleaned) } if instr != "" || cleaned != line { t.Fatalf("unexpected outputs: instr=%q cleaned=%q", instr, cleaned) } } func TestFindFirstInstructionInLine_StrictInline_Basic(t *testing.T) { line := "prefix >rename var> suffix" s := newTestServer() instr, cleaned, ok := s.findFirstInstructionInLine(line) if !ok { t.Fatalf("expected ok=true") } if instr != "rename var" { t.Fatalf("instr got %q want %q", instr, "rename var") } // Removal preserves inner spacing; trailing right spaces trimmed only. if cleaned != "prefix suffix" { t.Fatalf("cleaned got %q want %q", cleaned, "prefix suffix") } } func TestFindFirstInstructionInLine_StrictInline_TrailingSpacesTrimmed(t *testing.T) { line := "code>fix> \t\t" s := newTestServer() instr, cleaned, ok := s.findFirstInstructionInLine(line) if !ok { t.Fatalf("expected ok=true") } if instr != "fix" { t.Fatalf("instr got %q want %q", instr, "fix") } if cleaned != "code" { t.Fatalf("cleaned got %q want %q", cleaned, "code") } } func TestFindFirstInstructionInLine_Inline_InvalidPatterns(t *testing.T) { cases := []string{ "prefix > bad> suffix", // space after first '>' ⇒ invalid "prefix >bad > suffix", // space before closing '>' ⇒ invalid "prefix > > suffix", // empty inner ⇒ invalid } for _, line := range cases { s := newTestServer() if instr, _, ok := s.findFirstInstructionInLine(line); ok && instr != "" { t.Fatalf("%q: expected no inline instruction; got instr=%q", line, instr) } } } func TestFindFirstInstructionInLine_CBlockComment(t *testing.T) { line := "foo /* update this part */ bar" s := newTestServer() instr, cleaned, ok := s.findFirstInstructionInLine(line) if !ok { t.Fatalf("expected ok=true") } if instr != "update this part" { t.Fatalf("instr got %q want %q", instr, "update this part") } if cleaned != "foo bar" { t.Fatalf("cleaned got %q want %q", cleaned, "foo bar") } } func TestFindFirstInstructionInLine_HTMLComment(t *testing.T) { line := "foo bar" s := newTestServer() instr, cleaned, ok := s.findFirstInstructionInLine(line) if !ok { t.Fatalf("expected ok=true") } if instr != "do x" { t.Fatalf("instr got %q want %q", instr, "do x") } if cleaned != "foo bar" { t.Fatalf("cleaned got %q want %q", cleaned, "foo bar") } } func TestFindFirstInstructionInLine_SlashSlash(t *testing.T) { line := "val // do this change" s := newTestServer() instr, cleaned, ok := s.findFirstInstructionInLine(line) if !ok { t.Fatalf("expected ok=true") } if instr != "do this change" { t.Fatalf("instr got %q want %q", instr, "do this change") } if cleaned != "val" { t.Fatalf("cleaned got %q want %q", cleaned, "val") } } func TestFindFirstInstructionInLine_Hash(t *testing.T) { line := "val # do this" s := newTestServer() instr, cleaned, ok := s.findFirstInstructionInLine(line) if !ok { t.Fatalf("expected ok=true") } if instr != "do this" { t.Fatalf("instr got %q want %q", instr, "do this") } if cleaned != "val" { t.Fatalf("cleaned got %q want %q", cleaned, "val") } } func TestFindFirstInstructionInLine_DoubleDash(t *testing.T) { line := "SQL -- fix query" s := newTestServer() instr, cleaned, ok := s.findFirstInstructionInLine(line) if !ok { t.Fatalf("expected ok=true") } if instr != "fix query" { t.Fatalf("instr got %q want %q", instr, "fix query") } if cleaned != "SQL" { t.Fatalf("cleaned got %q want %q", cleaned, "SQL") } } func TestFindFirstInstructionInLine_EarliestWins_CommentOverInline(t *testing.T) { line := "aa // comment >not this> trailing" s := newTestServer() instr, cleaned, ok := s.findFirstInstructionInLine(line) if !ok { t.Fatalf("expected ok=true") } if instr != "comment >not this> trailing" { t.Fatalf("instr got %q want %q", instr, "comment >not this> trailing") } if cleaned != "aa" { t.Fatalf("cleaned got %q want %q", cleaned, "aa") } } func TestFindFirstInstructionInLine_EarliestWins_InlineOverComment(t *testing.T) { line := "aa >short> // comment" s := newTestServer() instr, cleaned, ok := s.findFirstInstructionInLine(line) if !ok { t.Fatalf("expected ok=true") } if instr != "short" { t.Fatalf("instr got %q want %q", instr, "short") } // Only the earliest marker is removed; the later comment remains. if cleaned != "aa // comment" { t.Fatalf("cleaned got %q want %q", cleaned, "aa // comment") } } func TestFindStrictInlineTag_Various(t *testing.T) { // basic if text, l, r, ok := findStrictInlineTag("pre>do it>post", '>', '>'); !ok || text != "do it" || l != 3 || r != 10 { t.Fatalf("unexpected: ok=%v text=%q l=%d r=%d", ok, text, l, r) } // at start if text, l, r, ok := findStrictInlineTag(">x>", '>', '>'); !ok || text != "x" || l != 0 || r != 3 { t.Fatalf("unexpected at start: ok=%v text=%q l=%d r=%d", ok, text, l, r) } // double opening '>>' should still allow a tag starting at the second '>' if text, _, _, ok := findStrictInlineTag("prefix >>bad> suffix", '>', '>'); !ok || text != "bad" { t.Fatalf("unexpected double-open handling: ok=%v text=%q", ok, text) } // inner spaces directly after first '>' or before last '>' invalidate the tag if _, _, _, ok := findStrictInlineTag("a> inner >b", '>', '>'); ok { t.Fatalf("expected invalid strict tag due to spaces at boundaries") } }