all repos

clerk @ 8ff5e11

missing tooling for ledger/hledger

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

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
lsp: semantic highlights, 2 months 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/journal/ast"
10
	"olexsmir.xyz/clerk/journal/lexer"
11
	"olexsmir.xyz/clerk/journal/parser"
12
)
13
14
func (s *server) DidOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error {
15
	s.openDoc(params.TextDocument.URI, params.TextDocument.Text, params.TextDocument.Version, params.TextDocument.LanguageID)
16
	s.scheduleDiagnostics(ctx)
17
	return nil
18
}
19
20
func (s *server) DidChange(ctx context.Context, params *protocol.DidChangeTextDocumentParams) error {
21
	s.updateDoc(params.TextDocument.URI, params.TextDocument.Version, params.ContentChanges)
22
	s.scheduleDiagnostics(ctx)
23
	return nil
24
}
25
26
func (s *server) DidClose(ctx context.Context, params *protocol.DidCloseTextDocumentParams) error {
27
	s.closeDoc(params.TextDocument.URI)
28
	s.scheduleDiagnostics(ctx)
29
	return nil
30
}
31
32
func (s *server) DidSave(ctx context.Context, params *protocol.DidSaveTextDocumentParams) error {
33
	return nil
34
}
35
36
// Document management
37
38
func (s *server) openDoc(u uri.URI, text string, version int32, langID protocol.LanguageKind) {
39
	j := parseJournalStr(text)
40
	s.mu.Lock()
41
	s.openDocs[u] = docState{
42
		text:       text,
43
		version:    version,
44
		languageID: langID,
45
		journal:    j,
46
	}
47
	s.mu.Unlock()
48
}
49
50
func (s *server) updateDoc(u uri.URI, version int32, changes []protocol.TextDocumentContentChangeEvent) {
51
	s.mu.Lock()
52
	defer s.mu.Unlock()
53
	state, ok := s.openDocs[u]
54
	if !ok {
55
		return
56
	}
57
	state.version = version
58
	for _, ch := range changes {
59
		switch ev := ch.(type) {
60
		case *protocol.TextDocumentContentChangeWholeDocument:
61
			state.text = ev.Text
62
			state.journal = parseJournalStr(ev.Text)
63
		case *protocol.TextDocumentContentChangePartial:
64
			_ = ev // TODO: incremental edit support
65
		}
66
	}
67
	s.openDocs[u] = state
68
}
69
70
func (s *server) closeDoc(u uri.URI) {
71
	s.mu.Lock()
72
	delete(s.openDocs, u)
73
	s.mu.Unlock()
74
}
75
76
func (s *server) getDocText(u uri.URI) (string, bool) {
77
	s.mu.Lock()
78
	state, ok := s.openDocs[u]
79
	s.mu.Unlock()
80
	return state.text, ok
81
}
82
83
func (s *server) getDocState(u uri.URI) (docState, bool) {
84
	s.mu.Lock()
85
	state, ok := s.openDocs[u]
86
	s.mu.Unlock()
87
	return state, ok
88
}
89
90
// parseJournalStr parses a raw journal string into an AST.
91
func parseJournalStr(content string) *ast.Journal {
92
	l := lexer.New("", []byte(content))
93
	p := parser.New(l)
94
	return p.ParseJournal()
95
}