all repos

clerk @ 17e6766

missing tooling for ledger/hledger

clerk/internal/lsp/textdocument_selection_range_test.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
lsp: textdocument/selectionRange..., 1 month ago
1
package lsp
2
3
import (
4
	"fmt"
5
	"path/filepath"
6
	"strings"
7
	"testing"
8
9
	"go.lsp.dev/protocol"
10
	"go.lsp.dev/uri"
11
12
	"olexsmir.xyz/clerk/internal/lsp/lsputil"
13
	"olexsmir.xyz/clerk/internal/testutil/golden"
14
	"olexsmir.xyz/clerk/journal"
15
)
16
17
func TestServer_SelectionRange_DocumentNotFound(t *testing.T) {
18
	srv := newServer(t)
19
	res, err := srv.server.SelectionRange(t.Context(), &protocol.SelectionRangeParams{
20
		TextDocument: protocol.TextDocumentIdentifier{URI: uri.URI("file:///nonexistent.journal")},
21
		Positions:    []protocol.Position{{Line: 0, Character: 0}},
22
	})
23
	if err != nil {
24
		t.Fatal(err)
25
	}
26
	if res != nil {
27
		t.Errorf("got %v, want nil", res)
28
	}
29
}
30
31
func TestGolden_SelectionRange(t *testing.T) {
32
	ar := golden.Read(t, "selection-range")
33
	h := newTxtarHarness(t, ar)
34
	li := lsputil.NewLineIndex(h.content)
35
36
	var b strings.Builder
37
	for i := range h.cursors {
38
		pos := lsputil.Position(h.content, h.cursors[i])
39
		res, err := h.srv.SelectionRange(t.Context(), &protocol.SelectionRangeParams{
40
			TextDocument: protocol.TextDocumentIdentifier{URI: h.uri},
41
			Positions:    []protocol.Position{pos},
42
		})
43
		if err != nil {
44
			t.Fatal(err)
45
		}
46
		if len(res) != 1 {
47
			t.Fatalf("cursor %d: got %d results, want 1", i, len(res))
48
		}
49
		chain := make([]string, 0, 4)
50
		for cur := &res[0]; ; cur = cur.Parent {
51
			if cur.Parent == nil {
52
				chain = append(chain, "<doc>")
53
				break
54
			}
55
			start := li.Offset(int(cur.Range.Start.Line), int(cur.Range.Start.Character))
56
			end := li.Offset(int(cur.Range.End.Line), int(cur.Range.End.Character))
57
			chain = append(chain, fmt.Sprintf("%q", h.content[start:end]))
58
		}
59
		fmt.Fprintf(&b, "%d:%d %s\n", pos.Line, pos.Character, strings.Join(chain, " -> "))
60
	}
61
	golden.Assert(t, ar, b.String())
62
}
63
64
func BenchmarkSelectionRange(b *testing.B) {
65
	path := "../../journal/testdata/journals/actual-1ktxns-100accts.journal"
66
	abs, err := filepath.Abs(path)
67
	if err != nil {
68
		b.Fatal(err)
69
	}
70
	rj, err := journal.NewLoader().Resolve(abs)
71
	if err != nil {
72
		b.Fatal(err)
73
	}
74
	content := string(rj.Occurrences[0].Src)
75
76
	srv := newServer(b)
77
	u := uri.File(abs)
78
	srv.server.openDoc(u, content, 1, "journal")
79
	srv.server.analysisFor(u) // warm the per-doc cache
80
81
	for tname, off := range map[string]int{
82
		"account seg, tx 3, early":  strings.Index(content, "  1:2:3:4:5 ") + 5,
83
		"date, tx 1, early":         strings.Index(content, "2000-01-01 ") + 3,
84
		"account seg, tx 999, late": strings.Index(content, "  5b:5c:5d:5e:5f:60:61 ") + 6,
85
		"date, tx 999, late":        strings.Index(content, "2002-09-25 ") + 3,
86
	} {
87
		b.Run(tname, func(b *testing.B) {
88
			params := &protocol.SelectionRangeParams{
89
				TextDocument: protocol.TextDocumentIdentifier{URI: u},
90
				Positions:    []protocol.Position{lsputil.Position(content, off)},
91
			}
92
			// warm up: first request resolves the lazily-built analysis; assert it found one
93
			res, err := srv.server.SelectionRange(b.Context(), params)
94
			if err != nil {
95
				b.Fatal(err)
96
			}
97
			if len(res) != 1 {
98
				b.Fatalf("%s: got %d results, want 1", tname, len(res))
99
			}
100
			b.ReportAllocs()
101
			b.ResetTimer()
102
			for b.Loop() {
103
				if _, err := srv.server.SelectionRange(b.Context(), params); err != nil {
104
					b.Fatal(err)
105
				}
106
			}
107
		})
108
	}
109
}