1package app
2
3import (
4 "context"
5 "maps"
6 "time"
7
8 "github.com/charmbracelet/crush/internal/csync"
9 "github.com/charmbracelet/crush/internal/lsp"
10 "github.com/charmbracelet/crush/internal/pubsub"
11)
12
13// LSPEventType represents the type of LSP event
14type LSPEventType string
15
16const (
17 LSPEventStateChanged LSPEventType = "state_changed"
18 LSPEventDiagnosticsChanged LSPEventType = "diagnostics_changed"
19)
20
21// LSPEvent represents an event in the LSP system
22type LSPEvent struct {
23 Type LSPEventType
24 Name string
25 State lsp.ServerState
26 Error error
27 DiagnosticCount int
28}
29
30// LSPClientInfo holds information about an LSP client's state
31type LSPClientInfo struct {
32 Name string
33 State lsp.ServerState
34 Error error
35 Client *lsp.Client
36 DiagnosticCount int
37 ConnectedAt time.Time
38}
39
40var (
41 lspStates = csync.NewMap[string, LSPClientInfo]()
42 lspBroker = pubsub.NewBroker[LSPEvent]()
43)
44
45// SubscribeLSPEvents returns a channel for LSP events
46func SubscribeLSPEvents(ctx context.Context) <-chan pubsub.Event[LSPEvent] {
47 return lspBroker.Subscribe(ctx)
48}
49
50// GetLSPStates returns the current state of all LSP clients
51func GetLSPStates() map[string]LSPClientInfo {
52 return maps.Collect(lspStates.Seq2())
53}
54
55// GetLSPState returns the state of a specific LSP client
56func GetLSPState(name string) (LSPClientInfo, bool) {
57 return lspStates.Get(name)
58}
59
60// updateLSPState updates the state of an LSP client and publishes an event
61func updateLSPState(name string, state lsp.ServerState, err error, client *lsp.Client, diagnosticCount int) {
62 info := LSPClientInfo{
63 Name: name,
64 State: state,
65 Error: err,
66 Client: client,
67 DiagnosticCount: diagnosticCount,
68 }
69 if state == lsp.StateReady {
70 info.ConnectedAt = time.Now()
71 }
72 lspStates.Set(name, info)
73
74 // Publish state change event
75 lspBroker.Publish(pubsub.UpdatedEvent, LSPEvent{
76 Type: LSPEventStateChanged,
77 Name: name,
78 State: state,
79 Error: err,
80 DiagnosticCount: diagnosticCount,
81 })
82}
83
84// updateLSPDiagnostics updates the diagnostic count for an LSP client and publishes an event
85func updateLSPDiagnostics(name string, diagnosticCount int) {
86 if info, exists := lspStates.Get(name); exists {
87 info.DiagnosticCount = diagnosticCount
88 lspStates.Set(name, info)
89
90 // Publish diagnostics change event
91 lspBroker.Publish(pubsub.UpdatedEvent, LSPEvent{
92 Type: LSPEventDiagnosticsChanged,
93 Name: name,
94 State: info.State,
95 Error: info.Error,
96 DiagnosticCount: diagnosticCount,
97 })
98 }
99}