all repos

clerk @ 1925839

missing tooling for ledger/hledger

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

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
perf: lsp: resolve positions and entries via cached line index..., 1 month ago
1
package lsp
2
3
import (
4
	"context"
5
6
	"go.lsp.dev/protocol"
7
	"go.lsp.dev/uri"
8
9
	"olexsmir.xyz/clerk/internal/lsp/lsputil"
10
	"olexsmir.xyz/clerk/journal/ast"
11
	"olexsmir.xyz/clerk/journal/lexer"
12
	"olexsmir.xyz/clerk/journal/parser"
13
)
14
15
func (s *server) DidOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error {
16
	s.openDoc(params.TextDocument.URI, params.TextDocument.Text, params.TextDocument.Version, params.TextDocument.LanguageID)
17
	s.scheduleDiagnostics(ctx)
18
	return nil
19
}
20
21
func (s *server) DidChange(ctx context.Context, params *protocol.DidChangeTextDocumentParams) error {
22
	s.updateDoc(params.TextDocument.URI, params.TextDocument.Version, params.ContentChanges)
23
	s.scheduleDiagnostics(ctx)
24
	return nil
25
}
26
27
func (s *server) DidClose(ctx context.Context, params *protocol.DidCloseTextDocumentParams) error {
28
	s.closeDoc(params.TextDocument.URI)
29
	s.scheduleDiagnostics(ctx)
30
	return nil
31
}
32
33
func (s *server) DidSave(ctx context.Context, params *protocol.DidSaveTextDocumentParams) error {
34
	return nil
35
}
36
37
// Document management
38
39
type docState struct {
40
	text       string
41
	version    int32
42
	languageID protocol.LanguageKind
43
	semTokens  []semanticToken    // cached semantic tokens
44
	lineIdx    *lsputil.LineIndex // cached line index for the text
45
}
46
47
func (s *server) openDoc(u uri.URI, text string, version int32, langID protocol.LanguageKind) {
48
	s.mu.Lock()
49
	s.openDocs[u] = docState{
50
		text:       text,
51
		version:    version,
52
		languageID: langID,
53
		lineIdx:    lsputil.NewLineIndex(text),
54
	}
55
	s.mu.Unlock()
56
}
57
58
func (s *server) updateDoc(u uri.URI, version int32, changes []protocol.TextDocumentContentChangeEvent) {
59
	s.mu.Lock()
60
	defer s.mu.Unlock()
61
	state, ok := s.openDocs[u]
62
	if !ok {
63
		return
64
	}
65
	state.version = version
66
	for _, ch := range changes {
67
		switch ev := ch.(type) {
68
		case *protocol.TextDocumentContentChangeWholeDocument:
69
			state.text = ev.Text
70
			state.semTokens = nil
71
			state.lineIdx = lsputil.NewLineIndex(ev.Text)
72
		case *protocol.TextDocumentContentChangePartial:
73
			_ = ev // TODO: incremental edit support
74
		}
75
	}
76
	s.openDocs[u] = state
77
}
78
79
func (s *server) getDocState(u uri.URI) (docState, bool) {
80
	s.mu.Lock()
81
	state, ok := s.openDocs[u]
82
	s.mu.Unlock()
83
	return state, ok
84
}
85
86
func (s *server) closeDoc(u uri.URI) {
87
	s.mu.Lock()
88
	delete(s.openDocs, u)
89
	s.mu.Unlock()
90
}
91
92
func parseJournalStr(content string) *ast.Journal {
93
	l := lexer.New("", []byte(content))
94
	p := parser.New(l)
95
	return p.ParseJournal()
96
}