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