lsp_events.go

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