summaryrefslogtreecommitdiff
path: root/internal/lsp/document_test.go
blob: 5fee18b402c3942b7504b8463f8b472ea7119d8e (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
// Summary: Tests for LSP document model (line management, edits, and transformations).
package lsp

import (
	"io"
	"log"
	"strings"
	"testing"
)

func newTestServer() *Server {
    s := &Server{
        logger: log.New(io.Discard, "", 0),
        docs:   make(map[string]*document),
        inlineOpen: ">",
        inlineClose: ">",
        chatSuffix: ">",
        chatPrefixes: []string{"?","!",":",";"},
    }
    // Keep package-level helpers in sync for tests using free functions
    inlineOpenChar = '>'
    inlineCloseChar = '>'
    chatSuffixChar = '>'
    chatPrefixSingles = []string{"?","!",":",";"}
    return s
}

func TestSplitLines(t *testing.T) {
	in := "a\r\nb\nc"
	got := splitLines(in)
	want := []string{"a", "b", "c"}
	if len(got) != len(want) {
		t.Fatalf("len mismatch: got %d want %d", len(got), len(want))
	}
	for i := range want {
		if got[i] != want[i] {
			t.Fatalf("line %d: got %q want %q", i, got[i], want[i])
		}
	}
}

func TestLineContext(t *testing.T) {
	s := newTestServer()
	src := "package main\n\nfunc add(a, b int) int {\n\treturn a + b\n}\n"
	uri := "file:///test.go"
	s.setDocument(uri, src)

	// Position on the return line (line 3, zero-based)
	above, current, below, funcCtx := s.lineContext(uri, Position{Line: 3, Character: 0})

	if want := "func add(a, b int) int {"; funcCtx != want {
		t.Fatalf("funcCtx got %q want %q", funcCtx, want)
	}
	if want := "func add(a, b int) int {"; above != want {
		t.Fatalf("above got %q want %q", above, want)
	}
	if want := "\treturn a + b"; current != want {
		t.Fatalf("current got %q want %q", current, want)
	}
	if want := "}"; below != want {
		t.Fatalf("below got %q want %q", below, want)
	}
}

func TestLineContext_EmptyDoc(t *testing.T) {
	s := newTestServer()
	a, c, b, f := s.lineContext("file:///missing.go", Position{Line: 0, Character: 0})
	if a != "" || b != "" || c != "" || f != "" {
		t.Fatalf("expected all empty for missing doc; got above=%q current=%q below=%q func=%q", a, c, b, f)
	}
}

func TestDocBeforeAfter_ClampsIndices(t *testing.T) {
    s := newTestServer()
    uri := "file:///clamp.go"
    s.setDocument(uri, "abc\nxyz")
    // Position beyond document length should be clamped safely
    before, after := s.docBeforeAfter(uri, Position{Line: 99, Character: 99})
    if before == "" && after == "" { t.Fatalf("expected some text with clamped indices") }
}

func TestTrimLen(t *testing.T) {
	long := strings.Repeat("a", 205)
	got := trimLen(long)
	want := strings.Repeat("a", 200) + "…"
	if got != want {
		t.Fatalf("trimLen got %q want %q", got, want)
	}
}

func TestFirstLine(t *testing.T) {
	s := "first line\r\nsecond line"
	if got := firstLine(s); got != "first line" {
		t.Fatalf("firstLine got %q want %q", got, "first line")
	}
}