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