summaryrefslogtreecommitdiff
path: root/internal/lsp/handlers_test.go
blob: 6803d1e570e29e588d1f86cffb980230ab3aff88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// 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 <!--  do x  --> 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")
	}
}