lsp_events.go

  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	return lspStates.Copy()
 52}
 53
 54// GetLSPState returns the state of a specific LSP client
 55func GetLSPState(name string) (LSPClientInfo, bool) {
 56	return lspStates.Get(name)
 57}
 58
 59// updateLSPState updates the state of an LSP client and publishes an event
 60func updateLSPState(name string, state lsp.ServerState, err error, client *lsp.Client, diagnosticCount int) {
 61	info := LSPClientInfo{
 62		Name:            name,
 63		State:           state,
 64		Error:           err,
 65		Client:          client,
 66		DiagnosticCount: diagnosticCount,
 67	}
 68	if state == lsp.StateReady {
 69		info.ConnectedAt = time.Now()
 70	} else if existing, ok := lspStates.Get(name); ok {
 71		info.ConnectedAt = existing.ConnectedAt
 72	}
 73	lspStates.Set(name, info)
 74
 75	// Publish state change event
 76	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 updateLSPDiagnostics(name string, diagnosticCount int) {
 87	if info, exists := lspStates.Get(name); exists {
 88		info.DiagnosticCount = diagnosticCount
 89		lspStates.Set(name, info)
 90
 91		// Publish diagnostics change event
 92		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}