1package lsp
2
3import (
4 "encoding/json"
5
6 "github.com/opencode-ai/opencode/internal/config"
7 "github.com/opencode-ai/opencode/internal/logging"
8 "github.com/opencode-ai/opencode/internal/lsp/protocol"
9 "github.com/opencode-ai/opencode/internal/lsp/util"
10)
11
12// Requests
13
14func HandleWorkspaceConfiguration(params json.RawMessage) (any, error) {
15 return []map[string]any{{}}, nil
16}
17
18func HandleRegisterCapability(params json.RawMessage) (any, error) {
19 var registerParams protocol.RegistrationParams
20 if err := json.Unmarshal(params, ®isterParams); err != nil {
21 logging.Error("Error unmarshaling registration params", "error", err)
22 return nil, err
23 }
24
25 for _, reg := range registerParams.Registrations {
26 switch reg.Method {
27 case "workspace/didChangeWatchedFiles":
28 // Parse the registration options
29 optionsJSON, err := json.Marshal(reg.RegisterOptions)
30 if err != nil {
31 logging.Error("Error marshaling registration options", "error", err)
32 continue
33 }
34
35 var options protocol.DidChangeWatchedFilesRegistrationOptions
36 if err := json.Unmarshal(optionsJSON, &options); err != nil {
37 logging.Error("Error unmarshaling registration options", "error", err)
38 continue
39 }
40
41 // Store the file watchers registrations
42 notifyFileWatchRegistration(reg.ID, options.Watchers)
43 }
44 }
45
46 return nil, nil
47}
48
49func HandleApplyEdit(params json.RawMessage) (any, error) {
50 var edit protocol.ApplyWorkspaceEditParams
51 if err := json.Unmarshal(params, &edit); err != nil {
52 return nil, err
53 }
54
55 err := util.ApplyWorkspaceEdit(edit.Edit)
56 if err != nil {
57 logging.Error("Error applying workspace edit", "error", err)
58 return protocol.ApplyWorkspaceEditResult{Applied: false, FailureReason: err.Error()}, nil
59 }
60
61 return protocol.ApplyWorkspaceEditResult{Applied: true}, nil
62}
63
64// FileWatchRegistrationHandler is a function that will be called when file watch registrations are received
65type FileWatchRegistrationHandler func(id string, watchers []protocol.FileSystemWatcher)
66
67// fileWatchHandler holds the current handler for file watch registrations
68var fileWatchHandler FileWatchRegistrationHandler
69
70// RegisterFileWatchHandler sets the handler for file watch registrations
71func RegisterFileWatchHandler(handler FileWatchRegistrationHandler) {
72 fileWatchHandler = handler
73}
74
75// notifyFileWatchRegistration notifies the handler about new file watch registrations
76func notifyFileWatchRegistration(id string, watchers []protocol.FileSystemWatcher) {
77 if fileWatchHandler != nil {
78 fileWatchHandler(id, watchers)
79 }
80}
81
82// Notifications
83
84func HandleServerMessage(params json.RawMessage) {
85 cnf := config.Get()
86 var msg struct {
87 Type int `json:"type"`
88 Message string `json:"message"`
89 }
90 if err := json.Unmarshal(params, &msg); err == nil {
91 if cnf.DebugLSP {
92 logging.Debug("Server message", "type", msg.Type, "message", msg.Message)
93 }
94 }
95}
96
97func HandleDiagnostics(client *Client, params json.RawMessage) {
98 var diagParams protocol.PublishDiagnosticsParams
99 if err := json.Unmarshal(params, &diagParams); err != nil {
100 logging.Error("Error unmarshaling diagnostics params", "error", err)
101 return
102 }
103
104 client.diagnosticsMu.Lock()
105 defer client.diagnosticsMu.Unlock()
106
107 client.diagnostics[diagParams.URI] = diagParams.Diagnostics
108}