lsp_events.go

  1package app
  2
  3import (
  4	"context"
  5	"sync"
  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	lspMutex  sync.RWMutex
 44)
 45
 46// SubscribeLSPEvents returns a channel for LSP events
 47func SubscribeLSPEvents(ctx context.Context) <-chan pubsub.Event[LSPEvent] {
 48	return lspBroker.Subscribe(ctx)
 49}
 50
 51// GetLSPStates returns the current state of all LSP clients
 52func GetLSPStates() map[string]LSPClientInfo {
 53	states := make(map[string]LSPClientInfo)
 54	for name, info := range lspStates.Seq2() {
 55		states[name] = info
 56	}
 57	return states
 58}
 59
 60// GetLSPState returns the state of a specific LSP client
 61func GetLSPState(name string) (LSPClientInfo, bool) {
 62	return lspStates.Get(name)
 63}
 64
 65// updateLSPState updates the state of an LSP client and publishes an event
 66func updateLSPState(name string, state lsp.ServerState, err error, client *lsp.Client, diagnosticCount int) {
 67	info := LSPClientInfo{
 68		Name:            name,
 69		State:           state,
 70		Error:           err,
 71		Client:          client,
 72		DiagnosticCount: diagnosticCount,
 73	}
 74	if state == lsp.StateReady {
 75		info.ConnectedAt = time.Now()
 76	}
 77	lspStates.Set(name, info)
 78
 79	// Publish state change event
 80	lspBroker.Publish(pubsub.UpdatedEvent, LSPEvent{
 81		Type:            LSPEventStateChanged,
 82		Name:            name,
 83		State:           state,
 84		Error:           err,
 85		DiagnosticCount: diagnosticCount,
 86	})
 87}
 88
 89// updateLSPDiagnostics updates the diagnostic count for an LSP client and publishes an event
 90func updateLSPDiagnostics(name string, diagnosticCount int) {
 91	if info, exists := lspStates.Get(name); exists {
 92		info.DiagnosticCount = diagnosticCount
 93		lspStates.Set(name, info)
 94
 95		// Publish diagnostics change event
 96		lspBroker.Publish(pubsub.UpdatedEvent, LSPEvent{
 97			Type:            LSPEventDiagnosticsChanged,
 98			Name:            name,
 99			State:           info.State,
100			Error:           info.Error,
101			DiagnosticCount: diagnosticCount,
102		})
103	}
104}