1package setup
2
3import (
4 "context"
5
6 "github.com/opencode-ai/opencode/internal/lsp/protocol"
7 "github.com/opencode-ai/opencode/internal/pubsub"
8)
9
10// LSPSetupEvent represents an event related to LSP setup
11type LSPSetupEvent struct {
12 Type LSPSetupEventType
13 Language protocol.LanguageKind
14 ServerName string
15 Success bool
16 Error error
17 Description string
18}
19
20// LSPSetupEventType defines the type of LSP setup event
21type LSPSetupEventType string
22
23const (
24 // EventLanguageDetected is emitted when a language is detected in the workspace
25 EventLanguageDetected LSPSetupEventType = "language_detected"
26 // EventServerDiscovered is emitted when an LSP server is discovered
27 EventServerDiscovered LSPSetupEventType = "server_discovered"
28 // EventServerInstalled is emitted when an LSP server is installed
29 EventServerInstalled LSPSetupEventType = "server_installed"
30 // EventServerInstallFailed is emitted when an LSP server installation fails
31 EventServerInstallFailed LSPSetupEventType = "server_install_failed"
32 // EventSetupCompleted is emitted when the LSP setup is completed
33 EventSetupCompleted LSPSetupEventType = "setup_completed"
34)
35
36// Service defines the interface for the LSP setup service
37type Service interface {
38 pubsub.Suscriber[LSPSetupEvent]
39
40 // DetectLanguages detects languages in the workspace
41 DetectLanguages(ctx context.Context, workspaceDir string) (map[protocol.LanguageKind]int, error)
42
43 // GetPrimaryLanguages returns the top N languages in the project
44 GetPrimaryLanguages(languages map[protocol.LanguageKind]int, limit int) []LanguageScore
45
46 // DetectMonorepo checks if the workspace is a monorepo
47 DetectMonorepo(ctx context.Context, workspaceDir string) (bool, []string)
48
49 // DiscoverInstalledLSPs discovers installed LSP servers
50 DiscoverInstalledLSPs(ctx context.Context) LSPServerMap
51
52 // GetRecommendedLSPServers returns recommended LSP servers for languages
53 GetRecommendedLSPServers(ctx context.Context, languages []LanguageScore) LSPServerMap
54
55 // InstallLSPServer installs an LSP server
56 InstallLSPServer(ctx context.Context, server LSPServerInfo) InstallationResult
57
58 // VerifyInstallation verifies that an LSP server is correctly installed
59 VerifyInstallation(ctx context.Context, serverName string) bool
60
61 // SaveConfiguration saves the LSP configuration
62 SaveConfiguration(ctx context.Context, servers map[protocol.LanguageKind]LSPServerInfo) error
63}
64
65type service struct {
66 *pubsub.Broker[LSPSetupEvent]
67}
68
69// NewService creates a new LSP setup service
70func NewService() Service {
71 broker := pubsub.NewBroker[LSPSetupEvent]()
72 return &service{
73 Broker: broker,
74 }
75}
76
77// DetectLanguages detects languages in the workspace
78func (s *service) DetectLanguages(ctx context.Context, workspaceDir string) (map[protocol.LanguageKind]int, error) {
79 languages, err := DetectProjectLanguages(workspaceDir)
80 if err != nil {
81 return nil, err
82 }
83
84 // Emit events for detected languages
85 for lang, score := range languages {
86 if lang != "" && score > 0 {
87 s.Publish(pubsub.CreatedEvent, LSPSetupEvent{
88 Type: EventLanguageDetected,
89 Language: lang,
90 Description: "Language detected in workspace",
91 })
92 }
93 }
94
95 return languages, nil
96}
97
98// GetPrimaryLanguages returns the top N languages in the project
99func (s *service) GetPrimaryLanguages(languages map[protocol.LanguageKind]int, limit int) []LanguageScore {
100 return GetPrimaryLanguages(languages, limit)
101}
102
103// DetectMonorepo checks if the workspace is a monorepo
104func (s *service) DetectMonorepo(ctx context.Context, workspaceDir string) (bool, []string) {
105 return DetectMonorepo(workspaceDir)
106}
107
108// DiscoverInstalledLSPs discovers installed LSP servers
109func (s *service) DiscoverInstalledLSPs(ctx context.Context) LSPServerMap {
110 servers := DiscoverInstalledLSPs()
111
112 // Emit events for discovered servers
113 for lang, serverList := range servers {
114 for _, server := range serverList {
115 s.Publish(pubsub.CreatedEvent, LSPSetupEvent{
116 Type: EventServerDiscovered,
117 Language: lang,
118 ServerName: server.Name,
119 Description: "LSP server discovered",
120 })
121 }
122 }
123
124 return servers
125}
126
127// GetRecommendedLSPServers returns recommended LSP servers for languages
128func (s *service) GetRecommendedLSPServers(ctx context.Context, languages []LanguageScore) LSPServerMap {
129 return GetRecommendedLSPServers(languages)
130}
131
132// InstallLSPServer installs an LSP server
133func (s *service) InstallLSPServer(ctx context.Context, server LSPServerInfo) InstallationResult {
134 result := InstallLSPServer(ctx, server)
135
136 // Emit event based on installation result
137 eventType := EventServerInstalled
138 if !result.Success {
139 eventType = EventServerInstallFailed
140 }
141
142 s.Publish(pubsub.CreatedEvent, LSPSetupEvent{
143 Type: eventType,
144 ServerName: server.Name,
145 Success: result.Success,
146 Error: result.Error,
147 Description: result.Output,
148 })
149
150 return result
151}
152
153// VerifyInstallation verifies that an LSP server is correctly installed
154func (s *service) VerifyInstallation(ctx context.Context, serverName string) bool {
155 return VerifyInstallation(serverName)
156}
157
158// SaveConfiguration saves the LSP configuration
159func (s *service) SaveConfiguration(ctx context.Context, servers map[protocol.LanguageKind]LSPServerInfo) error {
160 // Update the LSP configuration
161 err := UpdateLSPConfig(servers)
162
163 // Emit setup completed event
164 s.Publish(pubsub.CreatedEvent, LSPSetupEvent{
165 Type: EventSetupCompleted,
166 Success: err == nil,
167 Error: err,
168 Description: "LSP setup completed",
169 })
170
171 return err
172}