├── .gitignore ├── protocol_3_16 ├── telemetry.go ├── custom.go ├── trace.go ├── client.go ├── diagnostics.go ├── base-protocol.go ├── window.go ├── text-document-synchronization.go ├── workspace.go ├── handler.go └── base-structures.go ├── server ├── logging.go ├── run-nodejs.go ├── run-stdio.go ├── listener.go ├── run-tcp.go ├── serve.go ├── server.go ├── connections.go ├── run-websocket.go └── handler.go ├── common.go ├── go.mod ├── README.md ├── go.sum ├── protocol_3_17 ├── diagnostics.go ├── general-messages.go └── handler.go └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | go.work 3 | go.work.sum 4 | 5 | dist/ 6 | -------------------------------------------------------------------------------- /protocol_3_16/telemetry.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#telemetry_event 4 | 5 | const ServerTelemetryEvent = Method("telemetry/event") 6 | -------------------------------------------------------------------------------- /server/logging.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/tliron/commonlog" 7 | ) 8 | 9 | type JSONRPCLogger struct { 10 | log commonlog.Logger 11 | } 12 | 13 | // ([jsonrpc2.Logger] interface) 14 | func (self *JSONRPCLogger) Printf(format string, v ...any) { 15 | self.log.Debugf(strings.TrimSuffix(format, "\n"), v...) 16 | } 17 | -------------------------------------------------------------------------------- /protocol_3_16/custom.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/tliron/glsp" 7 | ) 8 | 9 | type CustomRequestHandler struct { 10 | Func CustomRequestFunc 11 | // This field should be private however it is used in both versions of the protocol 12 | Params json.RawMessage 13 | } 14 | 15 | type CustomRequestHandlers map[string]CustomRequestHandler 16 | 17 | type CustomRequestFunc func(context *glsp.Context, params json.RawMessage) (any, error) 18 | -------------------------------------------------------------------------------- /common.go: -------------------------------------------------------------------------------- 1 | package glsp 2 | 3 | import ( 4 | contextpkg "context" 5 | "encoding/json" 6 | ) 7 | 8 | type NotifyFunc func(method string, params any) 9 | type CallFunc func(method string, params any, result any) 10 | 11 | type Context struct { 12 | Method string 13 | Params json.RawMessage 14 | Notify NotifyFunc 15 | Call CallFunc 16 | Context contextpkg.Context // can be nil 17 | } 18 | 19 | type Handler interface { 20 | Handle(context *Context) (result any, validMethod bool, validParams bool, err error) 21 | } 22 | -------------------------------------------------------------------------------- /server/run-nodejs.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "errors" 5 | "os" 6 | "strconv" 7 | ) 8 | 9 | func (self *Server) RunNodeJs() error { 10 | nodeChannelFd := os.Getenv("NODE_CHANNEL_FD") 11 | if len(nodeChannelFd) == 0 { 12 | return errors.New("NODE_CHANNEL_FD not in environment") 13 | } 14 | nodeChannelFdInt, err := strconv.Atoi(nodeChannelFd) 15 | if err != nil { 16 | return err 17 | } 18 | file := os.NewFile(uintptr(nodeChannelFdInt), "/glsp/NODE_CHANNEL_FD") 19 | 20 | self.Log.Notice("listening for Node.js IPC connections") 21 | self.ServeStream(file, nil) 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /server/run-stdio.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "errors" 5 | "os" 6 | ) 7 | 8 | func (self *Server) RunStdio() error { 9 | self.Log.Notice("reading from stdin, writing to stdout") 10 | self.ServeStream(Stdio{}, nil) 11 | return nil 12 | } 13 | 14 | type Stdio struct{} 15 | 16 | // ([io.Reader] interface) 17 | func (Stdio) Read(p []byte) (int, error) { 18 | return os.Stdin.Read(p) 19 | } 20 | 21 | // ([io.Writer] interface) 22 | func (Stdio) Write(p []byte) (int, error) { 23 | return os.Stdout.Write(p) 24 | } 25 | 26 | // ([io.Closer] interface) 27 | func (Stdio) Close() error { 28 | return errors.Join(os.Stdin.Close(), os.Stdout.Close()) 29 | } 30 | -------------------------------------------------------------------------------- /server/listener.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "crypto/tls" 5 | "net" 6 | "os" 7 | ) 8 | 9 | func (self *Server) newNetworkListener(network string, address string) (*net.Listener, error) { 10 | listener, err := net.Listen(network, address) 11 | if err != nil { 12 | self.Log.Criticalf("could not bind to address %s: %v", address, err) 13 | return nil, err 14 | } 15 | 16 | cert := os.Getenv("TLS_CERT") 17 | key := os.Getenv("TLS_KEY") 18 | if (cert != "") && (key != "") { 19 | cert, err := tls.X509KeyPair([]byte(cert), []byte(key)) 20 | if err != nil { 21 | return nil, err 22 | } 23 | listener = tls.NewListener(listener, &tls.Config{ 24 | Certificates: []tls.Certificate{cert}, 25 | }) 26 | } 27 | 28 | return &listener, nil 29 | } 30 | -------------------------------------------------------------------------------- /server/run-tcp.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "github.com/tliron/commonlog" 5 | ) 6 | 7 | func (self *Server) RunTCP(address string) error { 8 | listener, err := self.newNetworkListener("tcp", address) 9 | if err != nil { 10 | return err 11 | } 12 | 13 | log := commonlog.NewKeyValueLogger(self.Log, "address", address) 14 | defer commonlog.CallAndLogError((*listener).Close, "listener.Close", log) 15 | log.Notice("listening for TCP connections") 16 | 17 | var connectionCount uint64 18 | 19 | for { 20 | connection, err := (*listener).Accept() 21 | if err != nil { 22 | return err 23 | } 24 | 25 | connectionCount++ 26 | connectionLog := commonlog.NewKeyValueLogger(log, "id", connectionCount) 27 | 28 | go self.ServeStream(connection, connectionLog) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /server/serve.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/gorilla/websocket" 7 | "github.com/tliron/commonlog" 8 | ) 9 | 10 | // See: https://github.com/sourcegraph/go-langserver/blob/master/main.go#L179 11 | 12 | func (self *Server) ServeStream(stream io.ReadWriteCloser, log commonlog.Logger) { 13 | if log == nil { 14 | log = self.Log 15 | } 16 | log.Info("new stream connection") 17 | <-self.newStreamConnection(stream).DisconnectNotify() 18 | log.Info("stream connection closed") 19 | } 20 | 21 | func (self *Server) ServeWebSocket(socket *websocket.Conn, log commonlog.Logger) { 22 | if log == nil { 23 | log = self.Log 24 | } 25 | log.Info("new web socket connection") 26 | <-self.newWebSocketConnection(socket).DisconnectNotify() 27 | log.Info("web socket connection closed") 28 | } 29 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tliron/glsp 2 | 3 | go 1.22 4 | 5 | require ( 6 | github.com/gorilla/websocket v1.5.3 7 | github.com/pkg/errors v0.9.1 8 | github.com/sourcegraph/jsonrpc2 v0.2.0 9 | github.com/tliron/commonlog v0.2.18 10 | ) 11 | 12 | require ( 13 | github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect 14 | github.com/iancoleman/strcase v0.3.0 // indirect 15 | github.com/lucasb-eyer/go-colorful v1.2.0 // indirect 16 | github.com/mattn/go-isatty v0.0.20 // indirect 17 | github.com/mattn/go-runewidth v0.0.14 // indirect 18 | github.com/muesli/termenv v0.15.2 // indirect 19 | github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect 20 | github.com/rivo/uniseg v0.2.0 // indirect 21 | github.com/sasha-s/go-deadlock v0.3.1 // indirect 22 | github.com/segmentio/ksuid v1.0.4 // indirect 23 | github.com/tliron/kutil v0.3.25 // indirect 24 | golang.org/x/crypto v0.26.0 // indirect 25 | golang.org/x/sys v0.23.0 // indirect 26 | golang.org/x/term v0.23.0 // indirect 27 | ) 28 | -------------------------------------------------------------------------------- /server/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/tliron/commonlog" 7 | "github.com/tliron/glsp" 8 | ) 9 | 10 | var DefaultTimeout = time.Minute 11 | 12 | // 13 | // Server 14 | // 15 | 16 | type Server struct { 17 | Handler glsp.Handler 18 | LogBaseName string 19 | Debug bool 20 | 21 | Log commonlog.Logger 22 | Timeout time.Duration 23 | ReadTimeout time.Duration 24 | WriteTimeout time.Duration 25 | StreamTimeout time.Duration 26 | WebSocketTimeout time.Duration 27 | } 28 | 29 | func NewServer(handler glsp.Handler, logName string, debug bool) *Server { 30 | return &Server{ 31 | Handler: handler, 32 | LogBaseName: logName, 33 | Debug: debug, 34 | Log: commonlog.GetLogger(logName), 35 | Timeout: DefaultTimeout, 36 | ReadTimeout: DefaultTimeout, 37 | WriteTimeout: DefaultTimeout, 38 | StreamTimeout: DefaultTimeout, 39 | WebSocketTimeout: DefaultTimeout, 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /server/connections.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | contextpkg "context" 5 | "io" 6 | 7 | "github.com/gorilla/websocket" 8 | "github.com/sourcegraph/jsonrpc2" 9 | wsjsonrpc2 "github.com/sourcegraph/jsonrpc2/websocket" 10 | "github.com/tliron/commonlog" 11 | ) 12 | 13 | func (self *Server) newStreamConnection(stream io.ReadWriteCloser) *jsonrpc2.Conn { 14 | handler := self.newHandler() 15 | connectionOptions := self.newConnectionOptions() 16 | 17 | context, cancel := contextpkg.WithTimeout(contextpkg.Background(), self.StreamTimeout) 18 | defer cancel() 19 | 20 | return jsonrpc2.NewConn(context, jsonrpc2.NewBufferedStream(stream, jsonrpc2.VSCodeObjectCodec{}), handler, connectionOptions...) 21 | } 22 | 23 | func (self *Server) newWebSocketConnection(socket *websocket.Conn) *jsonrpc2.Conn { 24 | handler := self.newHandler() 25 | connectionOptions := self.newConnectionOptions() 26 | 27 | context, cancel := contextpkg.WithTimeout(contextpkg.Background(), self.WebSocketTimeout) 28 | defer cancel() 29 | 30 | return jsonrpc2.NewConn(context, wsjsonrpc2.NewObjectStream(socket), handler, connectionOptions...) 31 | } 32 | 33 | func (self *Server) newConnectionOptions() []jsonrpc2.ConnOpt { 34 | if self.Debug { 35 | log := commonlog.NewScopeLogger(self.Log, "rpc") 36 | return []jsonrpc2.ConnOpt{jsonrpc2.LogMessages(&JSONRPCLogger{log})} 37 | } else { 38 | return nil 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /server/run-websocket.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "net/http" 5 | "sync/atomic" 6 | 7 | "github.com/gorilla/websocket" 8 | "github.com/pkg/errors" 9 | "github.com/tliron/commonlog" 10 | ) 11 | 12 | func (self *Server) RunWebSocket(address string) error { 13 | mux := http.NewServeMux() 14 | upgrader := websocket.Upgrader{CheckOrigin: func(request *http.Request) bool { return true }} 15 | 16 | var connectionCount uint64 17 | 18 | mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { 19 | connection, err := upgrader.Upgrade(writer, request, nil) 20 | if err != nil { 21 | self.Log.Warningf("error upgrading HTTP to web socket: %s", err.Error()) 22 | http.Error(writer, errors.Wrap(err, "could not upgrade to web socket").Error(), http.StatusBadRequest) 23 | return 24 | } 25 | 26 | log := commonlog.NewKeyValueLogger(self.Log, "id", atomic.AddUint64(&connectionCount, 1)) 27 | defer commonlog.CallAndLogError(connection.Close, "connection.Close", log) 28 | self.ServeWebSocket(connection, log) 29 | }) 30 | 31 | listener, err := self.newNetworkListener("tcp", address) 32 | if err != nil { 33 | return err 34 | } 35 | 36 | server := http.Server{ 37 | Handler: http.TimeoutHandler(mux, self.Timeout, ""), 38 | ReadTimeout: self.ReadTimeout, 39 | WriteTimeout: self.WriteTimeout, 40 | } 41 | 42 | self.Log.Notice("listening for web socket connections", "address", address) 43 | err = server.Serve(*listener) 44 | return errors.Wrap(err, "WebSocket") 45 | } 46 | -------------------------------------------------------------------------------- /protocol_3_16/trace.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | 7 | "github.com/tliron/glsp" 8 | ) 9 | 10 | var traceValue TraceValue = TraceValueOff 11 | var traceValueLock sync.Mutex 12 | 13 | func GetTraceValue() TraceValue { 14 | traceValueLock.Lock() 15 | defer traceValueLock.Unlock() 16 | return traceValue 17 | } 18 | 19 | func SetTraceValue(value TraceValue) { 20 | traceValueLock.Lock() 21 | defer traceValueLock.Unlock() 22 | 23 | // The spec clearly says "message", but some implementations use "messages" instead 24 | if value == "messages" { 25 | value = TraceValueMessage 26 | } 27 | 28 | traceValue = value 29 | } 30 | 31 | func HasTraceLevel(value TraceValue) bool { 32 | value_ := GetTraceValue() 33 | switch value_ { 34 | case TraceValueOff: 35 | return false 36 | 37 | case TraceValueMessage: 38 | return value == TraceValueMessage 39 | 40 | case TraceValueVerbose: 41 | return true 42 | 43 | default: 44 | panic(fmt.Sprintf("unsupported trace level: %s", value_)) 45 | } 46 | } 47 | 48 | func HasTraceMessageType(type_ MessageType) bool { 49 | switch type_ { 50 | case MessageTypeError, MessageTypeWarning, MessageTypeInfo: 51 | return HasTraceLevel(TraceValueMessage) 52 | 53 | case MessageTypeLog: 54 | return HasTraceLevel(TraceValueVerbose) 55 | 56 | default: 57 | panic(fmt.Sprintf("unsupported message type: %d", type_)) 58 | } 59 | } 60 | 61 | func Trace(context *glsp.Context, type_ MessageType, message string) error { 62 | if HasTraceMessageType(type_) { 63 | go context.Notify(ServerWindowLogMessage, &LogMessageParams{ 64 | Type: type_, 65 | Message: message, 66 | }) 67 | } 68 | return nil 69 | } 70 | -------------------------------------------------------------------------------- /protocol_3_16/client.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#client_registerCapability 4 | 5 | /** 6 | * General parameters to register for a capability. 7 | */ 8 | type Registration struct { 9 | /** 10 | * The id used to register the request. The id can be used to deregister 11 | * the request again. 12 | */ 13 | ID string `json:"id"` 14 | 15 | /** 16 | * The method / capability to register for. 17 | */ 18 | Method string `json:"method"` 19 | 20 | /** 21 | * Options necessary for the registration. 22 | */ 23 | RegisterOptions any `json:"registerOptions,omitempty"` 24 | } 25 | 26 | const ServerClientRegisterCapability = Method("client/registerCapability") 27 | 28 | type RegistrationParams struct { 29 | Registrations []Registration `json:"registrations"` 30 | } 31 | 32 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#client_unregisterCapability 33 | 34 | /** 35 | * General parameters to unregister a capability. 36 | */ 37 | type Unregistration struct { 38 | /** 39 | * The id used to unregister the request or notification. Usually an id 40 | * provided during the register request. 41 | */ 42 | ID string `json:"id"` 43 | 44 | /** 45 | * The method / capability to unregister for. 46 | */ 47 | Method string `json:"method"` 48 | } 49 | 50 | const ServerClientUnregisterCapability = Method("client/unregisterCapability") 51 | 52 | type UnregistrationParams struct { 53 | // This should correctly be named `unregistrations`. However changing this 54 | // is a breaking change and needs to wait until we deliver a 4.x version 55 | // of the specification. 56 | Unregisterations []Unregistration `json:"unregisterations"` 57 | } 58 | -------------------------------------------------------------------------------- /protocol_3_16/diagnostics.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocument_publishDiagnostics 4 | 5 | type PublishDiagnosticsClientCapabilities struct { 6 | /** 7 | * Whether the clients accepts diagnostics with related information. 8 | */ 9 | RelatedInformation *bool `json:"relatedInformation,omitempty"` 10 | 11 | /** 12 | * Client supports the tag property to provide meta data about a diagnostic. 13 | * Clients supporting tags have to handle unknown tags gracefully. 14 | * 15 | * @since 3.15.0 16 | */ 17 | TagSupport *struct { 18 | /** 19 | * The tags supported by the client. 20 | */ 21 | ValueSet []DiagnosticTag `json:"valueSet"` 22 | } `json:"tagSupport,omitempty"` 23 | 24 | /** 25 | * Whether the client interprets the version property of the 26 | * `textDocument/publishDiagnostics` notification's parameter. 27 | * 28 | * @since 3.15.0 29 | */ 30 | VersionSupport *bool `json:"versionSupport,omitempty"` 31 | 32 | /** 33 | * Client supports a codeDescription property 34 | * 35 | * @since 3.16.0 36 | */ 37 | CodeDescriptionSupport *bool `json:"codeDescriptionSupport,omitempty"` 38 | 39 | /** 40 | * Whether code action supports the `data` property which is 41 | * preserved between a `textDocument/publishDiagnostics` and 42 | * `textDocument/codeAction` request. 43 | * 44 | * @since 3.16.0 45 | */ 46 | DataSupport *bool `json:"dataSupport,omitempty"` 47 | } 48 | 49 | const ServerTextDocumentPublishDiagnostics = Method("textDocument/publishDiagnostics") 50 | 51 | type PublishDiagnosticsParams struct { 52 | /** 53 | * The URI for which diagnostic information is reported. 54 | */ 55 | URI DocumentUri `json:"uri"` 56 | 57 | /** 58 | * Optional the version number of the document the diagnostics are published 59 | * for. 60 | * 61 | * @since 3.15.0 62 | */ 63 | Version *UInteger `json:"version,omitempty"` 64 | 65 | /** 66 | * An array of diagnostic information items. 67 | */ 68 | Diagnostics []Diagnostic `json:"diagnostics"` 69 | } 70 | -------------------------------------------------------------------------------- /server/handler.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | contextpkg "context" 5 | "fmt" 6 | 7 | "github.com/sourcegraph/jsonrpc2" 8 | "github.com/tliron/glsp" 9 | ) 10 | 11 | // See: https://github.com/sourcegraph/go-langserver/blob/master/langserver/handler.go#L206 12 | 13 | func (self *Server) newHandler() jsonrpc2.Handler { 14 | return jsonrpc2.HandlerWithError(self.handle) 15 | } 16 | 17 | func (self *Server) handle(context contextpkg.Context, connection *jsonrpc2.Conn, request *jsonrpc2.Request) (any, error) { 18 | glspContext := glsp.Context{ 19 | Method: request.Method, 20 | Notify: func(method string, params any) { 21 | if err := connection.Notify(context, method, params); err != nil { 22 | self.Log.Error(err.Error()) 23 | } 24 | }, 25 | Call: func(method string, params any, result any) { 26 | if err := connection.Call(context, method, params, result); err != nil { 27 | self.Log.Error(err.Error()) 28 | } 29 | }, 30 | Context: context, 31 | } 32 | 33 | if request.Params != nil { 34 | glspContext.Params = *request.Params 35 | } 36 | 37 | switch request.Method { 38 | case "exit": 39 | // We're giving the attached handler a chance to handle it first, but we'll ignore any result 40 | self.Handler.Handle(&glspContext) 41 | err := connection.Close() 42 | return nil, err 43 | 44 | default: 45 | // Note: jsonrpc2 will not even call this function if reqest.Params is invalid JSON, 46 | // so we don't need to handle jsonrpc2.CodeParseError here 47 | result, validMethod, validParams, err := self.Handler.Handle(&glspContext) 48 | if !validMethod { 49 | return nil, &jsonrpc2.Error{ 50 | Code: jsonrpc2.CodeMethodNotFound, 51 | Message: fmt.Sprintf("method not supported: %s", request.Method), 52 | } 53 | } else if !validParams { 54 | if err == nil { 55 | return nil, &jsonrpc2.Error{ 56 | Code: jsonrpc2.CodeInvalidParams, 57 | } 58 | } else { 59 | return nil, &jsonrpc2.Error{ 60 | Code: jsonrpc2.CodeInvalidParams, 61 | Message: err.Error(), 62 | } 63 | } 64 | } else if err != nil { 65 | return nil, &jsonrpc2.Error{ 66 | Code: jsonrpc2.CodeInvalidRequest, 67 | Message: err.Error(), 68 | } 69 | } else { 70 | return result, nil 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | *This is an early release. Some features are not yet fully implemented.* 2 | 3 | GLSP 4 | ==== 5 | 6 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 7 | [![Go Reference](https://pkg.go.dev/badge/github.com/tliron/glsp.svg)](https://pkg.go.dev/github.com/tliron/kutglspil) 8 | [![Go Report Card](https://goreportcard.com/badge/github.com/tliron/glsp)](https://goreportcard.com/report/github.com/tliron/glsp) 9 | 10 | [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) SDK for Go. 11 | 12 | It enables you to more easily implement language servers by writing them in Go. GLSP contains: 13 | 14 | 1) all the message structures for easy serialization, 15 | 2) a handler for all client methods, and 16 | 3) a ready-to-run JSON-RPC 2.0 server supporting stdio, TCP, WebSockets, and Node.js IPC. 17 | 18 | All you need to do, then, is provide the features for the language you want to support. 19 | 20 | Projects using GLSP: 21 | 22 | * [Puccini TOSCA Language Server](https://github.com/tliron/puccini-language-server) 23 | * [zk](https://github.com/mickael-menu/zk) 24 | 25 | 26 | References 27 | ---------- 28 | 29 | * [go-lsp](https://github.com/sourcegraph/go-lsp) is another implementation with reduced coverage of the protocol 30 | 31 | 32 | Minimal Example 33 | --------------- 34 | 35 | ```go 36 | package main 37 | 38 | import ( 39 | "github.com/tliron/glsp" 40 | protocol "github.com/tliron/glsp/protocol_3_16" 41 | "github.com/tliron/glsp/server" 42 | "github.com/tliron/commonlog" 43 | 44 | // Must include a backend implementation 45 | // See CommonLog for other options: https://github.com/tliron/commonlog 46 | _ "github.com/tliron/commonlog/simple" 47 | ) 48 | 49 | const lsName = "my language" 50 | 51 | var ( 52 | version string = "0.0.1" 53 | handler protocol.Handler 54 | ) 55 | 56 | func main() { 57 | // This increases logging verbosity (optional) 58 | commonlog.Configure(1, nil) 59 | 60 | handler = protocol.Handler{ 61 | Initialize: initialize, 62 | Initialized: initialized, 63 | Shutdown: shutdown, 64 | SetTrace: setTrace, 65 | } 66 | 67 | server := server.NewServer(&handler, lsName, false) 68 | 69 | server.RunStdio() 70 | } 71 | 72 | func initialize(context *glsp.Context, params *protocol.InitializeParams) (any, error) { 73 | capabilities := handler.CreateServerCapabilities() 74 | 75 | return protocol.InitializeResult{ 76 | Capabilities: capabilities, 77 | ServerInfo: &protocol.InitializeResultServerInfo{ 78 | Name: lsName, 79 | Version: &version, 80 | }, 81 | }, nil 82 | } 83 | 84 | func initialized(context *glsp.Context, params *protocol.InitializedParams) error { 85 | return nil 86 | } 87 | 88 | func shutdown(context *glsp.Context) error { 89 | protocol.SetTraceValue(protocol.TraceValueOff) 90 | return nil 91 | } 92 | 93 | func setTrace(context *glsp.Context, params *protocol.SetTraceParams) error { 94 | protocol.SetTraceValue(params.Value) 95 | return nil 96 | } 97 | ``` 98 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= 2 | github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= 3 | github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 4 | github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= 5 | github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 6 | github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= 7 | github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= 8 | github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= 9 | github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= 10 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 11 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 12 | github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= 13 | github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 14 | github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= 15 | github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= 16 | github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= 17 | github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= 18 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 19 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 20 | github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= 21 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 22 | github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= 23 | github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= 24 | github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= 25 | github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= 26 | github.com/sourcegraph/jsonrpc2 v0.2.0 h1:KjN/dC4fP6aN9030MZCJs9WQbTOjWHhrtKVpzzSrr/U= 27 | github.com/sourcegraph/jsonrpc2 v0.2.0/go.mod h1:ZafdZgk/axhT1cvZAPOhw+95nz2I/Ra5qMlU4gTRwIo= 28 | github.com/tliron/commonlog v0.2.18 h1:F0zY09VDGTasPCpP9KvE8xqqVNMUfwMJQ0Xvo5Y6BRs= 29 | github.com/tliron/commonlog v0.2.18/go.mod h1:7f3OMSgVyGAFbRKwlvfUErnB6U75LgW8wa6NlWuswGg= 30 | github.com/tliron/kutil v0.3.25 h1:oaPN6K0zsH3KcVnsocA3kAlfR0XYDzADob6xdjqe56k= 31 | github.com/tliron/kutil v0.3.25/go.mod h1:ZvOJuF6PTGvjfHmn2dFcgz+EDEzRQqQUztK+7djlXIw= 32 | golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= 33 | golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= 34 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 35 | golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= 36 | golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 37 | golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= 38 | golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= 39 | -------------------------------------------------------------------------------- /protocol_3_16/base-protocol.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "encoding/json" 5 | "strconv" 6 | 7 | "github.com/tliron/glsp" 8 | ) 9 | 10 | var True bool = true 11 | var False bool = false 12 | 13 | type Method = string 14 | 15 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#number 16 | 17 | /** 18 | * Defines an integer number in the range of -2^31 to 2^31 - 1. 19 | */ 20 | type Integer = int32 21 | 22 | /** 23 | * Defines an unsigned integer number in the range of 0 to 2^31 - 1. 24 | */ 25 | type UInteger = uint32 26 | 27 | /** 28 | * Defines a decimal number. Since decimal numbers are very 29 | * rare in the language server specification we denote the 30 | * exact range with every decimal using the mathematics 31 | * interval notation (e.g. [0, 1] denotes all decimals d with 32 | * 0 <= d <= 1. 33 | */ 34 | type Decimal = float32 35 | 36 | type IntegerOrString struct { 37 | Value any // Integer | string 38 | } 39 | 40 | // ([json.Marshaler] interface) 41 | func (self *IntegerOrString) MarshalJSON() ([]byte, error) { 42 | return json.Marshal(self.Value) 43 | } 44 | 45 | // ([json.Unmarshaler] interface) 46 | func (self *IntegerOrString) UnmarshalJSON(data []byte) error { 47 | var value Integer 48 | if err := json.Unmarshal(data, &value); err == nil { 49 | self.Value = value 50 | return nil 51 | } else { 52 | var value string 53 | if err := json.Unmarshal(data, &value); err == nil { 54 | self.Value = value 55 | return nil 56 | } else { 57 | return err 58 | } 59 | } 60 | } 61 | 62 | type BoolOrString struct { 63 | Value any // bool | string 64 | } 65 | 66 | // ([json.Marshaler] interface) 67 | func (self BoolOrString) MarshalJSON() ([]byte, error) { 68 | return json.Marshal(self.Value) 69 | } 70 | 71 | // ([json.Unmarshaler] interface) 72 | func (self BoolOrString) UnmarshalJSON(data []byte) error { 73 | var value bool 74 | if err := json.Unmarshal(data, &value); err == nil { 75 | self.Value = value 76 | return nil 77 | } else { 78 | var value string 79 | if err := json.Unmarshal(data, &value); err == nil { 80 | self.Value = value 81 | return nil 82 | } else { 83 | return err 84 | } 85 | } 86 | } 87 | 88 | // ([fmt.Stringer] interface) 89 | func (self BoolOrString) String() string { 90 | if value, ok := self.Value.(bool); ok { 91 | return strconv.FormatBool(value) 92 | } else { 93 | return self.Value.(string) 94 | } 95 | } 96 | 97 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#cancelRequest 98 | 99 | const MethodCancelRequest = Method("$/cancelRequest") 100 | 101 | type CancelRequestFunc func(context *glsp.Context, params *CancelParams) error 102 | 103 | type CancelParams struct { 104 | /** 105 | * The request id to cancel. 106 | */ 107 | ID IntegerOrString `json:"id"` 108 | } 109 | 110 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#progress 111 | 112 | const MethodProgress = Method("$/progress") 113 | 114 | type ProgressFunc func(context *glsp.Context, params *ProgressParams) error 115 | 116 | type ProgressParams struct { 117 | /** 118 | * The progress token provided by the client or server. 119 | */ 120 | Token ProgressToken `json:"token"` 121 | 122 | /** 123 | * The progress data. 124 | */ 125 | Value any `json:"value"` 126 | } 127 | 128 | type ProgressToken = IntegerOrString 129 | -------------------------------------------------------------------------------- /protocol_3_16/window.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import "github.com/tliron/glsp" 4 | 5 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#window_showMessage 6 | 7 | const ServerWindowShowMessage = Method("window/showMessage") 8 | 9 | type ShowMessageParams struct { 10 | /** 11 | * The message type. See {@link MessageType}. 12 | */ 13 | Type MessageType `json:"type"` 14 | 15 | /** 16 | * The actual message. 17 | */ 18 | Message string `json:"message"` 19 | } 20 | 21 | type MessageType Integer 22 | 23 | const ( 24 | /** 25 | * An error message. 26 | */ 27 | MessageTypeError = MessageType(1) 28 | 29 | /** 30 | * A warning message. 31 | */ 32 | MessageTypeWarning = MessageType(2) 33 | 34 | /** 35 | * An information message. 36 | */ 37 | MessageTypeInfo = MessageType(3) 38 | 39 | /** 40 | * A log message. 41 | */ 42 | MessageTypeLog = MessageType(4) 43 | ) 44 | 45 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#window_showMessageRequest 46 | 47 | type ShowMessageRequestClientCapabilities struct { 48 | /** 49 | * Capabilities specific to the `MessageActionItem` type. 50 | */ 51 | MessageActionItem *struct { 52 | /** 53 | * Whether the client supports additional attributes which 54 | * are preserved and sent back to the server in the 55 | * request's response. 56 | */ 57 | AdditionalPropertiesSupport *bool `json:"additionalPropertiesSupport,omitempty"` 58 | } `json:"messageActionItem,omitempty"` 59 | } 60 | 61 | const ServerWindowShowMessageRequest = Method("window/showMessageRequest") 62 | 63 | type ShowMessageRequestParams struct { 64 | /** 65 | * The message type. See {@link MessageType} 66 | */ 67 | Type MessageType `json:"type"` 68 | 69 | /** 70 | * The actual message 71 | */ 72 | Message string `json:"message"` 73 | 74 | /** 75 | * The message action items to present. 76 | */ 77 | Actions []MessageActionItem `json:"actions,omitempty"` 78 | } 79 | 80 | type MessageActionItem struct { 81 | /** 82 | * A short title like 'Retry', 'Open Log' etc. 83 | */ 84 | Title string `json:"title"` 85 | } 86 | 87 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#window_showDocument 88 | 89 | /** 90 | * Client capabilities for the show document request. 91 | * 92 | * @since 3.16.0 93 | */ 94 | type ShowDocumentClientCapabilities struct { 95 | /** 96 | * The client has support for the show document 97 | * request. 98 | */ 99 | Support bool `json:"support"` 100 | } 101 | 102 | const ServerWindowShowDocument = Method("window/showDocument") 103 | 104 | /** 105 | * Params to show a document. 106 | * 107 | * @since 3.16.0 108 | */ 109 | type ShowDocumentParams struct { 110 | /** 111 | * The document uri to show. 112 | */ 113 | URI URI `json:"uri"` 114 | 115 | /** 116 | * Indicates to show the resource in an external program. 117 | * To show for example `https://code.visualstudio.com/` 118 | * in the default WEB browser set `external` to `true`. 119 | */ 120 | External *bool `json:"external,omitempty"` 121 | 122 | /** 123 | * An optional property to indicate whether the editor 124 | * showing the document should take focus or not. 125 | * Clients might ignore this property if an external 126 | * program is started. 127 | */ 128 | TakeFocus *bool `json:"takeFocus,omitempty"` 129 | 130 | /** 131 | * An optional selection range if the document is a text 132 | * document. Clients might ignore the property if an 133 | * external program is started or the file is not a text 134 | * file. 135 | */ 136 | Selection *Range `json:"selection,omitempty"` 137 | } 138 | 139 | /** 140 | * The result of an show document request. 141 | * 142 | * @since 3.16.0 143 | */ 144 | type ShowDocumentResult struct { 145 | /** 146 | * A boolean indicating if the show was successful. 147 | */ 148 | Success bool `json:"success"` 149 | } 150 | 151 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#window_logMessage 152 | 153 | const ServerWindowLogMessage = Method("window/logMessage") 154 | 155 | type LogMessageParams struct { 156 | /** 157 | * The message type. See {@link MessageType} 158 | */ 159 | Type MessageType `json:"type"` 160 | 161 | /** 162 | * The actual message 163 | */ 164 | Message string `json:"message"` 165 | } 166 | 167 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#window_workDoneProgress_create 168 | 169 | const ServerWindowWorkDoneProgressCreate = Method("window/workDoneProgress/create") 170 | 171 | type WorkDoneProgressCreateParams struct { 172 | /** 173 | * The token to be used to report progress. 174 | */ 175 | Token ProgressToken `json:"token"` 176 | } 177 | 178 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#window_workDoneProgress_cancel 179 | 180 | const MethodWindowWorkDoneProgressCancel = Method("window/workDoneProgress/cancel") 181 | 182 | type WindowWorkDoneProgressCancelFunc func(context *glsp.Context, params *WorkDoneProgressCancelParams) error 183 | 184 | type WorkDoneProgressCancelParams struct { 185 | /** 186 | * The token to be used to report progress. 187 | */ 188 | Token ProgressToken `json:"token"` 189 | } 190 | -------------------------------------------------------------------------------- /protocol_3_17/diagnostics.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "github.com/tliron/glsp" 5 | protocol316 "github.com/tliron/glsp/protocol_3_16" 6 | ) 7 | 8 | /** 9 | * Client capabilities specific to diagnostic pull requests. 10 | * 11 | * @since 3.17.0 12 | */ 13 | type DiagnosticClientCapabilities struct { 14 | /** 15 | * Whether implementation supports dynamic registration. If this is set to 16 | * `true` the client supports the new 17 | * `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` 18 | * return value for the corresponding server capability as well. 19 | */ 20 | DynamicRegistration bool `json:"dynamicRegistration"` 21 | 22 | /** 23 | * Whether the clients supports related documents for document diagnostic 24 | * pulls. 25 | */ 26 | RelatedDocumentSupport bool `json:"relatedDocumentSupport"` 27 | } 28 | 29 | /** 30 | * Diagnostic options. 31 | * 32 | * @since 3.17.0 33 | */ 34 | type DiagnosticOptions struct { 35 | protocol316.WorkDoneProgressOptions 36 | /** 37 | * An optional identifier under which the diagnostics are 38 | * managed by the client. 39 | */ 40 | Identifier *string `json:"identifier"` 41 | 42 | /** 43 | * Whether the language has inter file dependencies meaning that 44 | * editing code in one file can result in a different diagnostic 45 | * set in another file. Inter file dependencies are common for 46 | * most programming languages and typically uncommon for linters. 47 | */ 48 | InterFileDependencies bool `json:"interFileDependencies"` 49 | 50 | /** 51 | * The server provides support for workspace diagnostics as well. 52 | */ 53 | WorkspaceDiagnostics bool `json:"workspaceDiagnostics"` 54 | } 55 | 56 | /** 57 | * Diagnostic registration options. 58 | * 59 | * @since 3.17.0 60 | */ 61 | type DiagnosticRegistrationOptions struct { 62 | protocol316.TextDocumentRegistrationOptions 63 | DiagnosticOptions 64 | protocol316.StaticRegistrationOptions 65 | } 66 | 67 | const MethodTextDocumentDiagnostic = protocol316.Method("textDocument/diagnostic") 68 | 69 | type TextDocumentDiagnosticFunc func(context *glsp.Context, params *DocumentDiagnosticParams) (any, error) 70 | 71 | /** 72 | * Parameters of the document diagnostic request. 73 | * 74 | * @since 3.17.0 75 | */ 76 | type DocumentDiagnosticParams struct { 77 | protocol316.WorkDoneProgressParams 78 | protocol316.PartialResultParams 79 | 80 | /** 81 | * The text document. 82 | */ 83 | TextDocument protocol316.TextDocumentIdentifier `json:"textDocument"` 84 | 85 | /** 86 | * The additional identifier provided during registration. 87 | */ 88 | Identifier *string `json:"identifier,omitempty"` 89 | 90 | /** 91 | * The result id of a previous response if provided. 92 | */ 93 | PreviousResultId *string `json:"previousResultId,omitempty"` 94 | } 95 | 96 | /** 97 | * The result of a document diagnostic pull request. A report can 98 | * either be a full report containing all diagnostics for the 99 | * requested document or a unchanged report indicating that nothing 100 | * has changed in terms of diagnostics in comparison to the last 101 | * pull request. 102 | * 103 | * @since 3.17.0 104 | */ 105 | type DocumentDiagnosticReport any // RelatedFullDocumentDiagnosticReport | RelatedUnchangedDocumentDiagnosticReport 106 | 107 | /** 108 | * The document diagnostic report kinds. 109 | * 110 | * @since 3.17.0 111 | */ 112 | type DocumentDiagnosticReportKind string 113 | 114 | const ( 115 | /** 116 | * A diagnostic report with a full 117 | * set of problems. 118 | */ 119 | DocumentDiagnosticReportKindFull = DocumentDiagnosticReportKind("full") 120 | /** 121 | * A report indicating that the last 122 | * returned report is still accurate. 123 | */ 124 | DocumentDiagnosticReportKindUnchanged = DocumentDiagnosticReportKind("unchanged") 125 | ) 126 | 127 | /** 128 | * A diagnostic report with a full set of problems. 129 | * 130 | * @since 3.17.0 131 | */ 132 | type FullDocumentDiagnosticReport struct { 133 | /** 134 | * A full document diagnostic report. 135 | */ 136 | Kind string `json:"kind"` 137 | 138 | /** 139 | * An optional result id. If provided it will 140 | * be sent on the next diagnostic request for the 141 | * same document. 142 | */ 143 | ResultID *string `json:"resultId,omitempty"` 144 | 145 | /** 146 | * The actual items. 147 | */ 148 | Items []protocol316.Diagnostic `json:"items"` 149 | } 150 | 151 | /** 152 | * A diagnostic report indicating that the last returned 153 | * report is still accurate. 154 | * 155 | * @since 3.17.0 156 | */ 157 | type UnchangedDocumentDiagnosticReport struct { 158 | /** 159 | * A document diagnostic report indicating 160 | * no changes to the last result. A server can 161 | * only return `unchanged` if result ids are 162 | * provided. 163 | */ 164 | Kind string `json:"kind"` 165 | 166 | /** 167 | * A result id which will be sent on the next 168 | * diagnostic request for the same document. 169 | */ 170 | ResultID string `json:"resultId"` 171 | } 172 | 173 | /** 174 | * A full diagnostic report with a set of related documents. 175 | * 176 | * @since 3.17.0 177 | */ 178 | type RelatedFullDocumentDiagnosticReport struct { 179 | FullDocumentDiagnosticReport 180 | /** 181 | * Diagnostics of related documents. This information is useful 182 | * in programming languages where code in a file A can generate 183 | * diagnostics in a file B which A depends on. An example of 184 | * such a language is C/C++ where marco definitions in a file 185 | * a.cpp and result in errors in a header file b.hpp. 186 | * 187 | * @since 3.17.0 188 | */ 189 | RelatedDocuments map[protocol316.DocumentUri]interface{} `json:"relatedDocuments,omitempty"` 190 | } 191 | 192 | /** 193 | * An unchanged diagnostic report with a set of related documents. 194 | * 195 | * @since 3.17.0 196 | */ 197 | type RelatedUnchangedDocumentDiagnosticReport struct { 198 | UnchangedDocumentDiagnosticReport 199 | /** 200 | * Diagnostics of related documents. This information is useful 201 | * in programming languages where code in a file A can generate 202 | * diagnostics in a file B which A depends on. An example of 203 | * such a language is C/C++ where marco definitions in a file 204 | * a.cpp and result in errors in a header file b.hpp. 205 | * 206 | * @since 3.17.0 207 | */ 208 | RelatedDocuments map[protocol316.DocumentUri]interface{} `json:"relatedDocuments,omitempty"` 209 | } 210 | 211 | /** 212 | * A partial result for a document diagnostic report. 213 | * 214 | * @since 3.17.0 215 | */ 216 | type DocumentDiagnosticReportPartialResult struct { 217 | RelatedDocuments map[protocol316.DocumentUri]interface{} `json:"relatedDocuments"` 218 | } 219 | 220 | /** 221 | * Cancellation data returned from a diagnostic request. 222 | * 223 | * @since 3.17.0 224 | */ 225 | type DiagnosticServerCancellationData struct { 226 | RetriggerRequest bool `json:"retriggerRequest"` 227 | } 228 | -------------------------------------------------------------------------------- /protocol_3_16/text-document-synchronization.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/tliron/glsp" 7 | ) 8 | 9 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocument_synchronization 10 | 11 | type TextDocumentSyncKind Integer 12 | 13 | /** 14 | * Defines how the host (editor) should sync document changes to the language 15 | * server. 16 | */ 17 | const ( 18 | /** 19 | * Documents should not be synced at all. 20 | */ 21 | TextDocumentSyncKindNone = TextDocumentSyncKind(0) 22 | 23 | /** 24 | * Documents are synced by always sending the full content 25 | * of the document. 26 | */ 27 | TextDocumentSyncKindFull = TextDocumentSyncKind(1) 28 | 29 | /** 30 | * Documents are synced by sending the full content on open. 31 | * After that only incremental updates to the document are 32 | * send. 33 | */ 34 | TextDocumentSyncKindIncremental = TextDocumentSyncKind(2) 35 | ) 36 | 37 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocument_didOpen 38 | 39 | const MethodTextDocumentDidOpen = Method("textDocument/didOpen") 40 | 41 | type TextDocumentDidOpenFunc func(context *glsp.Context, params *DidOpenTextDocumentParams) error 42 | 43 | type DidOpenTextDocumentParams struct { 44 | /** 45 | * The document that was opened. 46 | */ 47 | TextDocument TextDocumentItem `json:"textDocument"` 48 | } 49 | 50 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocument_didChange 51 | 52 | /** 53 | * Describe options to be used when registering for text document change events. 54 | */ 55 | type TextDocumentChangeRegistrationOptions struct { 56 | TextDocumentRegistrationOptions 57 | 58 | /** 59 | * How documents are synced to the server. See TextDocumentSyncKind.Full 60 | * and TextDocumentSyncKind.Incremental. 61 | */ 62 | SyncKind TextDocumentSyncKind `json:"syncKind"` 63 | } 64 | 65 | const MethodTextDocumentDidChange = Method("textDocument/didChange") 66 | 67 | type TextDocumentDidChangeFunc func(context *glsp.Context, params *DidChangeTextDocumentParams) error 68 | 69 | type DidChangeTextDocumentParams struct { 70 | /** 71 | * The document that did change. The version number points 72 | * to the version after all provided content changes have 73 | * been applied. 74 | */ 75 | TextDocument VersionedTextDocumentIdentifier `json:"textDocument"` 76 | 77 | /** 78 | * The actual content changes. The content changes describe single state 79 | * changes to the document. So if there are two content changes c1 (at 80 | * array index 0) and c2 (at array index 1) for a document in state S then 81 | * c1 moves the document from S to S' and c2 from S' to S''. So c1 is 82 | * computed on the state S and c2 is computed on the state S'. 83 | * 84 | * To mirror the content of a document using change events use the following 85 | * approach: 86 | * - start with the same initial content 87 | * - apply the 'textDocument/didChange' notifications in the order you 88 | * receive them. 89 | * - apply the `TextDocumentContentChangeEvent`s in a single notification 90 | * in the order you receive them. 91 | */ 92 | ContentChanges []any `json:"contentChanges"` // TextDocumentContentChangeEvent or TextDocumentContentChangeEventWhole 93 | } 94 | 95 | // ([json.Unmarshaler] interface) 96 | func (self *DidChangeTextDocumentParams) UnmarshalJSON(data []byte) error { 97 | var value struct { 98 | TextDocument VersionedTextDocumentIdentifier `json:"textDocument"` 99 | ContentChanges []json.RawMessage `json:"contentChanges"` // TextDocumentContentChangeEvent or TextDocumentContentChangeEventWhole 100 | } 101 | 102 | if err := json.Unmarshal(data, &value); err == nil { 103 | self.TextDocument = value.TextDocument 104 | 105 | for _, contentChange := range value.ContentChanges { 106 | var changeEvent TextDocumentContentChangeEvent 107 | if err = json.Unmarshal(contentChange, &changeEvent); err == nil { 108 | if changeEvent.Range != nil { 109 | self.ContentChanges = append(self.ContentChanges, changeEvent) 110 | } else { 111 | changeEventWhole := TextDocumentContentChangeEventWhole{ 112 | Text: changeEvent.Text, 113 | } 114 | self.ContentChanges = append(self.ContentChanges, changeEventWhole) 115 | } 116 | } else { 117 | return err 118 | } 119 | } 120 | 121 | return nil 122 | } else { 123 | return err 124 | } 125 | } 126 | 127 | /** 128 | * An event describing a change to a text document. If range and rangeLength are 129 | * omitted the new text is considered to be the full content of the document. 130 | */ 131 | type TextDocumentContentChangeEvent struct { 132 | /** 133 | * The range of the document that changed. 134 | */ 135 | Range *Range `json:"range"` 136 | 137 | /** 138 | * The optional length of the range that got replaced. 139 | * 140 | * @deprecated use range instead. 141 | */ 142 | RangeLength *UInteger `json:"rangeLength,omitempty"` 143 | 144 | /** 145 | * The new text for the provided range. 146 | */ 147 | Text string `json:"text"` 148 | } 149 | 150 | type TextDocumentContentChangeEventWhole struct { 151 | /** 152 | * The new text of the whole document. 153 | */ 154 | Text string `json:"text"` 155 | } 156 | 157 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocument_willSave 158 | 159 | const MethodTextDocumentWillSave = Method("textDocument/willSave") 160 | 161 | type TextDocumentWillSaveFunc func(context *glsp.Context, params *WillSaveTextDocumentParams) error 162 | 163 | /** 164 | * The parameters send in a will save text document notification. 165 | */ 166 | type WillSaveTextDocumentParams struct { 167 | /** 168 | * The document that will be saved. 169 | */ 170 | TextDocument TextDocumentIdentifier `json:"textDocument"` 171 | 172 | /** 173 | * The 'TextDocumentSaveReason'. 174 | */ 175 | Reason TextDocumentSaveReason `json:"reason"` 176 | } 177 | 178 | type TextDocumentSaveReason Integer 179 | 180 | /** 181 | * Represents reasons why a text document is saved. 182 | */ 183 | const ( 184 | /** 185 | * Manually triggered, e.g. by the user pressing save, by starting 186 | * debugging, or by an API call. 187 | */ 188 | TextDocumentSaveReasonManual = TextDocumentSaveReason(1) 189 | 190 | /** 191 | * Automatic after a delay. 192 | */ 193 | TextDocumentSaveReasonAfterDelay = TextDocumentSaveReason(2) 194 | 195 | /** 196 | * When the editor lost focus. 197 | */ 198 | TextDocumentSaveReasonFocusOut = TextDocumentSaveReason(3) 199 | ) 200 | 201 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocument_willSaveWaitUntil 202 | 203 | const MethodTextDocumentWillSaveWaitUntil = Method("textDocument/willSaveWaitUntil") 204 | 205 | type TextDocumentWillSaveWaitUntilFunc func(context *glsp.Context, params *WillSaveTextDocumentParams) ([]TextEdit, error) 206 | 207 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocument_didSave 208 | 209 | type SaveOptions struct { 210 | /** 211 | * The client is supposed to include the content on save. 212 | */ 213 | IncludeText *bool `json:"includeText,omitempty"` 214 | } 215 | 216 | type TextDocumentSaveRegistrationOptions struct { 217 | TextDocumentRegistrationOptions 218 | 219 | /** 220 | * The client is supposed to include the content on save. 221 | */ 222 | IncludeText *bool `json:"includeText"` 223 | } 224 | 225 | const MethodTextDocumentDidSave = Method("textDocument/didSave") 226 | 227 | type TextDocumentDidSaveFunc func(context *glsp.Context, params *DidSaveTextDocumentParams) error 228 | 229 | type DidSaveTextDocumentParams struct { 230 | /** 231 | * The document that was saved. 232 | */ 233 | TextDocument TextDocumentIdentifier `json:"textDocument"` 234 | 235 | /** 236 | * Optional the content when saved. Depends on the includeText value 237 | * when the save notification was requested. 238 | */ 239 | Text *string `json:"text,omitempty"` 240 | } 241 | 242 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocument_didClose 243 | 244 | type TextDocumentSyncClientCapabilities struct { 245 | /** 246 | * Whether text document synchronization supports dynamic registration. 247 | */ 248 | DynamicRegistration *bool `json:"dynamicRegistration,omitempty"` 249 | 250 | /** 251 | * The client supports sending will save notifications. 252 | */ 253 | WillSave *bool `json:"willSave,omitempty"` 254 | 255 | /** 256 | * The client supports sending a will save request and 257 | * waits for a response providing text edits which will 258 | * be applied to the document before it is saved. 259 | */ 260 | WillSaveWaitUntil *bool `json:"willSaveWaitUntil,omitempty"` 261 | 262 | /** 263 | * The client supports did save notifications. 264 | */ 265 | DidSave *bool `json:"didSave,omitempty"` 266 | } 267 | 268 | type TextDocumentSyncOptions struct { 269 | /** 270 | * Open and close notifications are sent to the server. If omitted open 271 | * close notification should not be sent. 272 | */ 273 | OpenClose *bool `json:"openClose,omitempty"` 274 | 275 | /** 276 | * Change notifications are sent to the server. See 277 | * TextDocumentSyncKind.None, TextDocumentSyncKind.Full and 278 | * TextDocumentSyncKind.Incremental. If omitted it defaults to 279 | * TextDocumentSyncKind.None. 280 | */ 281 | Change *TextDocumentSyncKind `json:"change,omitempty"` 282 | 283 | /** 284 | * If present will save notifications are sent to the server. If omitted 285 | * the notification should not be sent. 286 | */ 287 | WillSave *bool `json:"willSave,omitempty"` 288 | 289 | /** 290 | * If present will save wait until requests are sent to the server. If 291 | * omitted the request should not be sent. 292 | */ 293 | WillSaveWaitUntil *bool `json:"willSaveWaitUntil,omitempty"` 294 | 295 | /** 296 | * If present save notifications are sent to the server. If omitted the 297 | * notification should not be sent. 298 | */ 299 | Save any `json:"save,omitempty"` // nil | bool | SaveOptions 300 | } 301 | 302 | // ([json.Unmarshaler] interface) 303 | func (self *TextDocumentSyncOptions) UnmarshalJSON(data []byte) error { 304 | var value struct { 305 | OpenClose *bool `json:"openClose"` 306 | Change *TextDocumentSyncKind `json:"change"` 307 | WillSave *bool `json:"willSave"` 308 | WillSaveWaitUntil *bool `json:"willSaveWaitUntil"` 309 | Save json.RawMessage `json:"save"` // nil | bool | SaveOptions 310 | } 311 | 312 | if err := json.Unmarshal(data, &value); err == nil { 313 | self.OpenClose = value.OpenClose 314 | self.Change = value.Change 315 | self.WillSave = value.WillSave 316 | self.WillSaveWaitUntil = value.WillSaveWaitUntil 317 | 318 | if value.Save != nil { 319 | var value_ bool 320 | if err = json.Unmarshal(value.Save, &value_); err == nil { 321 | self.Save = value_ 322 | } else { 323 | var value_ SaveOptions 324 | if err = json.Unmarshal(value.Save, &value_); err == nil { 325 | self.Save = value_ 326 | } else { 327 | return err 328 | } 329 | } 330 | } 331 | 332 | return nil 333 | } else { 334 | return err 335 | } 336 | } 337 | 338 | const MethodTextDocumentDidClose = Method("textDocument/didClose") 339 | 340 | type TextDocumentDidCloseFunc func(context *glsp.Context, params *DidCloseTextDocumentParams) error 341 | 342 | type DidCloseTextDocumentParams struct { 343 | /** 344 | * The document that was closed. 345 | */ 346 | TextDocument TextDocumentIdentifier `json:"textDocument"` 347 | } 348 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /protocol_3_16/workspace.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import "github.com/tliron/glsp" 4 | 5 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_workspaceFolders 6 | 7 | const ServerWorkspaceWorkspaceFolders = Method("workspace/workspaceFolders") 8 | 9 | type WorkspaceFoldersServerCapabilities struct { 10 | /** 11 | * The server has support for workspace folders 12 | */ 13 | Supported *bool `json:"supported"` 14 | 15 | /** 16 | * Whether the server wants to receive workspace folder 17 | * change notifications. 18 | * 19 | * If a string is provided, the string is treated as an ID 20 | * under which the notification is registered on the client 21 | * side. The ID can be used to unregister for these events 22 | * using the `client/unregisterCapability` request. 23 | */ 24 | ChangeNotifications *BoolOrString `json:"changeNotifications,omitempty"` 25 | } 26 | 27 | type WorkspaceFolder struct { 28 | /** 29 | * The associated URI for this workspace folder. 30 | */ 31 | URI DocumentUri `json:"uri"` 32 | 33 | /** 34 | * The name of the workspace folder. Used to refer to this 35 | * workspace folder in the user interface. 36 | */ 37 | Name string `json:"name"` 38 | } 39 | 40 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_didChangeWorkspaceFolders 41 | 42 | const MethodWorkspaceDidChangeWorkspaceFolders = Method("workspace/didChangeWorkspaceFolders") 43 | 44 | type WorkspaceDidChangeWorkspaceFoldersFunc func(context *glsp.Context, params *DidChangeWorkspaceFoldersParams) error 45 | 46 | type DidChangeWorkspaceFoldersParams struct { 47 | /** 48 | * The actual workspace folder change event. 49 | */ 50 | Event WorkspaceFoldersChangeEvent `json:"event"` 51 | } 52 | 53 | /** 54 | * The workspace folder change event. 55 | */ 56 | type WorkspaceFoldersChangeEvent struct { 57 | /** 58 | * The array of added workspace folders 59 | */ 60 | Added []WorkspaceFolder `json:"added"` 61 | 62 | /** 63 | * The array of the removed workspace folders 64 | */ 65 | Removed []WorkspaceFolder `json:"removed"` 66 | } 67 | 68 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_didChangeConfiguration 69 | 70 | type DidChangeConfigurationClientCapabilities struct { 71 | /** 72 | * Did change configuration notification supports dynamic registration. 73 | */ 74 | DynamicRegistration *bool `json:"dynamicRegistration,omitempty"` 75 | } 76 | 77 | const MethodWorkspaceDidChangeConfiguration = Method("workspace/didChangeConfiguration") 78 | 79 | type WorkspaceDidChangeConfigurationFunc func(context *glsp.Context, params *DidChangeConfigurationParams) error 80 | 81 | type DidChangeConfigurationParams struct { 82 | /** 83 | * The actual changed settings 84 | */ 85 | Settings any `json:"settings"` 86 | } 87 | 88 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_configuration 89 | 90 | const ServerWorkspaceConfiguration = Method("workspace/configuration") 91 | 92 | type ConfigurationParams struct { 93 | Items []ConfigurationItem `json:"items"` 94 | } 95 | 96 | type ConfigurationItem struct { 97 | /** 98 | * The scope to get the configuration section for. 99 | */ 100 | ScopeURI *DocumentUri `json:"scopeUri,omitempty"` 101 | 102 | /** 103 | * The configuration section asked for. 104 | */ 105 | Section *string `json:"section,omitempty"` 106 | } 107 | 108 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_didChangeWatchedFiles 109 | 110 | type DidChangeWatchedFilesClientCapabilities struct { 111 | /** 112 | * Did change watched files notification supports dynamic registration. 113 | * Please note that the current protocol doesn't support static 114 | * configuration for file changes from the server side. 115 | */ 116 | DynamicRegistration *bool `json:"dynamicRegistration,omitempty"` 117 | } 118 | 119 | /** 120 | * Describe options to be used when registering for file system change events. 121 | */ 122 | type DidChangeWatchedFilesRegistrationOptions struct { 123 | /** 124 | * The watchers to register. 125 | */ 126 | Watchers []FileSystemWatcher `json:"watchers"` 127 | } 128 | 129 | type FileSystemWatcher struct { 130 | /** 131 | * The glob pattern to watch. 132 | * 133 | * Glob patterns can have the following syntax: 134 | * - `*` to match one or more characters in a path segment 135 | * - `?` to match on one character in a path segment 136 | * - `**` to match any number of path segments, including none 137 | * - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript 138 | * and JavaScript files) 139 | * - `[]` to declare a range of characters to match in a path segment 140 | * (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) 141 | * - `[!...]` to negate a range of characters to match in a path segment 142 | * (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not 143 | * `example.0`) 144 | */ 145 | GlobPattern string `json:"globPattern"` 146 | 147 | /** 148 | * The kind of events of interest. If omitted it defaults 149 | * to WatchKind.Create | WatchKind.Change | WatchKind.Delete 150 | * which is 7. 151 | */ 152 | Kind *UInteger `json:"kind,omitempty"` 153 | } 154 | 155 | const ( 156 | /** 157 | * Interested in create events. 158 | */ 159 | WatchKindCreate = UInteger(1) 160 | 161 | /** 162 | * Interested in change events 163 | */ 164 | WatchKindChange = UInteger(2) 165 | 166 | /** 167 | * Interested in delete events 168 | */ 169 | WatchKindDelete = UInteger(4) 170 | ) 171 | 172 | const MethodWorkspaceDidChangeWatchedFiles = Method("workspace/didChangeWatchedFiles") 173 | 174 | type WorkspaceDidChangeWatchedFilesFunc func(context *glsp.Context, params *DidChangeWatchedFilesParams) error 175 | 176 | type DidChangeWatchedFilesParams struct { 177 | /** 178 | * The actual file events. 179 | */ 180 | Changes []FileEvent `json:"changes"` 181 | } 182 | 183 | /** 184 | * An event describing a file change. 185 | */ 186 | type FileEvent struct { 187 | /** 188 | * The file's URI. 189 | */ 190 | URI DocumentUri `json:"uri"` 191 | /** 192 | * The change type. 193 | */ 194 | Type UInteger `json:"type"` 195 | } 196 | 197 | /** 198 | * The file event type. 199 | */ 200 | const ( 201 | /** 202 | * The file got created. 203 | */ 204 | FileChangeTypeCreated = UInteger(1) 205 | 206 | /** 207 | * The file got changed. 208 | */ 209 | FileChangeTypeChanged = UInteger(2) 210 | 211 | /** 212 | * The file got deleted. 213 | */ 214 | FileChangeTypeDeleted = UInteger(3) 215 | ) 216 | 217 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_symbol 218 | 219 | type WorkspaceSymbolClientCapabilities struct { 220 | /** 221 | * Symbol request supports dynamic registration. 222 | */ 223 | DynamicRegistration *bool `json:"dynamicRegistration,omitempty"` 224 | 225 | /** 226 | * Specific capabilities for the `SymbolKind` in the `workspace/symbol` 227 | * request. 228 | */ 229 | SymbolKind *struct { 230 | /** 231 | * The symbol kind values the client supports. When this 232 | * property exists the client also guarantees that it will 233 | * handle values outside its set gracefully and falls back 234 | * to a default value when unknown. 235 | * 236 | * If this property is not present the client only supports 237 | * the symbol kinds from `File` to `Array` as defined in 238 | * the initial version of the protocol. 239 | */ 240 | ValueSet []SymbolKind `json:"valueSet,omitempty"` 241 | } `json:"symbolKind,omitempty"` 242 | 243 | /** 244 | * The client supports tags on `SymbolInformation`. 245 | * Clients supporting tags have to handle unknown tags gracefully. 246 | * 247 | * @since 3.16.0 248 | */ 249 | TagSupport *struct { 250 | /** 251 | * The tags supported by the client. 252 | */ 253 | ValueSet []SymbolTag `json:"valueSet"` 254 | } `json:"tagSupport,omitempty"` 255 | } 256 | 257 | type WorkspaceSymbolOptions struct { 258 | WorkDoneProgressOptions 259 | } 260 | 261 | type WorkspaceSymbolRegistrationOptions struct { 262 | WorkspaceSymbolOptions 263 | } 264 | 265 | const MethodWorkspaceSymbol = Method("workspace/symbol") 266 | 267 | type WorkspaceSymbolFunc func(context *glsp.Context, params *WorkspaceSymbolParams) ([]SymbolInformation, error) 268 | 269 | type WorkspaceSymbolParams struct { 270 | WorkDoneProgressParams 271 | PartialResultParams 272 | 273 | /** 274 | * A query string to filter symbols by. Clients may send an empty 275 | * string here to request all symbols. 276 | */ 277 | Query string `json:"query"` 278 | } 279 | 280 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_executeCommand 281 | 282 | type ExecuteCommandClientCapabilities struct { 283 | /** 284 | * Execute command supports dynamic registration. 285 | */ 286 | DynamicRegistration *bool `json:"dynamicRegistration,omitempty"` 287 | } 288 | 289 | type ExecuteCommandOptions struct { 290 | WorkDoneProgressOptions 291 | 292 | /** 293 | * The commands to be executed on the server 294 | */ 295 | Commands []string `json:"commands"` 296 | } 297 | 298 | /** 299 | * Execute command registration options. 300 | */ 301 | type ExecuteCommandRegistrationOptions struct { 302 | ExecuteCommandOptions 303 | } 304 | 305 | const MethodWorkspaceExecuteCommand = Method("workspace/executeCommand") 306 | 307 | type WorkspaceExecuteCommandFunc func(context *glsp.Context, params *ExecuteCommandParams) (any, error) 308 | 309 | type ExecuteCommandParams struct { 310 | WorkDoneProgressParams 311 | 312 | /** 313 | * The identifier of the actual command handler. 314 | */ 315 | Command string `json:"command"` 316 | 317 | /** 318 | * Arguments that the command should be invoked with. 319 | */ 320 | Arguments []any `json:"arguments,omitempty"` 321 | } 322 | 323 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_applyEdit 324 | 325 | const ServerWorkspaceApplyEdit = Method("workspace/applyEdit") 326 | 327 | type ApplyWorkspaceEditParams struct { 328 | /** 329 | * An optional label of the workspace edit. This label is 330 | * presented in the user interface for example on an undo 331 | * stack to undo the workspace edit. 332 | */ 333 | Label *string `json:"label,omitempty"` 334 | 335 | /** 336 | * The edits to apply. 337 | */ 338 | Edit WorkspaceEdit `json:"edit"` 339 | } 340 | 341 | type ApplyWorkspaceEditResponse struct { 342 | /** 343 | * Indicates whether the edit was applied or not. 344 | */ 345 | Applied bool `json:"applied"` 346 | 347 | /** 348 | * An optional textual description for why the edit was not applied. 349 | * This may be used by the server for diagnostic logging or to provide 350 | * a suitable error for a request that triggered the edit. 351 | */ 352 | FailureReason *string `json:"failureReason,omitempty"` 353 | 354 | /** 355 | * Depending on the client's failure handling strategy `failedChange` 356 | * might contain the index of the change that failed. This property is 357 | * only available if the client signals a `failureHandlingStrategy` 358 | * in its client capabilities. 359 | */ 360 | FailedChange *UInteger `json:"failedChange,omitempty"` 361 | } 362 | 363 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_willCreateFiles 364 | 365 | /** 366 | * The options to register for file operations. 367 | * 368 | * @since 3.16.0 369 | */ 370 | type FileOperationRegistrationOptions struct { 371 | /** 372 | * The actual filters. 373 | */ 374 | Filters []FileOperationFilter `json:"filters"` 375 | } 376 | 377 | type FileOperationPatternKind string 378 | 379 | /** 380 | * A pattern kind describing if a glob pattern matches a file a folder or 381 | * both. 382 | * 383 | * @since 3.16.0 384 | */ 385 | const ( 386 | /** 387 | * The pattern matches a file only. 388 | */ 389 | FileOperationPatternKindFile = FileOperationPatternKind("file") 390 | 391 | /** 392 | * The pattern matches a folder only. 393 | */ 394 | FileOperationPatternKindFolder = FileOperationPatternKind("folder") 395 | ) 396 | 397 | /** 398 | * Matching options for the file operation pattern. 399 | * 400 | * @since 3.16.0 401 | */ 402 | type FileOperationPatternOptions struct { 403 | 404 | /** 405 | * The pattern should be matched ignoring casing. 406 | */ 407 | IgnoreCase *bool `json:"ignoreCase,omitempty"` 408 | } 409 | 410 | /** 411 | * A pattern to describe in which file operation requests or notifications 412 | * the server is interested in. 413 | * 414 | * @since 3.16.0 415 | */ 416 | type FileOperationPattern struct { 417 | /** 418 | * The glob pattern to match. Glob patterns can have the following syntax: 419 | * - `*` to match one or more characters in a path segment 420 | * - `?` to match on one character in a path segment 421 | * - `**` to match any number of path segments, including none 422 | * - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript 423 | * and JavaScript files) 424 | * - `[]` to declare a range of characters to match in a path segment 425 | * (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) 426 | * - `[!...]` to negate a range of characters to match in a path segment 427 | * (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but 428 | * not `example.0`) 429 | */ 430 | Glob string `json:"glob"` 431 | 432 | /** 433 | * Whether to match files or folders with this pattern. 434 | * 435 | * Matches both if undefined. 436 | */ 437 | Matches *FileOperationPatternKind `json:"matches,omitempty"` 438 | 439 | /** 440 | * Additional options used during matching. 441 | */ 442 | Options *FileOperationPatternOptions `json:"options,omitempty"` 443 | } 444 | 445 | /** 446 | * A filter to describe in which file operation requests or notifications 447 | * the server is interested in. 448 | * 449 | * @since 3.16.0 450 | */ 451 | type FileOperationFilter struct { 452 | /** 453 | * A Uri like `file` or `untitled`. 454 | */ 455 | Scheme *string `json:"scheme,omitempty"` 456 | 457 | /** 458 | * The actual file operation pattern. 459 | */ 460 | Pattern FileOperationPattern `json:"pattern"` 461 | } 462 | 463 | const MethodWorkspaceWillCreateFiles = Method("workspace/willCreateFiles") 464 | 465 | type WorkspaceWillCreateFilesFunc func(context *glsp.Context, params *CreateFilesParams) (*WorkspaceEdit, error) 466 | 467 | /** 468 | * The parameters sent in notifications/requests for user-initiated creation 469 | * of files. 470 | * 471 | * @since 3.16.0 472 | */ 473 | type CreateFilesParams struct { 474 | /** 475 | * An array of all files/folders created in this operation. 476 | */ 477 | Files []FileCreate `json:"files"` 478 | } 479 | 480 | /** 481 | * Represents information on a file/folder create. 482 | * 483 | * @since 3.16.0 484 | */ 485 | type FileCreate struct { 486 | /** 487 | * A file:// URI for the location of the file/folder being created. 488 | */ 489 | URI string `json:"uri"` 490 | } 491 | 492 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_didCreateFiles 493 | 494 | const MethodWorkspaceDidCreateFiles = Method("workspace/didCreateFiles") 495 | 496 | type WorkspaceDidCreateFilesFunc func(context *glsp.Context, params *CreateFilesParams) error 497 | 498 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_willRenameFiles 499 | 500 | const MethodWorkspaceWillRenameFiles = Method("workspace/willRenameFiles") 501 | 502 | type WorkspaceWillRenameFilesFunc func(context *glsp.Context, params *RenameFilesParams) (*WorkspaceEdit, error) 503 | 504 | /** 505 | * The parameters sent in notifications/requests for user-initiated renames 506 | * of files. 507 | * 508 | * @since 3.16.0 509 | */ 510 | type RenameFilesParams struct { 511 | /** 512 | * An array of all files/folders renamed in this operation. When a folder 513 | * is renamed, only the folder will be included, and not its children. 514 | */ 515 | Files []FileRename `json:"files"` 516 | } 517 | 518 | /** 519 | * Represents information on a file/folder rename. 520 | * 521 | * @since 3.16.0 522 | */ 523 | type FileRename struct { 524 | /** 525 | * A file:// URI for the original location of the file/folder being renamed. 526 | */ 527 | OldURI string `json:"oldUri"` 528 | 529 | /** 530 | * A file:// URI for the new location of the file/folder being renamed. 531 | */ 532 | NewURI string `json:"newUri"` 533 | } 534 | 535 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_didRenameFiles 536 | 537 | const MethodWorkspaceDidRenameFiles = Method("workspace/didRenameFiles") 538 | 539 | type WorkspaceDidRenameFilesFunc func(context *glsp.Context, params *RenameFilesParams) error 540 | 541 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_willDeleteFiles 542 | 543 | const MethodWorkspaceWillDeleteFiles = Method("workspace/willDeleteFiles") 544 | 545 | type WorkspaceWillDeleteFilesFunc func(context *glsp.Context, params *DeleteFilesParams) (*WorkspaceEdit, error) 546 | 547 | /** 548 | * The parameters sent in notifications/requests for user-initiated deletes 549 | * of files. 550 | * 551 | * @since 3.16.0 552 | */ 553 | type DeleteFilesParams struct { 554 | /** 555 | * An array of all files/folders deleted in this operation. 556 | */ 557 | Files []FileDelete `json:"files"` 558 | } 559 | 560 | /** 561 | * Represents information on a file/folder delete. 562 | * 563 | * @since 3.16.0 564 | */ 565 | type FileDelete struct { 566 | /** 567 | * A file:// URI for the location of the file/folder being deleted. 568 | */ 569 | URI string `json:"uri"` 570 | } 571 | 572 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspace_didDeleteFiles 573 | 574 | const MethodWorkspaceDidDeleteFiles = Method("workspace/didDeleteFiles") 575 | 576 | type WorkspaceDidDeleteFilesFunc func(context *glsp.Context, params *DeleteFilesParams) error 577 | 578 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#textDocument_semanticTokens 579 | const MethodWorkspaceSemanticTokensRefresh = Method("workspace/semanticTokens/refresh") 580 | 581 | type WorkspaceSemanticTokensRefreshFunc func(context *glsp.Context) error 582 | 583 | type SemanticTokensWorkspaceClientCapabilities struct { 584 | /** 585 | * Whether the client implementation supports a refresh request sent from 586 | * the server to the client. 587 | * 588 | * Note that this event is global and will force the client to refresh all 589 | * semantic tokens currently shown. It should be used with absolute care 590 | * and is useful for situation where a server for example detect a project 591 | * wide change that requires such a calculation. 592 | */ 593 | RefreshSupport *bool `json:"refreshSupport,omitempty"` 594 | } 595 | -------------------------------------------------------------------------------- /protocol_3_17/general-messages.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/tliron/glsp" 7 | protocol316 "github.com/tliron/glsp/protocol_3_16" 8 | ) 9 | 10 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#initialize 11 | 12 | const MethodInitialize = protocol316.Method("initialize") 13 | 14 | // Returns: InitializeResult | InitializeError 15 | type InitializeFunc func(context *glsp.Context, params *InitializeParams) (any, error) 16 | 17 | type InitializeParams struct { 18 | protocol316.InitializeParams 19 | 20 | /** 21 | * The capabilities provided by the client (editor or tool) 22 | */ 23 | Capabilities ClientCapabilities `json:"capabilities"` 24 | } 25 | 26 | type ClientCapabilities struct { 27 | protocol316.ClientCapabilities 28 | 29 | TextDocument *TextDocumentClientCapabilities `json:"textDocument,omitempty"` 30 | } 31 | 32 | /** 33 | * Text document specific client capabilities. 34 | */ 35 | type TextDocumentClientCapabilities struct { 36 | protocol316.TextDocumentClientCapabilities 37 | 38 | /** 39 | * Capabilities specific to the diagnostic pull model. 40 | * 41 | * @since 3.17.0 42 | */ 43 | Diagnostic *DiagnosticClientCapabilities `json:"diagnostic,omitempty"` 44 | } 45 | 46 | type ServerCapabilities struct { 47 | protocol316.ServerCapabilities 48 | 49 | /** 50 | * The server has support for pull model diagnostics. 51 | * 52 | * @since 3.17.0 53 | */ 54 | DiagnosticProvider any `json:"diagnosticProvider,omitempty"` // nil | DiagnosticOptions | DiagnosticRegistrationOptions 55 | } 56 | 57 | func (self *ServerCapabilities) UnmarshalJSON(data []byte) error { 58 | var value struct { 59 | TextDocumentSync json.RawMessage `json:"textDocumentSync,omitempty"` // nil | TextDocumentSyncOptions | TextDocumentSyncKind 60 | CompletionProvider *protocol316.CompletionOptions `json:"completionProvider,omitempty"` 61 | HoverProvider json.RawMessage `json:"hoverProvider,omitempty"` // nil | bool | HoverOptions 62 | SignatureHelpProvider *protocol316.SignatureHelpOptions `json:"signatureHelpProvider,omitempty"` 63 | DeclarationProvider json.RawMessage `json:"declarationProvider,omitempty"` // nil | bool | DeclarationOptions | DeclarationRegistrationOptions 64 | DefinitionProvider json.RawMessage `json:"definitionProvider,omitempty"` // nil | bool | DefinitionOptions 65 | TypeDefinitionProvider json.RawMessage `json:"typeDefinitionProvider,omitempty"` // nil | bool | TypeDefinitionOption | TypeDefinitionRegistrationOptions 66 | ImplementationProvider json.RawMessage `json:"implementationProvider,omitempty"` // nil | bool | ImplementationOptions | ImplementationRegistrationOptions 67 | ReferencesProvider json.RawMessage `json:"referencesProvider,omitempty"` // nil | bool | ReferenceOptions 68 | DocumentHighlightProvider json.RawMessage `json:"documentHighlightProvider,omitempty"` // nil | bool | DocumentHighlightOptions 69 | DocumentSymbolProvider json.RawMessage `json:"documentSymbolProvider,omitempty"` // nil | bool | DocumentSymbolOptions 70 | CodeActionProvider json.RawMessage `json:"codeActionProvider,omitempty"` // nil | bool | CodeActionOptions 71 | CodeLensProvider *protocol316.CodeLensOptions `json:"codeLensProvider,omitempty"` 72 | DocumentLinkProvider *protocol316.DocumentLinkOptions `json:"documentLinkProvider,omitempty"` 73 | ColorProvider json.RawMessage `json:"colorProvider,omitempty"` // nil | bool | DocumentColorOptions | DocumentColorRegistrationOptions 74 | DocumentFormattingProvider json.RawMessage `json:"documentFormattingProvider,omitempty"` // nil | bool | DocumentFormattingOptions 75 | DocumentRangeFormattingProvider json.RawMessage `json:"documentRangeFormattingProvider,omitempty"` // nil | bool | DocumentRangeFormattingOptions 76 | DocumentOnTypeFormattingProvider *protocol316.DocumentOnTypeFormattingOptions `json:"documentOnTypeFormattingProvider,omitempty"` 77 | RenameProvider json.RawMessage `json:"renameProvider,omitempty"` // nil | bool | RenameOptions 78 | FoldingRangeProvider json.RawMessage `json:"foldingRangeProvider,omitempty"` // nil | bool | FoldingRangeOptions | FoldingRangeRegistrationOptions 79 | ExecuteCommandProvider *protocol316.ExecuteCommandOptions `json:"executeCommandProvider,omitempty"` 80 | SelectionRangeProvider json.RawMessage `json:"selectionRangeProvider,omitempty"` // nil | bool | SelectionRangeOptions | SelectionRangeRegistrationOptions 81 | LinkedEditingRangeProvider json.RawMessage `json:"linkedEditingRangeProvider,omitempty"` // nil | bool | LinkedEditingRangeOptions | LinkedEditingRangeRegistrationOptions 82 | CallHierarchyProvider json.RawMessage `json:"callHierarchyProvider,omitempty"` // nil | bool | CallHierarchyOptions | CallHierarchyRegistrationOptions 83 | SemanticTokensProvider json.RawMessage `json:"semanticTokensProvider,omitempty"` // nil | SemanticTokensOptions | SemanticTokensRegistrationOptions 84 | MonikerProvider json.RawMessage `json:"monikerProvider,omitempty"` // nil | bool | MonikerOptions | MonikerRegistrationOptions 85 | WorkspaceSymbolProvider json.RawMessage `json:"workspaceSymbolProvider,omitempty"` // nil | bool | WorkspaceSymbolOptions 86 | Workspace *protocol316.ServerCapabilitiesWorkspace `json:"workspace,omitempty"` 87 | Experimental *any `json:"experimental,omitempty"` 88 | DiagnosticProvider json.RawMessage `json:"diagnosticProvider,omitempty"` // nil | DiagnosticOptions | DiagnosticRegistrationOptions 89 | } 90 | 91 | if err := json.Unmarshal(data, &value); err == nil { 92 | self.CompletionProvider = value.CompletionProvider 93 | self.SignatureHelpProvider = value.SignatureHelpProvider 94 | self.CodeLensProvider = value.CodeLensProvider 95 | self.DocumentLinkProvider = value.DocumentLinkProvider 96 | self.DocumentOnTypeFormattingProvider = value.DocumentOnTypeFormattingProvider 97 | self.ExecuteCommandProvider = value.ExecuteCommandProvider 98 | self.Workspace = value.Workspace 99 | 100 | if value.TextDocumentSync != nil { 101 | var value_ protocol316.TextDocumentSyncOptions 102 | if err = json.Unmarshal(value.TextDocumentSync, &value_); err == nil { 103 | self.TextDocumentSync = value_ 104 | } else { 105 | var value_ protocol316.TextDocumentSyncKind 106 | if err = json.Unmarshal(value.TextDocumentSync, &value_); err == nil { 107 | self.TextDocumentSync = value_ 108 | } else { 109 | return err 110 | } 111 | } 112 | } 113 | 114 | if value.HoverProvider != nil { 115 | var value_ bool 116 | if err = json.Unmarshal(value.HoverProvider, &value_); err == nil { 117 | self.HoverProvider = value_ 118 | } else { 119 | var value_ protocol316.HoverOptions 120 | if err = json.Unmarshal(value.HoverProvider, &value_); err == nil { 121 | self.HoverProvider = value_ 122 | } else { 123 | return err 124 | } 125 | } 126 | } 127 | 128 | if value.DeclarationProvider != nil { 129 | var value_ bool 130 | if err = json.Unmarshal(value.DeclarationProvider, &value_); err == nil { 131 | self.DeclarationProvider = value_ 132 | } else { 133 | var value_ protocol316.DeclarationOptions 134 | if err = json.Unmarshal(value.DeclarationProvider, &value_); err == nil { 135 | self.DeclarationProvider = value_ 136 | } else { 137 | var value_ protocol316.DeclarationRegistrationOptions 138 | if err = json.Unmarshal(value.DeclarationProvider, &value_); err == nil { 139 | self.DeclarationProvider = value_ 140 | } else { 141 | return err 142 | } 143 | } 144 | } 145 | } 146 | 147 | if value.DefinitionProvider != nil { 148 | var value_ bool 149 | if err = json.Unmarshal(value.DefinitionProvider, &value_); err == nil { 150 | self.DefinitionProvider = value_ 151 | } else { 152 | var value_ protocol316.DefinitionOptions 153 | if err = json.Unmarshal(value.DefinitionProvider, &value_); err == nil { 154 | self.DefinitionProvider = value_ 155 | } else { 156 | return err 157 | } 158 | } 159 | } 160 | 161 | if value.TypeDefinitionProvider != nil { 162 | var value_ bool 163 | if err = json.Unmarshal(value.TypeDefinitionProvider, &value_); err == nil { 164 | self.TypeDefinitionProvider = value_ 165 | } else { 166 | var value_ protocol316.TypeDefinitionOptions 167 | if err = json.Unmarshal(value.TypeDefinitionProvider, &value_); err == nil { 168 | self.TypeDefinitionProvider = value_ 169 | } else { 170 | var value_ protocol316.TypeDefinitionRegistrationOptions 171 | if err = json.Unmarshal(value.TypeDefinitionProvider, &value_); err == nil { 172 | self.TypeDefinitionProvider = value_ 173 | } else { 174 | return err 175 | } 176 | } 177 | } 178 | } 179 | 180 | if value.ImplementationProvider != nil { 181 | var value_ bool 182 | if err = json.Unmarshal(value.ImplementationProvider, &value_); err == nil { 183 | self.ImplementationProvider = value_ 184 | } else { 185 | var value_ protocol316.ImplementationOptions 186 | if err = json.Unmarshal(value.ImplementationProvider, &value_); err == nil { 187 | self.ImplementationProvider = value_ 188 | } else { 189 | var value_ protocol316.ImplementationRegistrationOptions 190 | if err = json.Unmarshal(value.ImplementationProvider, &value_); err == nil { 191 | self.ImplementationProvider = value_ 192 | } else { 193 | return err 194 | } 195 | } 196 | } 197 | } 198 | 199 | if value.ReferencesProvider != nil { 200 | var value_ bool 201 | if err = json.Unmarshal(value.ReferencesProvider, &value_); err == nil { 202 | self.ReferencesProvider = value_ 203 | } else { 204 | var value_ protocol316.ReferenceOptions 205 | if err = json.Unmarshal(value.ReferencesProvider, &value_); err == nil { 206 | self.ReferencesProvider = value_ 207 | } else { 208 | return err 209 | } 210 | } 211 | } 212 | 213 | if value.DocumentHighlightProvider != nil { 214 | var value_ bool 215 | if err = json.Unmarshal(value.DocumentHighlightProvider, &value_); err == nil { 216 | self.DocumentHighlightProvider = value_ 217 | } else { 218 | var value_ protocol316.DocumentHighlightOptions 219 | if err = json.Unmarshal(value.DocumentHighlightProvider, &value_); err == nil { 220 | self.DocumentHighlightProvider = value_ 221 | } else { 222 | return err 223 | } 224 | } 225 | } 226 | 227 | if value.DocumentSymbolProvider != nil { 228 | var value_ bool 229 | if err = json.Unmarshal(value.DocumentSymbolProvider, &value_); err == nil { 230 | self.DocumentSymbolProvider = value_ 231 | } else { 232 | var value_ protocol316.DocumentSymbolOptions 233 | if err = json.Unmarshal(value.DocumentSymbolProvider, &value_); err == nil { 234 | self.DocumentSymbolProvider = value_ 235 | } else { 236 | return err 237 | } 238 | } 239 | } 240 | 241 | if value.CodeActionProvider != nil { 242 | var value_ bool 243 | if err = json.Unmarshal(value.CodeActionProvider, &value_); err == nil { 244 | self.CodeActionProvider = value_ 245 | } else { 246 | var value_ protocol316.CodeActionOptions 247 | if err = json.Unmarshal(value.CodeActionProvider, &value_); err == nil { 248 | self.CodeActionProvider = value_ 249 | } else { 250 | return err 251 | } 252 | } 253 | } 254 | 255 | if value.ColorProvider != nil { 256 | var value_ bool 257 | if err = json.Unmarshal(value.ColorProvider, &value_); err == nil { 258 | self.ColorProvider = value_ 259 | } else { 260 | var value_ protocol316.DocumentColorOptions 261 | if err = json.Unmarshal(value.ColorProvider, &value_); err == nil { 262 | self.ColorProvider = value_ 263 | } else { 264 | var value_ protocol316.DocumentColorRegistrationOptions 265 | if err = json.Unmarshal(value.ColorProvider, &value_); err == nil { 266 | self.ColorProvider = value_ 267 | } else { 268 | return err 269 | } 270 | } 271 | } 272 | } 273 | 274 | if value.DocumentFormattingProvider != nil { 275 | var value_ bool 276 | if err = json.Unmarshal(value.DocumentFormattingProvider, &value_); err == nil { 277 | self.DocumentFormattingProvider = value_ 278 | } else { 279 | var value_ protocol316.DocumentFormattingOptions 280 | if err = json.Unmarshal(value.DocumentFormattingProvider, &value_); err == nil { 281 | self.DocumentFormattingProvider = value_ 282 | } else { 283 | return err 284 | } 285 | } 286 | } 287 | 288 | if value.DocumentRangeFormattingProvider != nil { 289 | var value_ bool 290 | if err = json.Unmarshal(value.DocumentRangeFormattingProvider, &value_); err == nil { 291 | self.DocumentRangeFormattingProvider = value_ 292 | } else { 293 | var value_ protocol316.DocumentRangeFormattingOptions 294 | if err = json.Unmarshal(value.DocumentRangeFormattingProvider, &value_); err == nil { 295 | self.DocumentRangeFormattingProvider = value_ 296 | } else { 297 | return err 298 | } 299 | } 300 | } 301 | 302 | if value.RenameProvider != nil { 303 | var value_ bool 304 | if err = json.Unmarshal(value.RenameProvider, &value_); err == nil { 305 | self.RenameProvider = value_ 306 | } else { 307 | var value_ protocol316.RenameOptions 308 | if err = json.Unmarshal(value.RenameProvider, &value_); err == nil { 309 | self.RenameProvider = value_ 310 | } else { 311 | return err 312 | } 313 | } 314 | } 315 | 316 | if value.FoldingRangeProvider != nil { 317 | var value_ bool 318 | if err = json.Unmarshal(value.FoldingRangeProvider, &value_); err == nil { 319 | self.FoldingRangeProvider = value_ 320 | } else { 321 | var value_ protocol316.FoldingRangeOptions 322 | if err = json.Unmarshal(value.FoldingRangeProvider, &value_); err == nil { 323 | self.FoldingRangeProvider = value_ 324 | } else { 325 | var value_ protocol316.FoldingRangeRegistrationOptions 326 | if err = json.Unmarshal(value.FoldingRangeProvider, &value_); err == nil { 327 | self.FoldingRangeProvider = value_ 328 | } else { 329 | return err 330 | } 331 | } 332 | } 333 | } 334 | 335 | if value.SelectionRangeProvider != nil { 336 | var value_ bool 337 | if err = json.Unmarshal(value.SelectionRangeProvider, &value_); err == nil { 338 | self.SelectionRangeProvider = value_ 339 | } else { 340 | var value_ protocol316.SelectionRangeOptions 341 | if err = json.Unmarshal(value.SelectionRangeProvider, &value_); err == nil { 342 | self.SelectionRangeProvider = value_ 343 | } else { 344 | var value_ protocol316.SelectionRangeRegistrationOptions 345 | if err = json.Unmarshal(value.SelectionRangeProvider, &value_); err == nil { 346 | self.SelectionRangeProvider = value_ 347 | } else { 348 | return err 349 | } 350 | } 351 | } 352 | } 353 | 354 | if value.LinkedEditingRangeProvider != nil { 355 | var value_ bool 356 | if err = json.Unmarshal(value.LinkedEditingRangeProvider, &value_); err == nil { 357 | self.LinkedEditingRangeProvider = value_ 358 | } else { 359 | var value_ protocol316.LinkedEditingRangeOptions 360 | if err = json.Unmarshal(value.LinkedEditingRangeProvider, &value_); err == nil { 361 | self.LinkedEditingRangeProvider = value_ 362 | } else { 363 | var value_ protocol316.LinkedEditingRangeRegistrationOptions 364 | if err = json.Unmarshal(value.LinkedEditingRangeProvider, &value_); err == nil { 365 | self.LinkedEditingRangeProvider = value_ 366 | } else { 367 | return err 368 | } 369 | } 370 | } 371 | } 372 | 373 | if value.CallHierarchyProvider != nil { 374 | var value_ bool 375 | if err = json.Unmarshal(value.CallHierarchyProvider, &value_); err == nil { 376 | self.CallHierarchyProvider = value_ 377 | } else { 378 | var value_ protocol316.CallHierarchyOptions 379 | if err = json.Unmarshal(value.CallHierarchyProvider, &value_); err == nil { 380 | self.CallHierarchyProvider = value_ 381 | } else { 382 | var value_ protocol316.CallHierarchyRegistrationOptions 383 | if err = json.Unmarshal(value.CallHierarchyProvider, &value_); err == nil { 384 | self.CallHierarchyProvider = value_ 385 | } else { 386 | return err 387 | } 388 | } 389 | } 390 | } 391 | 392 | if value.SemanticTokensProvider != nil { 393 | var value_ protocol316.SemanticTokensOptions 394 | if err = json.Unmarshal(value.SemanticTokensProvider, &value_); err == nil { 395 | self.SemanticTokensProvider = value_ 396 | } else { 397 | var value_ protocol316.SemanticTokensRegistrationOptions 398 | if err = json.Unmarshal(value.SemanticTokensProvider, &value_); err == nil { 399 | self.SemanticTokensProvider = value_ 400 | } else { 401 | return err 402 | } 403 | } 404 | } 405 | 406 | if value.MonikerProvider != nil { 407 | var value_ bool 408 | if err = json.Unmarshal(value.MonikerProvider, &value_); err == nil { 409 | self.MonikerProvider = value_ 410 | } else { 411 | var value_ protocol316.MonikerOptions 412 | if err = json.Unmarshal(value.MonikerProvider, &value_); err == nil { 413 | self.MonikerProvider = value_ 414 | } else { 415 | var value_ protocol316.MonikerRegistrationOptions 416 | if err = json.Unmarshal(value.MonikerProvider, &value_); err == nil { 417 | self.MonikerProvider = value_ 418 | } else { 419 | return err 420 | } 421 | } 422 | } 423 | } 424 | 425 | if value.WorkspaceSymbolProvider != nil { 426 | var value_ bool 427 | if err = json.Unmarshal(value.WorkspaceSymbolProvider, &value_); err == nil { 428 | self.WorkspaceSymbolProvider = value_ 429 | } else { 430 | var value_ protocol316.WorkspaceSymbolOptions 431 | if err = json.Unmarshal(value.WorkspaceSymbolProvider, &value_); err == nil { 432 | self.WorkspaceSymbolProvider = value_ 433 | } else { 434 | return err 435 | } 436 | } 437 | } 438 | 439 | if value.DiagnosticProvider != nil { 440 | var value_ DiagnosticOptions 441 | if err = json.Unmarshal(value.DiagnosticProvider, &value_); err == nil { 442 | self.DiagnosticProvider = value_ 443 | } else { 444 | var value_ DiagnosticRegistrationOptions 445 | if err = json.Unmarshal(value.DiagnosticProvider, &value_); err == nil { 446 | self.DiagnosticProvider = value_ 447 | } else { 448 | return err 449 | } 450 | } 451 | } 452 | 453 | return nil 454 | } else { 455 | return err 456 | } 457 | } 458 | 459 | type InitializeResult struct { 460 | /** 461 | * The capabilities the language server provides. 462 | */ 463 | Capabilities ServerCapabilities `json:"capabilities"` 464 | 465 | /** 466 | * Information about the server. 467 | * 468 | * @since 3.15.0 469 | */ 470 | ServerInfo *protocol316.InitializeResultServerInfo `json:"serverInfo,omitempty"` 471 | } 472 | -------------------------------------------------------------------------------- /protocol_3_17/handler.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "sync" 7 | 8 | "github.com/tliron/glsp" 9 | protocol316 "github.com/tliron/glsp/protocol_3_16" 10 | ) 11 | 12 | type Handler struct { 13 | protocol316.Handler 14 | 15 | Initialize InitializeFunc 16 | TextDocumentDiagnostic TextDocumentDiagnosticFunc 17 | 18 | initialized bool 19 | lock sync.Mutex 20 | } 21 | 22 | func (self *Handler) Handle(context *glsp.Context) (r any, validMethod bool, validParams bool, err error) { 23 | if !self.IsInitialized() && (context.Method != protocol316.MethodInitialize) { 24 | return nil, true, true, errors.New("server not initialized") 25 | } 26 | 27 | switch context.Method { 28 | case protocol316.MethodCancelRequest: 29 | if self.CancelRequest != nil { 30 | validMethod = true 31 | var params protocol316.CancelParams 32 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 33 | validParams = true 34 | err = self.CancelRequest(context, ¶ms) 35 | } 36 | } 37 | 38 | case protocol316.MethodProgress: 39 | if self.Progress != nil { 40 | validMethod = true 41 | var params protocol316.ProgressParams 42 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 43 | validParams = true 44 | err = self.Progress(context, ¶ms) 45 | } 46 | } 47 | 48 | // General Messages 49 | 50 | case MethodInitialize: 51 | if self.Initialize != nil { 52 | validMethod = true 53 | var params InitializeParams 54 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 55 | validParams = true 56 | if r, err = self.Initialize(context, ¶ms); err == nil { 57 | self.SetInitialized(true) 58 | } 59 | } 60 | } 61 | 62 | case protocol316.MethodInitialized: 63 | if self.Initialized != nil { 64 | validMethod = true 65 | var params protocol316.InitializedParams 66 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 67 | validParams = true 68 | err = self.Initialized(context, ¶ms) 69 | } 70 | } 71 | 72 | case protocol316.MethodShutdown: 73 | self.SetInitialized(false) 74 | if self.Shutdown != nil { 75 | validMethod = true 76 | validParams = true 77 | err = self.Shutdown(context) 78 | } 79 | 80 | case protocol316.MethodExit: 81 | // Note that the server will close the connection after we handle it here 82 | if self.Exit != nil { 83 | validMethod = true 84 | validParams = true 85 | err = self.Exit(context) 86 | } 87 | 88 | case protocol316.MethodLogTrace: 89 | if self.LogTrace != nil { 90 | validMethod = true 91 | var params protocol316.LogTraceParams 92 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 93 | validParams = true 94 | err = self.LogTrace(context, ¶ms) 95 | } 96 | } 97 | 98 | case protocol316.MethodSetTrace: 99 | if self.SetTrace != nil { 100 | validMethod = true 101 | var params protocol316.SetTraceParams 102 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 103 | validParams = true 104 | err = self.SetTrace(context, ¶ms) 105 | } 106 | } 107 | 108 | // Window 109 | 110 | case protocol316.MethodWindowWorkDoneProgressCancel: 111 | if self.WindowWorkDoneProgressCancel != nil { 112 | validMethod = true 113 | var params protocol316.WorkDoneProgressCancelParams 114 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 115 | validParams = true 116 | err = self.WindowWorkDoneProgressCancel(context, ¶ms) 117 | } 118 | } 119 | 120 | // Workspace 121 | 122 | case protocol316.MethodWorkspaceDidChangeWorkspaceFolders: 123 | if self.WorkspaceDidChangeWorkspaceFolders != nil { 124 | validMethod = true 125 | var params protocol316.DidChangeWorkspaceFoldersParams 126 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 127 | validParams = true 128 | err = self.WorkspaceDidChangeWorkspaceFolders(context, ¶ms) 129 | } 130 | } 131 | 132 | case protocol316.MethodWorkspaceDidChangeConfiguration: 133 | if self.WorkspaceDidChangeConfiguration != nil { 134 | validMethod = true 135 | var params protocol316.DidChangeConfigurationParams 136 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 137 | validParams = true 138 | err = self.WorkspaceDidChangeConfiguration(context, ¶ms) 139 | } 140 | } 141 | 142 | case protocol316.MethodWorkspaceDidChangeWatchedFiles: 143 | if self.WorkspaceDidChangeWatchedFiles != nil { 144 | validMethod = true 145 | var params protocol316.DidChangeWatchedFilesParams 146 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 147 | validParams = true 148 | err = self.WorkspaceDidChangeWatchedFiles(context, ¶ms) 149 | } 150 | } 151 | 152 | case protocol316.MethodWorkspaceSymbol: 153 | if self.WorkspaceSymbol != nil { 154 | validMethod = true 155 | var params protocol316.WorkspaceSymbolParams 156 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 157 | validParams = true 158 | r, err = self.WorkspaceSymbol(context, ¶ms) 159 | } 160 | } 161 | 162 | case protocol316.MethodWorkspaceExecuteCommand: 163 | if self.WorkspaceExecuteCommand != nil { 164 | validMethod = true 165 | var params protocol316.ExecuteCommandParams 166 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 167 | validParams = true 168 | r, err = self.WorkspaceExecuteCommand(context, ¶ms) 169 | } 170 | } 171 | 172 | case protocol316.MethodWorkspaceWillCreateFiles: 173 | if self.WorkspaceWillCreateFiles != nil { 174 | validMethod = true 175 | var params protocol316.CreateFilesParams 176 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 177 | validParams = true 178 | r, err = self.WorkspaceWillCreateFiles(context, ¶ms) 179 | } 180 | } 181 | 182 | case protocol316.MethodWorkspaceDidCreateFiles: 183 | if self.WorkspaceDidCreateFiles != nil { 184 | validMethod = true 185 | var params protocol316.CreateFilesParams 186 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 187 | validParams = true 188 | err = self.WorkspaceDidCreateFiles(context, ¶ms) 189 | } 190 | } 191 | 192 | case protocol316.MethodWorkspaceWillRenameFiles: 193 | if self.WorkspaceWillRenameFiles != nil { 194 | validMethod = true 195 | var params protocol316.RenameFilesParams 196 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 197 | validParams = true 198 | r, err = self.WorkspaceWillRenameFiles(context, ¶ms) 199 | } 200 | } 201 | 202 | case protocol316.MethodWorkspaceDidRenameFiles: 203 | if self.WorkspaceDidRenameFiles != nil { 204 | validMethod = true 205 | var params protocol316.RenameFilesParams 206 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 207 | validParams = true 208 | err = self.WorkspaceDidRenameFiles(context, ¶ms) 209 | } 210 | } 211 | 212 | case protocol316.MethodWorkspaceWillDeleteFiles: 213 | if self.WorkspaceWillDeleteFiles != nil { 214 | validMethod = true 215 | var params protocol316.DeleteFilesParams 216 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 217 | validParams = true 218 | r, err = self.WorkspaceWillDeleteFiles(context, ¶ms) 219 | } 220 | } 221 | 222 | case protocol316.MethodWorkspaceDidDeleteFiles: 223 | if self.WorkspaceDidDeleteFiles != nil { 224 | validMethod = true 225 | var params protocol316.DeleteFilesParams 226 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 227 | validParams = true 228 | err = self.WorkspaceDidDeleteFiles(context, ¶ms) 229 | } 230 | } 231 | 232 | // Text Document Synchronization 233 | 234 | case protocol316.MethodTextDocumentDidOpen: 235 | if self.TextDocumentDidOpen != nil { 236 | validMethod = true 237 | var params protocol316.DidOpenTextDocumentParams 238 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 239 | validParams = true 240 | err = self.TextDocumentDidOpen(context, ¶ms) 241 | } 242 | } 243 | 244 | case protocol316.MethodTextDocumentDidChange: 245 | if self.TextDocumentDidChange != nil { 246 | validMethod = true 247 | var params protocol316.DidChangeTextDocumentParams 248 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 249 | validParams = true 250 | err = self.TextDocumentDidChange(context, ¶ms) 251 | } 252 | } 253 | 254 | case protocol316.MethodTextDocumentWillSave: 255 | if self.TextDocumentWillSave != nil { 256 | validMethod = true 257 | var params protocol316.WillSaveTextDocumentParams 258 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 259 | validParams = true 260 | err = self.TextDocumentWillSave(context, ¶ms) 261 | } 262 | } 263 | 264 | case protocol316.MethodTextDocumentWillSaveWaitUntil: 265 | if self.TextDocumentWillSaveWaitUntil != nil { 266 | validMethod = true 267 | var params protocol316.WillSaveTextDocumentParams 268 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 269 | validParams = true 270 | r, err = self.TextDocumentWillSaveWaitUntil(context, ¶ms) 271 | } 272 | } 273 | 274 | case protocol316.MethodTextDocumentDidSave: 275 | if self.TextDocumentDidSave != nil { 276 | validMethod = true 277 | var params protocol316.DidSaveTextDocumentParams 278 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 279 | validParams = true 280 | err = self.TextDocumentDidSave(context, ¶ms) 281 | } 282 | } 283 | 284 | case protocol316.MethodTextDocumentDidClose: 285 | if self.TextDocumentDidClose != nil { 286 | validMethod = true 287 | var params protocol316.DidCloseTextDocumentParams 288 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 289 | validParams = true 290 | err = self.TextDocumentDidClose(context, ¶ms) 291 | } 292 | } 293 | 294 | // Language Features 295 | 296 | case protocol316.MethodTextDocumentCompletion: 297 | if self.TextDocumentCompletion != nil { 298 | validMethod = true 299 | var params protocol316.CompletionParams 300 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 301 | validParams = true 302 | r, err = self.TextDocumentCompletion(context, ¶ms) 303 | } 304 | } 305 | 306 | case protocol316.MethodCompletionItemResolve: 307 | if self.CompletionItemResolve != nil { 308 | validMethod = true 309 | var params protocol316.CompletionItem 310 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 311 | validParams = true 312 | r, err = self.CompletionItemResolve(context, ¶ms) 313 | } 314 | } 315 | 316 | case protocol316.MethodTextDocumentHover: 317 | if self.TextDocumentHover != nil { 318 | validMethod = true 319 | var params protocol316.HoverParams 320 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 321 | validParams = true 322 | r, err = self.TextDocumentHover(context, ¶ms) 323 | } 324 | } 325 | 326 | case protocol316.MethodTextDocumentSignatureHelp: 327 | if self.TextDocumentSignatureHelp != nil { 328 | validMethod = true 329 | var params protocol316.SignatureHelpParams 330 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 331 | validParams = true 332 | r, err = self.TextDocumentSignatureHelp(context, ¶ms) 333 | } 334 | } 335 | 336 | case protocol316.MethodTextDocumentDeclaration: 337 | if self.TextDocumentDeclaration != nil { 338 | validMethod = true 339 | var params protocol316.DeclarationParams 340 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 341 | validParams = true 342 | r, err = self.TextDocumentDeclaration(context, ¶ms) 343 | } 344 | } 345 | 346 | case protocol316.MethodTextDocumentDefinition: 347 | if self.TextDocumentDefinition != nil { 348 | validMethod = true 349 | var params protocol316.DefinitionParams 350 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 351 | validParams = true 352 | r, err = self.TextDocumentDefinition(context, ¶ms) 353 | } 354 | } 355 | 356 | case protocol316.MethodTextDocumentTypeDefinition: 357 | if self.TextDocumentTypeDefinition != nil { 358 | validMethod = true 359 | var params protocol316.TypeDefinitionParams 360 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 361 | validParams = true 362 | r, err = self.TextDocumentTypeDefinition(context, ¶ms) 363 | } 364 | } 365 | 366 | case protocol316.MethodTextDocumentImplementation: 367 | if self.TextDocumentImplementation != nil { 368 | validMethod = true 369 | var params protocol316.ImplementationParams 370 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 371 | validParams = true 372 | r, err = self.TextDocumentImplementation(context, ¶ms) 373 | } 374 | } 375 | 376 | case protocol316.MethodTextDocumentReferences: 377 | if self.TextDocumentReferences != nil { 378 | validMethod = true 379 | var params protocol316.ReferenceParams 380 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 381 | validParams = true 382 | r, err = self.TextDocumentReferences(context, ¶ms) 383 | } 384 | } 385 | 386 | case protocol316.MethodTextDocumentDocumentHighlight: 387 | if self.TextDocumentDocumentHighlight != nil { 388 | validMethod = true 389 | var params protocol316.DocumentHighlightParams 390 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 391 | validParams = true 392 | r, err = self.TextDocumentDocumentHighlight(context, ¶ms) 393 | } 394 | } 395 | 396 | case protocol316.MethodTextDocumentDocumentSymbol: 397 | if self.TextDocumentDocumentSymbol != nil { 398 | validMethod = true 399 | var params protocol316.DocumentSymbolParams 400 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 401 | validParams = true 402 | r, err = self.TextDocumentDocumentSymbol(context, ¶ms) 403 | } 404 | } 405 | 406 | case protocol316.MethodTextDocumentCodeAction: 407 | if self.TextDocumentCodeAction != nil { 408 | validMethod = true 409 | var params protocol316.CodeActionParams 410 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 411 | validParams = true 412 | r, err = self.TextDocumentCodeAction(context, ¶ms) 413 | } 414 | } 415 | 416 | case protocol316.MethodCodeActionResolve: 417 | if self.CodeActionResolve != nil { 418 | validMethod = true 419 | var params protocol316.CodeAction 420 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 421 | validParams = true 422 | r, err = self.CodeActionResolve(context, ¶ms) 423 | } 424 | } 425 | 426 | case protocol316.MethodTextDocumentCodeLens: 427 | if self.TextDocumentCodeLens != nil { 428 | validMethod = true 429 | var params protocol316.CodeLensParams 430 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 431 | validParams = true 432 | r, err = self.TextDocumentCodeLens(context, ¶ms) 433 | } 434 | } 435 | 436 | case protocol316.MethodCodeLensResolve: 437 | if self.TextDocumentDidClose != nil { 438 | validMethod = true 439 | var params protocol316.CodeLens 440 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 441 | validParams = true 442 | r, err = self.CodeLensResolve(context, ¶ms) 443 | } 444 | } 445 | 446 | case protocol316.MethodTextDocumentDocumentLink: 447 | if self.TextDocumentDocumentLink != nil { 448 | validMethod = true 449 | var params protocol316.DocumentLinkParams 450 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 451 | validParams = true 452 | r, err = self.TextDocumentDocumentLink(context, ¶ms) 453 | } 454 | } 455 | 456 | case protocol316.MethodDocumentLinkResolve: 457 | if self.DocumentLinkResolve != nil { 458 | validMethod = true 459 | var params protocol316.DocumentLink 460 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 461 | validParams = true 462 | r, err = self.DocumentLinkResolve(context, ¶ms) 463 | } 464 | } 465 | 466 | case protocol316.MethodTextDocumentColor: 467 | if self.TextDocumentColor != nil { 468 | validMethod = true 469 | var params protocol316.DocumentColorParams 470 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 471 | validParams = true 472 | r, err = self.TextDocumentColor(context, ¶ms) 473 | } 474 | } 475 | 476 | case protocol316.MethodTextDocumentColorPresentation: 477 | if self.TextDocumentColorPresentation != nil { 478 | validMethod = true 479 | var params protocol316.ColorPresentationParams 480 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 481 | validParams = true 482 | r, err = self.TextDocumentColorPresentation(context, ¶ms) 483 | } 484 | } 485 | 486 | case protocol316.MethodTextDocumentFormatting: 487 | if self.TextDocumentFormatting != nil { 488 | validMethod = true 489 | var params protocol316.DocumentFormattingParams 490 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 491 | validParams = true 492 | r, err = self.TextDocumentFormatting(context, ¶ms) 493 | } 494 | } 495 | 496 | case protocol316.MethodTextDocumentRangeFormatting: 497 | if self.TextDocumentRangeFormatting != nil { 498 | validMethod = true 499 | var params protocol316.DocumentRangeFormattingParams 500 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 501 | validParams = true 502 | r, err = self.TextDocumentRangeFormatting(context, ¶ms) 503 | } 504 | } 505 | 506 | case protocol316.MethodTextDocumentOnTypeFormatting: 507 | if self.TextDocumentOnTypeFormatting != nil { 508 | validMethod = true 509 | var params protocol316.DocumentOnTypeFormattingParams 510 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 511 | validParams = true 512 | r, err = self.TextDocumentOnTypeFormatting(context, ¶ms) 513 | } 514 | } 515 | 516 | case protocol316.MethodTextDocumentRename: 517 | if self.TextDocumentRename != nil { 518 | validMethod = true 519 | var params protocol316.RenameParams 520 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 521 | validParams = true 522 | r, err = self.TextDocumentRename(context, ¶ms) 523 | } 524 | } 525 | 526 | case protocol316.MethodTextDocumentPrepareRename: 527 | if self.TextDocumentPrepareRename != nil { 528 | validMethod = true 529 | var params protocol316.PrepareRenameParams 530 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 531 | validParams = true 532 | r, err = self.TextDocumentPrepareRename(context, ¶ms) 533 | } 534 | } 535 | 536 | case protocol316.MethodTextDocumentFoldingRange: 537 | if self.TextDocumentFoldingRange != nil { 538 | validMethod = true 539 | var params protocol316.FoldingRangeParams 540 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 541 | validParams = true 542 | r, err = self.TextDocumentFoldingRange(context, ¶ms) 543 | } 544 | } 545 | 546 | case protocol316.MethodTextDocumentSelectionRange: 547 | if self.TextDocumentSelectionRange != nil { 548 | validMethod = true 549 | var params protocol316.SelectionRangeParams 550 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 551 | validParams = true 552 | r, err = self.TextDocumentSelectionRange(context, ¶ms) 553 | } 554 | } 555 | 556 | case protocol316.MethodTextDocumentPrepareCallHierarchy: 557 | if self.TextDocumentPrepareCallHierarchy != nil { 558 | validMethod = true 559 | var params protocol316.CallHierarchyPrepareParams 560 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 561 | validParams = true 562 | r, err = self.TextDocumentPrepareCallHierarchy(context, ¶ms) 563 | } 564 | } 565 | 566 | case protocol316.MethodCallHierarchyIncomingCalls: 567 | if self.CallHierarchyIncomingCalls != nil { 568 | validMethod = true 569 | var params protocol316.CallHierarchyIncomingCallsParams 570 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 571 | validParams = true 572 | r, err = self.CallHierarchyIncomingCalls(context, ¶ms) 573 | } 574 | } 575 | 576 | case protocol316.MethodCallHierarchyOutgoingCalls: 577 | if self.CallHierarchyOutgoingCalls != nil { 578 | validMethod = true 579 | var params protocol316.CallHierarchyOutgoingCallsParams 580 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 581 | validParams = true 582 | r, err = self.CallHierarchyOutgoingCalls(context, ¶ms) 583 | } 584 | } 585 | 586 | case protocol316.MethodTextDocumentSemanticTokensFull: 587 | if self.TextDocumentSemanticTokensFull != nil { 588 | validMethod = true 589 | var params protocol316.SemanticTokensParams 590 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 591 | validParams = true 592 | r, err = self.TextDocumentSemanticTokensFull(context, ¶ms) 593 | } 594 | } 595 | 596 | case protocol316.MethodTextDocumentSemanticTokensFullDelta: 597 | if self.TextDocumentSemanticTokensFullDelta != nil { 598 | validMethod = true 599 | var params protocol316.SemanticTokensDeltaParams 600 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 601 | validParams = true 602 | r, err = self.TextDocumentSemanticTokensFullDelta(context, ¶ms) 603 | } 604 | } 605 | 606 | case protocol316.MethodTextDocumentSemanticTokensRange: 607 | if self.TextDocumentSemanticTokensRange != nil { 608 | validMethod = true 609 | var params protocol316.SemanticTokensRangeParams 610 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 611 | validParams = true 612 | r, err = self.TextDocumentSemanticTokensRange(context, ¶ms) 613 | } 614 | } 615 | 616 | case protocol316.MethodWorkspaceSemanticTokensRefresh: 617 | if self.WorkspaceSemanticTokensRefresh != nil { 618 | validMethod = true 619 | validParams = true 620 | err = self.WorkspaceSemanticTokensRefresh(context) 621 | } 622 | 623 | case protocol316.MethodTextDocumentLinkedEditingRange: 624 | if self.TextDocumentLinkedEditingRange != nil { 625 | validMethod = true 626 | var params protocol316.LinkedEditingRangeParams 627 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 628 | validParams = true 629 | r, err = self.TextDocumentLinkedEditingRange(context, ¶ms) 630 | } 631 | } 632 | 633 | case protocol316.MethodTextDocumentMoniker: 634 | if self.TextDocumentMoniker != nil { 635 | validMethod = true 636 | var params protocol316.MonikerParams 637 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 638 | validParams = true 639 | r, err = self.TextDocumentMoniker(context, ¶ms) 640 | } 641 | } 642 | case MethodTextDocumentDiagnostic: 643 | if self.TextDocumentDiagnostic != nil { 644 | validMethod = true 645 | var params DocumentDiagnosticParams 646 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 647 | validParams = true 648 | r, err = self.TextDocumentDiagnostic(context, ¶ms) 649 | } 650 | } 651 | 652 | default: 653 | if self.CustomRequest != nil { 654 | if handler, ok := self.CustomRequest[context.Method]; ok && (handler.Func != nil) { 655 | validMethod = true 656 | if err = json.Unmarshal(context.Params, &handler.Params); err == nil { 657 | validParams = true 658 | r, err = handler.Func(context, handler.Params) 659 | } 660 | } 661 | } 662 | } 663 | 664 | return 665 | 666 | } 667 | 668 | func (self *Handler) IsInitialized() bool { 669 | self.lock.Lock() 670 | defer self.lock.Unlock() 671 | return self.initialized 672 | } 673 | 674 | func (self *Handler) SetInitialized(initialized bool) { 675 | self.lock.Lock() 676 | defer self.lock.Unlock() 677 | self.initialized = initialized 678 | } 679 | 680 | func (self *Handler) CreateServerCapabilities() ServerCapabilities { 681 | var capabilities ServerCapabilities 682 | 683 | if (self.TextDocumentDidOpen != nil) || (self.TextDocumentDidClose != nil) { 684 | if _, ok := capabilities.TextDocumentSync.(*protocol316.TextDocumentSyncOptions); !ok { 685 | capabilities.TextDocumentSync = &protocol316.TextDocumentSyncOptions{} 686 | } 687 | capabilities.TextDocumentSync.(*protocol316.TextDocumentSyncOptions).OpenClose = &protocol316.True 688 | } 689 | 690 | if self.TextDocumentDidChange != nil { 691 | if _, ok := capabilities.TextDocumentSync.(*protocol316.TextDocumentSyncOptions); !ok { 692 | capabilities.TextDocumentSync = &protocol316.TextDocumentSyncOptions{} 693 | } 694 | // This can be overriden to TextDocumentSyncKindFull 695 | value := protocol316.TextDocumentSyncKindIncremental 696 | capabilities.TextDocumentSync.(*protocol316.TextDocumentSyncOptions).Change = &value 697 | } 698 | 699 | if self.TextDocumentWillSave != nil { 700 | if _, ok := capabilities.TextDocumentSync.(*protocol316.TextDocumentSyncOptions); !ok { 701 | capabilities.TextDocumentSync = &protocol316.TextDocumentSyncOptions{} 702 | } 703 | capabilities.TextDocumentSync.(*protocol316.TextDocumentSyncOptions).WillSave = &protocol316.True 704 | } 705 | 706 | if self.TextDocumentWillSaveWaitUntil != nil { 707 | if _, ok := capabilities.TextDocumentSync.(*protocol316.TextDocumentSyncOptions); !ok { 708 | capabilities.TextDocumentSync = &protocol316.TextDocumentSyncOptions{} 709 | } 710 | capabilities.TextDocumentSync.(*protocol316.TextDocumentSyncOptions).WillSaveWaitUntil = &protocol316.True 711 | } 712 | 713 | if self.TextDocumentDidSave != nil { 714 | if _, ok := capabilities.TextDocumentSync.(*protocol316.TextDocumentSyncOptions); !ok { 715 | capabilities.TextDocumentSync = &protocol316.TextDocumentSyncOptions{} 716 | } 717 | capabilities.TextDocumentSync.(*protocol316.TextDocumentSyncOptions).Save = &protocol316.True 718 | } 719 | 720 | if self.TextDocumentCompletion != nil { 721 | capabilities.CompletionProvider = &protocol316.CompletionOptions{} 722 | } 723 | 724 | if self.TextDocumentHover != nil { 725 | capabilities.HoverProvider = true 726 | } 727 | 728 | if self.TextDocumentSignatureHelp != nil { 729 | capabilities.SignatureHelpProvider = &protocol316.SignatureHelpOptions{} 730 | } 731 | 732 | if self.TextDocumentDeclaration != nil { 733 | capabilities.DeclarationProvider = true 734 | } 735 | 736 | if self.TextDocumentDefinition != nil { 737 | capabilities.DefinitionProvider = true 738 | } 739 | 740 | if self.TextDocumentTypeDefinition != nil { 741 | capabilities.TypeDefinitionProvider = true 742 | } 743 | 744 | if self.TextDocumentImplementation != nil { 745 | capabilities.ImplementationProvider = true 746 | } 747 | 748 | if self.TextDocumentReferences != nil { 749 | capabilities.ReferencesProvider = true 750 | } 751 | 752 | if self.TextDocumentDocumentHighlight != nil { 753 | capabilities.DocumentHighlightProvider = true 754 | } 755 | 756 | if self.TextDocumentDocumentSymbol != nil { 757 | capabilities.DocumentSymbolProvider = true 758 | } 759 | 760 | if self.TextDocumentCodeAction != nil { 761 | capabilities.CodeActionProvider = true 762 | } 763 | 764 | if self.TextDocumentCodeLens != nil { 765 | capabilities.CodeLensProvider = &protocol316.CodeLensOptions{} 766 | } 767 | 768 | if self.TextDocumentDocumentLink != nil { 769 | capabilities.DocumentLinkProvider = &protocol316.DocumentLinkOptions{} 770 | } 771 | 772 | if self.TextDocumentColor != nil { 773 | capabilities.ColorProvider = true 774 | } 775 | 776 | if self.TextDocumentFormatting != nil { 777 | capabilities.DocumentFormattingProvider = true 778 | } 779 | 780 | if self.TextDocumentRangeFormatting != nil { 781 | capabilities.DocumentRangeFormattingProvider = true 782 | } 783 | 784 | if self.TextDocumentOnTypeFormatting != nil { 785 | capabilities.DocumentOnTypeFormattingProvider = &protocol316.DocumentOnTypeFormattingOptions{} 786 | } 787 | 788 | if self.TextDocumentRename != nil { 789 | capabilities.RenameProvider = true 790 | } 791 | 792 | if self.TextDocumentFoldingRange != nil { 793 | capabilities.FoldingRangeProvider = true 794 | } 795 | 796 | if self.WorkspaceExecuteCommand != nil { 797 | capabilities.ExecuteCommandProvider = &protocol316.ExecuteCommandOptions{} 798 | } 799 | 800 | if self.TextDocumentSelectionRange != nil { 801 | capabilities.SelectionRangeProvider = true 802 | } 803 | 804 | if self.TextDocumentLinkedEditingRange != nil { 805 | capabilities.LinkedEditingRangeProvider = true 806 | } 807 | 808 | if self.TextDocumentPrepareCallHierarchy != nil { 809 | capabilities.CallHierarchyProvider = true 810 | } 811 | 812 | if self.TextDocumentSemanticTokensFull != nil { 813 | if _, ok := capabilities.SemanticTokensProvider.(*protocol316.SemanticTokensOptions); !ok { 814 | capabilities.SemanticTokensProvider = &protocol316.SemanticTokensOptions{} 815 | } 816 | if self.TextDocumentSemanticTokensFullDelta != nil { 817 | capabilities.SemanticTokensProvider.(*protocol316.SemanticTokensOptions).Full = &protocol316.SemanticDelta{} 818 | capabilities.SemanticTokensProvider.(*protocol316.SemanticTokensOptions).Full.(*protocol316.SemanticDelta).Delta = &protocol316.True 819 | } else { 820 | capabilities.SemanticTokensProvider.(*protocol316.SemanticTokensOptions).Full = true 821 | } 822 | } 823 | 824 | if self.TextDocumentSemanticTokensRange != nil { 825 | if _, ok := capabilities.SemanticTokensProvider.(*protocol316.SemanticTokensOptions); !ok { 826 | capabilities.SemanticTokensProvider = &protocol316.SemanticTokensOptions{} 827 | } 828 | capabilities.SemanticTokensProvider.(*protocol316.SemanticTokensOptions).Range = true 829 | } 830 | 831 | // TODO: self.TextDocumentSemanticTokensRefresh? 832 | 833 | if self.TextDocumentMoniker != nil { 834 | capabilities.MonikerProvider = true 835 | } 836 | 837 | if self.WorkspaceSymbol != nil { 838 | capabilities.WorkspaceSymbolProvider = true 839 | } 840 | 841 | if self.WorkspaceDidCreateFiles != nil { 842 | if capabilities.Workspace == nil { 843 | capabilities.Workspace = &protocol316.ServerCapabilitiesWorkspace{} 844 | } 845 | if capabilities.Workspace.FileOperations == nil { 846 | capabilities.Workspace.FileOperations = &protocol316.ServerCapabilitiesWorkspaceFileOperations{} 847 | } 848 | capabilities.Workspace.FileOperations.DidCreate = &protocol316.FileOperationRegistrationOptions{ 849 | Filters: []protocol316.FileOperationFilter{}, 850 | } 851 | } 852 | 853 | if self.WorkspaceWillCreateFiles != nil { 854 | if capabilities.Workspace == nil { 855 | capabilities.Workspace = &protocol316.ServerCapabilitiesWorkspace{} 856 | } 857 | if capabilities.Workspace.FileOperations == nil { 858 | capabilities.Workspace.FileOperations = &protocol316.ServerCapabilitiesWorkspaceFileOperations{} 859 | } 860 | capabilities.Workspace.FileOperations.WillCreate = &protocol316.FileOperationRegistrationOptions{ 861 | Filters: []protocol316.FileOperationFilter{}, 862 | } 863 | } 864 | 865 | if self.WorkspaceDidRenameFiles != nil { 866 | capabilities.RenameProvider = true 867 | if capabilities.Workspace == nil { 868 | capabilities.Workspace = &protocol316.ServerCapabilitiesWorkspace{} 869 | } 870 | if capabilities.Workspace.FileOperations == nil { 871 | capabilities.Workspace.FileOperations = &protocol316.ServerCapabilitiesWorkspaceFileOperations{} 872 | } 873 | capabilities.Workspace.FileOperations.DidRename = &protocol316.FileOperationRegistrationOptions{ 874 | Filters: []protocol316.FileOperationFilter{}, 875 | } 876 | } 877 | 878 | if self.WorkspaceWillRenameFiles != nil { 879 | capabilities.RenameProvider = true 880 | if capabilities.Workspace == nil { 881 | capabilities.Workspace = &protocol316.ServerCapabilitiesWorkspace{} 882 | } 883 | if capabilities.Workspace.FileOperations == nil { 884 | capabilities.Workspace.FileOperations = &protocol316.ServerCapabilitiesWorkspaceFileOperations{} 885 | } 886 | capabilities.Workspace.FileOperations.WillRename = &protocol316.FileOperationRegistrationOptions{ 887 | Filters: []protocol316.FileOperationFilter{}, 888 | } 889 | } 890 | 891 | if self.WorkspaceDidDeleteFiles != nil { 892 | if capabilities.Workspace == nil { 893 | capabilities.Workspace = &protocol316.ServerCapabilitiesWorkspace{} 894 | } 895 | if capabilities.Workspace.FileOperations == nil { 896 | capabilities.Workspace.FileOperations = &protocol316.ServerCapabilitiesWorkspaceFileOperations{} 897 | } 898 | capabilities.Workspace.FileOperations.DidDelete = &protocol316.FileOperationRegistrationOptions{ 899 | Filters: []protocol316.FileOperationFilter{}, 900 | } 901 | } 902 | 903 | if self.WorkspaceWillDeleteFiles != nil { 904 | if capabilities.Workspace == nil { 905 | capabilities.Workspace = &protocol316.ServerCapabilitiesWorkspace{} 906 | } 907 | if capabilities.Workspace.FileOperations == nil { 908 | capabilities.Workspace.FileOperations = &protocol316.ServerCapabilitiesWorkspaceFileOperations{} 909 | } 910 | capabilities.Workspace.FileOperations.WillDelete = &protocol316.FileOperationRegistrationOptions{ 911 | Filters: []protocol316.FileOperationFilter{}, 912 | } 913 | } 914 | 915 | if self.TextDocumentDiagnostic != nil { 916 | capabilities.DiagnosticProvider = DiagnosticOptions{ 917 | InterFileDependencies: true, 918 | WorkspaceDiagnostics: false, 919 | } 920 | } 921 | 922 | return capabilities 923 | } 924 | -------------------------------------------------------------------------------- /protocol_3_16/handler.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "sync" 7 | 8 | "github.com/tliron/glsp" 9 | ) 10 | 11 | type Handler struct { 12 | // Base Protocol 13 | CancelRequest CancelRequestFunc 14 | Progress ProgressFunc 15 | 16 | // General Messages 17 | Initialize InitializeFunc 18 | Initialized InitializedFunc 19 | Shutdown ShutdownFunc 20 | Exit ExitFunc 21 | LogTrace LogTraceFunc 22 | SetTrace SetTraceFunc 23 | 24 | // Window 25 | WindowWorkDoneProgressCancel WindowWorkDoneProgressCancelFunc 26 | 27 | // Workspace 28 | WorkspaceDidChangeWorkspaceFolders WorkspaceDidChangeWorkspaceFoldersFunc 29 | WorkspaceDidChangeConfiguration WorkspaceDidChangeConfigurationFunc 30 | WorkspaceDidChangeWatchedFiles WorkspaceDidChangeWatchedFilesFunc 31 | WorkspaceSymbol WorkspaceSymbolFunc 32 | WorkspaceExecuteCommand WorkspaceExecuteCommandFunc 33 | WorkspaceWillCreateFiles WorkspaceWillCreateFilesFunc 34 | WorkspaceDidCreateFiles WorkspaceDidCreateFilesFunc 35 | WorkspaceWillRenameFiles WorkspaceWillRenameFilesFunc 36 | WorkspaceDidRenameFiles WorkspaceDidRenameFilesFunc 37 | WorkspaceWillDeleteFiles WorkspaceWillDeleteFilesFunc 38 | WorkspaceDidDeleteFiles WorkspaceDidDeleteFilesFunc 39 | WorkspaceSemanticTokensRefresh WorkspaceSemanticTokensRefreshFunc 40 | 41 | // Text Document Synchronization 42 | TextDocumentDidOpen TextDocumentDidOpenFunc 43 | TextDocumentDidChange TextDocumentDidChangeFunc 44 | TextDocumentWillSave TextDocumentWillSaveFunc 45 | TextDocumentWillSaveWaitUntil TextDocumentWillSaveWaitUntilFunc 46 | TextDocumentDidSave TextDocumentDidSaveFunc 47 | TextDocumentDidClose TextDocumentDidCloseFunc 48 | 49 | // Language Features 50 | TextDocumentCompletion TextDocumentCompletionFunc 51 | CompletionItemResolve CompletionItemResolveFunc 52 | TextDocumentHover TextDocumentHoverFunc 53 | TextDocumentSignatureHelp TextDocumentSignatureHelpFunc 54 | TextDocumentDeclaration TextDocumentDeclarationFunc 55 | TextDocumentDefinition TextDocumentDefinitionFunc 56 | TextDocumentTypeDefinition TextDocumentTypeDefinitionFunc 57 | TextDocumentImplementation TextDocumentImplementationFunc 58 | TextDocumentReferences TextDocumentReferencesFunc 59 | TextDocumentDocumentHighlight TextDocumentDocumentHighlightFunc 60 | TextDocumentDocumentSymbol TextDocumentDocumentSymbolFunc 61 | TextDocumentCodeAction TextDocumentCodeActionFunc 62 | CodeActionResolve CodeActionResolveFunc 63 | TextDocumentCodeLens TextDocumentCodeLensFunc 64 | CodeLensResolve CodeLensResolveFunc 65 | TextDocumentDocumentLink TextDocumentDocumentLinkFunc 66 | DocumentLinkResolve DocumentLinkResolveFunc 67 | TextDocumentColor TextDocumentColorFunc 68 | TextDocumentColorPresentation TextDocumentColorPresentationFunc 69 | TextDocumentFormatting TextDocumentFormattingFunc 70 | TextDocumentRangeFormatting TextDocumentRangeFormattingFunc 71 | TextDocumentOnTypeFormatting TextDocumentOnTypeFormattingFunc 72 | TextDocumentRename TextDocumentRenameFunc 73 | TextDocumentPrepareRename TextDocumentPrepareRenameFunc 74 | TextDocumentFoldingRange TextDocumentFoldingRangeFunc 75 | TextDocumentSelectionRange TextDocumentSelectionRangeFunc 76 | TextDocumentPrepareCallHierarchy TextDocumentPrepareCallHierarchyFunc 77 | CallHierarchyIncomingCalls CallHierarchyIncomingCallsFunc 78 | CallHierarchyOutgoingCalls CallHierarchyOutgoingCallsFunc 79 | TextDocumentSemanticTokensFull TextDocumentSemanticTokensFullFunc 80 | TextDocumentSemanticTokensFullDelta TextDocumentSemanticTokensFullDeltaFunc 81 | TextDocumentSemanticTokensRange TextDocumentSemanticTokensRangeFunc 82 | TextDocumentLinkedEditingRange TextDocumentLinkedEditingRangeFunc 83 | TextDocumentMoniker TextDocumentMonikerFunc 84 | 85 | // Custom Request/Notification 86 | CustomRequest map[string]CustomRequestHandler 87 | 88 | initialized bool 89 | lock sync.Mutex 90 | } 91 | 92 | // ([glsp.Handler] interface) 93 | func (self *Handler) Handle(context *glsp.Context) (r any, validMethod bool, validParams bool, err error) { 94 | if !self.IsInitialized() && (context.Method != MethodInitialize) { 95 | return nil, true, true, errors.New("server not initialized") 96 | } 97 | 98 | switch context.Method { 99 | // Base Protocol 100 | 101 | case MethodCancelRequest: 102 | if self.CancelRequest != nil { 103 | validMethod = true 104 | var params CancelParams 105 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 106 | validParams = true 107 | err = self.CancelRequest(context, ¶ms) 108 | } 109 | } 110 | 111 | case MethodProgress: 112 | if self.Progress != nil { 113 | validMethod = true 114 | var params ProgressParams 115 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 116 | validParams = true 117 | err = self.Progress(context, ¶ms) 118 | } 119 | } 120 | 121 | // General Messages 122 | 123 | case MethodInitialize: 124 | if self.Initialize != nil { 125 | validMethod = true 126 | var params InitializeParams 127 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 128 | validParams = true 129 | if r, err = self.Initialize(context, ¶ms); err == nil { 130 | self.SetInitialized(true) 131 | } 132 | } 133 | } 134 | 135 | case MethodInitialized: 136 | if self.Initialized != nil { 137 | validMethod = true 138 | var params InitializedParams 139 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 140 | validParams = true 141 | err = self.Initialized(context, ¶ms) 142 | } 143 | } 144 | 145 | case MethodShutdown: 146 | self.SetInitialized(false) 147 | if self.Shutdown != nil { 148 | validMethod = true 149 | validParams = true 150 | err = self.Shutdown(context) 151 | } 152 | 153 | case MethodExit: 154 | // Note that the server will close the connection after we handle it here 155 | if self.Exit != nil { 156 | validMethod = true 157 | validParams = true 158 | err = self.Exit(context) 159 | } 160 | 161 | case MethodLogTrace: 162 | if self.LogTrace != nil { 163 | validMethod = true 164 | var params LogTraceParams 165 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 166 | validParams = true 167 | err = self.LogTrace(context, ¶ms) 168 | } 169 | } 170 | 171 | case MethodSetTrace: 172 | if self.SetTrace != nil { 173 | validMethod = true 174 | var params SetTraceParams 175 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 176 | validParams = true 177 | err = self.SetTrace(context, ¶ms) 178 | } 179 | } 180 | 181 | // Window 182 | 183 | case MethodWindowWorkDoneProgressCancel: 184 | if self.WindowWorkDoneProgressCancel != nil { 185 | validMethod = true 186 | var params WorkDoneProgressCancelParams 187 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 188 | validParams = true 189 | err = self.WindowWorkDoneProgressCancel(context, ¶ms) 190 | } 191 | } 192 | 193 | // Workspace 194 | 195 | case MethodWorkspaceDidChangeWorkspaceFolders: 196 | if self.WorkspaceDidChangeWorkspaceFolders != nil { 197 | validMethod = true 198 | var params DidChangeWorkspaceFoldersParams 199 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 200 | validParams = true 201 | err = self.WorkspaceDidChangeWorkspaceFolders(context, ¶ms) 202 | } 203 | } 204 | 205 | case MethodWorkspaceDidChangeConfiguration: 206 | if self.WorkspaceDidChangeConfiguration != nil { 207 | validMethod = true 208 | var params DidChangeConfigurationParams 209 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 210 | validParams = true 211 | err = self.WorkspaceDidChangeConfiguration(context, ¶ms) 212 | } 213 | } 214 | 215 | case MethodWorkspaceDidChangeWatchedFiles: 216 | if self.WorkspaceDidChangeWatchedFiles != nil { 217 | validMethod = true 218 | var params DidChangeWatchedFilesParams 219 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 220 | validParams = true 221 | err = self.WorkspaceDidChangeWatchedFiles(context, ¶ms) 222 | } 223 | } 224 | 225 | case MethodWorkspaceSymbol: 226 | if self.WorkspaceSymbol != nil { 227 | validMethod = true 228 | var params WorkspaceSymbolParams 229 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 230 | validParams = true 231 | r, err = self.WorkspaceSymbol(context, ¶ms) 232 | } 233 | } 234 | 235 | case MethodWorkspaceExecuteCommand: 236 | if self.WorkspaceExecuteCommand != nil { 237 | validMethod = true 238 | var params ExecuteCommandParams 239 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 240 | validParams = true 241 | r, err = self.WorkspaceExecuteCommand(context, ¶ms) 242 | } 243 | } 244 | 245 | case MethodWorkspaceWillCreateFiles: 246 | if self.WorkspaceWillCreateFiles != nil { 247 | validMethod = true 248 | var params CreateFilesParams 249 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 250 | validParams = true 251 | r, err = self.WorkspaceWillCreateFiles(context, ¶ms) 252 | } 253 | } 254 | 255 | case MethodWorkspaceDidCreateFiles: 256 | if self.WorkspaceDidCreateFiles != nil { 257 | validMethod = true 258 | var params CreateFilesParams 259 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 260 | validParams = true 261 | err = self.WorkspaceDidCreateFiles(context, ¶ms) 262 | } 263 | } 264 | 265 | case MethodWorkspaceWillRenameFiles: 266 | if self.WorkspaceWillRenameFiles != nil { 267 | validMethod = true 268 | var params RenameFilesParams 269 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 270 | validParams = true 271 | r, err = self.WorkspaceWillRenameFiles(context, ¶ms) 272 | } 273 | } 274 | 275 | case MethodWorkspaceDidRenameFiles: 276 | if self.WorkspaceDidRenameFiles != nil { 277 | validMethod = true 278 | var params RenameFilesParams 279 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 280 | validParams = true 281 | err = self.WorkspaceDidRenameFiles(context, ¶ms) 282 | } 283 | } 284 | 285 | case MethodWorkspaceWillDeleteFiles: 286 | if self.WorkspaceWillDeleteFiles != nil { 287 | validMethod = true 288 | var params DeleteFilesParams 289 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 290 | validParams = true 291 | r, err = self.WorkspaceWillDeleteFiles(context, ¶ms) 292 | } 293 | } 294 | 295 | case MethodWorkspaceDidDeleteFiles: 296 | if self.WorkspaceDidDeleteFiles != nil { 297 | validMethod = true 298 | var params DeleteFilesParams 299 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 300 | validParams = true 301 | err = self.WorkspaceDidDeleteFiles(context, ¶ms) 302 | } 303 | } 304 | 305 | // Text Document Synchronization 306 | 307 | case MethodTextDocumentDidOpen: 308 | if self.TextDocumentDidOpen != nil { 309 | validMethod = true 310 | var params DidOpenTextDocumentParams 311 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 312 | validParams = true 313 | err = self.TextDocumentDidOpen(context, ¶ms) 314 | } 315 | } 316 | 317 | case MethodTextDocumentDidChange: 318 | if self.TextDocumentDidChange != nil { 319 | validMethod = true 320 | var params DidChangeTextDocumentParams 321 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 322 | validParams = true 323 | err = self.TextDocumentDidChange(context, ¶ms) 324 | } 325 | } 326 | 327 | case MethodTextDocumentWillSave: 328 | if self.TextDocumentWillSave != nil { 329 | validMethod = true 330 | var params WillSaveTextDocumentParams 331 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 332 | validParams = true 333 | err = self.TextDocumentWillSave(context, ¶ms) 334 | } 335 | } 336 | 337 | case MethodTextDocumentWillSaveWaitUntil: 338 | if self.TextDocumentWillSaveWaitUntil != nil { 339 | validMethod = true 340 | var params WillSaveTextDocumentParams 341 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 342 | validParams = true 343 | r, err = self.TextDocumentWillSaveWaitUntil(context, ¶ms) 344 | } 345 | } 346 | 347 | case MethodTextDocumentDidSave: 348 | if self.TextDocumentDidSave != nil { 349 | validMethod = true 350 | var params DidSaveTextDocumentParams 351 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 352 | validParams = true 353 | err = self.TextDocumentDidSave(context, ¶ms) 354 | } 355 | } 356 | 357 | case MethodTextDocumentDidClose: 358 | if self.TextDocumentDidClose != nil { 359 | validMethod = true 360 | var params DidCloseTextDocumentParams 361 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 362 | validParams = true 363 | err = self.TextDocumentDidClose(context, ¶ms) 364 | } 365 | } 366 | 367 | // Language Features 368 | 369 | case MethodTextDocumentCompletion: 370 | if self.TextDocumentCompletion != nil { 371 | validMethod = true 372 | var params CompletionParams 373 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 374 | validParams = true 375 | r, err = self.TextDocumentCompletion(context, ¶ms) 376 | } 377 | } 378 | 379 | case MethodCompletionItemResolve: 380 | if self.CompletionItemResolve != nil { 381 | validMethod = true 382 | var params CompletionItem 383 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 384 | validParams = true 385 | r, err = self.CompletionItemResolve(context, ¶ms) 386 | } 387 | } 388 | 389 | case MethodTextDocumentHover: 390 | if self.TextDocumentHover != nil { 391 | validMethod = true 392 | var params HoverParams 393 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 394 | validParams = true 395 | r, err = self.TextDocumentHover(context, ¶ms) 396 | } 397 | } 398 | 399 | case MethodTextDocumentSignatureHelp: 400 | if self.TextDocumentSignatureHelp != nil { 401 | validMethod = true 402 | var params SignatureHelpParams 403 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 404 | validParams = true 405 | r, err = self.TextDocumentSignatureHelp(context, ¶ms) 406 | } 407 | } 408 | 409 | case MethodTextDocumentDeclaration: 410 | if self.TextDocumentDeclaration != nil { 411 | validMethod = true 412 | var params DeclarationParams 413 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 414 | validParams = true 415 | r, err = self.TextDocumentDeclaration(context, ¶ms) 416 | } 417 | } 418 | 419 | case MethodTextDocumentDefinition: 420 | if self.TextDocumentDefinition != nil { 421 | validMethod = true 422 | var params DefinitionParams 423 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 424 | validParams = true 425 | r, err = self.TextDocumentDefinition(context, ¶ms) 426 | } 427 | } 428 | 429 | case MethodTextDocumentTypeDefinition: 430 | if self.TextDocumentTypeDefinition != nil { 431 | validMethod = true 432 | var params TypeDefinitionParams 433 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 434 | validParams = true 435 | r, err = self.TextDocumentTypeDefinition(context, ¶ms) 436 | } 437 | } 438 | 439 | case MethodTextDocumentImplementation: 440 | if self.TextDocumentImplementation != nil { 441 | validMethod = true 442 | var params ImplementationParams 443 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 444 | validParams = true 445 | r, err = self.TextDocumentImplementation(context, ¶ms) 446 | } 447 | } 448 | 449 | case MethodTextDocumentReferences: 450 | if self.TextDocumentReferences != nil { 451 | validMethod = true 452 | var params ReferenceParams 453 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 454 | validParams = true 455 | r, err = self.TextDocumentReferences(context, ¶ms) 456 | } 457 | } 458 | 459 | case MethodTextDocumentDocumentHighlight: 460 | if self.TextDocumentDocumentHighlight != nil { 461 | validMethod = true 462 | var params DocumentHighlightParams 463 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 464 | validParams = true 465 | r, err = self.TextDocumentDocumentHighlight(context, ¶ms) 466 | } 467 | } 468 | 469 | case MethodTextDocumentDocumentSymbol: 470 | if self.TextDocumentDocumentSymbol != nil { 471 | validMethod = true 472 | var params DocumentSymbolParams 473 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 474 | validParams = true 475 | r, err = self.TextDocumentDocumentSymbol(context, ¶ms) 476 | } 477 | } 478 | 479 | case MethodTextDocumentCodeAction: 480 | if self.TextDocumentCodeAction != nil { 481 | validMethod = true 482 | var params CodeActionParams 483 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 484 | validParams = true 485 | r, err = self.TextDocumentCodeAction(context, ¶ms) 486 | } 487 | } 488 | 489 | case MethodCodeActionResolve: 490 | if self.CodeActionResolve != nil { 491 | validMethod = true 492 | var params CodeAction 493 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 494 | validParams = true 495 | r, err = self.CodeActionResolve(context, ¶ms) 496 | } 497 | } 498 | 499 | case MethodTextDocumentCodeLens: 500 | if self.TextDocumentCodeLens != nil { 501 | validMethod = true 502 | var params CodeLensParams 503 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 504 | validParams = true 505 | r, err = self.TextDocumentCodeLens(context, ¶ms) 506 | } 507 | } 508 | 509 | case MethodCodeLensResolve: 510 | if self.TextDocumentDidClose != nil { 511 | validMethod = true 512 | var params CodeLens 513 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 514 | validParams = true 515 | r, err = self.CodeLensResolve(context, ¶ms) 516 | } 517 | } 518 | 519 | case MethodTextDocumentDocumentLink: 520 | if self.TextDocumentDocumentLink != nil { 521 | validMethod = true 522 | var params DocumentLinkParams 523 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 524 | validParams = true 525 | r, err = self.TextDocumentDocumentLink(context, ¶ms) 526 | } 527 | } 528 | 529 | case MethodDocumentLinkResolve: 530 | if self.DocumentLinkResolve != nil { 531 | validMethod = true 532 | var params DocumentLink 533 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 534 | validParams = true 535 | r, err = self.DocumentLinkResolve(context, ¶ms) 536 | } 537 | } 538 | 539 | case MethodTextDocumentColor: 540 | if self.TextDocumentColor != nil { 541 | validMethod = true 542 | var params DocumentColorParams 543 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 544 | validParams = true 545 | r, err = self.TextDocumentColor(context, ¶ms) 546 | } 547 | } 548 | 549 | case MethodTextDocumentColorPresentation: 550 | if self.TextDocumentColorPresentation != nil { 551 | validMethod = true 552 | var params ColorPresentationParams 553 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 554 | validParams = true 555 | r, err = self.TextDocumentColorPresentation(context, ¶ms) 556 | } 557 | } 558 | 559 | case MethodTextDocumentFormatting: 560 | if self.TextDocumentFormatting != nil { 561 | validMethod = true 562 | var params DocumentFormattingParams 563 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 564 | validParams = true 565 | r, err = self.TextDocumentFormatting(context, ¶ms) 566 | } 567 | } 568 | 569 | case MethodTextDocumentRangeFormatting: 570 | if self.TextDocumentRangeFormatting != nil { 571 | validMethod = true 572 | var params DocumentRangeFormattingParams 573 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 574 | validParams = true 575 | r, err = self.TextDocumentRangeFormatting(context, ¶ms) 576 | } 577 | } 578 | 579 | case MethodTextDocumentOnTypeFormatting: 580 | if self.TextDocumentOnTypeFormatting != nil { 581 | validMethod = true 582 | var params DocumentOnTypeFormattingParams 583 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 584 | validParams = true 585 | r, err = self.TextDocumentOnTypeFormatting(context, ¶ms) 586 | } 587 | } 588 | 589 | case MethodTextDocumentRename: 590 | if self.TextDocumentRename != nil { 591 | validMethod = true 592 | var params RenameParams 593 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 594 | validParams = true 595 | r, err = self.TextDocumentRename(context, ¶ms) 596 | } 597 | } 598 | 599 | case MethodTextDocumentPrepareRename: 600 | if self.TextDocumentPrepareRename != nil { 601 | validMethod = true 602 | var params PrepareRenameParams 603 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 604 | validParams = true 605 | r, err = self.TextDocumentPrepareRename(context, ¶ms) 606 | } 607 | } 608 | 609 | case MethodTextDocumentFoldingRange: 610 | if self.TextDocumentFoldingRange != nil { 611 | validMethod = true 612 | var params FoldingRangeParams 613 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 614 | validParams = true 615 | r, err = self.TextDocumentFoldingRange(context, ¶ms) 616 | } 617 | } 618 | 619 | case MethodTextDocumentSelectionRange: 620 | if self.TextDocumentSelectionRange != nil { 621 | validMethod = true 622 | var params SelectionRangeParams 623 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 624 | validParams = true 625 | r, err = self.TextDocumentSelectionRange(context, ¶ms) 626 | } 627 | } 628 | 629 | case MethodTextDocumentPrepareCallHierarchy: 630 | if self.TextDocumentPrepareCallHierarchy != nil { 631 | validMethod = true 632 | var params CallHierarchyPrepareParams 633 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 634 | validParams = true 635 | r, err = self.TextDocumentPrepareCallHierarchy(context, ¶ms) 636 | } 637 | } 638 | 639 | case MethodCallHierarchyIncomingCalls: 640 | if self.CallHierarchyIncomingCalls != nil { 641 | validMethod = true 642 | var params CallHierarchyIncomingCallsParams 643 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 644 | validParams = true 645 | r, err = self.CallHierarchyIncomingCalls(context, ¶ms) 646 | } 647 | } 648 | 649 | case MethodCallHierarchyOutgoingCalls: 650 | if self.CallHierarchyOutgoingCalls != nil { 651 | validMethod = true 652 | var params CallHierarchyOutgoingCallsParams 653 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 654 | validParams = true 655 | r, err = self.CallHierarchyOutgoingCalls(context, ¶ms) 656 | } 657 | } 658 | 659 | case MethodTextDocumentSemanticTokensFull: 660 | if self.TextDocumentSemanticTokensFull != nil { 661 | validMethod = true 662 | var params SemanticTokensParams 663 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 664 | validParams = true 665 | r, err = self.TextDocumentSemanticTokensFull(context, ¶ms) 666 | } 667 | } 668 | 669 | case MethodTextDocumentSemanticTokensFullDelta: 670 | if self.TextDocumentSemanticTokensFullDelta != nil { 671 | validMethod = true 672 | var params SemanticTokensDeltaParams 673 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 674 | validParams = true 675 | r, err = self.TextDocumentSemanticTokensFullDelta(context, ¶ms) 676 | } 677 | } 678 | 679 | case MethodTextDocumentSemanticTokensRange: 680 | if self.TextDocumentSemanticTokensRange != nil { 681 | validMethod = true 682 | var params SemanticTokensRangeParams 683 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 684 | validParams = true 685 | r, err = self.TextDocumentSemanticTokensRange(context, ¶ms) 686 | } 687 | } 688 | 689 | case MethodWorkspaceSemanticTokensRefresh: 690 | if self.WorkspaceSemanticTokensRefresh != nil { 691 | validMethod = true 692 | validParams = true 693 | err = self.WorkspaceSemanticTokensRefresh(context) 694 | } 695 | 696 | case MethodTextDocumentLinkedEditingRange: 697 | if self.TextDocumentLinkedEditingRange != nil { 698 | validMethod = true 699 | var params LinkedEditingRangeParams 700 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 701 | validParams = true 702 | r, err = self.TextDocumentLinkedEditingRange(context, ¶ms) 703 | } 704 | } 705 | 706 | case MethodTextDocumentMoniker: 707 | if self.TextDocumentMoniker != nil { 708 | validMethod = true 709 | var params MonikerParams 710 | if err = json.Unmarshal(context.Params, ¶ms); err == nil { 711 | validParams = true 712 | r, err = self.TextDocumentMoniker(context, ¶ms) 713 | } 714 | } 715 | 716 | default: 717 | if self.CustomRequest != nil { 718 | if handler, ok := self.CustomRequest[context.Method]; ok && (handler.Func != nil) { 719 | validMethod = true 720 | if err = json.Unmarshal(context.Params, &handler.Params); err == nil { 721 | validParams = true 722 | r, err = handler.Func(context, handler.Params) 723 | } 724 | } 725 | } 726 | } 727 | 728 | return 729 | } 730 | 731 | func (self *Handler) IsInitialized() bool { 732 | self.lock.Lock() 733 | defer self.lock.Unlock() 734 | return self.initialized 735 | } 736 | 737 | func (self *Handler) SetInitialized(initialized bool) { 738 | self.lock.Lock() 739 | defer self.lock.Unlock() 740 | self.initialized = initialized 741 | } 742 | 743 | func (self *Handler) CreateServerCapabilities() ServerCapabilities { 744 | var capabilities ServerCapabilities 745 | 746 | if (self.TextDocumentDidOpen != nil) || (self.TextDocumentDidClose != nil) { 747 | if _, ok := capabilities.TextDocumentSync.(*TextDocumentSyncOptions); !ok { 748 | capabilities.TextDocumentSync = &TextDocumentSyncOptions{} 749 | } 750 | capabilities.TextDocumentSync.(*TextDocumentSyncOptions).OpenClose = &True 751 | } 752 | 753 | if self.TextDocumentDidChange != nil { 754 | if _, ok := capabilities.TextDocumentSync.(*TextDocumentSyncOptions); !ok { 755 | capabilities.TextDocumentSync = &TextDocumentSyncOptions{} 756 | } 757 | // This can be overriden to TextDocumentSyncKindFull 758 | value := TextDocumentSyncKindIncremental 759 | capabilities.TextDocumentSync.(*TextDocumentSyncOptions).Change = &value 760 | } 761 | 762 | if self.TextDocumentWillSave != nil { 763 | if _, ok := capabilities.TextDocumentSync.(*TextDocumentSyncOptions); !ok { 764 | capabilities.TextDocumentSync = &TextDocumentSyncOptions{} 765 | } 766 | capabilities.TextDocumentSync.(*TextDocumentSyncOptions).WillSave = &True 767 | } 768 | 769 | if self.TextDocumentWillSaveWaitUntil != nil { 770 | if _, ok := capabilities.TextDocumentSync.(*TextDocumentSyncOptions); !ok { 771 | capabilities.TextDocumentSync = &TextDocumentSyncOptions{} 772 | } 773 | capabilities.TextDocumentSync.(*TextDocumentSyncOptions).WillSaveWaitUntil = &True 774 | } 775 | 776 | if self.TextDocumentDidSave != nil { 777 | if _, ok := capabilities.TextDocumentSync.(*TextDocumentSyncOptions); !ok { 778 | capabilities.TextDocumentSync = &TextDocumentSyncOptions{} 779 | } 780 | capabilities.TextDocumentSync.(*TextDocumentSyncOptions).Save = &True 781 | } 782 | 783 | if self.TextDocumentCompletion != nil { 784 | capabilities.CompletionProvider = &CompletionOptions{} 785 | } 786 | 787 | if self.TextDocumentHover != nil { 788 | capabilities.HoverProvider = true 789 | } 790 | 791 | if self.TextDocumentSignatureHelp != nil { 792 | capabilities.SignatureHelpProvider = &SignatureHelpOptions{} 793 | } 794 | 795 | if self.TextDocumentDeclaration != nil { 796 | capabilities.DeclarationProvider = true 797 | } 798 | 799 | if self.TextDocumentDefinition != nil { 800 | capabilities.DefinitionProvider = true 801 | } 802 | 803 | if self.TextDocumentTypeDefinition != nil { 804 | capabilities.TypeDefinitionProvider = true 805 | } 806 | 807 | if self.TextDocumentImplementation != nil { 808 | capabilities.ImplementationProvider = true 809 | } 810 | 811 | if self.TextDocumentReferences != nil { 812 | capabilities.ReferencesProvider = true 813 | } 814 | 815 | if self.TextDocumentDocumentHighlight != nil { 816 | capabilities.DocumentHighlightProvider = true 817 | } 818 | 819 | if self.TextDocumentDocumentSymbol != nil { 820 | capabilities.DocumentSymbolProvider = true 821 | } 822 | 823 | if self.TextDocumentCodeAction != nil { 824 | capabilities.CodeActionProvider = true 825 | } 826 | 827 | if self.TextDocumentCodeLens != nil { 828 | capabilities.CodeLensProvider = &CodeLensOptions{} 829 | } 830 | 831 | if self.TextDocumentDocumentLink != nil { 832 | capabilities.DocumentLinkProvider = &DocumentLinkOptions{} 833 | } 834 | 835 | if self.TextDocumentColor != nil { 836 | capabilities.ColorProvider = true 837 | } 838 | 839 | if self.TextDocumentFormatting != nil { 840 | capabilities.DocumentFormattingProvider = true 841 | } 842 | 843 | if self.TextDocumentRangeFormatting != nil { 844 | capabilities.DocumentRangeFormattingProvider = true 845 | } 846 | 847 | if self.TextDocumentOnTypeFormatting != nil { 848 | capabilities.DocumentOnTypeFormattingProvider = &DocumentOnTypeFormattingOptions{} 849 | } 850 | 851 | if self.TextDocumentRename != nil { 852 | capabilities.RenameProvider = true 853 | } 854 | 855 | if self.TextDocumentFoldingRange != nil { 856 | capabilities.FoldingRangeProvider = true 857 | } 858 | 859 | if self.WorkspaceExecuteCommand != nil { 860 | capabilities.ExecuteCommandProvider = &ExecuteCommandOptions{} 861 | } 862 | 863 | if self.TextDocumentSelectionRange != nil { 864 | capabilities.SelectionRangeProvider = true 865 | } 866 | 867 | if self.TextDocumentLinkedEditingRange != nil { 868 | capabilities.LinkedEditingRangeProvider = true 869 | } 870 | 871 | if self.TextDocumentPrepareCallHierarchy != nil { 872 | capabilities.CallHierarchyProvider = true 873 | } 874 | 875 | if self.TextDocumentSemanticTokensFull != nil { 876 | if _, ok := capabilities.SemanticTokensProvider.(*SemanticTokensOptions); !ok { 877 | capabilities.SemanticTokensProvider = &SemanticTokensOptions{} 878 | } 879 | if self.TextDocumentSemanticTokensFullDelta != nil { 880 | capabilities.SemanticTokensProvider.(*SemanticTokensOptions).Full = &SemanticDelta{} 881 | capabilities.SemanticTokensProvider.(*SemanticTokensOptions).Full.(*SemanticDelta).Delta = &True 882 | } else { 883 | capabilities.SemanticTokensProvider.(*SemanticTokensOptions).Full = true 884 | } 885 | } 886 | 887 | if self.TextDocumentSemanticTokensRange != nil { 888 | if _, ok := capabilities.SemanticTokensProvider.(*SemanticTokensOptions); !ok { 889 | capabilities.SemanticTokensProvider = &SemanticTokensOptions{} 890 | } 891 | capabilities.SemanticTokensProvider.(*SemanticTokensOptions).Range = true 892 | } 893 | 894 | // TODO: self.TextDocumentSemanticTokensRefresh? 895 | 896 | if self.TextDocumentMoniker != nil { 897 | capabilities.MonikerProvider = true 898 | } 899 | 900 | if self.WorkspaceSymbol != nil { 901 | capabilities.WorkspaceSymbolProvider = true 902 | } 903 | 904 | if self.WorkspaceDidCreateFiles != nil { 905 | if capabilities.Workspace == nil { 906 | capabilities.Workspace = &ServerCapabilitiesWorkspace{} 907 | } 908 | if capabilities.Workspace.FileOperations == nil { 909 | capabilities.Workspace.FileOperations = &ServerCapabilitiesWorkspaceFileOperations{} 910 | } 911 | capabilities.Workspace.FileOperations.DidCreate = &FileOperationRegistrationOptions{ 912 | Filters: []FileOperationFilter{}, 913 | } 914 | } 915 | 916 | if self.WorkspaceWillCreateFiles != nil { 917 | if capabilities.Workspace == nil { 918 | capabilities.Workspace = &ServerCapabilitiesWorkspace{} 919 | } 920 | if capabilities.Workspace.FileOperations == nil { 921 | capabilities.Workspace.FileOperations = &ServerCapabilitiesWorkspaceFileOperations{} 922 | } 923 | capabilities.Workspace.FileOperations.WillCreate = &FileOperationRegistrationOptions{ 924 | Filters: []FileOperationFilter{}, 925 | } 926 | } 927 | 928 | if self.WorkspaceDidRenameFiles != nil { 929 | capabilities.RenameProvider = true 930 | if capabilities.Workspace == nil { 931 | capabilities.Workspace = &ServerCapabilitiesWorkspace{} 932 | } 933 | if capabilities.Workspace.FileOperations == nil { 934 | capabilities.Workspace.FileOperations = &ServerCapabilitiesWorkspaceFileOperations{} 935 | } 936 | capabilities.Workspace.FileOperations.DidRename = &FileOperationRegistrationOptions{ 937 | Filters: []FileOperationFilter{}, 938 | } 939 | } 940 | 941 | if self.WorkspaceWillRenameFiles != nil { 942 | capabilities.RenameProvider = true 943 | if capabilities.Workspace == nil { 944 | capabilities.Workspace = &ServerCapabilitiesWorkspace{} 945 | } 946 | if capabilities.Workspace.FileOperations == nil { 947 | capabilities.Workspace.FileOperations = &ServerCapabilitiesWorkspaceFileOperations{} 948 | } 949 | capabilities.Workspace.FileOperations.WillRename = &FileOperationRegistrationOptions{ 950 | Filters: []FileOperationFilter{}, 951 | } 952 | } 953 | 954 | if self.WorkspaceDidDeleteFiles != nil { 955 | if capabilities.Workspace == nil { 956 | capabilities.Workspace = &ServerCapabilitiesWorkspace{} 957 | } 958 | if capabilities.Workspace.FileOperations == nil { 959 | capabilities.Workspace.FileOperations = &ServerCapabilitiesWorkspaceFileOperations{} 960 | } 961 | capabilities.Workspace.FileOperations.DidDelete = &FileOperationRegistrationOptions{ 962 | Filters: []FileOperationFilter{}, 963 | } 964 | } 965 | 966 | if self.WorkspaceWillDeleteFiles != nil { 967 | if capabilities.Workspace == nil { 968 | capabilities.Workspace = &ServerCapabilitiesWorkspace{} 969 | } 970 | if capabilities.Workspace.FileOperations == nil { 971 | capabilities.Workspace.FileOperations = &ServerCapabilitiesWorkspaceFileOperations{} 972 | } 973 | capabilities.Workspace.FileOperations.WillDelete = &FileOperationRegistrationOptions{ 974 | Filters: []FileOperationFilter{}, 975 | } 976 | } 977 | 978 | return capabilities 979 | } 980 | -------------------------------------------------------------------------------- /protocol_3_16/base-structures.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "encoding/json" 5 | "strings" 6 | "unicode/utf8" 7 | ) 8 | 9 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#uri 10 | 11 | type DocumentUri = string 12 | 13 | type URI = string 14 | 15 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#regExp 16 | 17 | /** 18 | * Client capabilities specific to regular expressions. 19 | */ 20 | type RegularExpressionsClientCapabilities struct { 21 | /** 22 | * The engine's name. 23 | */ 24 | Engine string `json:"engine"` 25 | 26 | /** 27 | * The engine's version. 28 | */ 29 | Version *string `json:"version,omitempty"` 30 | } 31 | 32 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocuments 33 | 34 | var EOL = []string{"\n", "\r\n", "\r"} 35 | 36 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#position 37 | 38 | type Position struct { 39 | /** 40 | * Line position in a document (zero-based). 41 | */ 42 | Line UInteger `json:"line"` 43 | 44 | /** 45 | * Character offset on a line in a document (zero-based). Assuming that 46 | * the line is represented as a string, the `character` value represents 47 | * the gap between the `character` and `character + 1`. 48 | * 49 | * If the character value is greater than the line length it defaults back 50 | * to the line length. 51 | */ 52 | Character UInteger `json:"character"` 53 | } 54 | 55 | func (self Position) IndexIn(content string) int { 56 | // This code is modified from the gopls implementation found: 57 | // https://cs.opensource.google/go/x/tools/+/refs/tags/v0.1.5:internal/span/utf16.go;l=70 58 | 59 | // In accordance with the LSP Spec: 60 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocuments 61 | // self.Character represents utf-16 code units, not bytes and so we need to 62 | // convert utf-16 code units to a byte offset. 63 | 64 | // Find the byte offset for the line 65 | index := 0 66 | for row := UInteger(0); row < self.Line; row++ { 67 | content_ := content[index:] 68 | if next := strings.Index(content_, "\n"); next != -1 { 69 | index += next + 1 70 | } else { 71 | return 0 72 | } 73 | } 74 | 75 | // The index represents the byte offset from the beginning of the line 76 | // count self.Character utf-16 code units from the index byte offset. 77 | 78 | byteOffset := index 79 | remains := content[index:] 80 | chr := int(self.Character) 81 | 82 | for count := 1; count <= chr; count++ { 83 | 84 | if len(remains) <= 0 { 85 | // char goes past content 86 | // this a error 87 | return 0 88 | } 89 | 90 | r, w := utf8.DecodeRuneInString(remains) 91 | if r == '\n' { 92 | // Per the LSP spec: 93 | // 94 | // > If the character value is greater than the line length it 95 | // > defaults back to the line length. 96 | break 97 | } 98 | 99 | remains = remains[w:] 100 | if r >= 0x10000 { 101 | // a two point rune 102 | count++ 103 | // if we finished in a two point rune, do not advance past the first 104 | if count > chr { 105 | break 106 | } 107 | } 108 | byteOffset += w 109 | 110 | } 111 | 112 | return byteOffset 113 | } 114 | 115 | func (self Position) EndOfLineIn(content string) Position { 116 | index := self.IndexIn(content) 117 | content_ := content[index:] 118 | if eol := strings.Index(content_, "\n"); eol != -1 { 119 | return Position{ 120 | Line: self.Line, 121 | Character: self.Character + UInteger(eol), 122 | } 123 | } else { 124 | return self 125 | } 126 | } 127 | 128 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#range 129 | 130 | type Range struct { 131 | /** 132 | * The range's start position. 133 | */ 134 | Start Position `json:"start"` 135 | 136 | /** 137 | * The range's end position. 138 | */ 139 | End Position `json:"end"` 140 | } 141 | 142 | func (self Range) IndexesIn(content string) (int, int) { 143 | return self.Start.IndexIn(content), self.End.IndexIn(content) 144 | } 145 | 146 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#location 147 | 148 | type Location struct { 149 | URI DocumentUri `json:"uri"` 150 | Range Range `json:"range"` 151 | } 152 | 153 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#locationLink 154 | 155 | type LocationLink struct { 156 | /** 157 | * Span of the origin of this link. 158 | * 159 | * Used as the underlined span for mouse interaction. Defaults to the word 160 | * range at the mouse position. 161 | */ 162 | OriginSelectionRange *Range `json:"originSelectionRange,omitempty"` 163 | 164 | /** 165 | * The target resource identifier of this link. 166 | */ 167 | TargetURI DocumentUri `json:"targetUri"` 168 | 169 | /** 170 | * The full target range of this link. If the target for example is a symbol 171 | * then target range is the range enclosing this symbol not including 172 | * leading/trailing whitespace but everything else like comments. This 173 | * information is typically used to highlight the range in the editor. 174 | */ 175 | TargetRange Range `json:"targetRange"` 176 | 177 | /** 178 | * The range that should be selected and revealed when this link is being 179 | * followed, e.g the name of a function. Must be contained by the the 180 | * `targetRange`. See also `DocumentSymbol#range` 181 | */ 182 | TargetSelectionRange Range `json:"targetSelectionRange"` 183 | } 184 | 185 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#diagnostic 186 | 187 | type Diagnostic struct { 188 | /** 189 | * The range at which the message applies. 190 | */ 191 | Range Range `json:"range"` 192 | 193 | /** 194 | * The diagnostic's severity. Can be omitted. If omitted it is up to the 195 | * client to interpret diagnostics as error, warning, info or hint. 196 | */ 197 | Severity *DiagnosticSeverity `json:"severity,omitempty"` 198 | 199 | /** 200 | * The diagnostic's code, which might appear in the user interface. 201 | */ 202 | Code *IntegerOrString `json:"code,omitempty"` 203 | 204 | /** 205 | * An optional property to describe the error code. 206 | * 207 | * @since 3.16.0 208 | */ 209 | CodeDescription *CodeDescription `json:"codeDescription,omitempty"` 210 | 211 | /** 212 | * A human-readable string describing the source of this 213 | * diagnostic, e.g. 'typescript' or 'super lint'. 214 | */ 215 | Source *string `json:"source,omitempty"` 216 | 217 | /** 218 | * The diagnostic's message. 219 | */ 220 | Message string `json:"message"` 221 | 222 | /** 223 | * Additional metadata about the diagnostic. 224 | * 225 | * @since 3.15.0 226 | */ 227 | Tags []DiagnosticTag `json:"tags,omitempty"` 228 | 229 | /** 230 | * An array of related diagnostic information, e.g. when symbol-names within 231 | * a scope collide all definitions can be marked via this property. 232 | */ 233 | RelatedInformation []DiagnosticRelatedInformation `json:"relatedInformation,omitempty"` 234 | 235 | /** 236 | * A data entry field that is preserved between a 237 | * `textDocument/publishDiagnostics` notification and 238 | * `textDocument/codeAction` request. 239 | * 240 | * @since 3.16.0 241 | */ 242 | Data any `json:"data,omitempty"` 243 | } 244 | 245 | type DiagnosticSeverity Integer 246 | 247 | const ( 248 | /** 249 | * Reports an error. 250 | */ 251 | DiagnosticSeverityError = DiagnosticSeverity(1) 252 | 253 | /** 254 | * Reports a warning. 255 | */ 256 | DiagnosticSeverityWarning = DiagnosticSeverity(2) 257 | 258 | /** 259 | * Reports an information. 260 | */ 261 | DiagnosticSeverityInformation = DiagnosticSeverity(3) 262 | 263 | /** 264 | * Reports a hint. 265 | */ 266 | DiagnosticSeverityHint = DiagnosticSeverity(4) 267 | ) 268 | 269 | /** 270 | * The diagnostic tags. 271 | * 272 | * @since 3.15.0 273 | */ 274 | type DiagnosticTag Integer 275 | 276 | const ( 277 | /** 278 | * Unused or unnecessary code. 279 | * 280 | * Clients are allowed to render diagnostics with this tag faded out 281 | * instead of having an error squiggle. 282 | */ 283 | DiagnosticTagUnnecessary = DiagnosticTag(1) 284 | 285 | /** 286 | * Deprecated or obsolete code. 287 | * 288 | * Clients are allowed to rendered diagnostics with this tag strike through. 289 | */ 290 | DiagnosticTagDeprecated = DiagnosticTag(2) 291 | ) 292 | 293 | /** 294 | * Represents a related message and source code location for a diagnostic. 295 | * This should be used to point to code locations that cause or are related to 296 | * a diagnostics, e.g when duplicating a symbol in a scope. 297 | */ 298 | type DiagnosticRelatedInformation struct { 299 | /** 300 | * The location of this related diagnostic information. 301 | */ 302 | Location Location `json:"location"` 303 | 304 | /** 305 | * The message of this related diagnostic information. 306 | */ 307 | Message string `json:"message"` 308 | } 309 | 310 | /** 311 | * Structure to capture a description for an error code. 312 | * 313 | * @since 3.16.0 314 | */ 315 | type CodeDescription struct { 316 | /** 317 | * An URI to open with more information about the diagnostic error. 318 | */ 319 | HRef URI `json:"href"` 320 | } 321 | 322 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#command 323 | 324 | type Command struct { 325 | /** 326 | * Title of the command, like `save`. 327 | */ 328 | Title string `json:"title"` 329 | 330 | /** 331 | * The identifier of the actual command handler. 332 | */ 333 | Command string `json:"command"` 334 | 335 | /** 336 | * Arguments that the command handler should be 337 | * invoked with. 338 | */ 339 | Arguments []any `json:"arguments,omitempty"` 340 | } 341 | 342 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textEdit 343 | 344 | type TextEdit struct { 345 | /** 346 | * The range of the text document to be manipulated. To insert 347 | * text into a document create a range where start === end. 348 | */ 349 | Range Range `json:"range"` 350 | 351 | /** 352 | * The string to be inserted. For delete operations use an 353 | * empty string. 354 | */ 355 | NewText string `json:"newText"` 356 | } 357 | 358 | /** 359 | * Additional information that describes document changes. 360 | * 361 | * @since 3.16.0 362 | */ 363 | type ChangeAnnotation struct { 364 | /** 365 | * A human-readable string describing the actual change. The string 366 | * is rendered prominent in the user interface. 367 | */ 368 | Label string `json:"label"` 369 | 370 | /** 371 | * A flag which indicates that user confirmation is needed 372 | * before applying the change. 373 | */ 374 | NeedsConfirmation *bool `json:"needsConfirmation,omitempty"` 375 | 376 | /** 377 | * A human-readable string which is rendered less prominent in 378 | * the user interface. 379 | */ 380 | Description *string `json:"description,omitempty"` 381 | } 382 | 383 | /** 384 | * An identifier referring to a change annotation managed by a workspace 385 | * edit. 386 | * 387 | * @since 3.16.0 388 | */ 389 | type ChangeAnnotationIdentifier = string 390 | 391 | /** 392 | * A special text edit with an additional change annotation. 393 | * 394 | * @since 3.16.0 395 | */ 396 | type AnnotatedTextEdit struct { 397 | TextEdit 398 | 399 | /** 400 | * The actual annotation identifier. 401 | */ 402 | AnnotationID ChangeAnnotationIdentifier `json:"annotationId"` 403 | } 404 | 405 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocumentEdit 406 | 407 | type TextDocumentEdit struct { 408 | /** 409 | * The text document to change. 410 | */ 411 | TextDocument OptionalVersionedTextDocumentIdentifier `json:"textDocument"` 412 | 413 | /** 414 | * The edits to be applied. 415 | * 416 | * @since 3.16.0 - support for AnnotatedTextEdit. This is guarded by the 417 | * client capability `workspace.workspaceEdit.changeAnnotationSupport` 418 | */ 419 | Edits []any `json:"edits"` // TextEdit | AnnotatedTextEdit 420 | } 421 | 422 | // ([json.Unmarshaler] interface) 423 | func (self *TextDocumentEdit) UnmarshalJSON(data []byte) error { 424 | var value struct { 425 | TextDocument OptionalVersionedTextDocumentIdentifier `json:"textDocument"` 426 | Edits []json.RawMessage `json:"edits"` // TextEdit | AnnotatedTextEdit 427 | } 428 | 429 | if err := json.Unmarshal(data, &value); err == nil { 430 | self.TextDocument = value.TextDocument 431 | 432 | for _, edit := range value.Edits { 433 | var value TextEdit 434 | if err = json.Unmarshal(edit, &value); err == nil { 435 | self.Edits = append(self.Edits, value) 436 | } else { 437 | var value AnnotatedTextEdit 438 | if err = json.Unmarshal(edit, &value); err == nil { 439 | self.Edits = append(self.Edits, value) 440 | } else { 441 | return err 442 | } 443 | } 444 | } 445 | 446 | return nil 447 | } else { 448 | return err 449 | } 450 | } 451 | 452 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#resourceChanges 453 | 454 | /** 455 | * Options to create a file. 456 | */ 457 | type CreateFileOptions struct { 458 | /** 459 | * Overwrite existing file. Overwrite wins over `ignoreIfExists` 460 | */ 461 | Overwrite *bool `json:"overwrite,omitempty"` 462 | 463 | /** 464 | * Ignore if exists. 465 | */ 466 | IgnoreIfExists *bool `json:"ignoreIfExists,omitempty"` 467 | } 468 | 469 | /** 470 | * Create file operation 471 | */ 472 | type CreateFile struct { 473 | /** 474 | * A create 475 | */ 476 | Kind string `json:"kind"` // == "create" 477 | 478 | /** 479 | * The resource to create. 480 | */ 481 | URI DocumentUri `json:"uri"` 482 | 483 | /** 484 | * Additional options 485 | */ 486 | Options *CreateFileOptions `json:"options,omitempty"` 487 | 488 | /** 489 | * An optional annotation identifer describing the operation. 490 | * 491 | * @since 3.16.0 492 | */ 493 | AnnotationID *ChangeAnnotationIdentifier `json:"annotationId,omitempty"` 494 | } 495 | 496 | /** 497 | * Rename file options 498 | */ 499 | type RenameFileOptions struct { 500 | /** 501 | * Overwrite target if existing. Overwrite wins over `ignoreIfExists` 502 | */ 503 | Overwrite *bool `json:"overwrite,omitempty"` 504 | 505 | /** 506 | * Ignores if target exists. 507 | */ 508 | IgnoreIfExists *bool `json:"ignoreIfExists,omitempty"` 509 | } 510 | 511 | /** 512 | * Rename file operation 513 | */ 514 | type RenameFile struct { 515 | /** 516 | * A rename 517 | */ 518 | Kind string `json:"kind"` // == "rename" 519 | 520 | /** 521 | * The old (existing) location. 522 | */ 523 | OldURI DocumentUri `json:"oldUri"` 524 | 525 | /** 526 | * The new location. 527 | */ 528 | NewURI DocumentUri `json:"newUri"` 529 | 530 | /** 531 | * Rename options. 532 | */ 533 | Options *RenameFileOptions `json:"options,omitempty"` 534 | 535 | /** 536 | * An optional annotation identifer describing the operation. 537 | * 538 | * @since 3.16.0 539 | */ 540 | AnnotationID *ChangeAnnotationIdentifier `json:"annotationId,omitempty"` 541 | } 542 | 543 | /** 544 | * Delete file options 545 | */ 546 | type DeleteFileOptions struct { 547 | /** 548 | * Delete the content recursively if a folder is denoted. 549 | */ 550 | Recursive *bool `json:"recursive,omitempty"` 551 | 552 | /** 553 | * Ignore the operation if the file doesn't exist. 554 | */ 555 | IgnoreIfNotExists *bool `json:"ignoreIfNotExists,omitempty"` 556 | } 557 | 558 | /** 559 | * Delete file operation 560 | */ 561 | type DeleteFile struct { 562 | /** 563 | * A delete 564 | */ 565 | Kind string `json:"kind"` // == "delete" 566 | 567 | /** 568 | * The file to delete. 569 | */ 570 | URI DocumentUri `json:"uri"` 571 | 572 | /** 573 | * Delete options. 574 | */ 575 | Options *DeleteFileOptions `json:"options,omitempty"` 576 | 577 | /** 578 | * An optional annotation identifer describing the operation. 579 | * 580 | * @since 3.16.0 581 | */ 582 | AnnotationID *ChangeAnnotationIdentifier `json:"annotationId,omitempty"` 583 | } 584 | 585 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspaceEdit 586 | 587 | type WorkspaceEdit struct { 588 | /** 589 | * Holds changes to existing resources. 590 | */ 591 | Changes map[DocumentUri][]TextEdit `json:"changes,omitempty"` 592 | 593 | /** 594 | * Depending on the client capability 595 | * `workspace.workspaceEdit.resourceOperations` document changes are either 596 | * an array of `TextDocumentEdit`s to express changes to n different text 597 | * documents where each text document edit addresses a specific version of 598 | * a text document. Or it can contain above `TextDocumentEdit`s mixed with 599 | * create, rename and delete file / folder operations. 600 | * 601 | * Whether a client supports versioned document edits is expressed via 602 | * `workspace.workspaceEdit.documentChanges` client capability. 603 | * 604 | * If a client neither supports `documentChanges` nor 605 | * `workspace.workspaceEdit.resourceOperations` then only plain `TextEdit`s 606 | * using the `changes` property are supported. 607 | */ 608 | DocumentChanges []any `json:"documentChanges,omitempty"` // TextDocumentEdit | CreateFile | RenameFile | DeleteFile 609 | 610 | /** 611 | * A map of change annotations that can be referenced in 612 | * `AnnotatedTextEdit`s or create, rename and delete file / folder 613 | * operations. 614 | * 615 | * Whether clients honor this property depends on the client capability 616 | * `workspace.changeAnnotationSupport`. 617 | * 618 | * @since 3.16.0 619 | */ 620 | ChangeAnnotations map[ChangeAnnotationIdentifier]ChangeAnnotation `json:"changeAnnotations,omitempty"` 621 | } 622 | 623 | // ([json.Unmarshaler] interface) 624 | func (self *WorkspaceEdit) UnmarshalJSON(data []byte) error { 625 | var value struct { 626 | Changes map[DocumentUri][]TextEdit `json:"changes"` 627 | DocumentChanges []json.RawMessage `json:"documentChanges"` // TextDocumentEdit | CreateFile | RenameFile | DeleteFile 628 | ChangeAnnotations map[ChangeAnnotationIdentifier]ChangeAnnotation `json:"changeAnnotations"` 629 | } 630 | 631 | if err := json.Unmarshal(data, &value); err == nil { 632 | self.Changes = value.Changes 633 | self.ChangeAnnotations = value.ChangeAnnotations 634 | 635 | for _, documentChange := range value.DocumentChanges { 636 | var value TextDocumentEdit 637 | if err = json.Unmarshal(documentChange, &value); err == nil { 638 | self.DocumentChanges = append(self.DocumentChanges, value) 639 | } else { 640 | var value CreateFile 641 | if err = json.Unmarshal(documentChange, &value); err == nil { 642 | self.DocumentChanges = append(self.DocumentChanges, value) 643 | } else { 644 | var value RenameFile 645 | if err = json.Unmarshal(documentChange, &value); err == nil { 646 | self.DocumentChanges = append(self.DocumentChanges, value) 647 | } else { 648 | var value DeleteFile 649 | if err = json.Unmarshal(documentChange, &value); err == nil { 650 | self.DocumentChanges = append(self.DocumentChanges, value) 651 | } else { 652 | return err 653 | } 654 | } 655 | } 656 | } 657 | } 658 | 659 | return nil 660 | } else { 661 | return err 662 | } 663 | } 664 | 665 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workspaceEditClientCapabilities 666 | 667 | type WorkspaceEditClientCapabilities struct { 668 | /** 669 | * The client supports versioned document changes in `WorkspaceEdit`s 670 | */ 671 | DocumentChanges *bool `json:"documentChanges,omitempty"` 672 | 673 | /** 674 | * The resource operations the client supports. Clients should at least 675 | * support 'create', 'rename' and 'delete' files and folders. 676 | * 677 | * @since 3.13.0 678 | */ 679 | ResourceOperations []ResourceOperationKind `json:"resourceOperations,omitempty"` 680 | 681 | /** 682 | * The failure handling strategy of a client if applying the workspace edit 683 | * fails. 684 | * 685 | * @since 3.13.0 686 | */ 687 | FailureHandling *FailureHandlingKind `json:"failureHandling,omitempty"` 688 | 689 | /** 690 | * Whether the client normalizes line endings to the client specific 691 | * setting. 692 | * If set to `true` the client will normalize line ending characters 693 | * in a workspace edit to the client specific new line character(s). 694 | * 695 | * @since 3.16.0 696 | */ 697 | NormalizesLineEndings *bool `json:"normalizesLineEndings,omitempty"` 698 | 699 | /** 700 | * Whether the client in general supports change annotations on text edits, 701 | * create file, rename file and delete file changes. 702 | * 703 | * @since 3.16.0 704 | */ 705 | ChangeAnnotationSupport struct { 706 | /** 707 | * Whether the client groups edits with equal labels into tree nodes, 708 | * for instance all edits labelled with "Changes in Strings" would 709 | * be a tree node. 710 | */ 711 | GroupsOnLabel *bool `json:"groupsOnLabel,omitempty"` 712 | } `json:"changeAnnotationSupport,omitempty"` 713 | } 714 | 715 | /** 716 | * The kind of resource operations supported by the client. 717 | */ 718 | type ResourceOperationKind string 719 | 720 | const ( 721 | /** 722 | * Supports creating new files and folders. 723 | */ 724 | ResourceOperationKindCreate = ResourceOperationKind("create") 725 | 726 | /** 727 | * Supports renaming existing files and folders. 728 | */ 729 | ResourceOperationKindRename = ResourceOperationKind("rename") 730 | 731 | /** 732 | * Supports deleting existing files and folders. 733 | */ 734 | ResourceOperationKindDelete = ResourceOperationKind("delete") 735 | ) 736 | 737 | type FailureHandlingKind string 738 | 739 | const ( 740 | /** 741 | * Applying the workspace change is simply aborted if one of the changes 742 | * provided fails. All operations executed before the failing operation 743 | * stay executed. 744 | */ 745 | FailureHandlingKindAbort = FailureHandlingKind("abort") 746 | 747 | /** 748 | * All operations are executed transactional. That means they either all 749 | * succeed or no changes at all are applied to the workspace. 750 | */ 751 | FailureHandlingKindTransactional = FailureHandlingKind("transactional") 752 | 753 | /** 754 | * If the workspace edit contains only textual file changes they are 755 | * executed transactional. If resource changes (create, rename or delete 756 | * file) are part of the change the failure handling strategy is abort. 757 | */ 758 | FailureHandlingKindTextOnlyTransactional = FailureHandlingKind("textOnlyTransactional") 759 | 760 | /** 761 | * The client tries to undo the operations already executed. But there is no 762 | * guarantee that this is succeeding. 763 | */ 764 | FailureHandlingKindUndo = FailureHandlingKind("undo") 765 | ) 766 | 767 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocumentIdentifier 768 | 769 | type TextDocumentIdentifier struct { 770 | /** 771 | * The text document's URI. 772 | */ 773 | URI DocumentUri `json:"uri"` 774 | } 775 | 776 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocumentItem 777 | 778 | type TextDocumentItem struct { 779 | /** 780 | * The text document's URI. 781 | */ 782 | URI DocumentUri `json:"uri"` 783 | 784 | /** 785 | * The text document's language identifier. 786 | */ 787 | LanguageID string `json:"languageId"` 788 | 789 | /** 790 | * The version number of this document (it will increase after each 791 | * change, including undo/redo). 792 | */ 793 | Version Integer `json:"version"` 794 | 795 | /** 796 | * The content of the opened text document. 797 | */ 798 | Text string `json:"text"` 799 | } 800 | 801 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#versionedTextDocumentIdentifier 802 | 803 | type VersionedTextDocumentIdentifier struct { 804 | TextDocumentIdentifier 805 | 806 | /** 807 | * The version number of this document. 808 | * 809 | * The version number of a document will increase after each change, 810 | * including undo/redo. The number doesn't need to be consecutive. 811 | */ 812 | Version Integer `json:"version"` 813 | } 814 | 815 | type OptionalVersionedTextDocumentIdentifier struct { 816 | TextDocumentIdentifier 817 | 818 | /** 819 | * The version number of this document. If an optional versioned text document 820 | * identifier is sent from the server to the client and the file is not 821 | * open in the editor (the server has not received an open notification 822 | * before) the server can send `null` to indicate that the version is 823 | * known and the content on disk is the master (as specified with document 824 | * content ownership). 825 | * 826 | * The version number of a document will increase after each change, 827 | * including undo/redo. The number doesn't need to be consecutive. 828 | */ 829 | Version *Integer `json:"version"` 830 | } 831 | 832 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocumentPositionParams 833 | 834 | type TextDocumentPositionParams struct { 835 | /** 836 | * The text document. 837 | */ 838 | TextDocument TextDocumentIdentifier `json:"textDocument"` 839 | 840 | /** 841 | * The position inside the text document. 842 | */ 843 | Position Position `json:"position"` 844 | } 845 | 846 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#documentFilter 847 | 848 | type DocumentFilter struct { 849 | /** 850 | * A language id, like `typescript`. 851 | */ 852 | Language *string `json:"language,omitempty"` 853 | 854 | /** 855 | * A Uri [scheme](#Uri.scheme), like `file` or `untitled`. 856 | */ 857 | Scheme *string `json:"scheme,omitempty"` 858 | 859 | /** 860 | * A glob pattern, like `*.{ts,js}`. 861 | * 862 | * Glob patterns can have the following syntax: 863 | * - `*` to match one or more characters in a path segment 864 | * - `?` to match on one character in a path segment 865 | * - `**` to match any number of path segments, including none 866 | * - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript 867 | * and JavaScript files) 868 | * - `[]` to declare a range of characters to match in a path segment 869 | * (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) 870 | * - `[!...]` to negate a range of characters to match in a path segment 871 | * (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but 872 | * not `example.0`) 873 | */ 874 | Pattern *string `json:"pattern,omitempty"` 875 | } 876 | 877 | type DocumentSelector []DocumentFilter 878 | 879 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#staticRegistrationOptions 880 | 881 | /** 882 | * Static registration options to be returned in the initialize request. 883 | */ 884 | type StaticRegistrationOptions struct { 885 | /** 886 | * The id used to register the request. The id can be used to deregister 887 | * the request again. See also Registration#id. 888 | */ 889 | ID *string `json:"id,omitempty"` 890 | } 891 | 892 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#textDocumentRegistrationOptions 893 | 894 | /** 895 | * General text document registration options. 896 | */ 897 | type TextDocumentRegistrationOptions struct { 898 | /** 899 | * A document selector to identify the scope of the registration. If set to 900 | * null the document selector provided on the client side will be used. 901 | */ 902 | DocumentSelector *DocumentSelector `json:"documentSelector"` 903 | } 904 | 905 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#markupContent 906 | 907 | /** 908 | * Describes the content type that a client supports in various 909 | * result literals like `Hover`, `ParameterInfo` or `CompletionItem`. 910 | * 911 | * Please note that `MarkupKinds` must not start with a `$`. This kinds 912 | * are reserved for internal usage. 913 | */ 914 | type MarkupKind string 915 | 916 | const ( 917 | /** 918 | * Plain text is supported as a content format 919 | */ 920 | MarkupKindPlainText = MarkupKind("plaintext") 921 | 922 | /** 923 | * Markdown is supported as a content format 924 | */ 925 | MarkupKindMarkdown = MarkupKind("markdown") 926 | ) 927 | 928 | /** 929 | * A `MarkupContent` literal represents a string value which content is 930 | * interpreted base on its kind flag. Currently the protocol supports 931 | * `plaintext` and `markdown` as markup kinds. 932 | * 933 | * If the kind is `markdown` then the value can contain fenced code blocks like 934 | * in GitHub issues. 935 | * 936 | * Here is an example how such a string can be constructed using 937 | * JavaScript / TypeScript: 938 | * ```typescript 939 | * let markdown: MarkdownContent = { 940 | * kind: MarkupKind.Markdown, 941 | * value: [ 942 | * '# Header', 943 | * 'Some text', 944 | * '```typescript', 945 | * 'someCode();', 946 | * '```' 947 | * ].join('\n') 948 | * }; 949 | * ``` 950 | * 951 | * *Please Note* that clients might sanitize the return markdown. A client could 952 | * decide to remove HTML from the markdown to avoid script execution. 953 | */ 954 | type MarkupContent struct { 955 | /** 956 | * The type of the Markup 957 | */ 958 | Kind MarkupKind `json:"kind"` 959 | 960 | /** 961 | * The content itself 962 | */ 963 | Value string `json:"value"` 964 | } 965 | 966 | /** 967 | * Client capabilities specific to the used markdown parser. 968 | * 969 | * @since 3.16.0 970 | */ 971 | type MarkdownClientCapabilities struct { 972 | /** 973 | * The name of the parser. 974 | */ 975 | Parser string `json:"parser"` 976 | 977 | /** 978 | * The version of the parser. 979 | */ 980 | Version *string `json:"version,omitempty"` 981 | } 982 | 983 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#workDoneProgress 984 | 985 | type WorkDoneProgressBegin struct { 986 | Kind string `json:"kind"` // == "begin" 987 | 988 | /** 989 | * Mandatory title of the progress operation. Used to briefly inform about 990 | * the kind of operation being performed. 991 | * 992 | * Examples: "Indexing" or "Linking dependencies". 993 | */ 994 | Title string `json:"title"` 995 | 996 | /** 997 | * Controls if a cancel button should show to allow the user to cancel the 998 | * long running operation. Clients that don't support cancellation are 999 | * allowed to ignore the setting. 1000 | */ 1001 | Cancellable *bool `json:"cancellable,omitempty"` 1002 | 1003 | /** 1004 | * Optional, more detailed associated progress message. Contains 1005 | * complementary information to the `title`. 1006 | * 1007 | * Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". 1008 | * If unset, the previous progress message (if any) is still valid. 1009 | */ 1010 | Message *string `json:"message,omitempty"` 1011 | 1012 | /** 1013 | * Optional progress percentage to display (value 100 is considered 100%). 1014 | * If not provided infinite progress is assumed and clients are allowed 1015 | * to ignore the `percentage` value in subsequent in report notifications. 1016 | * 1017 | * The value should be steadily rising. Clients are free to ignore values 1018 | * that are not following this rule. The value range is [0, 100] 1019 | */ 1020 | Percentage *UInteger `json:"percentage,omitempty"` 1021 | } 1022 | 1023 | type WorkDoneProgressReport struct { 1024 | Kind string `json:"kind"` // == "report" 1025 | 1026 | /** 1027 | * Controls enablement state of a cancel button. This property is only valid 1028 | * if a cancel button got requested in the `WorkDoneProgressStart` payload. 1029 | * 1030 | * Clients that don't support cancellation or don't support control the 1031 | * button's enablement state are allowed to ignore the setting. 1032 | */ 1033 | Cancellable *bool `json:"cancellable,omitempty"` 1034 | 1035 | /** 1036 | * Optional, more detailed associated progress message. Contains 1037 | * complementary information to the `title`. 1038 | * 1039 | * Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". 1040 | * If unset, the previous progress message (if any) is still valid. 1041 | */ 1042 | Message *string `json:"message,omitempty"` 1043 | 1044 | /** 1045 | * Optional progress percentage to display (value 100 is considered 100%). 1046 | * If not provided infinite progress is assumed and clients are allowed 1047 | * to ignore the `percentage` value in subsequent in report notifications. 1048 | * 1049 | * The value should be steadily rising. Clients are free to ignore values 1050 | * that are not following this rule. The value range is [0, 100] 1051 | */ 1052 | Percentage *UInteger `json:"percentage,omitempty"` 1053 | } 1054 | 1055 | type WorkDoneProgressEnd struct { 1056 | Kind string `json:"kind"` // == "end" 1057 | 1058 | /** 1059 | * Optional, a final message indicating to for example indicate the outcome 1060 | * of the operation. 1061 | */ 1062 | Message *string `json:"message,omitempty"` 1063 | } 1064 | 1065 | type WorkDoneProgressParams struct { 1066 | /** 1067 | * An optional token that a server can use to report work done progress. 1068 | */ 1069 | WorkDoneToken *ProgressToken `json:"workDoneToken,omitempty"` 1070 | } 1071 | 1072 | type WorkDoneProgressOptions struct { 1073 | WorkDoneProgress *bool `json:"workDoneProgress,omitempty"` 1074 | } 1075 | 1076 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#partialResults 1077 | 1078 | type PartialResultParams struct { 1079 | /** 1080 | * An optional token that a server can use to report partial results (e.g. 1081 | * streaming) to the client. 1082 | */ 1083 | PartialResultToken *ProgressToken `json:"partialResultToken,omitempty"` 1084 | } 1085 | 1086 | // https://microsoft.github.io/language-server-protocol/specifications/specification-3-16#traceValue 1087 | 1088 | type TraceValue string 1089 | 1090 | const ( 1091 | TraceValueOff = TraceValue("off") 1092 | TraceValueMessage = TraceValue("message") // The spec clearly says "message", but some implementations use "messages" instead 1093 | TraceValueVerbose = TraceValue("verbose") 1094 | ) 1095 | --------------------------------------------------------------------------------