1package lsp
2
3import (
4 "context"
5 "encoding/json"
6 "log/slog"
7
8 "github.com/charmbracelet/crush/internal/lsp/util"
9 "github.com/charmbracelet/x/powernap/pkg/lsp/protocol"
10)
11
12// HandleWorkspaceConfiguration handles workspace configuration requests
13func HandleWorkspaceConfiguration(_ context.Context, _ string, params json.RawMessage) (any, error) {
14 return []map[string]any{{}}, nil
15}
16
17// HandleRegisterCapability handles capability registration requests
18func HandleRegisterCapability(_ context.Context, _ string, params json.RawMessage) (any, error) {
19 var registerParams protocol.RegistrationParams
20 if err := json.Unmarshal(params, ®isterParams); err != nil {
21 slog.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 slog.Error("Error marshaling registration options", "error", err)
32 continue
33 }
34 var options protocol.DidChangeWatchedFilesRegistrationOptions
35 if err := json.Unmarshal(optionsJSON, &options); err != nil {
36 slog.Error("Error unmarshaling registration options", "error", err)
37 continue
38 }
39 // Store the file watchers registrations
40 notifyFileWatchRegistration(reg.ID, options.Watchers)
41 }
42 }
43 return nil, nil
44}
45
46// HandleApplyEdit handles workspace edit requests
47func HandleApplyEdit(_ context.Context, _ string, params json.RawMessage) (any, error) {
48 var edit protocol.ApplyWorkspaceEditParams
49 if err := json.Unmarshal(params, &edit); err != nil {
50 return nil, err
51 }
52
53 err := util.ApplyWorkspaceEdit(edit.Edit)
54 if err != nil {
55 slog.Error("Error applying workspace edit", "error", err)
56 return protocol.ApplyWorkspaceEditResult{Applied: false, FailureReason: err.Error()}, nil
57 }
58
59 return protocol.ApplyWorkspaceEditResult{Applied: true}, nil
60}
61
62// FileWatchRegistrationHandler is a function that will be called when file watch registrations are received
63type FileWatchRegistrationHandler func(id string, watchers []protocol.FileSystemWatcher)
64
65// fileWatchHandler holds the current handler for file watch registrations
66var fileWatchHandler FileWatchRegistrationHandler
67
68// RegisterFileWatchHandler sets the handler for file watch registrations
69func RegisterFileWatchHandler(handler FileWatchRegistrationHandler) {
70 fileWatchHandler = handler
71}
72
73// notifyFileWatchRegistration notifies the handler about new file watch registrations
74func notifyFileWatchRegistration(id string, watchers []protocol.FileSystemWatcher) {
75 if fileWatchHandler != nil {
76 fileWatchHandler(id, watchers)
77 }
78}
79
80// HandleServerMessage handles server messages
81func HandleServerMessage(_ context.Context, method string, params json.RawMessage) {
82 var msg protocol.ShowMessageParams
83 if err := json.Unmarshal(params, &msg); err != nil {
84 slog.Debug("Error unmarshal server message", "error", err)
85 return
86 }
87
88 switch msg.Type {
89 case protocol.Error:
90 slog.Error("LSP Server", "message", msg.Message)
91 case protocol.Warning:
92 slog.Warn("LSP Server", "message", msg.Message)
93 case protocol.Info:
94 slog.Info("LSP Server", "message", msg.Message)
95 case protocol.Log:
96 slog.Debug("LSP Server", "message", msg.Message)
97 }
98}
99
100// HandleDiagnostics handles diagnostic notifications from the LSP server
101func HandleDiagnostics(client *Client, params json.RawMessage) {
102 var diagParams protocol.PublishDiagnosticsParams
103 if err := json.Unmarshal(params, &diagParams); err != nil {
104 slog.Error("Error unmarshaling diagnostics params", "error", err)
105 return
106 }
107
108 client.diagnostics.Set(diagParams.URI, diagParams.Diagnostics)
109
110 // Calculate total diagnostic count
111 totalCount := 0
112 for _, diagnostics := range client.diagnostics.Seq2() {
113 totalCount += len(diagnostics)
114 }
115
116 // Trigger callback if set
117 if client.onDiagnosticsChanged != nil {
118 client.onDiagnosticsChanged(client.name, totalCount)
119 }
120}