1package lsp
  2
  3import (
  4	"encoding/json"
  5
  6	"github.com/charmbracelet/crush/internal/config"
  7	"github.com/charmbracelet/crush/internal/logging"
  8	"github.com/charmbracelet/crush/internal/lsp/protocol"
  9	"github.com/charmbracelet/crush/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	cfg := 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 cfg.Options.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}