diff --git a/utils/vscode/src/lsp/LICENSE b/utils/vscode/src/lsp/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/utils/vscode/src/lsp/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/utils/vscode/src/lsp/README.md b/utils/vscode/src/lsp/README.md new file mode 100644 index 000000000..c78f183f3 --- /dev/null +++ b/utils/vscode/src/lsp/README.md @@ -0,0 +1,5 @@ +This directory contains code forked from https://github.com/golang/tools/tree/master/internal/lsp. + +This code has been modified to remove unneeded features and dependencies. + +Submitted on behalf of a third-party: The Go Authors diff --git a/utils/vscode/src/lsp/jsonrpc2/handler.go b/utils/vscode/src/lsp/jsonrpc2/handler.go new file mode 100644 index 000000000..20d484178 --- /dev/null +++ b/utils/vscode/src/lsp/jsonrpc2/handler.go @@ -0,0 +1,134 @@ +// Copyright 2019 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package jsonrpc2 + +import ( + "context" +) + +// Handler is the interface used to hook into the message handling of an rpc +// connection. +type Handler interface { + // Deliver is invoked to handle incoming requests. + // If the request returns false from IsNotify then the Handler must eventually + // call Reply on the Conn with the supplied request. + // Handlers are called synchronously, they should pass the work off to a go + // routine if they are going to take a long time. + // If Deliver returns true all subsequent handlers will be invoked with + // delivered set to true, and should not attempt to deliver the message. + Deliver(ctx context.Context, r *Request, delivered bool) bool + + // Cancel is invoked for cancelled outgoing requests. + // It is okay to use the connection to send notifications, but the context will + // be in the cancelled state, so you must do it with the background context + // instead. + // If Cancel returns true all subsequent handlers will be invoked with + // cancelled set to true, and should not attempt to cancel the message. + Cancel(ctx context.Context, conn *Conn, id ID, cancelled bool) bool + + // Log is invoked for all messages flowing through a Conn. + // direction indicates if the message being received or sent + // id is the message id, if not set it was a notification + // elapsed is the time between a call being seen and the response, and is + // negative for anything that is not a response. + // method is the method name specified in the message + // payload is the parameters for a call or notification, and the result for a + // response + + // Request is called near the start of processing any request. + Request(ctx context.Context, conn *Conn, direction Direction, r *WireRequest) context.Context + // Response is called near the start of processing any response. + Response(ctx context.Context, conn *Conn, direction Direction, r *WireResponse) context.Context + // Done is called when any request is fully processed. + // For calls, this means the response has also been processed, for notifies + // this is as soon as the message has been written to the stream. + // If err is set, it implies the request failed. + Done(ctx context.Context, err error) + // Read is called with a count each time some data is read from the stream. + // The read calls are delayed until after the data has been interpreted so + // that it can be attributed to a request/response. + Read(ctx context.Context, bytes int64) context.Context + // Wrote is called each time some data is written to the stream. + Wrote(ctx context.Context, bytes int64) context.Context + // Error is called with errors that cannot be delivered through the normal + // mechanisms, for instance a failure to process a notify cannot be delivered + // back to the other party. + Error(ctx context.Context, err error) +} + +// Direction is used to indicate to a logger whether the logged message was being +// sent or received. +type Direction bool + +const ( + // Send indicates the message is outgoing. + Send = Direction(true) + // Receive indicates the message is incoming. + Receive = Direction(false) +) + +func (d Direction) String() string { + switch d { + case Send: + return "send" + case Receive: + return "receive" + default: + panic("unreachable") + } +} + +type EmptyHandler struct{} + +func (EmptyHandler) Deliver(ctx context.Context, r *Request, delivered bool) bool { + return false +} + +func (EmptyHandler) Cancel(ctx context.Context, conn *Conn, id ID, cancelled bool) bool { + return false +} + +func (EmptyHandler) Request(ctx context.Context, conn *Conn, direction Direction, r *WireRequest) context.Context { + return ctx +} + +func (EmptyHandler) Response(ctx context.Context, conn *Conn, direction Direction, r *WireResponse) context.Context { + return ctx +} + +func (EmptyHandler) Done(ctx context.Context, err error) { +} + +func (EmptyHandler) Read(ctx context.Context, bytes int64) context.Context { + return ctx +} + +func (EmptyHandler) Wrote(ctx context.Context, bytes int64) context.Context { + return ctx +} + +func (EmptyHandler) Error(ctx context.Context, err error) {} + +type defaultHandler struct{ EmptyHandler } + +func (defaultHandler) Deliver(ctx context.Context, r *Request, delivered bool) bool { + if delivered { + return false + } + if !r.IsNotify() { + r.Reply(ctx, nil, NewErrorf(CodeMethodNotFound, "method %q not found", r.Method)) + } + return true +} diff --git a/utils/vscode/src/lsp/jsonrpc2/jsonrpc2.go b/utils/vscode/src/lsp/jsonrpc2/jsonrpc2.go new file mode 100644 index 000000000..b8436d27b --- /dev/null +++ b/utils/vscode/src/lsp/jsonrpc2/jsonrpc2.go @@ -0,0 +1,416 @@ +// Copyright 2018 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package jsonrpc2 is a minimal implementation of the JSON RPC 2 spec. +// https://www.jsonrpc.org/specification +// It is intended to be compatible with other implementations at the wire level. +package jsonrpc2 + +import ( + "context" + "encoding/json" + "fmt" + "sync" + "sync/atomic" +) + +// Conn is a JSON RPC 2 client server connection. +// Conn is bidirectional; it does not have a designated server or client end. +type Conn struct { + seq int64 // must only be accessed using atomic operations + handlers []Handler + stream Stream + err error + pendingMu sync.Mutex // protects the pending map + pending map[ID]chan *WireResponse + handlingMu sync.Mutex // protects the handling map + handling map[ID]*Request +} + +type requestState int + +const ( + requestWaiting = requestState(iota) + requestSerial + requestParallel + requestReplied + requestDone +) + +// Request is sent to a server to represent a Call or Notify operaton. +type Request struct { + conn *Conn + cancel context.CancelFunc + state requestState + nextRequest chan struct{} + + // The Wire values of the request. + WireRequest +} + +// NewErrorf builds a Error struct for the supplied message and code. +// If args is not empty, message and args will be passed to Sprintf. +func NewErrorf(code int64, format string, args ...interface{}) *Error { + return &Error{ + Code: code, + Message: fmt.Sprintf(format, args...), + } +} + +// NewConn creates a new connection object around the supplied stream. +// You must call Run for the connection to be active. +func NewConn(s Stream) *Conn { + conn := &Conn{ + handlers: []Handler{defaultHandler{}}, + stream: s, + pending: make(map[ID]chan *WireResponse), + handling: make(map[ID]*Request), + } + return conn +} + +// AddHandler adds a new handler to the set the connection will invoke. +// Handlers are invoked in the reverse order of how they were added, this +// allows the most recent addition to be the first one to attempt to handle a +// message. +func (c *Conn) AddHandler(handler Handler) { + // prepend the new handlers so we use them first + c.handlers = append([]Handler{handler}, c.handlers...) +} + +// Cancel cancels a pending Call on the server side. +// The call is identified by its id. +// JSON RPC 2 does not specify a cancel message, so cancellation support is not +// directly wired in. This method allows a higher level protocol to choose how +// to propagate the cancel. +func (c *Conn) Cancel(id ID) { + c.handlingMu.Lock() + handling, found := c.handling[id] + c.handlingMu.Unlock() + if found { + handling.cancel() + } +} + +// Notify is called to send a notification request over the connection. +// It will return as soon as the notification has been sent, as no response is +// possible. +func (c *Conn) Notify(ctx context.Context, method string, params interface{}) (err error) { + jsonParams, err := marshalToRaw(params) + if err != nil { + return fmt.Errorf("marshalling notify parameters: %v", err) + } + request := &WireRequest{ + Method: method, + Params: jsonParams, + } + data, err := json.Marshal(request) + if err != nil { + return fmt.Errorf("marshalling notify request: %v", err) + } + for _, h := range c.handlers { + ctx = h.Request(ctx, c, Send, request) + } + defer func() { + for _, h := range c.handlers { + h.Done(ctx, err) + } + }() + n, err := c.stream.Write(ctx, data) + for _, h := range c.handlers { + ctx = h.Wrote(ctx, n) + } + return err +} + +// Call sends a request over the connection and then waits for a response. +// If the response is not an error, it will be decoded into result. +// result must be of a type you an pass to json.Unmarshal. +func (c *Conn) Call(ctx context.Context, method string, params, result interface{}) (err error) { + // generate a new request identifier + id := ID{Number: atomic.AddInt64(&c.seq, 1)} + jsonParams, err := marshalToRaw(params) + if err != nil { + return fmt.Errorf("marshalling call parameters: %v", err) + } + request := &WireRequest{ + ID: &id, + Method: method, + Params: jsonParams, + } + // marshal the request now it is complete + data, err := json.Marshal(request) + if err != nil { + return fmt.Errorf("marshalling call request: %v", err) + } + for _, h := range c.handlers { + ctx = h.Request(ctx, c, Send, request) + } + // we have to add ourselves to the pending map before we send, otherwise we + // are racing the response + rchan := make(chan *WireResponse) + c.pendingMu.Lock() + c.pending[id] = rchan + c.pendingMu.Unlock() + defer func() { + // clean up the pending response handler on the way out + c.pendingMu.Lock() + delete(c.pending, id) + c.pendingMu.Unlock() + for _, h := range c.handlers { + h.Done(ctx, err) + } + }() + // now we are ready to send + n, err := c.stream.Write(ctx, data) + for _, h := range c.handlers { + ctx = h.Wrote(ctx, n) + } + if err != nil { + // sending failed, we will never get a response, so don't leave it pending + return err + } + // now wait for the response + select { + case response := <-rchan: + for _, h := range c.handlers { + ctx = h.Response(ctx, c, Receive, response) + } + // is it an error response? + if response.Error != nil { + return response.Error + } + if result == nil || response.Result == nil { + return nil + } + if err := json.Unmarshal(*response.Result, result); err != nil { + return fmt.Errorf("unmarshalling result: %v", err) + } + return nil + case <-ctx.Done(): + // allow the handler to propagate the cancel + cancelled := false + for _, h := range c.handlers { + if h.Cancel(ctx, c, id, cancelled) { + cancelled = true + } + } + return ctx.Err() + } +} + +// Conn returns the connection that created this request. +func (r *Request) Conn() *Conn { return r.conn } + +// IsNotify returns true if this request is a notification. +func (r *Request) IsNotify() bool { + return r.ID == nil +} + +// Parallel indicates that the system is now allowed to process other requests +// in parallel with this one. +// It is safe to call any number of times, but must only be called from the +// request handling go routine. +// It is implied by both reply and by the handler returning. +func (r *Request) Parallel() { + if r.state >= requestParallel { + return + } + r.state = requestParallel + close(r.nextRequest) +} + +// Reply sends a reply to the given request. +// It is an error to call this if request was not a call. +// You must call this exactly once for any given request. +// It should only be called from the handler go routine. +// If err is set then result will be ignored. +// If the request has not yet dropped into parallel mode +// it will be before this function returns. +func (r *Request) Reply(ctx context.Context, result interface{}, err error) error { + if r.state >= requestReplied { + return fmt.Errorf("reply invoked more than once") + } + if r.IsNotify() { + return fmt.Errorf("reply not invoked with a valid call") + } + // reply ends the handling phase of a call, so if we are not yet + // parallel we should be now. The go routine is allowed to continue + // to do work after replying, which is why it is important to unlock + // the rpc system at this point. + r.Parallel() + r.state = requestReplied + + var raw *json.RawMessage + if err == nil { + raw, err = marshalToRaw(result) + } + response := &WireResponse{ + Result: raw, + ID: r.ID, + } + if err != nil { + if callErr, ok := err.(*Error); ok { + response.Error = callErr + } else { + response.Error = NewErrorf(0, "%s", err) + } + } + data, err := json.Marshal(response) + if err != nil { + return err + } + for _, h := range r.conn.handlers { + ctx = h.Response(ctx, r.conn, Send, response) + } + n, err := r.conn.stream.Write(ctx, data) + for _, h := range r.conn.handlers { + ctx = h.Wrote(ctx, n) + } + + if err != nil { + // TODO(iancottrell): if a stream write fails, we really need to shut down + // the whole stream + return err + } + return nil +} + +func (c *Conn) setHandling(r *Request, active bool) { + if r.ID == nil { + return + } + r.conn.handlingMu.Lock() + defer r.conn.handlingMu.Unlock() + if active { + r.conn.handling[*r.ID] = r + } else { + delete(r.conn.handling, *r.ID) + } +} + +// combined has all the fields of both Request and Response. +// We can decode this and then work out which it is. +type combined struct { + VersionTag VersionTag `json:"jsonrpc"` + ID *ID `json:"id,omitempty"` + Method string `json:"method"` + Params *json.RawMessage `json:"params,omitempty"` + Result *json.RawMessage `json:"result,omitempty"` + Error *Error `json:"error,omitempty"` +} + +// Run blocks until the connection is terminated, and returns any error that +// caused the termination. +// It must be called exactly once for each Conn. +// It returns only when the reader is closed or there is an error in the stream. +func (c *Conn) Run(runCtx context.Context) error { + // we need to make the next request "lock" in an unlocked state to allow + // the first incoming request to proceed. All later requests are unlocked + // by the preceding request going to parallel mode. + nextRequest := make(chan struct{}) + close(nextRequest) + for { + // get the data for a message + data, n, err := c.stream.Read(runCtx) + if err != nil { + // the stream failed, we cannot continue + return err + } + // read a combined message + msg := &combined{} + if err := json.Unmarshal(data, msg); err != nil { + // a badly formed message arrived, log it and continue + // we trust the stream to have isolated the error to just this message + for _, h := range c.handlers { + h.Error(runCtx, fmt.Errorf("unmarshal failed: %v", err)) + } + continue + } + // work out which kind of message we have + switch { + case msg.Method != "": + // if method is set it must be a request + reqCtx, cancelReq := context.WithCancel(runCtx) + thisRequest := nextRequest + nextRequest = make(chan struct{}) + req := &Request{ + conn: c, + cancel: cancelReq, + nextRequest: nextRequest, + WireRequest: WireRequest{ + VersionTag: msg.VersionTag, + Method: msg.Method, + Params: msg.Params, + ID: msg.ID, + }, + } + for _, h := range c.handlers { + reqCtx = h.Request(reqCtx, c, Receive, &req.WireRequest) + reqCtx = h.Read(reqCtx, n) + } + c.setHandling(req, true) + go func() { + <-thisRequest + req.state = requestSerial + defer func() { + c.setHandling(req, false) + if !req.IsNotify() && req.state < requestReplied { + req.Reply(reqCtx, nil, NewErrorf(CodeInternalError, "method %q did not reply", req.Method)) + } + req.Parallel() + for _, h := range c.handlers { + h.Done(reqCtx, err) + } + cancelReq() + }() + delivered := false + for _, h := range c.handlers { + if h.Deliver(reqCtx, req, delivered) { + delivered = true + } + } + }() + case msg.ID != nil: + // we have a response, get the pending entry from the map + c.pendingMu.Lock() + rchan := c.pending[*msg.ID] + if rchan != nil { + delete(c.pending, *msg.ID) + } + c.pendingMu.Unlock() + // and send the reply to the channel + response := &WireResponse{ + Result: msg.Result, + Error: msg.Error, + ID: msg.ID, + } + rchan <- response + close(rchan) + default: + for _, h := range c.handlers { + h.Error(runCtx, fmt.Errorf("message not a call, notify or response, ignoring")) + } + } + } +} + +func marshalToRaw(obj interface{}) (*json.RawMessage, error) { + data, err := json.Marshal(obj) + if err != nil { + return nil, err + } + raw := json.RawMessage(data) + return &raw, nil +} diff --git a/utils/vscode/src/lsp/jsonrpc2/stream.go b/utils/vscode/src/lsp/jsonrpc2/stream.go new file mode 100644 index 000000000..2c6ad6dfd --- /dev/null +++ b/utils/vscode/src/lsp/jsonrpc2/stream.go @@ -0,0 +1,160 @@ +// Copyright 2018 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package jsonrpc2 + +import ( + "bufio" + "context" + "encoding/json" + "fmt" + "io" + "strconv" + "strings" + "sync" +) + +// Stream abstracts the transport mechanics from the JSON RPC protocol. +// A Conn reads and writes messages using the stream it was provided on +// construction, and assumes that each call to Read or Write fully transfers +// a single message, or returns an error. +type Stream interface { + // Read gets the next message from the stream. + // It is never called concurrently. + Read(context.Context) ([]byte, int64, error) + // Write sends a message to the stream. + // It must be safe for concurrent use. + Write(context.Context, []byte) (int64, error) +} + +// NewStream returns a Stream built on top of an io.Reader and io.Writer +// The messages are sent with no wrapping, and rely on json decode consistency +// to determine message boundaries. +func NewStream(in io.Reader, out io.Writer) Stream { + return &plainStream{ + in: json.NewDecoder(in), + out: out, + } +} + +type plainStream struct { + in *json.Decoder + outMu sync.Mutex + out io.Writer +} + +func (s *plainStream) Read(ctx context.Context) ([]byte, int64, error) { + select { + case <-ctx.Done(): + return nil, 0, ctx.Err() + default: + } + var raw json.RawMessage + if err := s.in.Decode(&raw); err != nil { + return nil, 0, err + } + return raw, int64(len(raw)), nil +} + +func (s *plainStream) Write(ctx context.Context, data []byte) (int64, error) { + select { + case <-ctx.Done(): + return 0, ctx.Err() + default: + } + s.outMu.Lock() + n, err := s.out.Write(data) + s.outMu.Unlock() + return int64(n), err +} + +// NewHeaderStream returns a Stream built on top of an io.Reader and io.Writer +// The messages are sent with HTTP content length and MIME type headers. +// This is the format used by LSP and others. +func NewHeaderStream(in io.Reader, out io.Writer) Stream { + return &headerStream{ + in: bufio.NewReader(in), + out: out, + } +} + +type headerStream struct { + in *bufio.Reader + outMu sync.Mutex + out io.Writer +} + +func (s *headerStream) Read(ctx context.Context) ([]byte, int64, error) { + select { + case <-ctx.Done(): + return nil, 0, ctx.Err() + default: + } + var total, length int64 + // read the header, stop on the first empty line + for { + line, err := s.in.ReadString('\n') + total += int64(len(line)) + if err != nil { + return nil, total, fmt.Errorf("failed reading header line %q", err) + } + line = strings.TrimSpace(line) + // check we have a header line + if line == "" { + break + } + colon := strings.IndexRune(line, ':') + if colon < 0 { + return nil, total, fmt.Errorf("invalid header line %q", line) + } + name, value := line[:colon], strings.TrimSpace(line[colon+1:]) + switch name { + case "Content-Length": + if length, err = strconv.ParseInt(value, 10, 32); err != nil { + return nil, total, fmt.Errorf("failed parsing Content-Length: %v", value) + } + if length <= 0 { + return nil, total, fmt.Errorf("invalid Content-Length: %v", length) + } + default: + // ignoring unknown headers + } + } + if length == 0 { + return nil, total, fmt.Errorf("missing Content-Length header") + } + data := make([]byte, length) + if _, err := io.ReadFull(s.in, data); err != nil { + return nil, total, err + } + total += length + return data, total, nil +} + +func (s *headerStream) Write(ctx context.Context, data []byte) (int64, error) { + select { + case <-ctx.Done(): + return 0, ctx.Err() + default: + } + s.outMu.Lock() + defer s.outMu.Unlock() + n, err := fmt.Fprintf(s.out, "Content-Length: %v\r\n\r\n", len(data)) + total := int64(n) + if err == nil { + n, err = s.out.Write(data) + total += int64(n) + } + return total, err +} diff --git a/utils/vscode/src/lsp/jsonrpc2/wire.go b/utils/vscode/src/lsp/jsonrpc2/wire.go new file mode 100644 index 000000000..3e31c340d --- /dev/null +++ b/utils/vscode/src/lsp/jsonrpc2/wire.go @@ -0,0 +1,148 @@ +// Copyright 2018 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package jsonrpc2 + +import ( + "encoding/json" + "fmt" + "strconv" +) + +// this file contains the go forms of the wire specification +// see http://www.jsonrpc.org/specification for details + +const ( + // CodeUnknownError should be used for all non coded errors. + CodeUnknownError = -32001 + // CodeParseError is used when invalid JSON was received by the server. + CodeParseError = -32700 + //CodeInvalidRequest is used when the JSON sent is not a valid Request object. + CodeInvalidRequest = -32600 + // CodeMethodNotFound should be returned by the handler when the method does + // not exist / is not available. + CodeMethodNotFound = -32601 + // CodeInvalidParams should be returned by the handler when method + // parameter(s) were invalid. + CodeInvalidParams = -32602 + // CodeInternalError is not currently returned but defined for completeness. + CodeInternalError = -32603 + + //CodeServerOverloaded is returned when a message was refused due to a + //server being temporarily unable to accept any new messages. + CodeServerOverloaded = -32000 +) + +// WireRequest is sent to a server to represent a Call or Notify operaton. +type WireRequest struct { + // VersionTag is always encoded as the string "2.0" + VersionTag VersionTag `json:"jsonrpc"` + // Method is a string containing the method name to invoke. + Method string `json:"method"` + // Params is either a struct or an array with the parameters of the method. + Params *json.RawMessage `json:"params,omitempty"` + // The id of this request, used to tie the Response back to the request. + // Will be either a string or a number. If not set, the Request is a notify, + // and no response is possible. + ID *ID `json:"id,omitempty"` +} + +// WireResponse is a reply to a Request. +// It will always have the ID field set to tie it back to a request, and will +// have either the Result or Error fields set depending on whether it is a +// success or failure response. +type WireResponse struct { + // VersionTag is always encoded as the string "2.0" + VersionTag VersionTag `json:"jsonrpc"` + // Result is the response value, and is required on success. + Result *json.RawMessage `json:"result,omitempty"` + // Error is a structured error response if the call fails. + Error *Error `json:"error,omitempty"` + // ID must be set and is the identifier of the Request this is a response to. + ID *ID `json:"id,omitempty"` +} + +// Error represents a structured error in a Response. +type Error struct { + // Code is an error code indicating the type of failure. + Code int64 `json:"code"` + // Message is a short description of the error. + Message string `json:"message"` + // Data is optional structured data containing additional information about the error. + Data *json.RawMessage `json:"data"` +} + +// VersionTag is a special 0 sized struct that encodes as the jsonrpc version +// tag. +// It will fail during decode if it is not the correct version tag in the +// stream. +type VersionTag struct{} + +// ID is a Request identifier. +// Only one of either the Name or Number members will be set, using the +// number form if the Name is the empty string. +type ID struct { + Name string + Number int64 +} + +func (err *Error) Error() string { + if err == nil { + return "" + } + return err.Message +} + +func (VersionTag) MarshalJSON() ([]byte, error) { + return json.Marshal("2.0") +} + +func (VersionTag) UnmarshalJSON(data []byte) error { + version := "" + if err := json.Unmarshal(data, &version); err != nil { + return err + } + if version != "2.0" { + return fmt.Errorf("Invalid RPC version %v", version) + } + return nil +} + +// String returns a string representation of the ID. +// The representation is non ambiguous, string forms are quoted, number forms +// are preceded by a # +func (id *ID) String() string { + if id == nil { + return "" + } + if id.Name != "" { + return strconv.Quote(id.Name) + } + return "#" + strconv.FormatInt(id.Number, 10) +} + +func (id *ID) MarshalJSON() ([]byte, error) { + if id.Name != "" { + return json.Marshal(id.Name) + } + return json.Marshal(id.Number) +} + +func (id *ID) UnmarshalJSON(data []byte) error { + *id = ID{} + if err := json.Unmarshal(data, &id.Number); err == nil { + return nil + } + return json.Unmarshal(data, &id.Name) +} diff --git a/utils/vscode/src/lsp/protocol/context.go b/utils/vscode/src/lsp/protocol/context.go new file mode 100644 index 000000000..7833d40e1 --- /dev/null +++ b/utils/vscode/src/lsp/protocol/context.go @@ -0,0 +1,29 @@ +// Copyright 2018 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package protocol + +import ( + "context" +) + +type contextKey int + +const ( + clientKey = contextKey(iota) +) + +func WithClient(ctx context.Context, client Client) context.Context { + return context.WithValue(ctx, clientKey, client) +} diff --git a/utils/vscode/src/lsp/protocol/doc.go b/utils/vscode/src/lsp/protocol/doc.go new file mode 100644 index 000000000..3c9198d3b --- /dev/null +++ b/utils/vscode/src/lsp/protocol/doc.go @@ -0,0 +1,26 @@ +// Copyright 2018 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package protocol contains the structs that map directly to the wire format +// of the "Language Server Protocol". +// +// It is a literal transcription, with unmodified comments, and only the changes +// required to make it go code. +// Names are uppercased to export them. +// All fields have JSON tags added to correct the names. +// Fields marked with a ? are also marked as "omitempty" +// Fields that are "|| null" are made pointers +// Fields that are string or number are left as string +// Fields that are type "number" are made float64 +package protocol diff --git a/utils/vscode/src/lsp/protocol/enums.go b/utils/vscode/src/lsp/protocol/enums.go new file mode 100644 index 000000000..db76ca39c --- /dev/null +++ b/utils/vscode/src/lsp/protocol/enums.go @@ -0,0 +1,256 @@ +// Copyright 2018 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package protocol + +import ( + "fmt" +) + +var ( + namesTextDocumentSyncKind [int(Incremental) + 1]string + namesInitializeError [int(UnknownProtocolVersion) + 1]string + namesMessageType [int(Log) + 1]string + namesFileChangeType [int(Deleted) + 1]string + namesWatchKind [int(WatchDelete) + 1]string + namesCompletionTriggerKind [int(TriggerForIncompleteCompletions) + 1]string + namesDiagnosticSeverity [int(SeverityHint) + 1]string + namesDiagnosticTag [int(Unnecessary) + 1]string + namesCompletionItemKind [int(TypeParameterCompletion) + 1]string + namesInsertTextFormat [int(SnippetTextFormat) + 1]string + namesDocumentHighlightKind [int(Write) + 1]string + namesSymbolKind [int(TypeParameter) + 1]string + namesTextDocumentSaveReason [int(FocusOut) + 1]string +) + +func init() { + namesTextDocumentSyncKind[int(None)] = "None" + namesTextDocumentSyncKind[int(Full)] = "Full" + namesTextDocumentSyncKind[int(Incremental)] = "Incremental" + + namesInitializeError[int(UnknownProtocolVersion)] = "UnknownProtocolVersion" + + namesMessageType[int(Error)] = "Error" + namesMessageType[int(Warning)] = "Warning" + namesMessageType[int(Info)] = "Info" + namesMessageType[int(Log)] = "Log" + + namesFileChangeType[int(Created)] = "Created" + namesFileChangeType[int(Changed)] = "Changed" + namesFileChangeType[int(Deleted)] = "Deleted" + + namesWatchKind[int(WatchCreate)] = "WatchCreate" + namesWatchKind[int(WatchChange)] = "WatchChange" + namesWatchKind[int(WatchDelete)] = "WatchDelete" + + namesCompletionTriggerKind[int(Invoked)] = "Invoked" + namesCompletionTriggerKind[int(TriggerCharacter)] = "TriggerCharacter" + namesCompletionTriggerKind[int(TriggerForIncompleteCompletions)] = "TriggerForIncompleteCompletions" + + namesDiagnosticSeverity[int(SeverityError)] = "Error" + namesDiagnosticSeverity[int(SeverityWarning)] = "Warning" + namesDiagnosticSeverity[int(SeverityInformation)] = "Information" + namesDiagnosticSeverity[int(SeverityHint)] = "Hint" + + namesDiagnosticTag[int(Unnecessary)] = "Unnecessary" + + namesCompletionItemKind[int(TextCompletion)] = "text" + namesCompletionItemKind[int(MethodCompletion)] = "method" + namesCompletionItemKind[int(FunctionCompletion)] = "func" + namesCompletionItemKind[int(ConstructorCompletion)] = "constructor" + namesCompletionItemKind[int(FieldCompletion)] = "field" + namesCompletionItemKind[int(VariableCompletion)] = "var" + namesCompletionItemKind[int(ClassCompletion)] = "type" + namesCompletionItemKind[int(InterfaceCompletion)] = "interface" + namesCompletionItemKind[int(ModuleCompletion)] = "package" + namesCompletionItemKind[int(PropertyCompletion)] = "property" + namesCompletionItemKind[int(UnitCompletion)] = "unit" + namesCompletionItemKind[int(ValueCompletion)] = "value" + namesCompletionItemKind[int(EnumCompletion)] = "enum" + namesCompletionItemKind[int(KeywordCompletion)] = "keyword" + namesCompletionItemKind[int(SnippetCompletion)] = "snippet" + namesCompletionItemKind[int(ColorCompletion)] = "color" + namesCompletionItemKind[int(FileCompletion)] = "file" + namesCompletionItemKind[int(ReferenceCompletion)] = "reference" + namesCompletionItemKind[int(FolderCompletion)] = "folder" + namesCompletionItemKind[int(EnumMemberCompletion)] = "enumMember" + namesCompletionItemKind[int(ConstantCompletion)] = "const" + namesCompletionItemKind[int(StructCompletion)] = "struct" + namesCompletionItemKind[int(EventCompletion)] = "event" + namesCompletionItemKind[int(OperatorCompletion)] = "operator" + namesCompletionItemKind[int(TypeParameterCompletion)] = "typeParam" + + namesInsertTextFormat[int(PlainTextTextFormat)] = "PlainText" + namesInsertTextFormat[int(SnippetTextFormat)] = "Snippet" + + namesDocumentHighlightKind[int(Text)] = "Text" + namesDocumentHighlightKind[int(Read)] = "Read" + namesDocumentHighlightKind[int(Write)] = "Write" + + namesSymbolKind[int(File)] = "File" + namesSymbolKind[int(Module)] = "Module" + namesSymbolKind[int(Namespace)] = "Namespace" + namesSymbolKind[int(Package)] = "Package" + namesSymbolKind[int(Class)] = "Class" + namesSymbolKind[int(Method)] = "Method" + namesSymbolKind[int(Property)] = "Property" + namesSymbolKind[int(Field)] = "Field" + namesSymbolKind[int(Constructor)] = "Constructor" + namesSymbolKind[int(Enum)] = "Enum" + namesSymbolKind[int(Interface)] = "Interface" + namesSymbolKind[int(Function)] = "Function" + namesSymbolKind[int(Variable)] = "Variable" + namesSymbolKind[int(Constant)] = "Constant" + namesSymbolKind[int(String)] = "String" + namesSymbolKind[int(Number)] = "Number" + namesSymbolKind[int(Boolean)] = "Boolean" + namesSymbolKind[int(Array)] = "Array" + namesSymbolKind[int(Object)] = "Object" + namesSymbolKind[int(Key)] = "Key" + namesSymbolKind[int(Null)] = "Null" + namesSymbolKind[int(EnumMember)] = "EnumMember" + namesSymbolKind[int(Struct)] = "Struct" + namesSymbolKind[int(Event)] = "Event" + namesSymbolKind[int(Operator)] = "Operator" + namesSymbolKind[int(TypeParameter)] = "TypeParameter" + + namesTextDocumentSaveReason[int(Manual)] = "Manual" + namesTextDocumentSaveReason[int(AfterDelay)] = "AfterDelay" + namesTextDocumentSaveReason[int(FocusOut)] = "FocusOut" +} + +func formatEnum(f fmt.State, c rune, i int, names []string, unknown string) { + s := "" + if i >= 0 && i < len(names) { + s = names[i] + } + if s != "" { + fmt.Fprint(f, s) + } else { + fmt.Fprintf(f, "%s(%d)", unknown, i) + } +} + +func parseEnum(s string, names []string) int { + for i, name := range names { + if s == name { + return i + } + } + return 0 +} + +func (e TextDocumentSyncKind) Format(f fmt.State, c rune) { + formatEnum(f, c, int(e), namesTextDocumentSyncKind[:], "TextDocumentSyncKind") +} + +func ParseTextDocumentSyncKind(s string) TextDocumentSyncKind { + return TextDocumentSyncKind(parseEnum(s, namesTextDocumentSyncKind[:])) +} + +func (e InitializeError) Format(f fmt.State, c rune) { + formatEnum(f, c, int(e), namesInitializeError[:], "InitializeError") +} + +func ParseInitializeError(s string) InitializeError { + return InitializeError(parseEnum(s, namesInitializeError[:])) +} + +func (e MessageType) Format(f fmt.State, c rune) { + formatEnum(f, c, int(e), namesMessageType[:], "MessageType") +} + +func ParseMessageType(s string) MessageType { + return MessageType(parseEnum(s, namesMessageType[:])) +} + +func (e FileChangeType) Format(f fmt.State, c rune) { + formatEnum(f, c, int(e), namesFileChangeType[:], "FileChangeType") +} + +func ParseFileChangeType(s string) FileChangeType { + return FileChangeType(parseEnum(s, namesFileChangeType[:])) +} + +func (e WatchKind) Format(f fmt.State, c rune) { + formatEnum(f, c, int(e), namesWatchKind[:], "WatchKind") +} + +func ParseWatchKind(s string) WatchKind { + return WatchKind(parseEnum(s, namesWatchKind[:])) +} + +func (e CompletionTriggerKind) Format(f fmt.State, c rune) { + formatEnum(f, c, int(e), namesCompletionTriggerKind[:], "CompletionTriggerKind") +} + +func ParseCompletionTriggerKind(s string) CompletionTriggerKind { + return CompletionTriggerKind(parseEnum(s, namesCompletionTriggerKind[:])) +} + +func (e DiagnosticSeverity) Format(f fmt.State, c rune) { + formatEnum(f, c, int(e), namesDiagnosticSeverity[:], "DiagnosticSeverity") +} + +func ParseDiagnosticSeverity(s string) DiagnosticSeverity { + return DiagnosticSeverity(parseEnum(s, namesDiagnosticSeverity[:])) +} + +func (e DiagnosticTag) Format(f fmt.State, c rune) { + formatEnum(f, c, int(e), namesDiagnosticTag[:], "DiagnosticTag") +} + +func ParseDiagnosticTag(s string) DiagnosticTag { + return DiagnosticTag(parseEnum(s, namesDiagnosticTag[:])) +} + +func (e CompletionItemKind) Format(f fmt.State, c rune) { + formatEnum(f, c, int(e), namesCompletionItemKind[:], "CompletionItemKind") +} + +func ParseCompletionItemKind(s string) CompletionItemKind { + return CompletionItemKind(parseEnum(s, namesCompletionItemKind[:])) +} + +func (e InsertTextFormat) Format(f fmt.State, c rune) { + formatEnum(f, c, int(e), namesInsertTextFormat[:], "InsertTextFormat") +} + +func ParseInsertTextFormat(s string) InsertTextFormat { + return InsertTextFormat(parseEnum(s, namesInsertTextFormat[:])) +} + +func (e DocumentHighlightKind) Format(f fmt.State, c rune) { + formatEnum(f, c, int(e), namesDocumentHighlightKind[:], "DocumentHighlightKind") +} + +func ParseDocumentHighlightKind(s string) DocumentHighlightKind { + return DocumentHighlightKind(parseEnum(s, namesDocumentHighlightKind[:])) +} + +func (e SymbolKind) Format(f fmt.State, c rune) { + formatEnum(f, c, int(e), namesSymbolKind[:], "SymbolKind") +} + +func ParseSymbolKind(s string) SymbolKind { + return SymbolKind(parseEnum(s, namesSymbolKind[:])) +} + +func (e TextDocumentSaveReason) Format(f fmt.State, c rune) { + formatEnum(f, c, int(e), namesTextDocumentSaveReason[:], "TextDocumentSaveReason") +} + +func ParseTextDocumentSaveReason(s string) TextDocumentSaveReason { + return TextDocumentSaveReason(parseEnum(s, namesTextDocumentSaveReason[:])) +} diff --git a/utils/vscode/src/lsp/protocol/log.go b/utils/vscode/src/lsp/protocol/log.go new file mode 100644 index 000000000..f245881e1 --- /dev/null +++ b/utils/vscode/src/lsp/protocol/log.go @@ -0,0 +1,258 @@ +// Copyright 2018 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package protocol + +import ( + "context" + "encoding/json" + "fmt" + "io" + "strings" + "sync" + "time" + + "../jsonrpc2" +) + +type loggingStream struct { + stream jsonrpc2.Stream + log io.Writer +} + +// LoggingStream returns a stream that does LSP protocol logging too +func LoggingStream(str jsonrpc2.Stream, w io.Writer) jsonrpc2.Stream { + return &loggingStream{str, w} +} + +func (s *loggingStream) Read(ctx context.Context) ([]byte, int64, error) { + data, count, err := s.stream.Read(ctx) + if err == nil { + logIn(s.log, data) + } + return data, count, err +} + +func (s *loggingStream) Write(ctx context.Context, data []byte) (int64, error) { + logOut(s.log, data) + count, err := s.stream.Write(ctx, data) + return count, err +} + +// Combined has all the fields of both Request and Response. +// We can decode this and then work out which it is. +type Combined struct { + VersionTag jsonrpc2.VersionTag `json:"jsonrpc"` + ID *jsonrpc2.ID `json:"id,omitempty"` + Method string `json:"method"` + Params *json.RawMessage `json:"params,omitempty"` + Result *json.RawMessage `json:"result,omitempty"` + Error *jsonrpc2.Error `json:"error,omitempty"` +} + +type req struct { + method string + start time.Time +} + +type mapped struct { + mu sync.Mutex + clientCalls map[string]req + serverCalls map[string]req +} + +var maps = &mapped{ + sync.Mutex{}, + make(map[string]req), + make(map[string]req), +} + +// these 4 methods are each used exactly once, but it seemed +// better to have the encapsulation rather than ad hoc mutex +// code in 4 places +func (m *mapped) client(id string, del bool) req { + m.mu.Lock() + defer m.mu.Unlock() + v := m.clientCalls[id] + if del { + delete(m.clientCalls, id) + } + return v +} + +func (m *mapped) server(id string, del bool) req { + m.mu.Lock() + defer m.mu.Unlock() + v := m.serverCalls[id] + if del { + delete(m.serverCalls, id) + } + return v +} + +func (m *mapped) setClient(id string, r req) { + m.mu.Lock() + defer m.mu.Unlock() + m.clientCalls[id] = r +} + +func (m *mapped) setServer(id string, r req) { + m.mu.Lock() + defer m.mu.Unlock() + m.serverCalls[id] = r +} + +const eor = "\r\n\r\n\r\n" + +func strID(x *jsonrpc2.ID) string { + if x == nil { + // should never happen, but we need a number + return "999999999" + } + if x.Name != "" { + return x.Name + } + return fmt.Sprintf("%d", x.Number) +} + +func logCommon(outfd io.Writer, data []byte) (*Combined, time.Time, string) { + if outfd == nil { + return nil, time.Time{}, "" + } + var v Combined + err := json.Unmarshal(data, &v) + if err != nil { + fmt.Fprintf(outfd, "Unmarshal %v\n", err) + panic(err) // do better + } + tm := time.Now() + tmfmt := tm.Format("15:04:05.000 PM") + return &v, tm, tmfmt +} + +// logOut and logIn could be combined. "received"<->"Sending", serverCalls<->clientCalls +// but it wouldn't be a lot shorter or clearer and "shutdown" is a special case + +// Writing a message to the client, log it +func logOut(outfd io.Writer, data []byte) { + v, tm, tmfmt := logCommon(outfd, data) + if v == nil { + return + } + if v.Error != nil { + id := strID(v.ID) + fmt.Fprintf(outfd, "[Error - %s] Received #%s %s%s", tmfmt, id, v.Error, eor) + return + } + buf := strings.Builder{} + id := strID(v.ID) + fmt.Fprintf(&buf, "[Trace - %s] ", tmfmt) // common beginning + if v.ID != nil && v.Method != "" && v.Params != nil { + fmt.Fprintf(&buf, "Received request '%s - (%s)'.\n", v.Method, id) + fmt.Fprintf(&buf, "Params: %s%s", *v.Params, eor) + maps.setServer(id, req{method: v.Method, start: tm}) + } else if v.ID != nil && v.Method == "" && v.Params == nil { + cc := maps.client(id, true) + elapsed := tm.Sub(cc.start) + fmt.Fprintf(&buf, "Received response '%s - (%s)' in %dms.\n", + cc.method, id, elapsed/time.Millisecond) + if v.Result == nil { + fmt.Fprintf(&buf, "Result: {}%s", eor) + } else { + fmt.Fprintf(&buf, "Result: %s%s", string(*v.Result), eor) + } + } else if v.ID == nil && v.Method != "" && v.Params != nil { + p := "null" + if v.Params != nil { + p = string(*v.Params) + } + fmt.Fprintf(&buf, "Received notification '%s'.\n", v.Method) + fmt.Fprintf(&buf, "Params: %s%s", p, eor) + } else { // for completeness, as it should never happen + buf = strings.Builder{} // undo common Trace + fmt.Fprintf(&buf, "[Error - %s] on write ID?%v method:%q Params:%v Result:%v Error:%v%s", + tmfmt, v.ID != nil, v.Method, v.Params != nil, + v.Result != nil, v.Error != nil, eor) + p := "null" + if v.Params != nil { + p = string(*v.Params) + } + r := "null" + if v.Result != nil { + r = string(*v.Result) + } + fmt.Fprintf(&buf, "%s\n%s\n%s%s", p, r, v.Error, eor) + } + outfd.Write([]byte(buf.String())) +} + +// Got a message from the client, log it +func logIn(outfd io.Writer, data []byte) { + v, tm, tmfmt := logCommon(outfd, data) + if v == nil { + return + } + // ID Method Params => Sending request + // ID !Method Result(might be null, but !Params) => Sending response (could we get an Error?) + // !ID Method Params => Sending notification + if v.Error != nil { // does this ever happen? + id := strID(v.ID) + fmt.Fprintf(outfd, "[Error - %s] Sent #%s %s%s", tmfmt, id, v.Error, eor) + return + } + buf := strings.Builder{} + id := strID(v.ID) + fmt.Fprintf(&buf, "[Trace - %s] ", tmfmt) // common beginning + if v.ID != nil && v.Method != "" && (v.Params != nil || v.Method == "shutdown") { + fmt.Fprintf(&buf, "Sending request '%s - (%s)'.\n", v.Method, id) + x := "{}" + if v.Params != nil { + x = string(*v.Params) + } + fmt.Fprintf(&buf, "Params: %s%s", x, eor) + maps.setClient(id, req{method: v.Method, start: tm}) + } else if v.ID != nil && v.Method == "" && v.Params == nil { + sc := maps.server(id, true) + elapsed := tm.Sub(sc.start) + fmt.Fprintf(&buf, "Sending response '%s - (%s)' took %dms.\n", + sc.method, id, elapsed/time.Millisecond) + if v.Result == nil { + fmt.Fprintf(&buf, "Result: {}%s", eor) + } else { + fmt.Fprintf(&buf, "Result: %s%s", string(*v.Result), eor) + } + } else if v.ID == nil && v.Method != "" { + p := "null" + if v.Params != nil { + p = string(*v.Params) + } + fmt.Fprintf(&buf, "Sending notification '%s'.\n", v.Method) + fmt.Fprintf(&buf, "Params: %s%s", p, eor) + } else { // for completeness, as it should never happen + buf = strings.Builder{} // undo common Trace + fmt.Fprintf(&buf, "[Error - %s] on read ID?%v method:%q Params:%v Result:%v Error:%v%s", + tmfmt, v.ID != nil, v.Method, v.Params != nil, + v.Result != nil, v.Error != nil, eor) + p := "null" + if v.Params != nil { + p = string(*v.Params) + } + r := "null" + if v.Result != nil { + r = string(*v.Result) + } + fmt.Fprintf(&buf, "%s\n%s\n%s%s", p, r, v.Error, eor) + } + outfd.Write([]byte(buf.String())) +} diff --git a/utils/vscode/src/lsp/protocol/protocol.go b/utils/vscode/src/lsp/protocol/protocol.go new file mode 100644 index 000000000..e396c8325 --- /dev/null +++ b/utils/vscode/src/lsp/protocol/protocol.go @@ -0,0 +1,86 @@ +// Copyright 2018 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package protocol + +import ( + "context" + "encoding/json" + "log" + + "../jsonrpc2" +) + +const ( + // RequestCancelledError should be used when a request is cancelled early. + RequestCancelledError = -32800 +) + +type DocumentUri = string + +type canceller struct{ jsonrpc2.EmptyHandler } + +type clientHandler struct { + canceller + client Client +} + +type serverHandler struct { + canceller + server Server +} + +func (canceller) Request(ctx context.Context, conn *jsonrpc2.Conn, direction jsonrpc2.Direction, r *jsonrpc2.WireRequest) context.Context { + if direction == jsonrpc2.Receive && r.Method == "$/cancelRequest" { + var params CancelParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + log.Printf("%v", err) + } else { + conn.Cancel(params.ID) + } + } + return ctx +} + +func (canceller) Cancel(ctx context.Context, conn *jsonrpc2.Conn, id jsonrpc2.ID, cancelled bool) bool { + if cancelled { + return false + } + conn.Notify(ctx, "$/cancelRequest", &CancelParams{ID: id}) + return true +} + +func NewClient(ctx context.Context, stream jsonrpc2.Stream, client Client) (context.Context, *jsonrpc2.Conn, Server) { + ctx = WithClient(ctx, client) + conn := jsonrpc2.NewConn(stream) + conn.AddHandler(&clientHandler{client: client}) + return ctx, conn, &serverDispatcher{Conn: conn} +} + +func NewServer(ctx context.Context, stream jsonrpc2.Stream, server Server) (context.Context, *jsonrpc2.Conn, Client) { + conn := jsonrpc2.NewConn(stream) + client := &clientDispatcher{Conn: conn} + ctx = WithClient(ctx, client) + conn.AddHandler(&serverHandler{server: server}) + return ctx, conn, client +} + +func sendParseError(ctx context.Context, req *jsonrpc2.Request, err error) { + if _, ok := err.(*jsonrpc2.Error); !ok { + err = jsonrpc2.NewErrorf(jsonrpc2.CodeParseError, "%v", err) + } + if err := req.Reply(ctx, nil, err); err != nil { + log.Printf("%v", err) + } +} diff --git a/utils/vscode/src/lsp/protocol/span.go b/utils/vscode/src/lsp/protocol/span.go new file mode 100644 index 000000000..33cc2a651 --- /dev/null +++ b/utils/vscode/src/lsp/protocol/span.go @@ -0,0 +1,137 @@ +// Copyright 2018 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// this file contains protocol<->span converters + +package protocol + +import ( + "fmt" + + "../span" + errors "golang.org/x/xerrors" +) + +type ColumnMapper struct { + URI span.URI + Converter *span.TokenConverter + Content []byte +} + +func NewURI(uri span.URI) string { + return string(uri) +} + +func (m *ColumnMapper) Location(s span.Span) (Location, error) { + rng, err := m.Range(s) + if err != nil { + return Location{}, err + } + return Location{URI: NewURI(s.URI()), Range: rng}, nil +} + +func (m *ColumnMapper) Range(s span.Span) (Range, error) { + if span.CompareURI(m.URI, s.URI()) != 0 { + return Range{}, errors.Errorf("column mapper is for file %q instead of %q", m.URI, s.URI()) + } + s, err := s.WithAll(m.Converter) + if err != nil { + return Range{}, err + } + start, err := m.Position(s.Start()) + if err != nil { + return Range{}, err + } + end, err := m.Position(s.End()) + if err != nil { + return Range{}, err + } + return Range{Start: start, End: end}, nil +} + +func (m *ColumnMapper) Position(p span.Point) (Position, error) { + chr, err := span.ToUTF16Column(p, m.Content) + if err != nil { + return Position{}, err + } + return Position{ + Line: float64(p.Line() - 1), + Character: float64(chr - 1), + }, nil +} + +func (m *ColumnMapper) Span(l Location) (span.Span, error) { + return m.RangeSpan(l.Range) +} + +func (m *ColumnMapper) RangeSpan(r Range) (span.Span, error) { + start, err := m.Point(r.Start) + if err != nil { + return span.Span{}, err + } + end, err := m.Point(r.End) + if err != nil { + return span.Span{}, err + } + return span.New(m.URI, start, end).WithAll(m.Converter) +} + +func (m *ColumnMapper) PointSpan(p Position) (span.Span, error) { + start, err := m.Point(p) + if err != nil { + return span.Span{}, err + } + return span.New(m.URI, start, start).WithAll(m.Converter) +} + +func (m *ColumnMapper) Point(p Position) (span.Point, error) { + line := int(p.Line) + 1 + offset, err := m.Converter.ToOffset(line, 1) + if err != nil { + return span.Point{}, err + } + lineStart := span.NewPoint(line, 1, offset) + return span.FromUTF16Column(lineStart, int(p.Character)+1, m.Content) +} + +func IsPoint(r Range) bool { + return r.Start.Line == r.End.Line && r.Start.Character == r.End.Character +} + +func CompareRange(a, b Range) int { + if r := ComparePosition(a.Start, b.Start); r != 0 { + return r + } + return ComparePosition(a.End, b.End) +} + +func ComparePosition(a, b Position) int { + if a.Line < b.Line { + return -1 + } + if a.Line > b.Line { + return 1 + } + if a.Character < b.Character { + return -1 + } + if a.Character > b.Character { + return 1 + } + return 0 +} + +func (r Range) Format(f fmt.State, _ rune) { + fmt.Fprintf(f, "%v:%v-%v:%v", r.Start.Line, r.Start.Character, r.End.Line, r.End.Character) +} diff --git a/utils/vscode/src/lsp/protocol/tsclient.go b/utils/vscode/src/lsp/protocol/tsclient.go new file mode 100644 index 000000000..2f9beef46 --- /dev/null +++ b/utils/vscode/src/lsp/protocol/tsclient.go @@ -0,0 +1,221 @@ +// Copyright 2019 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package protocol + +import ( + "context" + "encoding/json" + "log" + + "../jsonrpc2" +) + +type Client interface { + ShowMessage(context.Context, *ShowMessageParams) error + LogMessage(context.Context, *LogMessageParams) error + Event(context.Context, *interface{}) error + PublishDiagnostics(context.Context, *PublishDiagnosticsParams) error + WorkspaceFolders(context.Context) ([]WorkspaceFolder, error) + Configuration(context.Context, *ParamConfig) ([]interface{}, error) + RegisterCapability(context.Context, *RegistrationParams) error + UnregisterCapability(context.Context, *UnregistrationParams) error + ShowMessageRequest(context.Context, *ShowMessageRequestParams) (*MessageActionItem, error) + ApplyEdit(context.Context, *ApplyWorkspaceEditParams) (*ApplyWorkspaceEditResponse, error) +} + +func (h clientHandler) Deliver(ctx context.Context, r *jsonrpc2.Request, delivered bool) bool { + if delivered { + return false + } + if ctx.Err() != nil { + r.Reply(ctx, nil, jsonrpc2.NewErrorf(RequestCancelledError, "")) + return true + } + switch r.Method { + case "window/showMessage": // notif + var params ShowMessageParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.client.ShowMessage(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "window/logMessage": // notif + var params LogMessageParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.client.LogMessage(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "telemetry/event": // notif + var params interface{} + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.client.Event(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/publishDiagnostics": // notif + var params PublishDiagnosticsParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.client.PublishDiagnostics(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "workspace/workspaceFolders": // req + if r.Params != nil { + r.Reply(ctx, nil, jsonrpc2.NewErrorf(jsonrpc2.CodeInvalidParams, "Expected no params")) + return true + } + resp, err := h.client.WorkspaceFolders(ctx) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "workspace/configuration": // req + var params ParamConfig + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.client.Configuration(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "client/registerCapability": // req + var params RegistrationParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + err := h.client.RegisterCapability(ctx, ¶ms) + if err := r.Reply(ctx, nil, err); err != nil { + log.Printf("%v", err) + } + return true + case "client/unregisterCapability": // req + var params UnregistrationParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + err := h.client.UnregisterCapability(ctx, ¶ms) + if err := r.Reply(ctx, nil, err); err != nil { + log.Printf("%v", err) + } + return true + case "window/showMessageRequest": // req + var params ShowMessageRequestParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.client.ShowMessageRequest(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "workspace/applyEdit": // req + var params ApplyWorkspaceEditParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.client.ApplyEdit(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + + default: + return false + } +} + +type clientDispatcher struct { + *jsonrpc2.Conn +} + +func (s *clientDispatcher) ShowMessage(ctx context.Context, params *ShowMessageParams) error { + return s.Conn.Notify(ctx, "window/showMessage", params) +} + +func (s *clientDispatcher) LogMessage(ctx context.Context, params *LogMessageParams) error { + return s.Conn.Notify(ctx, "window/logMessage", params) +} + +func (s *clientDispatcher) Event(ctx context.Context, params *interface{}) error { + return s.Conn.Notify(ctx, "telemetry/event", params) +} + +func (s *clientDispatcher) PublishDiagnostics(ctx context.Context, params *PublishDiagnosticsParams) error { + return s.Conn.Notify(ctx, "textDocument/publishDiagnostics", params) +} +func (s *clientDispatcher) WorkspaceFolders(ctx context.Context) ([]WorkspaceFolder, error) { + var result []WorkspaceFolder + if err := s.Conn.Call(ctx, "workspace/workspaceFolders", nil, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *clientDispatcher) Configuration(ctx context.Context, params *ParamConfig) ([]interface{}, error) { + var result []interface{} + if err := s.Conn.Call(ctx, "workspace/configuration", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *clientDispatcher) RegisterCapability(ctx context.Context, params *RegistrationParams) error { + return s.Conn.Call(ctx, "client/registerCapability", params, nil) // Call, not Notify +} + +func (s *clientDispatcher) UnregisterCapability(ctx context.Context, params *UnregistrationParams) error { + return s.Conn.Call(ctx, "client/unregisterCapability", params, nil) // Call, not Notify +} + +func (s *clientDispatcher) ShowMessageRequest(ctx context.Context, params *ShowMessageRequestParams) (*MessageActionItem, error) { + var result MessageActionItem + if err := s.Conn.Call(ctx, "window/showMessageRequest", params, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (s *clientDispatcher) ApplyEdit(ctx context.Context, params *ApplyWorkspaceEditParams) (*ApplyWorkspaceEditResponse, error) { + var result ApplyWorkspaceEditResponse + if err := s.Conn.Call(ctx, "workspace/applyEdit", params, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Types constructed to avoid structs as formal argument types +type ParamConfig struct { + ConfigurationParams + PartialResultParams +} diff --git a/utils/vscode/src/lsp/protocol/tsprotocol.go b/utils/vscode/src/lsp/protocol/tsprotocol.go new file mode 100644 index 000000000..50543fc81 --- /dev/null +++ b/utils/vscode/src/lsp/protocol/tsprotocol.go @@ -0,0 +1,4630 @@ +// Copyright 2019 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package protocol contains data types and code for LSP jsonrpcs +// generated automatically from vscode-languageserver-node +// commit: 36ac51f057215e6e2e0408384e07ecf564a938da +// last fetched Tue Sep 24 2019 17:44:28 GMT-0400 (Eastern Daylight Time) +package protocol + +// Code generated (see typescript/README.md) DO NOT EDIT. + +/*ImplementationClientCapabilities defined: + * Since 3.6.0 + */ +type ImplementationClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether implementation supports dynamic registration. If this is set to `true` + * the client supports the new `ImplementationRegistrationOptions` return value + * for the corresponding server capability as well. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*LinkSupport defined: + * The client supports additional metadata in the form of definition links. + * + * Since 3.14.0 + */ + LinkSupport bool `json:"linkSupport,omitempty"` +} + +// ImplementationOptions is +type ImplementationOptions struct { + WorkDoneProgressOptions +} + +// ImplementationRegistrationOptions is +type ImplementationRegistrationOptions struct { + TextDocumentRegistrationOptions + ImplementationOptions + StaticRegistrationOptions +} + +// ImplementationParams is +type ImplementationParams struct { + TextDocumentPositionParams + WorkDoneProgressParams + PartialResultParams +} + +/*TypeDefinitionClientCapabilities defined: + * Since 3.6.0 + */ +type TypeDefinitionClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether implementation supports dynamic registration. If this is set to `true` + * the client supports the new `TypeDefinitionRegistrationOptions` return value + * for the corresponding server capability as well. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*LinkSupport defined: + * The client supports additional metadata in the form of definition links. + * + * Since 3.14.0 + */ + LinkSupport bool `json:"linkSupport,omitempty"` +} + +// TypeDefinitionOptions is +type TypeDefinitionOptions struct { + WorkDoneProgressOptions +} + +// TypeDefinitionRegistrationOptions is +type TypeDefinitionRegistrationOptions struct { + TextDocumentRegistrationOptions + TypeDefinitionOptions + StaticRegistrationOptions +} + +// TypeDefinitionParams is +type TypeDefinitionParams struct { + TextDocumentPositionParams + WorkDoneProgressParams + PartialResultParams +} + +// WorkspaceFoldersInitializeParams is +type WorkspaceFoldersInitializeParams struct { + + /*WorkspaceFolders defined: + * The actual configured workspace folders. + */ + WorkspaceFolders []WorkspaceFolder `json:"workspaceFolders"` +} + +// WorkspaceFoldersClientCapabilities is +type WorkspaceFoldersClientCapabilities struct { + + /*Workspace defined: + * The workspace client capabilities + */ + Workspace *struct { + + /*WorkspaceFolders defined: + * The client has support for workspace folders + */ + WorkspaceFolders bool `json:"workspaceFolders,omitempty"` + } `json:"workspace,omitempty"` +} + +// WorkspaceFoldersServerCapabilities is +type WorkspaceFoldersServerCapabilities struct { + + /*Workspace defined: + * The workspace server capabilities + */ + Workspace *struct { + + // WorkspaceFolders is + WorkspaceFolders *struct { + + /*Supported defined: + * The Server has support for workspace folders + */ + Supported bool `json:"supported,omitempty"` + + /*ChangeNotifications defined: + * Whether the server wants to receive workspace folder + * change notifications. + * + * If a strings is provided the string is treated as a ID + * under which the notification is registed on the client + * side. The ID can be used to unregister for these events + * using the `client/unregisterCapability` request. + */ + ChangeNotifications string `json:"changeNotifications,omitempty"` // string | boolean + } `json:"workspaceFolders,omitempty"` + } `json:"workspace,omitempty"` +} + +// WorkspaceFolder is +type WorkspaceFolder struct { + + /*URI defined: + * The associated URI for this workspace folder. + */ + URI string `json:"uri"` + + /*Name defined: + * The name of the workspace folder. Used to refer to this + * workspace folder in thge user interface. + */ + Name string `json:"name"` +} + +/*DidChangeWorkspaceFoldersParams defined: + * The parameters of a `workspace/didChangeWorkspaceFolders` notification. + */ +type DidChangeWorkspaceFoldersParams struct { + + /*Event defined: + * The actual workspace folder change event. + */ + Event WorkspaceFoldersChangeEvent `json:"event"` +} + +/*WorkspaceFoldersChangeEvent defined: + * The workspace folder change event. + */ +type WorkspaceFoldersChangeEvent struct { + + /*Added defined: + * The array of added workspace folders + */ + Added []WorkspaceFolder `json:"added"` + + /*Removed defined: + * The array of the removed workspace folders + */ + Removed []WorkspaceFolder `json:"removed"` +} + +// ConfigurationClientCapabilities is +type ConfigurationClientCapabilities struct { + + /*Workspace defined: + * The workspace client capabilities + */ + Workspace *struct { + + /*Configuration defined: + * The client supports `workspace/configuration` requests. + */ + Configuration bool `json:"configuration,omitempty"` + } `json:"workspace,omitempty"` +} + +// ConfigurationItem is +type ConfigurationItem struct { + + /*ScopeURI defined: + * The scope to get the configuration section for. + */ + ScopeURI string `json:"scopeUri,omitempty"` + + /*Section defined: + * The configuration section asked for. + */ + Section string `json:"section,omitempty"` +} + +/*ConfigurationParams defined: + * The parameters of a configuration request. + */ +type ConfigurationParams struct { + + // Items is + Items []ConfigurationItem `json:"items"` +} + +// DocumentColorClientCapabilities is +type DocumentColorClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether implementation supports dynamic registration. If this is set to `true` + * the client supports the new `DocumentColorRegistrationOptions` return value + * for the corresponding server capability as well. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` +} + +// DocumentColorOptions is +type DocumentColorOptions struct { + + /*ResolveProvider defined: + * Code lens has a resolve provider as well. + */ + ResolveProvider bool `json:"resolveProvider,omitempty"` + WorkDoneProgressOptions +} + +// DocumentColorRegistrationOptions is +type DocumentColorRegistrationOptions struct { + TextDocumentRegistrationOptions + StaticRegistrationOptions + DocumentColorOptions +} + +/*DocumentColorParams defined: + * Parameters for a [DocumentColorRequest](#DocumentColorRequest). + */ +type DocumentColorParams struct { + + /*TextDocument defined: + * The text document. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + WorkDoneProgressParams + PartialResultParams +} + +/*ColorPresentationParams defined: + * Parameters for a [ColorPresentationRequest](#ColorPresentationRequest). + */ +type ColorPresentationParams struct { + + /*TextDocument defined: + * The text document. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + + /*Color defined: + * The color to request presentations for. + */ + Color Color `json:"color"` + + /*Range defined: + * The range where the color would be inserted. Serves as a context. + */ + Range Range `json:"range"` + WorkDoneProgressParams + PartialResultParams +} + +// FoldingRangeClientCapabilities is +type FoldingRangeClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether implementation supports dynamic registration for folding range providers. If this is set to `true` + * the client supports the new `FoldingRangeRegistrationOptions` return value for the corresponding server + * capability as well. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*RangeLimit defined: + * The maximum number of folding ranges that the client prefers to receive per document. The value serves as a + * hint, servers are free to follow the limit. + */ + RangeLimit float64 `json:"rangeLimit,omitempty"` + + /*LineFoldingOnly defined: + * If set, the client signals that it only supports folding complete lines. If set, client will + * ignore specified `startCharacter` and `endCharacter` properties in a FoldingRange. + */ + LineFoldingOnly bool `json:"lineFoldingOnly,omitempty"` +} + +// FoldingRangeOptions is +type FoldingRangeOptions struct { + WorkDoneProgressOptions +} + +// FoldingRangeRegistrationOptions is +type FoldingRangeRegistrationOptions struct { + TextDocumentRegistrationOptions + FoldingRangeOptions + StaticRegistrationOptions +} + +/*FoldingRange defined: + * Represents a folding range. + */ +type FoldingRange struct { + + /*StartLine defined: + * The zero-based line number from where the folded range starts. + */ + StartLine float64 `json:"startLine"` + + /*StartCharacter defined: + * The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line. + */ + StartCharacter float64 `json:"startCharacter,omitempty"` + + /*EndLine defined: + * The zero-based line number where the folded range ends. + */ + EndLine float64 `json:"endLine"` + + /*EndCharacter defined: + * The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line. + */ + EndCharacter float64 `json:"endCharacter,omitempty"` + + /*Kind defined: + * Describes the kind of the folding range such as `comment' or 'region'. The kind + * is used to categorize folding ranges and used by commands like 'Fold all comments'. See + * [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds. + */ + Kind string `json:"kind,omitempty"` +} + +/*FoldingRangeParams defined: + * Parameters for a [FoldingRangeRequest](#FoldingRangeRequest). + */ +type FoldingRangeParams struct { + + /*TextDocument defined: + * The text document. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + WorkDoneProgressParams + PartialResultParams +} + +/*DeclarationClientCapabilities defined: + * Since 3.14.0 + */ +type DeclarationClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether declaration supports dynamic registration. If this is set to `true` + * the client supports the new `DeclarationRegistrationOptions` return value + * for the corresponding server capability as well. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*LinkSupport defined: + * The client supports additional metadata in the form of declaration links. + */ + LinkSupport bool `json:"linkSupport,omitempty"` +} + +// DeclarationOptions is +type DeclarationOptions struct { + WorkDoneProgressOptions +} + +// DeclarationRegistrationOptions is +type DeclarationRegistrationOptions struct { + DeclarationOptions + TextDocumentRegistrationOptions + StaticRegistrationOptions +} + +// DeclarationParams is +type DeclarationParams struct { + TextDocumentPositionParams + WorkDoneProgressParams + PartialResultParams +} + +// SelectionRangeClientCapabilities is +type SelectionRangeClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether implementation supports dynamic registration for selection range providers. If this is set to `true` + * the client supports the new `SelectionRangeRegistrationOptions` return value for the corresponding server + * capability as well. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` +} + +// SelectionRangeOptions is +type SelectionRangeOptions struct { + WorkDoneProgressOptions +} + +// SelectionRangeRegistrationOptions is +type SelectionRangeRegistrationOptions struct { + SelectionRangeOptions + TextDocumentRegistrationOptions + StaticRegistrationOptions +} + +/*SelectionRangeParams defined: + * A parameter literal used in selection range requests. + */ +type SelectionRangeParams struct { + + /*TextDocument defined: + * The text document. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + + /*Positions defined: + * The positions inside the text document. + */ + Positions []Position `json:"positions"` + WorkDoneProgressParams + PartialResultParams +} + +/*Registration defined: + * General parameters to to register for an notification or to register a provider. + */ +type Registration struct { + + /*ID defined: + * The id used to register the request. The id can be used to deregister + * the request again. + */ + ID string `json:"id"` + + /*Method defined: + * The method to register for. + */ + Method string `json:"method"` + + /*RegisterOptions defined: + * Options necessary for the registration. + */ + RegisterOptions interface{} `json:"registerOptions,omitempty"` +} + +// RegistrationParams is +type RegistrationParams struct { + + // Registrations is + Registrations []Registration `json:"registrations"` +} + +/*Unregistration defined: + * General parameters to unregister a request or notification. + */ +type Unregistration struct { + + /*ID defined: + * The id used to unregister the request or notification. Usually an id + * provided during the register request. + */ + ID string `json:"id"` + + /*Method defined: + * The method to unregister for. + */ + Method string `json:"method"` +} + +// UnregistrationParams is +type UnregistrationParams struct { + + // Unregisterations is + Unregisterations []Unregistration `json:"unregisterations"` +} + +// WorkDoneProgressParams is +type WorkDoneProgressParams struct { + + /*WorkDoneToken defined: + * An optional token that a server can use to report work done progress. + */ + WorkDoneToken *ProgressToken `json:"workDoneToken,omitempty"` +} + +// PartialResultParams is +type PartialResultParams struct { + + /*PartialResultToken defined: + * An optional token that a server can use to report partial results (e.g. streaming) to + * the client. + */ + PartialResultToken *ProgressToken `json:"partialResultToken,omitempty"` +} + +/*TextDocumentPositionParams defined: + * A parameter literal used in requests to pass a text document and a position inside that + * document. + */ +type TextDocumentPositionParams struct { + + /*TextDocument defined: + * The text document. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + + /*Position defined: + * The position inside the text document. + */ + Position Position `json:"position"` +} + +/*WorkspaceClientCapabilities defined: + * Workspace specific client capabilities. + */ +type WorkspaceClientCapabilities struct { + + /*ApplyEdit defined: + * The client supports applying batch edits + * to the workspace by supporting the request + * 'workspace/applyEdit' + */ + ApplyEdit bool `json:"applyEdit,omitempty"` + + /*WorkspaceEdit defined: + * Capabilities specific to `WorkspaceEdit`s + */ + WorkspaceEdit *WorkspaceEditClientCapabilities `json:"workspaceEdit,omitempty"` + + /*DidChangeConfiguration defined: + * Capabilities specific to the `workspace/didChangeConfiguration` notification. + */ + DidChangeConfiguration *DidChangeConfigurationClientCapabilities `json:"didChangeConfiguration,omitempty"` + + /*DidChangeWatchedFiles defined: + * Capabilities specific to the `workspace/didChangeWatchedFiles` notification. + */ + DidChangeWatchedFiles *DidChangeWatchedFilesClientCapabilities `json:"didChangeWatchedFiles,omitempty"` + + /*Symbol defined: + * Capabilities specific to the `workspace/symbol` request. + */ + Symbol *WorkspaceSymbolClientCapabilities `json:"symbol,omitempty"` + + /*ExecuteCommand defined: + * Capabilities specific to the `workspace/executeCommand` request. + */ + ExecuteCommand *ExecuteCommandClientCapabilities `json:"executeCommand,omitempty"` +} + +/*TextDocumentClientCapabilities defined: + * Text document specific client capabilities. + */ +type TextDocumentClientCapabilities struct { + + /*Synchronization defined: + * Defines which synchronization capabilities the client supports. + */ + Synchronization *TextDocumentSyncClientCapabilities `json:"synchronization,omitempty"` + + /*Completion defined: + * Capabilities specific to the `textDocument/completion` + */ + Completion *CompletionClientCapabilities `json:"completion,omitempty"` + + /*Hover defined: + * Capabilities specific to the `textDocument/hover` + */ + Hover *HoverClientCapabilities `json:"hover,omitempty"` + + /*SignatureHelp defined: + * Capabilities specific to the `textDocument/signatureHelp` + */ + SignatureHelp *SignatureHelpClientCapabilities `json:"signatureHelp,omitempty"` + + /*Declaration defined: + * Capabilities specific to the `textDocument/declaration` + * + * @since 3.14.0 + */ + Declaration *DeclarationClientCapabilities `json:"declaration,omitempty"` + + /*Definition defined: + * Capabilities specific to the `textDocument/definition` + */ + Definition *DefinitionClientCapabilities `json:"definition,omitempty"` + + /*TypeDefinition defined: + * Capabilities specific to the `textDocument/typeDefinition` + * + * @since 3.6.0 + */ + TypeDefinition *TypeDefinitionClientCapabilities `json:"typeDefinition,omitempty"` + + /*Implementation defined: + * Capabilities specific to the `textDocument/implementation` + * + * @since 3.6.0 + */ + Implementation *ImplementationClientCapabilities `json:"implementation,omitempty"` + + /*References defined: + * Capabilities specific to the `textDocument/references` + */ + References *ReferenceClientCapabilities `json:"references,omitempty"` + + /*DocumentHighlight defined: + * Capabilities specific to the `textDocument/documentHighlight` + */ + DocumentHighlight *DocumentHighlightClientCapabilities `json:"documentHighlight,omitempty"` + + /*DocumentSymbol defined: + * Capabilities specific to the `textDocument/documentSymbol` + */ + DocumentSymbol *DocumentSymbolClientCapabilities `json:"documentSymbol,omitempty"` + + /*CodeAction defined: + * Capabilities specific to the `textDocument/codeAction` + */ + CodeAction *CodeActionClientCapabilities `json:"codeAction,omitempty"` + + /*CodeLens defined: + * Capabilities specific to the `textDocument/codeLens` + */ + CodeLens *CodeLensClientCapabilities `json:"codeLens,omitempty"` + + /*DocumentLink defined: + * Capabilities specific to the `textDocument/documentLink` + */ + DocumentLink *DocumentLinkClientCapabilities `json:"documentLink,omitempty"` + + /*ColorProvider defined: + * Capabilities specific to the `textDocument/documentColor` + */ + ColorProvider *DocumentColorClientCapabilities `json:"colorProvider,omitempty"` + + /*Formatting defined: + * Capabilities specific to the `textDocument/formatting` + */ + Formatting *DocumentFormattingClientCapabilities `json:"formatting,omitempty"` + + /*RangeFormatting defined: + * Capabilities specific to the `textDocument/rangeFormatting` + */ + RangeFormatting *DocumentRangeFormattingClientCapabilities `json:"rangeFormatting,omitempty"` + + /*OnTypeFormatting defined: + * Capabilities specific to the `textDocument/onTypeFormatting` + */ + OnTypeFormatting *DocumentOnTypeFormattingClientCapabilities `json:"onTypeFormatting,omitempty"` + + /*Rename defined: + * Capabilities specific to the `textDocument/rename` + */ + Rename *RenameClientCapabilities `json:"rename,omitempty"` + + /*FoldingRange defined: + * Capabilities specific to `textDocument/foldingRange` requests. + * + * @since 3.10.0 + */ + FoldingRange *FoldingRangeClientCapabilities `json:"foldingRange,omitempty"` + + /*SelectionRange defined: + * Capabilities specific to `textDocument/selectionRange` requests + * + * @since 3.15.0 + */ + SelectionRange *SelectionRangeClientCapabilities `json:"selectionRange,omitempty"` + + /*PublishDiagnostics defined: + * Capabilities specific to `textDocument/publishDiagnostics`. + */ + PublishDiagnostics *PublishDiagnosticsClientCapabilities `json:"publishDiagnostics,omitempty"` +} + +/*InnerClientCapabilities defined: + * Defines the capabilities provided by the client. + */ +type InnerClientCapabilities struct { + + /*Workspace defined: + * Workspace specific client capabilities. + */ + Workspace *WorkspaceClientCapabilities `json:"workspace,omitempty"` + + /*TextDocument defined: + * Text document specific client capabilities. + */ + TextDocument *TextDocumentClientCapabilities `json:"textDocument,omitempty"` + + /*Window defined: + * Window specific client capabilities. + */ + Window interface{} `json:"window,omitempty"` + + /*Experimental defined: + * Experimental client capabilities. + */ + Experimental interface{} `json:"experimental,omitempty"` +} + +// ClientCapabilities is +type ClientCapabilities struct { + + /*Workspace defined: + * Workspace specific client capabilities. + */ + Workspace struct { + + /*ApplyEdit defined: + * The client supports applying batch edits + * to the workspace by supporting the request + * 'workspace/applyEdit' + */ + ApplyEdit bool `json:"applyEdit,omitempty"` + + /*WorkspaceEdit defined: + * Capabilities specific to `WorkspaceEdit`s + */ + WorkspaceEdit WorkspaceEditClientCapabilities `json:"workspaceEdit,omitempty"` + + /*DidChangeConfiguration defined: + * Capabilities specific to the `workspace/didChangeConfiguration` notification. + */ + DidChangeConfiguration DidChangeConfigurationClientCapabilities `json:"didChangeConfiguration,omitempty"` + + /*DidChangeWatchedFiles defined: + * Capabilities specific to the `workspace/didChangeWatchedFiles` notification. + */ + DidChangeWatchedFiles DidChangeWatchedFilesClientCapabilities `json:"didChangeWatchedFiles,omitempty"` + + /*Symbol defined: + * Capabilities specific to the `workspace/symbol` request. + */ + Symbol WorkspaceSymbolClientCapabilities `json:"symbol,omitempty"` + + /*ExecuteCommand defined: + * Capabilities specific to the `workspace/executeCommand` request. + */ + ExecuteCommand ExecuteCommandClientCapabilities `json:"executeCommand,omitempty"` + + /*WorkspaceFolders defined: + * The client has support for workspace folders + */ + WorkspaceFolders bool `json:"workspaceFolders,omitempty"` + + /*Configuration defined: + * The client supports `workspace/configuration` requests. + */ + Configuration bool `json:"configuration,omitempty"` + } `json:"workspace,omitempty"` + + /*TextDocument defined: + * Text document specific client capabilities. + */ + TextDocument TextDocumentClientCapabilities `json:"textDocument,omitempty"` + + /*Window defined: + * Window specific client capabilities. + */ + Window interface{} `json:"window,omitempty"` + + /*Experimental defined: + * Experimental client capabilities. + */ + Experimental interface{} `json:"experimental,omitempty"` + + /*DynamicRegistration defined: + * Whether implementation supports dynamic registration for selection range providers. If this is set to `true` + * the client supports the new `SelectionRangeRegistrationOptions` return value for the corresponding server + * capability as well. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` +} + +/*StaticRegistrationOptions defined: + * Static registration options to be returned in the initialize + * request. + */ +type StaticRegistrationOptions struct { + + /*ID defined: + * The id used to register the request. The id can be used to deregister + * the request again. See also Registration#id. + */ + ID string `json:"id,omitempty"` +} + +/*TextDocumentRegistrationOptions defined: + * General text document registration options. + */ +type TextDocumentRegistrationOptions struct { + + /*DocumentSelector defined: + * A document selector to identify the scope of the registration. If set to null + * the document selector provided on the client side will be used. + */ + DocumentSelector DocumentSelector `json:"documentSelector"` +} + +/*SaveOptions defined: + * Save options. + */ +type SaveOptions struct { + + /*IncludeText defined: + * The client is supposed to include the content on save. + */ + IncludeText bool `json:"includeText,omitempty"` +} + +// WorkDoneProgressOptions is +type WorkDoneProgressOptions struct { + + // WorkDoneProgress is + WorkDoneProgress bool `json:"workDoneProgress,omitempty"` +} + +/*InnerServerCapabilities defined: + * Defines the capabilities provided by a language + * server. + */ +type InnerServerCapabilities struct { + + /*TextDocumentSync defined: + * Defines how text documents are synced. Is either a detailed structure defining each notification or + * for backwards compatibility the TextDocumentSyncKind number. + */ + TextDocumentSync interface{} `json:"textDocumentSync,omitempty"` // TextDocumentSyncOptions | TextDocumentSyncKind + + /*CompletionProvider defined: + * The server provides completion support. + */ + CompletionProvider *CompletionOptions `json:"completionProvider,omitempty"` + + /*HoverProvider defined: + * The server provides hover support. + */ + HoverProvider bool `json:"hoverProvider,omitempty"` // boolean | HoverOptions + + /*SignatureHelpProvider defined: + * The server provides signature help support. + */ + SignatureHelpProvider *SignatureHelpOptions `json:"signatureHelpProvider,omitempty"` + + /*DeclarationProvider defined: + * The server provides Goto Declaration support. + */ + DeclarationProvider bool `json:"declarationProvider,omitempty"` // boolean | DeclarationOptions | DeclarationRegistrationOptions + + /*DefinitionProvider defined: + * The server provides goto definition support. + */ + DefinitionProvider bool `json:"definitionProvider,omitempty"` // boolean | DefinitionOptions + + /*TypeDefinitionProvider defined: + * The server provides Goto Type Definition support. + */ + TypeDefinitionProvider bool `json:"typeDefinitionProvider,omitempty"` // boolean | TypeDefinitionOptions | TypeDefinitionRegistrationOptions + + /*ImplementationProvider defined: + * The server provides Goto Implementation support. + */ + ImplementationProvider bool `json:"implementationProvider,omitempty"` // boolean | ImplementationOptions | ImplementationRegistrationOptions + + /*ReferencesProvider defined: + * The server provides find references support. + */ + ReferencesProvider bool `json:"referencesProvider,omitempty"` // boolean | ReferenceOptions + + /*DocumentHighlightProvider defined: + * The server provides document highlight support. + */ + DocumentHighlightProvider bool `json:"documentHighlightProvider,omitempty"` // boolean | DocumentHighlightOptions + + /*DocumentSymbolProvider defined: + * The server provides document symbol support. + */ + DocumentSymbolProvider bool `json:"documentSymbolProvider,omitempty"` // boolean | DocumentSymbolOptions + + /*CodeActionProvider defined: + * The server provides code actions. CodeActionOptions may only be + * specified if the client states that it supports + * `codeActionLiteralSupport` in its initial `initialize` request. + */ + CodeActionProvider interface{} `json:"codeActionProvider,omitempty"` // boolean | CodeActionOptions + + /*CodeLensProvider defined: + * The server provides code lens. + */ + CodeLensProvider *CodeLensOptions `json:"codeLensProvider,omitempty"` + + /*DocumentLinkProvider defined: + * The server provides document link support. + */ + DocumentLinkProvider *DocumentLinkOptions `json:"documentLinkProvider,omitempty"` + + /*ColorProvider defined: + * The server provides color provider support. + */ + ColorProvider bool `json:"colorProvider,omitempty"` // boolean | DocumentColorOptions | DocumentColorRegistrationOptions + + /*WorkspaceSymbolProvider defined: + * The server provides workspace symbol support. + */ + WorkspaceSymbolProvider bool `json:"workspaceSymbolProvider,omitempty"` // boolean | WorkspaceSymbolOptions + + /*DocumentFormattingProvider defined: + * The server provides document formatting. + */ + DocumentFormattingProvider bool `json:"documentFormattingProvider,omitempty"` // boolean | DocumentFormattingOptions + + /*DocumentRangeFormattingProvider defined: + * The server provides document range formatting. + */ + DocumentRangeFormattingProvider bool `json:"documentRangeFormattingProvider,omitempty"` // boolean | DocumentRangeFormattingOptions + + /*DocumentOnTypeFormattingProvider defined: + * The server provides document formatting on typing. + */ + DocumentOnTypeFormattingProvider *DocumentOnTypeFormattingOptions `json:"documentOnTypeFormattingProvider,omitempty"` + + /*RenameProvider defined: + * The server provides rename support. RenameOptions may only be + * specified if the client states that it supports + * `prepareSupport` in its initial `initialize` request. + */ + RenameProvider interface{} `json:"renameProvider,omitempty"` // boolean | RenameOptions + + /*FoldingRangeProvider defined: + * The server provides folding provider support. + */ + FoldingRangeProvider bool `json:"foldingRangeProvider,omitempty"` // boolean | FoldingRangeOptions | FoldingRangeRegistrationOptions + + /*SelectionRangeProvider defined: + * The server provides selection range support. + */ + SelectionRangeProvider bool `json:"selectionRangeProvider,omitempty"` // boolean | SelectionRangeOptions | SelectionRangeRegistrationOptions + + /*ExecuteCommandProvider defined: + * The server provides execute command support. + */ + ExecuteCommandProvider *ExecuteCommandOptions `json:"executeCommandProvider,omitempty"` + + /*Experimental defined: + * Experimental server capabilities. + */ + Experimental interface{} `json:"experimental,omitempty"` +} + +// ServerCapabilities is +type ServerCapabilities struct { + + /*TextDocumentSync defined: + * Defines how text documents are synced. Is either a detailed structure defining each notification or + * for backwards compatibility the TextDocumentSyncKind number. + */ + TextDocumentSync interface{} `json:"textDocumentSync,omitempty"` // TextDocumentSyncOptions | TextDocumentSyncKind + + /*CompletionProvider defined: + * The server provides completion support. + */ + CompletionProvider *CompletionOptions `json:"completionProvider,omitempty"` + + /*HoverProvider defined: + * The server provides hover support. + */ + HoverProvider bool `json:"hoverProvider,omitempty"` // boolean | HoverOptions + + /*SignatureHelpProvider defined: + * The server provides signature help support. + */ + SignatureHelpProvider *SignatureHelpOptions `json:"signatureHelpProvider,omitempty"` + + /*DeclarationProvider defined: + * The server provides Goto Declaration support. + */ + DeclarationProvider bool `json:"declarationProvider,omitempty"` // boolean | DeclarationOptions | DeclarationRegistrationOptions + + /*DefinitionProvider defined: + * The server provides goto definition support. + */ + DefinitionProvider bool `json:"definitionProvider,omitempty"` // boolean | DefinitionOptions + + /*TypeDefinitionProvider defined: + * The server provides Goto Type Definition support. + */ + TypeDefinitionProvider bool `json:"typeDefinitionProvider,omitempty"` // boolean | TypeDefinitionOptions | TypeDefinitionRegistrationOptions + + /*ImplementationProvider defined: + * The server provides Goto Implementation support. + */ + ImplementationProvider bool `json:"implementationProvider,omitempty"` // boolean | ImplementationOptions | ImplementationRegistrationOptions + + /*ReferencesProvider defined: + * The server provides find references support. + */ + ReferencesProvider bool `json:"referencesProvider,omitempty"` // boolean | ReferenceOptions + + /*DocumentHighlightProvider defined: + * The server provides document highlight support. + */ + DocumentHighlightProvider bool `json:"documentHighlightProvider,omitempty"` // boolean | DocumentHighlightOptions + + /*DocumentSymbolProvider defined: + * The server provides document symbol support. + */ + DocumentSymbolProvider bool `json:"documentSymbolProvider,omitempty"` // boolean | DocumentSymbolOptions + + /*CodeActionProvider defined: + * The server provides code actions. CodeActionOptions may only be + * specified if the client states that it supports + * `codeActionLiteralSupport` in its initial `initialize` request. + */ + CodeActionProvider interface{} `json:"codeActionProvider,omitempty"` // boolean | CodeActionOptions + + /*CodeLensProvider defined: + * The server provides code lens. + */ + CodeLensProvider *CodeLensOptions `json:"codeLensProvider,omitempty"` + + /*DocumentLinkProvider defined: + * The server provides document link support. + */ + DocumentLinkProvider *DocumentLinkOptions `json:"documentLinkProvider,omitempty"` + + /*ColorProvider defined: + * The server provides color provider support. + */ + ColorProvider bool `json:"colorProvider,omitempty"` // boolean | DocumentColorOptions | DocumentColorRegistrationOptions + + /*WorkspaceSymbolProvider defined: + * The server provides workspace symbol support. + */ + WorkspaceSymbolProvider bool `json:"workspaceSymbolProvider,omitempty"` // boolean | WorkspaceSymbolOptions + + /*DocumentFormattingProvider defined: + * The server provides document formatting. + */ + DocumentFormattingProvider bool `json:"documentFormattingProvider,omitempty"` // boolean | DocumentFormattingOptions + + /*DocumentRangeFormattingProvider defined: + * The server provides document range formatting. + */ + DocumentRangeFormattingProvider bool `json:"documentRangeFormattingProvider,omitempty"` // boolean | DocumentRangeFormattingOptions + + /*DocumentOnTypeFormattingProvider defined: + * The server provides document formatting on typing. + */ + DocumentOnTypeFormattingProvider *DocumentOnTypeFormattingOptions `json:"documentOnTypeFormattingProvider,omitempty"` + + /*RenameProvider defined: + * The server provides rename support. RenameOptions may only be + * specified if the client states that it supports + * `prepareSupport` in its initial `initialize` request. + */ + RenameProvider interface{} `json:"renameProvider,omitempty"` // boolean | RenameOptions + + /*FoldingRangeProvider defined: + * The server provides folding provider support. + */ + FoldingRangeProvider bool `json:"foldingRangeProvider,omitempty"` // boolean | FoldingRangeOptions | FoldingRangeRegistrationOptions + + /*SelectionRangeProvider defined: + * The server provides selection range support. + */ + SelectionRangeProvider bool `json:"selectionRangeProvider,omitempty"` // boolean | SelectionRangeOptions | SelectionRangeRegistrationOptions + + /*ExecuteCommandProvider defined: + * The server provides execute command support. + */ + ExecuteCommandProvider *ExecuteCommandOptions `json:"executeCommandProvider,omitempty"` + + /*Experimental defined: + * Experimental server capabilities. + */ + Experimental interface{} `json:"experimental,omitempty"` + + /*Workspace defined: + * The workspace server capabilities + */ + Workspace *struct { + + // WorkspaceFolders is + WorkspaceFolders *struct { + + /*Supported defined: + * The Server has support for workspace folders + */ + Supported bool `json:"supported,omitempty"` + + /*ChangeNotifications defined: + * Whether the server wants to receive workspace folder + * change notifications. + * + * If a strings is provided the string is treated as a ID + * under which the notification is registed on the client + * side. The ID can be used to unregister for these events + * using the `client/unregisterCapability` request. + */ + ChangeNotifications string `json:"changeNotifications,omitempty"` // string | boolean + } `json:"workspaceFolders,omitempty"` + } `json:"workspace,omitempty"` +} + +/*InnerInitializeParams defined: + * The initialize parameters + */ +type InnerInitializeParams struct { + + /*ProcessID defined: + * The process Id of the parent process that started + * the server. + */ + ProcessID float64 `json:"processId"` + + /*ClientInfo defined: + * Information about the client + * + * @since 3.15.0 + */ + ClientInfo *struct { + + /*Name defined: + * The name of the client as defined by the client. + */ + Name string `json:"name"` + + /*Version defined: + * The client's version as defined by the client. + */ + Version string `json:"version,omitempty"` + } `json:"clientInfo,omitempty"` + + /*RootPath defined: + * The rootPath of the workspace. Is null + * if no folder is open. + * + * @deprecated in favour of rootUri. + */ + RootPath string `json:"rootPath,omitempty"` + + /*RootURI defined: + * The rootUri of the workspace. Is null if no + * folder is open. If both `rootPath` and `rootUri` are set + * `rootUri` wins. + * + * @deprecated in favour of workspaceFolders. + */ + RootURI DocumentURI `json:"rootUri"` + + /*Capabilities defined: + * The capabilities provided by the client (editor or tool) + */ + Capabilities ClientCapabilities `json:"capabilities"` + + /*InitializationOptions defined: + * User provided initialization options. + */ + InitializationOptions interface{} `json:"initializationOptions,omitempty"` + + /*Trace defined: + * The initial trace setting. If omitted trace is disabled ('off'). + */ + Trace string `json:"trace,omitempty"` // 'off' | 'messages' | 'verbose' + WorkDoneProgressParams +} + +// InitializeParams is +type InitializeParams struct { + + /*ProcessID defined: + * The process Id of the parent process that started + * the server. + */ + ProcessID float64 `json:"processId"` + + /*ClientInfo defined: + * Information about the client + * + * @since 3.15.0 + */ + ClientInfo *struct { + + /*Name defined: + * The name of the client as defined by the client. + */ + Name string `json:"name"` + + /*Version defined: + * The client's version as defined by the client. + */ + Version string `json:"version,omitempty"` + } `json:"clientInfo,omitempty"` + + /*RootPath defined: + * The rootPath of the workspace. Is null + * if no folder is open. + * + * @deprecated in favour of rootUri. + */ + RootPath string `json:"rootPath,omitempty"` + + /*RootURI defined: + * The rootUri of the workspace. Is null if no + * folder is open. If both `rootPath` and `rootUri` are set + * `rootUri` wins. + * + * @deprecated in favour of workspaceFolders. + */ + RootURI DocumentURI `json:"rootUri"` + + /*Capabilities defined: + * The capabilities provided by the client (editor or tool) + */ + Capabilities ClientCapabilities `json:"capabilities"` + + /*InitializationOptions defined: + * User provided initialization options. + */ + InitializationOptions interface{} `json:"initializationOptions,omitempty"` + + /*Trace defined: + * The initial trace setting. If omitted trace is disabled ('off'). + */ + Trace string `json:"trace,omitempty"` // 'off' | 'messages' | 'verbose' + + /*WorkspaceFolders defined: + * The actual configured workspace folders. + */ + WorkspaceFolders []WorkspaceFolder `json:"workspaceFolders"` +} + +/*InitializeResult defined: + * The result returned from an initialize request. + */ +type InitializeResult struct { + + /*Capabilities defined: + * The capabilities the language server provides. + */ + Capabilities ServerCapabilities `json:"capabilities"` + + /*ServerInfo defined: + * Information about the server. + * + * @since 3.15.0 + */ + ServerInfo *struct { + + /*Name defined: + * The name of the server as defined by the server. + */ + Name string `json:"name"` + + /*Version defined: + * The servers's version as defined by the server. + */ + Version string `json:"version,omitempty"` + } `json:"serverInfo,omitempty"` + + /*Custom defined: + * Custom initialization results. + */ + Custom map[string]interface{} `json:"custom"` // [custom: string]: any; +} + +// InitializedParams is +type InitializedParams struct { +} + +// DidChangeConfigurationClientCapabilities is +type DidChangeConfigurationClientCapabilities struct { + + /*DynamicRegistration defined: + * Did change configuration notification supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` +} + +// DidChangeConfigurationRegistrationOptions is +type DidChangeConfigurationRegistrationOptions struct { + + // Section is + Section string `json:"section,omitempty"` // string | string[] +} + +/*DidChangeConfigurationParams defined: + * The parameters of a change configuration notification. + */ +type DidChangeConfigurationParams struct { + + /*Settings defined: + * The actual changed settings + */ + Settings interface{} `json:"settings"` +} + +/*ShowMessageParams defined: + * The parameters of a notification message. + */ +type ShowMessageParams struct { + + /*Type defined: + * The message type. See {@link MessageType} + */ + Type MessageType `json:"type"` + + /*Message defined: + * The actual message + */ + Message string `json:"message"` +} + +// MessageActionItem is +type MessageActionItem struct { + + /*Title defined: + * A short title like 'Retry', 'Open Log' etc. + */ + Title string `json:"title"` +} + +// ShowMessageRequestParams is +type ShowMessageRequestParams struct { + + /*Type defined: + * The message type. See {@link MessageType} + */ + Type MessageType `json:"type"` + + /*Message defined: + * The actual message + */ + Message string `json:"message"` + + /*Actions defined: + * The message action items to present. + */ + Actions []MessageActionItem `json:"actions,omitempty"` +} + +/*LogMessageParams defined: + * The log message parameters. + */ +type LogMessageParams struct { + + /*Type defined: + * The message type. See {@link MessageType} + */ + Type MessageType `json:"type"` + + /*Message defined: + * The actual message + */ + Message string `json:"message"` +} + +// TextDocumentSyncClientCapabilities is +type TextDocumentSyncClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether text document synchronization supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*WillSave defined: + * The client supports sending will save notifications. + */ + WillSave bool `json:"willSave,omitempty"` + + /*WillSaveWaitUntil defined: + * The client supports sending a will save request and + * waits for a response providing text edits which will + * be applied to the document before it is saved. + */ + WillSaveWaitUntil bool `json:"willSaveWaitUntil,omitempty"` + + /*DidSave defined: + * The client supports did save notifications. + */ + DidSave bool `json:"didSave,omitempty"` +} + +// TextDocumentSyncOptions is +type TextDocumentSyncOptions struct { + + /*OpenClose defined: + * Open and close notifications are sent to the server. If omitted open close notification should not + * be sent. + */ + OpenClose bool `json:"openClose,omitempty"` + + /*Change defined: + * Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full + * and TextDocumentSyncKind.Incremental. If omitted it defaults to TextDocumentSyncKind.None. + */ + Change TextDocumentSyncKind `json:"change,omitempty"` + + /*WillSave defined: + * If present will save notifications are sent to the server. If omitted the notification should not be + * sent. + */ + WillSave bool `json:"willSave,omitempty"` + + /*WillSaveWaitUntil defined: + * If present will save wait until requests are sent to the server. If omitted the request should not be + * sent. + */ + WillSaveWaitUntil bool `json:"willSaveWaitUntil,omitempty"` + + /*Save defined: + * If present save notifications are sent to the server. If omitted the notification should not be + * sent. + */ + Save *SaveOptions `json:"save,omitempty"` +} + +/*DidOpenTextDocumentParams defined: + * The parameters send in a open text document notification + */ +type DidOpenTextDocumentParams struct { + + /*TextDocument defined: + * The document that was opened. + */ + TextDocument TextDocumentItem `json:"textDocument"` +} + +/*DidChangeTextDocumentParams defined: + * The change text document notification's parameters. + */ +type DidChangeTextDocumentParams struct { + + /*TextDocument defined: + * The document that did change. The version number points + * to the version after all provided content changes have + * been applied. + */ + TextDocument VersionedTextDocumentIdentifier `json:"textDocument"` + + /*ContentChanges defined: + * The actual content changes. The content changes describe single state changes + * to the document. So if there are two content changes c1 and c2 for a document + * in state S then c1 move the document to S' and c2 to S''. + */ + ContentChanges []TextDocumentContentChangeEvent `json:"contentChanges"` +} + +/*TextDocumentChangeRegistrationOptions defined: + * Describe options to be used when registered for text document change events. + */ +type TextDocumentChangeRegistrationOptions struct { + + /*SyncKind defined: + * How documents are synced to the server. + */ + SyncKind TextDocumentSyncKind `json:"syncKind"` + TextDocumentRegistrationOptions +} + +/*DidCloseTextDocumentParams defined: + * The parameters send in a close text document notification + */ +type DidCloseTextDocumentParams struct { + + /*TextDocument defined: + * The document that was closed. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` +} + +/*DidSaveTextDocumentParams defined: + * The parameters send in a save text document notification + */ +type DidSaveTextDocumentParams struct { + + /*TextDocument defined: + * The document that was closed. + */ + TextDocument VersionedTextDocumentIdentifier `json:"textDocument"` + + /*Text defined: + * Optional the content when saved. Depends on the includeText value + * when the save notification was requested. + */ + Text string `json:"text,omitempty"` +} + +/*TextDocumentSaveRegistrationOptions defined: + * Save registration options. + */ +type TextDocumentSaveRegistrationOptions struct { + TextDocumentRegistrationOptions + SaveOptions +} + +/*WillSaveTextDocumentParams defined: + * The parameters send in a will save text document notification. + */ +type WillSaveTextDocumentParams struct { + + /*TextDocument defined: + * The document that will be saved. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + + /*Reason defined: + * The 'TextDocumentSaveReason'. + */ + Reason TextDocumentSaveReason `json:"reason"` +} + +// DidChangeWatchedFilesClientCapabilities is +type DidChangeWatchedFilesClientCapabilities struct { + + /*DynamicRegistration defined: + * Did change watched files notification supports dynamic registration. Please note + * that the current protocol doesn't support static configuration for file changes + * from the server side. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` +} + +/*DidChangeWatchedFilesParams defined: + * The watched files change notification's parameters. + */ +type DidChangeWatchedFilesParams struct { + + /*Changes defined: + * The actual file events. + */ + Changes []FileEvent `json:"changes"` +} + +/*FileEvent defined: + * An event describing a file change. + */ +type FileEvent struct { + + /*URI defined: + * The file's uri. + */ + URI DocumentURI `json:"uri"` + + /*Type defined: + * The change type. + */ + Type FileChangeType `json:"type"` +} + +/*DidChangeWatchedFilesRegistrationOptions defined: + * Describe options to be used when registered for text document change events. + */ +type DidChangeWatchedFilesRegistrationOptions struct { + + /*Watchers defined: + * The watchers to register. + */ + Watchers []FileSystemWatcher `json:"watchers"` +} + +// FileSystemWatcher is +type FileSystemWatcher struct { + + /*GlobPattern defined: + * The glob pattern to watch. Glob patterns can have the following syntax: + * - `*` to match one or more characters in a path segment + * - `?` to match on one character in a path segment + * - `**` to match any number of path segments, including none + * - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files) + * - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) + * - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) + */ + GlobPattern string `json:"globPattern"` + + /*Kind defined: + * The kind of events of interest. If omitted it defaults + * to WatchKind.Create | WatchKind.Change | WatchKind.Delete + * which is 7. + */ + Kind float64 `json:"kind,omitempty"` +} + +/*PublishDiagnosticsClientCapabilities defined: + * The publish diagnostic client capabilities. + */ +type PublishDiagnosticsClientCapabilities struct { + + /*RelatedInformation defined: + * Whether the clients accepts diagnostics with related information. + */ + RelatedInformation bool `json:"relatedInformation,omitempty"` + + /*TagSupport defined: + * Client supports the tag property to provide meta data about a diagnostic. + * Clients supporting tags have to handle unknown tags gracefully. + * + * @since 3.15.0 + */ + TagSupport *struct { + + /*ValueSet defined: + * The tags supported by the client. + */ + ValueSet []DiagnosticTag `json:"valueSet"` + } `json:"tagSupport,omitempty"` +} + +/*PublishDiagnosticsParams defined: + * The publish diagnostic notification's parameters. + */ +type PublishDiagnosticsParams struct { + + /*URI defined: + * The URI for which diagnostic information is reported. + */ + URI DocumentURI `json:"uri"` + + /*Version defined: + * Optional the version number of the document the diagnostics are published for. + * + * @since 3.15.0 + */ + Version float64 `json:"version,omitempty"` + + /*Diagnostics defined: + * An array of diagnostic information items. + */ + Diagnostics []Diagnostic `json:"diagnostics"` +} + +/*CompletionClientCapabilities defined: + * Completion client capabilities + */ +type CompletionClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether completion supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*CompletionItem defined: + * The client supports the following `CompletionItem` specific + * capabilities. + */ + CompletionItem *struct { + + /*SnippetSupport defined: + * Client supports snippets as insert text. + * + * A snippet can define tab stops and placeholders with `$1`, `$2` + * and `${3:foo}`. `$0` defines the final tab stop, it defaults to + * the end of the snippet. Placeholders with equal identifiers are linked, + * that is typing in one will update others too. + */ + SnippetSupport bool `json:"snippetSupport,omitempty"` + + /*CommitCharactersSupport defined: + * Client supports commit characters on a completion item. + */ + CommitCharactersSupport bool `json:"commitCharactersSupport,omitempty"` + + /*DocumentationFormat defined: + * Client supports the follow content formats for the documentation + * property. The order describes the preferred format of the client. + */ + DocumentationFormat []MarkupKind `json:"documentationFormat,omitempty"` + + /*DeprecatedSupport defined: + * Client supports the deprecated property on a completion item. + */ + DeprecatedSupport bool `json:"deprecatedSupport,omitempty"` + + /*PreselectSupport defined: + * Client supports the preselect property on a completion item. + */ + PreselectSupport bool `json:"preselectSupport,omitempty"` + + /*TagSupport defined: + * Client supports the tag property on a completion item. Clients supporting + * tags have to handle unknown tags gracefully. Clients especially need to + * preserve unknown tags when sending a completion item back to the server in + * a resolve call. + * + * @since 3.15.0 + */ + TagSupport *struct { + + /*ValueSet defined: + * The tags supported by the client. + */ + ValueSet []CompletionItemTag `json:"valueSet"` + } `json:"tagSupport,omitempty"` + } `json:"completionItem,omitempty"` + + // CompletionItemKind is + CompletionItemKind *struct { + + /*ValueSet defined: + * The completion item kind values the client supports. When this + * property exists the client also guarantees that it will + * handle values outside its set gracefully and falls back + * to a default value when unknown. + * + * If this property is not present the client only supports + * the completion items kinds from `Text` to `Reference` as defined in + * the initial version of the protocol. + */ + ValueSet []CompletionItemKind `json:"valueSet,omitempty"` + } `json:"completionItemKind,omitempty"` + + /*ContextSupport defined: + * The client supports to send additional context information for a + * `textDocument/completion` requestion. + */ + ContextSupport bool `json:"contextSupport,omitempty"` +} + +/*CompletionContext defined: + * Contains additional information about the context in which a completion request is triggered. + */ +type CompletionContext struct { + + /*TriggerKind defined: + * How the completion was triggered. + */ + TriggerKind CompletionTriggerKind `json:"triggerKind"` + + /*TriggerCharacter defined: + * The trigger character (a single character) that has trigger code complete. + * Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter` + */ + TriggerCharacter string `json:"triggerCharacter,omitempty"` +} + +/*CompletionParams defined: + * Completion parameters + */ +type CompletionParams struct { + + /*Context defined: + * The completion context. This is only available it the client specifies + * to send this using the client capability `textDocument.completion.contextSupport === true` + */ + Context *CompletionContext `json:"context,omitempty"` + TextDocumentPositionParams + WorkDoneProgressParams + PartialResultParams +} + +/*CompletionOptions defined: + * Completion options. + */ +type CompletionOptions struct { + + /*TriggerCharacters defined: + * Most tools trigger completion request automatically without explicitly requesting + * it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user + * starts to type an identifier. For example if the user types `c` in a JavaScript file + * code complete will automatically pop up present `console` besides others as a + * completion item. Characters that make up identifiers don't need to be listed here. + * + * If code complete should automatically be trigger on characters not being valid inside + * an identifier (for example `.` in JavaScript) list them in `triggerCharacters`. + */ + TriggerCharacters []string `json:"triggerCharacters,omitempty"` + + /*AllCommitCharacters defined: + * The list of all possible characters that commit a completion. This field can be used + * if clients don't support individual commmit characters per completion item. See + * `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport` + * + * @since 3.2.0 + */ + AllCommitCharacters []string `json:"allCommitCharacters,omitempty"` + + /*ResolveProvider defined: + * The server provides support to resolve additional + * information for a completion item. + */ + ResolveProvider bool `json:"resolveProvider,omitempty"` + WorkDoneProgressOptions +} + +/*CompletionRegistrationOptions defined: + * Registration options for a [CompletionRequest](#CompletionRequest). + */ +type CompletionRegistrationOptions struct { + TextDocumentRegistrationOptions + CompletionOptions +} + +// HoverClientCapabilities is +type HoverClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether hover supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*ContentFormat defined: + * Client supports the follow content formats for the content + * property. The order describes the preferred format of the client. + */ + ContentFormat []MarkupKind `json:"contentFormat,omitempty"` +} + +/*HoverOptions defined: + * Hover options. + */ +type HoverOptions struct { + WorkDoneProgressOptions +} + +/*HoverParams defined: + * Parameters for a [HoverRequest](#HoverRequest). + */ +type HoverParams struct { + TextDocumentPositionParams + WorkDoneProgressParams +} + +/*HoverRegistrationOptions defined: + * Registration options for a [HoverRequest](#HoverRequest). + */ +type HoverRegistrationOptions struct { + TextDocumentRegistrationOptions + HoverOptions +} + +/*SignatureHelpClientCapabilities defined: + * Client Capabilities for a [SignatureHelpRequest](#SignatureHelpRequest). + */ +type SignatureHelpClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether signature help supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*SignatureInformation defined: + * The client supports the following `SignatureInformation` + * specific properties. + */ + SignatureInformation *struct { + + /*DocumentationFormat defined: + * Client supports the follow content formats for the documentation + * property. The order describes the preferred format of the client. + */ + DocumentationFormat []MarkupKind `json:"documentationFormat,omitempty"` + + /*ParameterInformation defined: + * Client capabilities specific to parameter information. + */ + ParameterInformation *struct { + + /*LabelOffsetSupport defined: + * The client supports processing label offsets instead of a + * simple label string. + * + * @since 3.14.0 + */ + LabelOffsetSupport bool `json:"labelOffsetSupport,omitempty"` + } `json:"parameterInformation,omitempty"` + } `json:"signatureInformation,omitempty"` + + /*ContextSupport defined: + * The client supports to send additional context information for a + * `textDocument/signatureHelp` request. A client that opts into + * contextSupport will also support the `retriggerCharacters` on + * `SignatureHelpOptions`. + * + * @since 3.15.0 + */ + ContextSupport bool `json:"contextSupport,omitempty"` +} + +/*SignatureHelpOptions defined: + * Server Capabilities for a [SignatureHelpRequest](#SignatureHelpRequest). + */ +type SignatureHelpOptions struct { + + /*TriggerCharacters defined: + * List of characters that trigger signature help. + */ + TriggerCharacters []string `json:"triggerCharacters,omitempty"` + + /*RetriggerCharacters defined: + * List of characters that re-trigger signature help. + * + * These trigger characters are only active when signature help is already showing. All trigger characters + * are also counted as re-trigger characters. + * + * @since 3.15.0 + */ + RetriggerCharacters []string `json:"retriggerCharacters,omitempty"` + WorkDoneProgressOptions +} + +/*SignatureHelpContext defined: + * Additional information about the context in which a signature help request was triggered. + * + * @since 3.15.0 + */ +type SignatureHelpContext struct { + + /*TriggerKind defined: + * Action that caused signature help to be triggered. + */ + TriggerKind SignatureHelpTriggerKind `json:"triggerKind"` + + /*TriggerCharacter defined: + * Character that caused signature help to be triggered. + * + * This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter` + */ + TriggerCharacter string `json:"triggerCharacter,omitempty"` + + /*IsRetrigger defined: + * `true` if signature help was already showing when it was triggered. + * + * Retriggers occur when the signature help is already active and can be caused by actions such as + * typing a trigger character, a cursor move, or document content changes. + */ + IsRetrigger bool `json:"isRetrigger"` + + /*ActiveSignatureHelp defined: + * The currently active `SignatureHelp`. + * + * The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on + * the user navigating through available signatures. + */ + ActiveSignatureHelp *SignatureHelp `json:"activeSignatureHelp,omitempty"` +} + +/*SignatureHelpParams defined: + * Parameters for a [SignatureHelpRequest](#SignatureHelpRequest). + */ +type SignatureHelpParams struct { + + /*Context defined: + * The signature help context. This is only available if the client specifies + * to send this using the client capability `textDocument.signatureHelp.contextSupport === true` + * + * @since 3.15.0 + */ + Context *SignatureHelpContext `json:"context,omitempty"` + TextDocumentPositionParams + WorkDoneProgressParams +} + +/*SignatureHelpRegistrationOptions defined: + * Registration options for a [SignatureHelpRequest](#SignatureHelpRequest). + */ +type SignatureHelpRegistrationOptions struct { + TextDocumentRegistrationOptions + SignatureHelpOptions +} + +/*DefinitionClientCapabilities defined: + * Client Capabilities for a [DefinitionRequest](#DefinitionRequest). + */ +type DefinitionClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether definition supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*LinkSupport defined: + * The client supports additional metadata in the form of definition links. + * + * @since 3.14.0 + */ + LinkSupport bool `json:"linkSupport,omitempty"` +} + +/*DefinitionOptions defined: + * Server Capabilities for a [DefinitionRequest](#DefinitionRequest). + */ +type DefinitionOptions struct { + WorkDoneProgressOptions +} + +/*DefinitionParams defined: + * Parameters for a [DefinitionRequest](#DefinitionRequest). + */ +type DefinitionParams struct { + TextDocumentPositionParams + WorkDoneProgressParams + PartialResultParams +} + +/*DefinitionRegistrationOptions defined: + * Registration options for a [DefinitionRequest](#DefinitionRequest). + */ +type DefinitionRegistrationOptions struct { + TextDocumentRegistrationOptions + DefinitionOptions +} + +/*ReferenceClientCapabilities defined: + * Client Capabilities for a [ReferencesRequest](#ReferencesRequest). + */ +type ReferenceClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether references supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` +} + +/*ReferenceParams defined: + * Parameters for a [ReferencesRequest](#ReferencesRequest). + */ +type ReferenceParams struct { + + // Context is + Context ReferenceContext `json:"context"` + TextDocumentPositionParams + WorkDoneProgressParams + PartialResultParams +} + +/*ReferenceOptions defined: + * Reference options. + */ +type ReferenceOptions struct { + WorkDoneProgressOptions +} + +/*ReferenceRegistrationOptions defined: + * Registration options for a [ReferencesRequest](#ReferencesRequest). + */ +type ReferenceRegistrationOptions struct { + TextDocumentRegistrationOptions + ReferenceOptions +} + +/*DocumentHighlightClientCapabilities defined: + * Client Capabilities for a [DocumentHighlightRequest](#DocumentHighlightRequest). + */ +type DocumentHighlightClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether document highlight supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` +} + +/*DocumentHighlightParams defined: + * Parameters for a [DocumentHighlightRequest](#DocumentHighlightRequest). + */ +type DocumentHighlightParams struct { + TextDocumentPositionParams + WorkDoneProgressParams + PartialResultParams +} + +/*DocumentHighlightOptions defined: + * Provider options for a [DocumentHighlightRequest](#DocumentHighlightRequest). + */ +type DocumentHighlightOptions struct { + WorkDoneProgressOptions +} + +/*DocumentHighlightRegistrationOptions defined: + * Registration options for a [DocumentHighlightRequest](#DocumentHighlightRequest). + */ +type DocumentHighlightRegistrationOptions struct { + TextDocumentRegistrationOptions + DocumentHighlightOptions +} + +/*DocumentSymbolClientCapabilities defined: + * Client Capabilities for a [DocumentSymbolRequest](#DocumentSymbolRequest). + */ +type DocumentSymbolClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether document symbol supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*SymbolKind defined: + * Specific capabilities for the `SymbolKind`. + */ + SymbolKind *struct { + + /*ValueSet defined: + * The symbol kind values the client supports. When this + * property exists the client also guarantees that it will + * handle values outside its set gracefully and falls back + * to a default value when unknown. + * + * If this property is not present the client only supports + * the symbol kinds from `File` to `Array` as defined in + * the initial version of the protocol. + */ + ValueSet []SymbolKind `json:"valueSet,omitempty"` + } `json:"symbolKind,omitempty"` + + /*HierarchicalDocumentSymbolSupport defined: + * The client support hierarchical document symbols. + */ + HierarchicalDocumentSymbolSupport bool `json:"hierarchicalDocumentSymbolSupport,omitempty"` +} + +/*DocumentSymbolParams defined: + * Parameters for a [DocumentSymbolRequest](#DocumentSymbolRequest). + */ +type DocumentSymbolParams struct { + + /*TextDocument defined: + * The text document. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + WorkDoneProgressParams + PartialResultParams +} + +/*DocumentSymbolOptions defined: + * Provider options for a [DocumentSymbolRequest](#DocumentSymbolRequest). + */ +type DocumentSymbolOptions struct { + WorkDoneProgressOptions +} + +/*DocumentSymbolRegistrationOptions defined: + * Registration options for a [DocumentSymbolRequest](#DocumentSymbolRequest). + */ +type DocumentSymbolRegistrationOptions struct { + TextDocumentRegistrationOptions + DocumentSymbolOptions +} + +/*CodeActionClientCapabilities defined: + * The Client Capabilities of a [CodeActionRequest](#CodeActionRequest). + */ +type CodeActionClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether code action supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*CodeActionLiteralSupport defined: + * The client support code action literals as a valid + * response of the `textDocument/codeAction` request. + * + * @since 3.8.0 + */ + CodeActionLiteralSupport *struct { + + /*CodeActionKind defined: + * The code action kind is support with the following value + * set. + */ + CodeActionKind struct { + + /*ValueSet defined: + * The code action kind values the client supports. When this + * property exists the client also guarantees that it will + * handle values outside its set gracefully and falls back + * to a default value when unknown. + */ + ValueSet []CodeActionKind `json:"valueSet"` + } `json:"codeActionKind"` + } `json:"codeActionLiteralSupport,omitempty"` + + /*IsPreferredSupport defined: + * Whether code action supports the `isPreferred` property. + * @since 3.15.0 + */ + IsPreferredSupport bool `json:"isPreferredSupport,omitempty"` +} + +/*CodeActionParams defined: + * The parameters of a [CodeActionRequest](#CodeActionRequest). + */ +type CodeActionParams struct { + + /*TextDocument defined: + * The document in which the command was invoked. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + + /*Range defined: + * The range for which the command was invoked. + */ + Range Range `json:"range"` + + /*Context defined: + * Context carrying additional information. + */ + Context CodeActionContext `json:"context"` + WorkDoneProgressParams + PartialResultParams +} + +/*CodeActionOptions defined: + * Provider options for a [CodeActionRequest](#CodeActionRequest). + */ +type CodeActionOptions struct { + + /*CodeActionKinds defined: + * CodeActionKinds that this server may return. + * + * The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server + * may list out every specific kind they provide. + */ + CodeActionKinds []CodeActionKind `json:"codeActionKinds,omitempty"` + WorkDoneProgressOptions +} + +/*CodeActionRegistrationOptions defined: + * Registration options for a [CodeActionRequest](#CodeActionRequest). + */ +type CodeActionRegistrationOptions struct { + TextDocumentRegistrationOptions + CodeActionOptions +} + +/*WorkspaceSymbolClientCapabilities defined: + * Client capabilities for a [WorkspaceSymbolRequest](#WorkspaceSymbolRequest). + */ +type WorkspaceSymbolClientCapabilities struct { + + /*DynamicRegistration defined: + * Symbol request supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*SymbolKind defined: + * Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. + */ + SymbolKind *struct { + + /*ValueSet defined: + * The symbol kind values the client supports. When this + * property exists the client also guarantees that it will + * handle values outside its set gracefully and falls back + * to a default value when unknown. + * + * If this property is not present the client only supports + * the symbol kinds from `File` to `Array` as defined in + * the initial version of the protocol. + */ + ValueSet []SymbolKind `json:"valueSet,omitempty"` + } `json:"symbolKind,omitempty"` +} + +/*WorkspaceSymbolParams defined: + * The parameters of a [WorkspaceSymbolRequest](#WorkspaceSymbolRequest). + */ +type WorkspaceSymbolParams struct { + + /*Query defined: + * A query string to filter symbols by. Clients may send an empty + * string here to request all symbols. + */ + Query string `json:"query"` + WorkDoneProgressParams + PartialResultParams +} + +/*WorkspaceSymbolOptions defined: + * Server capabilities for a [WorkspaceSymbolRequest](#WorkspaceSymbolRequest). + */ +type WorkspaceSymbolOptions struct { + WorkDoneProgressOptions +} + +/*WorkspaceSymbolRegistrationOptions defined: + * Registration options for a [WorkspaceSymbolRequest](#WorkspaceSymbolRequest). + */ +type WorkspaceSymbolRegistrationOptions struct { + WorkspaceSymbolOptions +} + +/*CodeLensClientCapabilities defined: + * The client capabilities of a [CodeLensRequest](#CodeLensRequest). + */ +type CodeLensClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether code lens supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` +} + +/*CodeLensParams defined: + * The parameters of a [CodeLensRequest](#CodeLensRequest). + */ +type CodeLensParams struct { + + /*TextDocument defined: + * The document to request code lens for. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + WorkDoneProgressParams + PartialResultParams +} + +/*CodeLensOptions defined: + * Code Lens provider options of a [CodeLensRequest](#CodeLensRequest). + */ +type CodeLensOptions struct { + + /*ResolveProvider defined: + * Code lens has a resolve provider as well. + */ + ResolveProvider bool `json:"resolveProvider,omitempty"` + WorkDoneProgressOptions +} + +/*CodeLensRegistrationOptions defined: + * Registration options for a [CodeLensRequest](#CodeLensRequest). + */ +type CodeLensRegistrationOptions struct { + TextDocumentRegistrationOptions + CodeLensOptions +} + +/*DocumentLinkClientCapabilities defined: + * The client capabilities of a [DocumentLinkRequest](#DocumentLinkRequest). + */ +type DocumentLinkClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether document link supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*TooltipSupport defined: + * Whether the client support the `tooltip` property on `DocumentLink`. + * + * @since 3.15.0 + */ + TooltipSupport bool `json:"tooltipSupport,omitempty"` +} + +/*DocumentLinkParams defined: + * The parameters of a [DocumentLinkRequest](#DocumentLinkRequest). + */ +type DocumentLinkParams struct { + + /*TextDocument defined: + * The document to provide document links for. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + WorkDoneProgressParams + PartialResultParams +} + +/*DocumentLinkOptions defined: + * Provider options for a [DocumentLinkRequest](#DocumentLinkRequest). + */ +type DocumentLinkOptions struct { + + /*ResolveProvider defined: + * Document links have a resolve provider as well. + */ + ResolveProvider bool `json:"resolveProvider,omitempty"` + WorkDoneProgressOptions +} + +/*DocumentLinkRegistrationOptions defined: + * Registration options for a [DocumentLinkRequest](#DocumentLinkRequest). + */ +type DocumentLinkRegistrationOptions struct { + TextDocumentRegistrationOptions + DocumentLinkOptions +} + +/*DocumentFormattingClientCapabilities defined: + * Client capabilities of a [DocumentFormattingRequest](#DocumentFormattingRequest). + */ +type DocumentFormattingClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether formatting supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` +} + +/*DocumentFormattingParams defined: + * The parameters of a [DocumentFormattingRequest](#DocumentFormattingRequest). + */ +type DocumentFormattingParams struct { + + /*TextDocument defined: + * The document to format. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + + /*Options defined: + * The format options + */ + Options FormattingOptions `json:"options"` + WorkDoneProgressParams +} + +/*DocumentFormattingOptions defined: + * Provider options for a [DocumentFormattingRequest](#DocumentFormattingRequest). + */ +type DocumentFormattingOptions struct { + WorkDoneProgressOptions +} + +/*DocumentFormattingRegistrationOptions defined: + * Registration options for a [DocumentFormattingRequest](#DocumentFormattingRequest). + */ +type DocumentFormattingRegistrationOptions struct { + TextDocumentRegistrationOptions + DocumentFormattingOptions +} + +/*DocumentRangeFormattingClientCapabilities defined: + * Client capabilities of a [DocumentRangeFormattingRequest](#DocumentRangeFormattingRequest). + */ +type DocumentRangeFormattingClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether range formatting supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` +} + +/*DocumentRangeFormattingParams defined: + * The parameters of a [DocumentRangeFormattingRequest](#DocumentRangeFormattingRequest). + */ +type DocumentRangeFormattingParams struct { + + /*TextDocument defined: + * The document to format. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + + /*Range defined: + * The range to format + */ + Range Range `json:"range"` + + /*Options defined: + * The format options + */ + Options FormattingOptions `json:"options"` + WorkDoneProgressParams +} + +/*DocumentRangeFormattingOptions defined: + * Provider options for a [DocumentRangeFormattingRequest](#DocumentRangeFormattingRequest). + */ +type DocumentRangeFormattingOptions struct { + WorkDoneProgressOptions +} + +/*DocumentRangeFormattingRegistrationOptions defined: + * Registration options for a [DocumentRangeFormattingRequest](#DocumentRangeFormattingRequest). + */ +type DocumentRangeFormattingRegistrationOptions struct { + TextDocumentRegistrationOptions + DocumentRangeFormattingOptions +} + +/*DocumentOnTypeFormattingClientCapabilities defined: + * Client capabilities of a [DocumentOnTypeFormattingRequest](#DocumentOnTypeFormattingRequest). + */ +type DocumentOnTypeFormattingClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether on type formatting supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` +} + +/*DocumentOnTypeFormattingParams defined: + * The parameters of a [DocumentOnTypeFormattingRequest](#DocumentOnTypeFormattingRequest). + */ +type DocumentOnTypeFormattingParams struct { + + /*TextDocument defined: + * The document to format. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + + /*Position defined: + * The position at which this request was send. + */ + Position Position `json:"position"` + + /*Ch defined: + * The character that has been typed. + */ + Ch string `json:"ch"` + + /*Options defined: + * The format options. + */ + Options FormattingOptions `json:"options"` +} + +/*DocumentOnTypeFormattingOptions defined: + * Provider options for a [DocumentOnTypeFormattingRequest](#DocumentOnTypeFormattingRequest). + */ +type DocumentOnTypeFormattingOptions struct { + + /*FirstTriggerCharacter defined: + * A character on which formatting should be triggered, like `}`. + */ + FirstTriggerCharacter string `json:"firstTriggerCharacter"` + + /*MoreTriggerCharacter defined: + * More trigger characters. + */ + MoreTriggerCharacter []string `json:"moreTriggerCharacter,omitempty"` +} + +/*DocumentOnTypeFormattingRegistrationOptions defined: + * Registration options for a [DocumentOnTypeFormattingRequest](#DocumentOnTypeFormattingRequest). + */ +type DocumentOnTypeFormattingRegistrationOptions struct { + TextDocumentRegistrationOptions + DocumentOnTypeFormattingOptions +} + +// RenameClientCapabilities is +type RenameClientCapabilities struct { + + /*DynamicRegistration defined: + * Whether rename supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` + + /*PrepareSupport defined: + * Client supports testing for validity of rename operations + * before execution. + * + * @since version 3.12.0 + */ + PrepareSupport bool `json:"prepareSupport,omitempty"` +} + +/*RenameParams defined: + * The parameters of a [RenameRequest](#RenameRequest). + */ +type RenameParams struct { + + /*TextDocument defined: + * The document to rename. + */ + TextDocument TextDocumentIdentifier `json:"textDocument"` + + /*Position defined: + * The position at which this request was sent. + */ + Position Position `json:"position"` + + /*NewName defined: + * The new name of the symbol. If the given name is not valid the + * request must return a [ResponseError](#ResponseError) with an + * appropriate message set. + */ + NewName string `json:"newName"` + WorkDoneProgressParams +} + +/*RenameOptions defined: + * Provider options for a [RenameRequest](#RenameRequest). + */ +type RenameOptions struct { + + /*PrepareProvider defined: + * Renames should be checked and tested before being executed. + * + * @since version 3.12.0 + */ + PrepareProvider bool `json:"prepareProvider,omitempty"` + WorkDoneProgressOptions +} + +/*RenameRegistrationOptions defined: + * Registration options for a [RenameRequest](#RenameRequest). + */ +type RenameRegistrationOptions struct { + TextDocumentRegistrationOptions + RenameOptions +} + +// PrepareRenameParams is +type PrepareRenameParams struct { + TextDocumentPositionParams + WorkDoneProgressParams +} + +/*ExecuteCommandClientCapabilities defined: + * The client capabilities of a [ExecuteCommandRequest](#ExecuteCommandRequest). + */ +type ExecuteCommandClientCapabilities struct { + + /*DynamicRegistration defined: + * Execute command supports dynamic registration. + */ + DynamicRegistration bool `json:"dynamicRegistration,omitempty"` +} + +/*ExecuteCommandParams defined: + * The parameters of a [ExecuteCommandRequest](#ExecuteCommandRequest). + */ +type ExecuteCommandParams struct { + + /*Command defined: + * The identifier of the actual command handler. + */ + Command string `json:"command"` + + /*Arguments defined: + * Arguments that the command should be invoked with. + */ + Arguments []interface{} `json:"arguments,omitempty"` + WorkDoneProgressParams +} + +/*ExecuteCommandOptions defined: + * The server capabilities of a [ExecuteCommandRequest](#ExecuteCommandRequest). + */ +type ExecuteCommandOptions struct { + + /*Commands defined: + * The commands to be executed on the server + */ + Commands []string `json:"commands"` + WorkDoneProgressOptions +} + +/*ExecuteCommandRegistrationOptions defined: + * Registration options for a [ExecuteCommandRequest](#ExecuteCommandRequest). + */ +type ExecuteCommandRegistrationOptions struct { + ExecuteCommandOptions +} + +// WorkspaceEditClientCapabilities is +type WorkspaceEditClientCapabilities struct { + + /*DocumentChanges defined: + * The client supports versioned document changes in `WorkspaceEdit`s + */ + DocumentChanges bool `json:"documentChanges,omitempty"` + + /*ResourceOperations defined: + * The resource operations the client supports. Clients should at least + * support 'create', 'rename' and 'delete' files and folders. + * + * @since 3.13.0 + */ + ResourceOperations []ResourceOperationKind `json:"resourceOperations,omitempty"` + + /*FailureHandling defined: + * The failure handling strategy of a client if applying the workspace edit + * fails. + * + * @since 3.13.0 + */ + FailureHandling FailureHandlingKind `json:"failureHandling,omitempty"` +} + +/*ApplyWorkspaceEditParams defined: + * The parameters passed via a apply workspace edit request. + */ +type ApplyWorkspaceEditParams struct { + + /*Label defined: + * An optional label of the workspace edit. This label is + * presented in the user interface for example on an undo + * stack to undo the workspace edit. + */ + Label string `json:"label,omitempty"` + + /*Edit defined: + * The edits to apply. + */ + Edit WorkspaceEdit `json:"edit"` +} + +/*ApplyWorkspaceEditResponse defined: + * A response returned from the apply workspace edit request. + */ +type ApplyWorkspaceEditResponse struct { + + /*Applied defined: + * Indicates whether the edit was applied or not. + */ + Applied bool `json:"applied"` + + /*FailureReason defined: + * An optional textual description for why the edit was not applied. + * This may be used by the server for diagnostic logging or to provide + * a suitable error for a request that triggered the edit. + */ + FailureReason string `json:"failureReason,omitempty"` + + /*FailedChange defined: + * Depending on the client's failure handling strategy `failedChange` might + * contain the index of the change that failed. This property is only available + * if the client signals a `failureHandlingStrategy` in its client capabilities. + */ + FailedChange float64 `json:"failedChange,omitempty"` +} + +/*Position defined: + * Position in a text document expressed as zero-based line and character offset. + * The offsets are based on a UTF-16 string representation. So a string of the form + * `a𐐀b` the character offset of the character `a` is 0, the character offset of `𐐀` + * is 1 and the character offset of b is 3 since `𐐀` is represented using two code + * units in UTF-16. + * + * Positions are line end character agnostic. So you can not specify a position that + * denotes `\r|\n` or `\n|` where `|` represents the character offset. + */ +type Position struct { + + /*Line defined: + * Line position in a document (zero-based). + * If a line number is greater than the number of lines in a document, it defaults back to the number of lines in the document. + * If a line number is negative, it defaults to 0. + */ + Line float64 `json:"line"` + + /*Character defined: + * Character offset on a line in a document (zero-based). Assuming that the line is + * represented as a string, the `character` value represents the gap between the + * `character` and `character + 1`. + * + * If the character value is greater than the line length it defaults back to the + * line length. + * If a line number is negative, it defaults to 0. + */ + Character float64 `json:"character"` +} + +/*Range defined: + * A range in a text document expressed as (zero-based) start and end positions. + * + * If you want to specify a range that contains a line including the line ending + * character(s) then use an end position denoting the start of the next line. + * For example: + * ```ts + * { + * start: { line: 5, character: 23 } + * end : { line 6, character : 0 } + * } + * ``` + */ +type Range struct { + + /*Start defined: + * The range's start position + */ + Start Position `json:"start"` + + /*End defined: + * The range's end position. + */ + End Position `json:"end"` +} + +/*Location defined: + * Represents a location inside a resource, such as a line + * inside a text file. + */ +type Location struct { + + // URI is + URI DocumentURI `json:"uri"` + + // Range is + Range Range `json:"range"` +} + +/*LocationLink defined: + * Represents the connection of two locations. Provides additional metadata over normal [locations](#Location), + * including an origin range. + */ +type LocationLink struct { + + /*OriginSelectionRange defined: + * Span of the origin of this link. + * + * Used as the underlined span for mouse definition hover. Defaults to the word range at + * the definition position. + */ + OriginSelectionRange *Range `json:"originSelectionRange,omitempty"` + + /*TargetURI defined: + * The target resource identifier of this link. + */ + TargetURI DocumentURI `json:"targetUri"` + + /*TargetRange defined: + * The full target range of this link. If the target for example is a symbol then target range is the + * range enclosing this symbol not including leading/trailing whitespace but everything else + * like comments. This information is typically used to highlight the range in the editor. + */ + TargetRange Range `json:"targetRange"` + + /*TargetSelectionRange defined: + * The range that should be selected and revealed when this link is being followed, e.g the name of a function. + * Must be contained by the the `targetRange`. See also `DocumentSymbol#range` + */ + TargetSelectionRange Range `json:"targetSelectionRange"` +} + +/*Color defined: + * Represents a color in RGBA space. + */ +type Color struct { + + /*Red defined: + * The red component of this color in the range [0-1]. + */ + Red float64 `json:"red"` + + /*Green defined: + * The green component of this color in the range [0-1]. + */ + Green float64 `json:"green"` + + /*Blue defined: + * The blue component of this color in the range [0-1]. + */ + Blue float64 `json:"blue"` + + /*Alpha defined: + * The alpha component of this color in the range [0-1]. + */ + Alpha float64 `json:"alpha"` +} + +/*ColorInformation defined: + * Represents a color range from a document. + */ +type ColorInformation struct { + + /*Range defined: + * The range in the document where this color appers. + */ + Range Range `json:"range"` + + /*Color defined: + * The actual color value for this color range. + */ + Color Color `json:"color"` +} + +// ColorPresentation is +type ColorPresentation struct { + + /*Label defined: + * The label of this color presentation. It will be shown on the color + * picker header. By default this is also the text that is inserted when selecting + * this color presentation. + */ + Label string `json:"label"` + + /*TextEdit defined: + * An [edit](#TextEdit) which is applied to a document when selecting + * this presentation for the color. When `falsy` the [label](#ColorPresentation.label) + * is used. + */ + TextEdit *TextEdit `json:"textEdit,omitempty"` + + /*AdditionalTextEdits defined: + * An optional array of additional [text edits](#TextEdit) that are applied when + * selecting this color presentation. Edits must not overlap with the main [edit](#ColorPresentation.textEdit) nor with themselves. + */ + AdditionalTextEdits []TextEdit `json:"additionalTextEdits,omitempty"` +} + +/*DiagnosticRelatedInformation defined: + * Represents a related message and source code location for a diagnostic. This should be + * used to point to code locations that cause or related to a diagnostics, e.g when duplicating + * a symbol in a scope. + */ +type DiagnosticRelatedInformation struct { + + /*Location defined: + * The location of this related diagnostic information. + */ + Location Location `json:"location"` + + /*Message defined: + * The message of this related diagnostic information. + */ + Message string `json:"message"` +} + +/*Diagnostic defined: + * Represents a diagnostic, such as a compiler error or warning. Diagnostic objects + * are only valid in the scope of a resource. + */ +type Diagnostic struct { + + /*Range defined: + * The range at which the message applies + */ + Range Range `json:"range"` + + /*Severity defined: + * The diagnostic's severity. Can be omitted. If omitted it is up to the + * client to interpret diagnostics as error, warning, info or hint. + */ + Severity DiagnosticSeverity `json:"severity,omitempty"` + + /*Code defined: + * The diagnostic's code, which usually appear in the user interface. + */ + Code interface{} `json:"code,omitempty"` // number | string + + /*Source defined: + * A human-readable string describing the source of this + * diagnostic, e.g. 'typescript' or 'super lint'. It usually + * appears in the user interface. + */ + Source string `json:"source,omitempty"` + + /*Message defined: + * The diagnostic's message. It usually appears in the user interface + */ + Message string `json:"message"` + + /*Tags defined: + * Additional metadata about the diagnostic. + */ + Tags []DiagnosticTag `json:"tags,omitempty"` + + /*RelatedInformation defined: + * An array of related diagnostic information, e.g. when symbol-names within + * a scope collide all definitions can be marked via this property. + */ + RelatedInformation []DiagnosticRelatedInformation `json:"relatedInformation,omitempty"` +} + +/*Command defined: + * Represents a reference to a command. Provides a title which + * will be used to represent a command in the UI and, optionally, + * an array of arguments which will be passed to the command handler + * function when invoked. + */ +type Command struct { + + /*Title defined: + * Title of the command, like `save`. + */ + Title string `json:"title"` + + /*Command defined: + * The identifier of the actual command handler. + */ + Command string `json:"command"` + + /*Arguments defined: + * Arguments that the command handler should be + * invoked with. + */ + Arguments []interface{} `json:"arguments,omitempty"` +} + +/*TextEdit defined: + * A text edit applicable to a text document. + */ +type TextEdit struct { + + /*Range defined: + * The range of the text document to be manipulated. To insert + * text into a document create a range where start === end. + */ + Range Range `json:"range"` + + /*NewText defined: + * The string to be inserted. For delete operations use an + * empty string. + */ + NewText string `json:"newText"` +} + +/*TextDocumentEdit defined: + * Describes textual changes on a text document. + */ +type TextDocumentEdit struct { + + /*TextDocument defined: + * The text document to change. + */ + TextDocument VersionedTextDocumentIdentifier `json:"textDocument"` + + /*Edits defined: + * The edits to be applied. + */ + Edits []TextEdit `json:"edits"` +} + +// ResourceOperation is +type ResourceOperation struct { + + // Kind is + Kind string `json:"kind"` +} + +/*CreateFileOptions defined: + * Options to create a file. + */ +type CreateFileOptions struct { + + /*Overwrite defined: + * Overwrite existing file. Overwrite wins over `ignoreIfExists` + */ + Overwrite bool `json:"overwrite,omitempty"` + + /*IgnoreIfExists defined: + * Ignore if exists. + */ + IgnoreIfExists bool `json:"ignoreIfExists,omitempty"` +} + +/*CreateFile defined: + * Create file operation. + */ +type CreateFile struct { + + /*Kind defined: + * A create + */ + Kind string `json:"kind"` // 'create' + + /*URI defined: + * The resource to create. + */ + URI DocumentURI `json:"uri"` + + /*Options defined: + * Additional options + */ + Options *CreateFileOptions `json:"options,omitempty"` +} + +/*RenameFileOptions defined: + * Rename file options + */ +type RenameFileOptions struct { + + /*Overwrite defined: + * Overwrite target if existing. Overwrite wins over `ignoreIfExists` + */ + Overwrite bool `json:"overwrite,omitempty"` + + /*IgnoreIfExists defined: + * Ignores if target exists. + */ + IgnoreIfExists bool `json:"ignoreIfExists,omitempty"` +} + +/*RenameFile defined: + * Rename file operation + */ +type RenameFile struct { + + /*Kind defined: + * A rename + */ + Kind string `json:"kind"` // 'rename' + + /*OldURI defined: + * The old (existing) location. + */ + OldURI DocumentURI `json:"oldUri"` + + /*NewURI defined: + * The new location. + */ + NewURI DocumentURI `json:"newUri"` + + /*Options defined: + * Rename options. + */ + Options *RenameFileOptions `json:"options,omitempty"` +} + +/*DeleteFileOptions defined: + * Delete file options + */ +type DeleteFileOptions struct { + + /*Recursive defined: + * Delete the content recursively if a folder is denoted. + */ + Recursive bool `json:"recursive,omitempty"` + + /*IgnoreIfNotExists defined: + * Ignore the operation if the file doesn't exist. + */ + IgnoreIfNotExists bool `json:"ignoreIfNotExists,omitempty"` +} + +/*DeleteFile defined: + * Delete file operation + */ +type DeleteFile struct { + + /*Kind defined: + * A delete + */ + Kind string `json:"kind"` // 'delete' + + /*URI defined: + * The file to delete. + */ + URI DocumentURI `json:"uri"` + + /*Options defined: + * Delete options. + */ + Options *DeleteFileOptions `json:"options,omitempty"` +} + +/*WorkspaceEdit defined: + * A workspace edit represents changes to many resources managed in the workspace. The edit + * should either provide `changes` or `documentChanges`. If documentChanges are present + * they are preferred over `changes` if the client can handle versioned document edits. + */ +type WorkspaceEdit struct { + + /*Changes defined: + * Holds changes to existing resources. + */ + Changes *map[string][]TextEdit `json:"changes,omitempty"` // [uri: string]: TextEdit[]; + + /*DocumentChanges defined: + * Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes + * are either an array of `TextDocumentEdit`s to express changes to n different text documents + * where each text document edit addresses a specific version of a text document. Or it can contain + * above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations. + * + * Whether a client supports versioned document edits is expressed via + * `workspace.workspaceEdit.documentChanges` client capability. + * + * If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then + * only plain `TextEdit`s using the `changes` property are supported. + */ + DocumentChanges []TextDocumentEdit `json:"documentChanges,omitempty"` // (TextDocumentEdit | CreateFile | RenameFile | DeleteFile) +} + +/*TextEditChange defined: + * A change to capture text edits for existing resources. + */ +type TextEditChange struct { +} + +/*TextDocumentIdentifier defined: + * A literal to identify a text document in the client. + */ +type TextDocumentIdentifier struct { + + /*URI defined: + * The text document's uri. + */ + URI DocumentURI `json:"uri"` +} + +/*VersionedTextDocumentIdentifier defined: + * An identifier to denote a specific version of a text document. + */ +type VersionedTextDocumentIdentifier struct { + + /*Version defined: + * The version number of this document. If a versioned text document identifier + * is sent from the server to the client and the file is not open in the editor + * (the server has not received an open notification before) the server can send + * `null` to indicate that the version is unknown and the content on disk is the + * truth (as speced with document content ownership). + */ + Version float64 `json:"version"` + TextDocumentIdentifier +} + +/*TextDocumentItem defined: + * An item to transfer a text document from the client to the + * server. + */ +type TextDocumentItem struct { + + /*URI defined: + * The text document's uri. + */ + URI DocumentURI `json:"uri"` + + /*LanguageID defined: + * The text document's language identifier + */ + LanguageID string `json:"languageId"` + + /*Version defined: + * The version number of this document (it will increase after each + * change, including undo/redo). + */ + Version float64 `json:"version"` + + /*Text defined: + * The content of the opened text document. + */ + Text string `json:"text"` +} + +/*MarkupContent defined: + * A `MarkupContent` literal represents a string value which content is interpreted base on its + * kind flag. Currently the protocol supports `plaintext` and `markdown` as markup kinds. + * + * If the kind is `markdown` then the value can contain fenced code blocks like in GitHub issues. + * See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting + * + * Here is an example how such a string can be constructed using JavaScript / TypeScript: + * ```ts + * let markdown: MarkdownContent = { + * kind: MarkupKind.Markdown, + * value: [ + * '# Header', + * 'Some text', + * '```typescript', + * 'someCode();', + * '```' + * ].join('\n') + * }; + * ``` + * + * *Please Note* that clients might sanitize the return markdown. A client could decide to + * remove HTML from the markdown to avoid script execution. + */ +type MarkupContent struct { + + /*Kind defined: + * The type of the Markup + */ + Kind MarkupKind `json:"kind"` + + /*Value defined: + * The content itself + */ + Value string `json:"value"` +} + +/*CompletionItem defined: + * A completion item represents a text snippet that is + * proposed to complete text that is being typed. + */ +type CompletionItem struct { + + /*Label defined: + * The label of this completion item. By default + * also the text that is inserted when selecting + * this completion. + */ + Label string `json:"label"` + + /*Kind defined: + * The kind of this completion item. Based of the kind + * an icon is chosen by the editor. + */ + Kind CompletionItemKind `json:"kind,omitempty"` + + /*Tags defined: + * Tags for this completion item. + * + * @since 3.15.0 + */ + Tags []CompletionItemTag `json:"tags,omitempty"` + + /*Detail defined: + * A human-readable string with additional information + * about this item, like type or symbol information. + */ + Detail string `json:"detail,omitempty"` + + /*Documentation defined: + * A human-readable string that represents a doc-comment. + */ + Documentation string `json:"documentation,omitempty"` // string | MarkupContent + + /*Deprecated defined: + * Indicates if this item is deprecated. + * @deprecated Use `tags` instead. + */ + Deprecated bool `json:"deprecated,omitempty"` + + /*Preselect defined: + * Select this item when showing. + * + * *Note* that only one completion item can be selected and that the + * tool / client decides which item that is. The rule is that the *first* + * item of those that match best is selected. + */ + Preselect bool `json:"preselect,omitempty"` + + /*SortText defined: + * A string that should be used when comparing this item + * with other items. When `falsy` the [label](#CompletionItem.label) + * is used. + */ + SortText string `json:"sortText,omitempty"` + + /*FilterText defined: + * A string that should be used when filtering a set of + * completion items. When `falsy` the [label](#CompletionItem.label) + * is used. + */ + FilterText string `json:"filterText,omitempty"` + + /*InsertText defined: + * A string that should be inserted into a document when selecting + * this completion. When `falsy` the [label](#CompletionItem.label) + * is used. + * + * The `insertText` is subject to interpretation by the client side. + * Some tools might not take the string literally. For example + * VS Code when code complete is requested in this example `con` + * and a completion item with an `insertText` of `console` is provided it + * will only insert `sole`. Therefore it is recommended to use `textEdit` instead + * since it avoids additional client side interpretation. + */ + InsertText string `json:"insertText,omitempty"` + + /*InsertTextFormat defined: + * The format of the insert text. The format applies to both the `insertText` property + * and the `newText` property of a provided `textEdit`. + */ + InsertTextFormat InsertTextFormat `json:"insertTextFormat,omitempty"` + + /*TextEdit defined: + * An [edit](#TextEdit) which is applied to a document when selecting + * this completion. When an edit is provided the value of + * [insertText](#CompletionItem.insertText) is ignored. + * + * *Note:* The text edit's range must be a [single line] and it must contain the position + * at which completion has been requested. + */ + TextEdit *TextEdit `json:"textEdit,omitempty"` + + /*AdditionalTextEdits defined: + * An optional array of additional [text edits](#TextEdit) that are applied when + * selecting this completion. Edits must not overlap (including the same insert position) + * with the main [edit](#CompletionItem.textEdit) nor with themselves. + * + * Additional text edits should be used to change text unrelated to the current cursor position + * (for example adding an import statement at the top of the file if the completion item will + * insert an unqualified type). + */ + AdditionalTextEdits []TextEdit `json:"additionalTextEdits,omitempty"` + + /*CommitCharacters defined: + * An optional set of characters that when pressed while this completion is active will accept it first and + * then type that character. *Note* that all commit characters should have `length=1` and that superfluous + * characters will be ignored. + */ + CommitCharacters []string `json:"commitCharacters,omitempty"` + + /*Command defined: + * An optional [command](#Command) that is executed *after* inserting this completion. *Note* that + * additional modifications to the current document should be described with the + * [additionalTextEdits](#CompletionItem.additionalTextEdits)-property. + */ + Command *Command `json:"command,omitempty"` + + /*Data defined: + * An data entry field that is preserved on a completion item between + * a [CompletionRequest](#CompletionRequest) and a [CompletionResolveRequest] + * (#CompletionResolveRequest) + */ + Data interface{} `json:"data,omitempty"` +} + +/*CompletionList defined: + * Represents a collection of [completion items](#CompletionItem) to be presented + * in the editor. + */ +type CompletionList struct { + + /*IsIncomplete defined: + * This list it not complete. Further typing results in recomputing this list. + */ + IsIncomplete bool `json:"isIncomplete"` + + /*Items defined: + * The completion items. + */ + Items []CompletionItem `json:"items"` +} + +/*Hover defined: + * The result of a hover request. + */ +type Hover struct { + + /*Contents defined: + * The hover's content + */ + Contents MarkupContent `json:"contents"` // MarkupContent | MarkedString | MarkedString[] + + /*Range defined: + * An optional range + */ + Range *Range `json:"range,omitempty"` +} + +/*ParameterInformation defined: + * Represents a parameter of a callable-signature. A parameter can + * have a label and a doc-comment. + */ +type ParameterInformation struct { + + /*Label defined: + * The label of this parameter information. + * + * Either a string or an inclusive start and exclusive end offsets within its containing + * signature label. (see SignatureInformation.label). The offsets are based on a UTF-16 + * string representation as `Position` and `Range` does. + * + * *Note*: a label of type string should be a substring of its containing signature label. + * Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`. + */ + Label string `json:"label"` // string | [number, number] + + /*Documentation defined: + * The human-readable doc-comment of this signature. Will be shown + * in the UI but can be omitted. + */ + Documentation string `json:"documentation,omitempty"` // string | MarkupContent +} + +/*SignatureInformation defined: + * Represents the signature of something callable. A signature + * can have a label, like a function-name, a doc-comment, and + * a set of parameters. + */ +type SignatureInformation struct { + + /*Label defined: + * The label of this signature. Will be shown in + * the UI. + */ + Label string `json:"label"` + + /*Documentation defined: + * The human-readable doc-comment of this signature. Will be shown + * in the UI but can be omitted. + */ + Documentation string `json:"documentation,omitempty"` // string | MarkupContent + + /*Parameters defined: + * The parameters of this signature. + */ + Parameters []ParameterInformation `json:"parameters,omitempty"` +} + +/*SignatureHelp defined: + * Signature help represents the signature of something + * callable. There can be multiple signature but only one + * active and only one active parameter. + */ +type SignatureHelp struct { + + /*Signatures defined: + * One or more signatures. + */ + Signatures []SignatureInformation `json:"signatures"` + + /*ActiveSignature defined: + * The active signature. Set to `null` if no + * signatures exist. + */ + ActiveSignature float64 `json:"activeSignature"` + + /*ActiveParameter defined: + * The active parameter of the active signature. Set to `null` + * if the active signature has no parameters. + */ + ActiveParameter float64 `json:"activeParameter"` +} + +/*ReferenceContext defined: + * Value-object that contains additional information when + * requesting references. + */ +type ReferenceContext struct { + + /*IncludeDeclaration defined: + * Include the declaration of the current symbol. + */ + IncludeDeclaration bool `json:"includeDeclaration"` +} + +/*DocumentHighlight defined: + * A document highlight is a range inside a text document which deserves + * special attention. Usually a document highlight is visualized by changing + * the background color of its range. + */ +type DocumentHighlight struct { + + /*Range defined: + * The range this highlight applies to. + */ + Range Range `json:"range"` + + /*Kind defined: + * The highlight kind, default is [text](#DocumentHighlightKind.Text). + */ + Kind *DocumentHighlightKind `json:"kind,omitempty"` +} + +/*SymbolInformation defined: + * Represents information about programming constructs like variables, classes, + * interfaces etc. + */ +type SymbolInformation struct { + + /*Name defined: + * The name of this symbol. + */ + Name string `json:"name"` + + /*Kind defined: + * The kind of this symbol. + */ + Kind SymbolKind `json:"kind"` + + /*Deprecated defined: + * Indicates if this symbol is deprecated. + */ + Deprecated bool `json:"deprecated,omitempty"` + + /*Location defined: + * The location of this symbol. The location's range is used by a tool + * to reveal the location in the editor. If the symbol is selected in the + * tool the range's start information is used to position the cursor. So + * the range usually spans more than the actual symbol's name and does + * normally include thinks like visibility modifiers. + * + * The range doesn't have to denote a node range in the sense of a abstract + * syntax tree. It can therefore not be used to re-construct a hierarchy of + * the symbols. + */ + Location Location `json:"location"` + + /*ContainerName defined: + * The name of the symbol containing this symbol. This information is for + * user interface purposes (e.g. to render a qualifier in the user interface + * if necessary). It can't be used to re-infer a hierarchy for the document + * symbols. + */ + ContainerName string `json:"containerName,omitempty"` +} + +/*DocumentSymbol defined: + * Represents programming constructs like variables, classes, interfaces etc. + * that appear in a document. Document symbols can be hierarchical and they + * have two ranges: one that encloses its definition and one that points to + * its most interesting range, e.g. the range of an identifier. + */ +type DocumentSymbol struct { + + /*Name defined: + * The name of this symbol. Will be displayed in the user interface and therefore must not be + * an empty string or a string only consisting of white spaces. + */ + Name string `json:"name"` + + /*Detail defined: + * More detail for this symbol, e.g the signature of a function. + */ + Detail string `json:"detail,omitempty"` + + /*Kind defined: + * The kind of this symbol. + */ + Kind SymbolKind `json:"kind"` + + /*Deprecated defined: + * Indicates if this symbol is deprecated. + */ + Deprecated bool `json:"deprecated,omitempty"` + + /*Range defined: + * The range enclosing this symbol not including leading/trailing whitespace but everything else + * like comments. This information is typically used to determine if the the clients cursor is + * inside the symbol to reveal in the symbol in the UI. + */ + Range Range `json:"range"` + + /*SelectionRange defined: + * The range that should be selected and revealed when this symbol is being picked, e.g the name of a function. + * Must be contained by the the `range`. + */ + SelectionRange Range `json:"selectionRange"` + + /*Children defined: + * Children of this symbol, e.g. properties of a class. + */ + Children []DocumentSymbol `json:"children,omitempty"` +} + +/*CodeActionContext defined: + * Contains additional diagnostic information about the context in which + * a [code action](#CodeActionProvider.provideCodeActions) is run. + */ +type CodeActionContext struct { + + /*Diagnostics defined: + * An array of diagnostics known on the client side overlapping the range provided to the + * `textDocument/codeAction` request. They are provied so that the server knows which + * errors are currently presented to the user for the given range. There is no guarantee + * that these accurately reflect the error state of the resource. The primary parameter + * to compute code actions is the provided range. + */ + Diagnostics []Diagnostic `json:"diagnostics"` + + /*Only defined: + * Requested kind of actions to return. + * + * Actions not of this kind are filtered out by the client before being shown. So servers + * can omit computing them. + */ + Only []CodeActionKind `json:"only,omitempty"` +} + +/*CodeAction defined: + * A code action represents a change that can be performed in code, e.g. to fix a problem or + * to refactor code. + * + * A CodeAction must set either `edit` and/or a `command`. If both are supplied, the `edit` is applied first, then the `command` is executed. + */ +type CodeAction struct { + + /*Title defined: + * A short, human-readable, title for this code action. + */ + Title string `json:"title"` + + /*Kind defined: + * The kind of the code action. + * + * Used to filter code actions. + */ + Kind CodeActionKind `json:"kind,omitempty"` + + /*Diagnostics defined: + * The diagnostics that this code action resolves. + */ + Diagnostics []Diagnostic `json:"diagnostics,omitempty"` + + /*IsPreferred defined: + * Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted + * by keybindings. + * + * A quick fix should be marked preferred if it properly addresses the underlying error. + * A refactoring should be marked preferred if it is the most reasonable choice of actions to take. + * + * @since 3.15.0 + */ + IsPreferred bool `json:"isPreferred,omitempty"` + + /*Edit defined: + * The workspace edit this code action performs. + */ + Edit *WorkspaceEdit `json:"edit,omitempty"` + + /*Command defined: + * A command this code action executes. If a code action + * provides a edit and a command, first the edit is + * executed and then the command. + */ + Command *Command `json:"command,omitempty"` +} + +/*CodeLens defined: + * A code lens represents a [command](#Command) that should be shown along with + * source text, like the number of references, a way to run tests, etc. + * + * A code lens is _unresolved_ when no command is associated to it. For performance + * reasons the creation of a code lens and resolving should be done to two stages. + */ +type CodeLens struct { + + /*Range defined: + * The range in which this code lens is valid. Should only span a single line. + */ + Range Range `json:"range"` + + /*Command defined: + * The command this code lens represents. + */ + Command *Command `json:"command,omitempty"` + + /*Data defined: + * An data entry field that is preserved on a code lens item between + * a [CodeLensRequest](#CodeLensRequest) and a [CodeLensResolveRequest] + * (#CodeLensResolveRequest) + */ + Data interface{} `json:"data,omitempty"` +} + +/*FormattingOptions defined: + * Value-object describing what options formatting should use. + */ +type FormattingOptions struct { + + /*TabSize defined: + * Size of a tab in spaces. + */ + TabSize float64 `json:"tabSize"` + + /*InsertSpaces defined: + * Prefer spaces over tabs. + */ + InsertSpaces bool `json:"insertSpaces"` + + /*TrimTrailingWhitespace defined: + * Trim trailing whitespaces on a line. + * + * @since 3.15.0 + */ + TrimTrailingWhitespace bool `json:"trimTrailingWhitespace,omitempty"` + + /*InsertFinalNewline defined: + * Insert a newline character at the end of the file if one does not exist. + * + * @since 3.15.0 + */ + InsertFinalNewline bool `json:"insertFinalNewline,omitempty"` + + /*TrimFinalNewlines defined: + * Trim all newlines after the final newline at the end of the file. + * + * @since 3.15.0 + */ + TrimFinalNewlines bool `json:"trimFinalNewlines,omitempty"` + + /*Key defined: + * Signature for further properties. + */ + Key map[string]bool `json:"key"` // [key: string]: boolean | number | string | undefined; +} + +/*DocumentLink defined: + * A document link is a range in a text document that links to an internal or external resource, like another + * text document or a web site. + */ +type DocumentLink struct { + + /*Range defined: + * The range this link applies to. + */ + Range Range `json:"range"` + + /*Target defined: + * The uri this link points to. + */ + Target string `json:"target,omitempty"` + + /*Tooltip defined: + * The tooltip text when you hover over this link. + * + * If a tooltip is provided, is will be displayed in a string that includes instructions on how to + * trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary depending on OS, + * user settings, and localization. + * + * @since 3.15.0 + */ + Tooltip string `json:"tooltip,omitempty"` + + /*Data defined: + * A data entry field that is preserved on a document link between a + * DocumentLinkRequest and a DocumentLinkResolveRequest. + */ + Data interface{} `json:"data,omitempty"` +} + +/*SelectionRange defined: + * A selection range represents a part of a selection hierarchy. A selection range + * may have a parent selection range that contains it. + */ +type SelectionRange struct { + + /*Range defined: + * The [range](#Range) of this selection range. + */ + Range Range `json:"range"` + + /*Parent defined: + * The parent selection range containing this range. Therefore `parent.range` must contain `this.range`. + */ + Parent *SelectionRange `json:"parent,omitempty"` +} + +/*TextDocument defined: + * A simple text document. Not to be implemented. + */ +type TextDocument struct { + + /*URI defined: + * The associated URI for this document. Most documents have the __file__-scheme, indicating that they + * represent files on disk. However, some documents may have other schemes indicating that they are not + * available on disk. + * + * @readonly + */ + URI DocumentURI `json:"uri"` + + /*LanguageID defined: + * The identifier of the language associated with this document. + * + * @readonly + */ + LanguageID string `json:"languageId"` + + /*Version defined: + * The version number of this document (it will increase after each + * change, including undo/redo). + * + * @readonly + */ + Version float64 `json:"version"` + + /*LineCount defined: + * The number of lines in this document. + * + * @readonly + */ + LineCount float64 `json:"lineCount"` +} + +/*TextDocumentChangeEvent defined: + * Event to signal changes to a simple text document. + */ +type TextDocumentChangeEvent struct { + + /*Document defined: + * The document that has changed. + */ + Document TextDocument `json:"document"` +} + +// TextDocumentWillSaveEvent is +type TextDocumentWillSaveEvent struct { + + /*Document defined: + * The document that will be saved + */ + Document TextDocument `json:"document"` + + /*Reason defined: + * The reason why save was triggered. + */ + Reason TextDocumentSaveReason `json:"reason"` +} + +/*TextDocumentContentChangeEvent defined: + * An event describing a change to a text document. If range and rangeLength are omitted + * the new text is considered to be the full content of the document. + */ +type TextDocumentContentChangeEvent struct { + + /*Range defined: + * The range of the document that changed. + */ + Range *Range `json:"range,omitempty"` + + /*RangeLength defined: + * The length of the range that got replaced. + */ + RangeLength float64 `json:"rangeLength,omitempty"` + + /*Text defined: + * The new text of the document. + */ + Text string `json:"text"` +} + +// ProgressParams is +type ProgressParams struct { + + /*Token defined: + * The progress token provided by the client or server. + */ + Token ProgressToken `json:"token"` + + /*Value defined: + * The progress data. + */ + Value interface{} `json:"value"` +} + +// SetTraceParams is +type SetTraceParams struct { + + // Value is + Value TraceValues `json:"value"` +} + +// LogTraceParams is +type LogTraceParams struct { + + // Message is + Message string `json:"message"` + + // Verbose is + Verbose string `json:"verbose,omitempty"` +} + +// Tracer is +type Tracer struct { +} + +// FoldingRangeKind defines constants +type FoldingRangeKind string + +// ResourceOperationKind defines constants +type ResourceOperationKind string + +// FailureHandlingKind defines constants +type FailureHandlingKind string + +// InitializeError defines constants +type InitializeError float64 + +// MessageType defines constants +type MessageType float64 + +// TextDocumentSyncKind defines constants +type TextDocumentSyncKind float64 + +// FileChangeType defines constants +type FileChangeType float64 + +// WatchKind defines constants +type WatchKind float64 + +// CompletionTriggerKind defines constants +type CompletionTriggerKind float64 + +// SignatureHelpTriggerKind defines constants +type SignatureHelpTriggerKind float64 + +// DiagnosticSeverity defines constants +type DiagnosticSeverity float64 + +// DiagnosticTag defines constants +type DiagnosticTag float64 + +// MarkupKind defines constants +type MarkupKind string + +// CompletionItemKind defines constants +type CompletionItemKind float64 + +// InsertTextFormat defines constants +type InsertTextFormat float64 + +// CompletionItemTag defines constants +type CompletionItemTag float64 + +// DocumentHighlightKind defines constants +type DocumentHighlightKind float64 + +// SymbolKind defines constants +type SymbolKind float64 + +// CodeActionKind defines constants +type CodeActionKind string + +// TextDocumentSaveReason defines constants +type TextDocumentSaveReason float64 + +// ErrorCodes defines constants +type ErrorCodes float64 + +// Touch defines constants +type Touch float64 + +// Trace defines constants +type Trace string + +// TraceFormat defines constants +type TraceFormat string + +// ConnectionErrors defines constants +type ConnectionErrors float64 + +// ConnectionState defines constants +type ConnectionState float64 + +const ( + + /*Comment defined: + * Folding range for a comment + */ + Comment FoldingRangeKind = "comment" + + /*Imports defined: + * Folding range for a imports or includes + */ + Imports FoldingRangeKind = "imports" + + /*Region defined: + * Folding range for a region (e.g. `#region`) + */ + Region FoldingRangeKind = "region" + + /*Create defined: + * Supports creating new files and folders. + */ + Create ResourceOperationKind = "create" + + /*Rename defined: + * Supports renaming existing files and folders. + */ + Rename ResourceOperationKind = "rename" + + /*Delete defined: + * Supports deleting existing files and folders. + */ + Delete ResourceOperationKind = "delete" + + /*Abort defined: + * Applying the workspace change is simply aborted if one of the changes provided + * fails. All operations executed before the failing operation stay executed. + */ + Abort FailureHandlingKind = "abort" + + /*Transactional defined: + * All operations are executed transactional. That means they either all + * succeed or no changes at all are applied to the workspace. + */ + Transactional FailureHandlingKind = "transactional" + + /*TextOnlyTransactional defined: + * If the workspace edit contains only textual file changes they are executed transactional. + * If resource changes (create, rename or delete file) are part of the change the failure + * handling startegy is abort. + */ + TextOnlyTransactional FailureHandlingKind = "textOnlyTransactional" + + /*Undo defined: + * The client tries to undo the operations already executed. But there is no + * guaruntee that this is succeeding. + */ + Undo FailureHandlingKind = "undo" + + /*UnknownProtocolVersion defined: + * If the protocol version provided by the client can't be handled by the server. + * @deprecated This initialize error got replaced by client capabilities. There is + * no version handshake in version 3.0x + */ + UnknownProtocolVersion InitializeError = 1 + + /*Error defined: + * An error message. + */ + Error MessageType = 1 + + /*Warning defined: + * A warning message. + */ + Warning MessageType = 2 + + /*Info defined: + * An information message. + */ + Info MessageType = 3 + + /*Log defined: + * A log message. + */ + Log MessageType = 4 + + /*None defined: + * Documents should not be synced at all. + */ + None TextDocumentSyncKind = 0 + + /*Full defined: + * Documents are synced by always sending the full content + * of the document. + */ + Full TextDocumentSyncKind = 1 + + /*Incremental defined: + * Documents are synced by sending the full content on open. + * After that only incremental updates to the document are + * send. + */ + Incremental TextDocumentSyncKind = 2 + + /*Created defined: + * The file got created. + */ + Created FileChangeType = 1 + + /*Changed defined: + * The file got changed. + */ + Changed FileChangeType = 2 + + /*Deleted defined: + * The file got deleted. + */ + Deleted FileChangeType = 3 + + /*WatchCreate defined: + * Interested in create events. + */ + WatchCreate WatchKind = 1 + + /*WatchChange defined: + * Interested in change events + */ + WatchChange WatchKind = 2 + + /*WatchDelete defined: + * Interested in delete events + */ + WatchDelete WatchKind = 4 + + /*Invoked defined: + * Completion was triggered by typing an identifier (24x7 code + * complete), manual invocation (e.g Ctrl+Space) or via API. + */ + Invoked CompletionTriggerKind = 1 + + /*TriggerCharacter defined: + * Completion was triggered by a trigger character specified by + * the `triggerCharacters` properties of the `CompletionRegistrationOptions`. + */ + TriggerCharacter CompletionTriggerKind = 2 + + /*TriggerForIncompleteCompletions defined: + * Completion was re-triggered as current completion list is incomplete + */ + TriggerForIncompleteCompletions CompletionTriggerKind = 3 + + /*ContentChange defined: + * Signature help was triggered by the cursor moving or by the document content changing. + */ + ContentChange SignatureHelpTriggerKind = 3 + + /*SeverityError defined: + * Reports an error. + */ + SeverityError DiagnosticSeverity = 1 + + /*SeverityWarning defined: + * Reports a warning. + */ + SeverityWarning DiagnosticSeverity = 2 + + /*SeverityInformation defined: + * Reports an information. + */ + SeverityInformation DiagnosticSeverity = 3 + + /*SeverityHint defined: + * Reports a hint. + */ + SeverityHint DiagnosticSeverity = 4 + + /*Unnecessary defined: + * Unused or unnecessary code. + * + * Clients are allowed to render diagnostics with this tag faded out instead of having + * an error squiggle. + */ + Unnecessary DiagnosticTag = 1 + + /*Deprecated defined: + * Deprecated or obsolete code. + * + * Clients are allowed to rendered diagnostics with this tag strike through. + */ + Deprecated DiagnosticTag = 2 + + /*PlainText defined: + * Plain text is supported as a content format + */ + PlainText MarkupKind = "plaintext" + + /*Markdown defined: + * Markdown is supported as a content format + */ + Markdown MarkupKind = "markdown" + + // TextCompletion is + TextCompletion CompletionItemKind = 1 + + // MethodCompletion is + MethodCompletion CompletionItemKind = 2 + + // FunctionCompletion is + FunctionCompletion CompletionItemKind = 3 + + // ConstructorCompletion is + ConstructorCompletion CompletionItemKind = 4 + + // FieldCompletion is + FieldCompletion CompletionItemKind = 5 + + // VariableCompletion is + VariableCompletion CompletionItemKind = 6 + + // ClassCompletion is + ClassCompletion CompletionItemKind = 7 + + // InterfaceCompletion is + InterfaceCompletion CompletionItemKind = 8 + + // ModuleCompletion is + ModuleCompletion CompletionItemKind = 9 + + // PropertyCompletion is + PropertyCompletion CompletionItemKind = 10 + + // UnitCompletion is + UnitCompletion CompletionItemKind = 11 + + // ValueCompletion is + ValueCompletion CompletionItemKind = 12 + + // EnumCompletion is + EnumCompletion CompletionItemKind = 13 + + // KeywordCompletion is + KeywordCompletion CompletionItemKind = 14 + + // SnippetCompletion is + SnippetCompletion CompletionItemKind = 15 + + // ColorCompletion is + ColorCompletion CompletionItemKind = 16 + + // FileCompletion is + FileCompletion CompletionItemKind = 17 + + // ReferenceCompletion is + ReferenceCompletion CompletionItemKind = 18 + + // FolderCompletion is + FolderCompletion CompletionItemKind = 19 + + // EnumMemberCompletion is + EnumMemberCompletion CompletionItemKind = 20 + + // ConstantCompletion is + ConstantCompletion CompletionItemKind = 21 + + // StructCompletion is + StructCompletion CompletionItemKind = 22 + + // EventCompletion is + EventCompletion CompletionItemKind = 23 + + // OperatorCompletion is + OperatorCompletion CompletionItemKind = 24 + + // TypeParameterCompletion is + TypeParameterCompletion CompletionItemKind = 25 + + /*PlainTextTextFormat defined: + * The primary text to be inserted is treated as a plain string. + */ + PlainTextTextFormat InsertTextFormat = 1 + + /*SnippetTextFormat defined: + * The primary text to be inserted is treated as a snippet. + * + * A snippet can define tab stops and placeholders with `$1`, `$2` + * and `${3:foo}`. `$0` defines the final tab stop, it defaults to + * the end of the snippet. Placeholders with equal identifiers are linked, + * that is typing in one will update others too. + * + * See also: https://github.com/Microsoft/vscode/blob/master/src/vs/editor/contrib/snippet/common/snippet.md + */ + SnippetTextFormat InsertTextFormat = 2 + + /*Text defined: + * A textual occurrence. + */ + Text DocumentHighlightKind = 1 + + /*Read defined: + * Read-access of a symbol, like reading a variable. + */ + Read DocumentHighlightKind = 2 + + /*Write defined: + * Write-access of a symbol, like writing to a variable. + */ + Write DocumentHighlightKind = 3 + + // File is + File SymbolKind = 1 + + // Module is + Module SymbolKind = 2 + + // Namespace is + Namespace SymbolKind = 3 + + // Package is + Package SymbolKind = 4 + + // Class is + Class SymbolKind = 5 + + // Method is + Method SymbolKind = 6 + + // Property is + Property SymbolKind = 7 + + // Field is + Field SymbolKind = 8 + + // Constructor is + Constructor SymbolKind = 9 + + // Enum is + Enum SymbolKind = 10 + + // Interface is + Interface SymbolKind = 11 + + // Function is + Function SymbolKind = 12 + + // Variable is + Variable SymbolKind = 13 + + // Constant is + Constant SymbolKind = 14 + + // String is + String SymbolKind = 15 + + // Number is + Number SymbolKind = 16 + + // Boolean is + Boolean SymbolKind = 17 + + // Array is + Array SymbolKind = 18 + + // Object is + Object SymbolKind = 19 + + // Key is + Key SymbolKind = 20 + + // Null is + Null SymbolKind = 21 + + // EnumMember is + EnumMember SymbolKind = 22 + + // Struct is + Struct SymbolKind = 23 + + // Event is + Event SymbolKind = 24 + + // Operator is + Operator SymbolKind = 25 + + // TypeParameter is + TypeParameter SymbolKind = 26 + + /*Empty defined: + * Empty kind. + */ + Empty CodeActionKind = "" + + /*QuickFix defined: + * Base kind for quickfix actions: 'quickfix' + */ + QuickFix CodeActionKind = "quickfix" + + /*Refactor defined: + * Base kind for refactoring actions: 'refactor' + */ + Refactor CodeActionKind = "refactor" + + /*RefactorExtract defined: + * Base kind for refactoring extraction actions: 'refactor.extract' + * + * Example extract actions: + * + * - Extract method + * - Extract function + * - Extract variable + * - Extract interface from class + * - ... + */ + RefactorExtract CodeActionKind = "refactor.extract" + + /*RefactorInline defined: + * Base kind for refactoring inline actions: 'refactor.inline' + * + * Example inline actions: + * + * - Inline function + * - Inline variable + * - Inline constant + * - ... + */ + RefactorInline CodeActionKind = "refactor.inline" + + /*RefactorRewrite defined: + * Base kind for refactoring rewrite actions: 'refactor.rewrite' + * + * Example rewrite actions: + * + * - Convert JavaScript function to class + * - Add or remove parameter + * - Encapsulate field + * - Make method static + * - Move method to base class + * - ... + */ + RefactorRewrite CodeActionKind = "refactor.rewrite" + + /*Source defined: + * Base kind for source actions: `source` + * + * Source code actions apply to the entire file. + */ + Source CodeActionKind = "source" + + /*SourceOrganizeImports defined: + * Base kind for an organize imports source action: `source.organizeImports` + */ + SourceOrganizeImports CodeActionKind = "source.organizeImports" + + /*Manual defined: + * Manually triggered, e.g. by the user pressing save, by starting debugging, + * or by an API call. + */ + Manual TextDocumentSaveReason = 1 + + /*AfterDelay defined: + * Automatic after a delay. + */ + AfterDelay TextDocumentSaveReason = 2 + + /*FocusOut defined: + * When the editor lost focus. + */ + FocusOut TextDocumentSaveReason = 3 + + // MessageWriteError is + MessageWriteError ErrorCodes = 1 + + // MessageReadError is + MessageReadError ErrorCodes = 2 + + // First is + First Touch = 1 + + // Last is + Last Touch = 2 + + // JSON is + JSON TraceFormat = "json" + + /*Closed defined: + * The connection is closed. + */ + Closed ConnectionErrors = 1 + + /*Disposed defined: + * The connection got disposed. + */ + Disposed ConnectionErrors = 2 + + /*AlreadyListening defined: + * The connection is already in listening mode. + */ + AlreadyListening ConnectionErrors = 3 + + // New is + New ConnectionState = 1 + + // Listening is + Listening ConnectionState = 2 +) + +// DocumentFilter is a type +/** + * A document filter denotes a document by different properties like + * the [language](#TextDocument.languageId), the [scheme](#Uri.scheme) of + * its resource, or a glob-pattern that is applied to the [path](#TextDocument.fileName). + * + * Glob patterns can have the following syntax: + * - `*` to match one or more characters in a path segment + * - `?` to match on one character in a path segment + * - `**` to match any number of path segments, including none + * - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files) + * - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) + * - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) + * + * @sample A language filter that applies to typescript files on disk: `{ language: 'typescript', scheme: 'file' }` + * @sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**package.json' }` + */ +type DocumentFilter = struct { + + /*Language defined: A language id, like `typescript`. */ + Language string `json:"language,omitempty"` + + /*Scheme defined: A Uri [scheme](#Uri.scheme), like `file` or `untitled`. */ + Scheme string `json:"scheme,omitempty"` + + /*Pattern defined: A glob pattern, like `*.{ts,js}`. */ + Pattern string `json:"pattern,omitempty"` +} + +// DocumentSelector is a type +/** + * A document selector is the combination of one or many document filters. + * + * @sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language: 'json', pattern: '**∕tsconfig.json' }]`; + */ +type DocumentSelector = []DocumentFilter + +// DocumentURI is a type +/** + * A tagging type for string properties that are actually URIs. + */ +type DocumentURI = string + +// MarkedString is a type +/** + * MarkedString can be used to render human readable text. It is either a markdown string + * or a code-block that provides a language and a code snippet. The language identifier + * is semantically equal to the optional language identifier in fenced code blocks in GitHub + * issues. See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting + * + * The pair of a language and a value is an equivalent to markdown: + * ```${language} + * ${value} + * ``` + * + * Note that markdown strings will be sanitized - that means html will be escaped. + * @deprecated use MarkupContent instead. + */ +type MarkedString = string + +// DefinitionLink is a type +/** + * Information about where a symbol is defined. + * + * Provides additional metadata over normal [location](#Location) definitions, including the range of + * the defining symbol + */ +type DefinitionLink = LocationLink + +// DeclarationLink is a type +/** + * Information about where a symbol is declared. + * + * Provides additional metadata over normal [location](#Location) declarations, including the range of + * the declaring symbol. + * + * Servers should prefer returning `DeclarationLink` over `Declaration` if supported + * by the client. + */ +type DeclarationLink = LocationLink + +// LSPMessageType is a type +/** + * A LSP Log Entry. + */ +type LSPMessageType = string + +// ProgressToken is a type +type ProgressToken = interface{} // number | string +// TraceValues is a type +type TraceValues = string diff --git a/utils/vscode/src/lsp/protocol/tsserver.go b/utils/vscode/src/lsp/protocol/tsserver.go new file mode 100644 index 000000000..d76050121 --- /dev/null +++ b/utils/vscode/src/lsp/protocol/tsserver.go @@ -0,0 +1,842 @@ +// Copyright 2019 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package protocol + +import ( + "context" + "encoding/json" + "log" + + "../jsonrpc2" +) + +type Server interface { + DidChangeWorkspaceFolders(context.Context, *DidChangeWorkspaceFoldersParams) error + Initialized(context.Context, *InitializedParams) error + Exit(context.Context) error + DidChangeConfiguration(context.Context, *DidChangeConfigurationParams) error + DidOpen(context.Context, *DidOpenTextDocumentParams) error + DidChange(context.Context, *DidChangeTextDocumentParams) error + DidClose(context.Context, *DidCloseTextDocumentParams) error + DidSave(context.Context, *DidSaveTextDocumentParams) error + WillSave(context.Context, *WillSaveTextDocumentParams) error + DidChangeWatchedFiles(context.Context, *DidChangeWatchedFilesParams) error + Progress(context.Context, *ProgressParams) error + SetTraceNotification(context.Context, *SetTraceParams) error + LogTraceNotification(context.Context, *LogTraceParams) error + Implementation(context.Context, *ImplementationParams) ([]Location, error) + TypeDefinition(context.Context, *TypeDefinitionParams) ([]Location, error) + DocumentColor(context.Context, *DocumentColorParams) ([]ColorInformation, error) + ColorPresentation(context.Context, *ColorPresentationParams) ([]ColorPresentation, error) + FoldingRange(context.Context, *FoldingRangeParams) ([]FoldingRange, error) + Declaration(context.Context, *DeclarationParams) ([]DeclarationLink, error) + SelectionRange(context.Context, *SelectionRangeParams) ([]SelectionRange, error) + Initialize(context.Context, *ParamInitia) (*InitializeResult, error) + Shutdown(context.Context) error + WillSaveWaitUntil(context.Context, *WillSaveTextDocumentParams) ([]TextEdit, error) + Completion(context.Context, *CompletionParams) (*CompletionList, error) + Resolve(context.Context, *CompletionItem) (*CompletionItem, error) + Hover(context.Context, *HoverParams) (*Hover, error) + SignatureHelp(context.Context, *SignatureHelpParams) (*SignatureHelp, error) + Definition(context.Context, *DefinitionParams) ([]Location, error) + References(context.Context, *ReferenceParams) ([]Location, error) + DocumentHighlight(context.Context, *DocumentHighlightParams) ([]DocumentHighlight, error) + DocumentSymbol(context.Context, *DocumentSymbolParams) ([]DocumentSymbol, error) + CodeAction(context.Context, *CodeActionParams) ([]CodeAction, error) + Symbol(context.Context, *WorkspaceSymbolParams) ([]SymbolInformation, error) + CodeLens(context.Context, *CodeLensParams) ([]CodeLens, error) + ResolveCodeLens(context.Context, *CodeLens) (*CodeLens, error) + DocumentLink(context.Context, *DocumentLinkParams) ([]DocumentLink, error) + ResolveDocumentLink(context.Context, *DocumentLink) (*DocumentLink, error) + Formatting(context.Context, *DocumentFormattingParams) ([]TextEdit, error) + RangeFormatting(context.Context, *DocumentRangeFormattingParams) ([]TextEdit, error) + OnTypeFormatting(context.Context, *DocumentOnTypeFormattingParams) ([]TextEdit, error) + Rename(context.Context, *RenameParams) (*WorkspaceEdit, error) + PrepareRename(context.Context, *PrepareRenameParams) (*Range, error) + ExecuteCommand(context.Context, *ExecuteCommandParams) (interface{}, error) +} + +func (h serverHandler) Deliver(ctx context.Context, r *jsonrpc2.Request, delivered bool) bool { + if delivered { + return false + } + if ctx.Err() != nil { + r.Reply(ctx, nil, jsonrpc2.NewErrorf(RequestCancelledError, "")) + return true + } + switch r.Method { + case "workspace/didChangeWorkspaceFolders": // notif + var params DidChangeWorkspaceFoldersParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.server.DidChangeWorkspaceFolders(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "initialized": // notif + var params InitializedParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.server.Initialized(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "exit": // notif + if err := h.server.Exit(ctx); err != nil { + log.Printf("%v", err) + } + return true + case "workspace/didChangeConfiguration": // notif + var params DidChangeConfigurationParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.server.DidChangeConfiguration(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/didOpen": // notif + var params DidOpenTextDocumentParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.server.DidOpen(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/didChange": // notif + var params DidChangeTextDocumentParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.server.DidChange(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/didClose": // notif + var params DidCloseTextDocumentParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.server.DidClose(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/didSave": // notif + var params DidSaveTextDocumentParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.server.DidSave(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/willSave": // notif + var params WillSaveTextDocumentParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.server.WillSave(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "workspace/didChangeWatchedFiles": // notif + var params DidChangeWatchedFilesParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.server.DidChangeWatchedFiles(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "$/progress": // notif + var params ProgressParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.server.Progress(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "$/setTraceNotification": // notif + var params SetTraceParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.server.SetTraceNotification(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "$/logTraceNotification": // notif + var params LogTraceParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + if err := h.server.LogTraceNotification(ctx, ¶ms); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/implementation": // req + var params ImplementationParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.Implementation(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/typeDefinition": // req + var params TypeDefinitionParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.TypeDefinition(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/documentColor": // req + var params DocumentColorParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.DocumentColor(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/colorPresentation": // req + var params ColorPresentationParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.ColorPresentation(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/foldingRange": // req + var params FoldingRangeParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.FoldingRange(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/declaration": // req + var params DeclarationParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.Declaration(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/selectionRange": // req + var params SelectionRangeParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.SelectionRange(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "initialize": // req + var params ParamInitia + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.Initialize(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "shutdown": // req + if r.Params != nil { + r.Reply(ctx, nil, jsonrpc2.NewErrorf(jsonrpc2.CodeInvalidParams, "Expected no params")) + return true + } + err := h.server.Shutdown(ctx) + if err := r.Reply(ctx, nil, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/willSaveWaitUntil": // req + var params WillSaveTextDocumentParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.WillSaveWaitUntil(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/completion": // req + var params CompletionParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.Completion(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "completionItem/resolve": // req + var params CompletionItem + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.Resolve(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/hover": // req + var params HoverParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.Hover(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/signatureHelp": // req + var params SignatureHelpParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.SignatureHelp(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/definition": // req + var params DefinitionParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.Definition(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/references": // req + var params ReferenceParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.References(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/documentHighlight": // req + var params DocumentHighlightParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.DocumentHighlight(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/documentSymbol": // req + var params DocumentSymbolParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.DocumentSymbol(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/codeAction": // req + var params CodeActionParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.CodeAction(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "workspace/symbol": // req + var params WorkspaceSymbolParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.Symbol(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/codeLens": // req + var params CodeLensParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.CodeLens(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "codeLens/resolve": // req + var params CodeLens + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.ResolveCodeLens(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/documentLink": // req + var params DocumentLinkParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.DocumentLink(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "documentLink/resolve": // req + var params DocumentLink + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.ResolveDocumentLink(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/formatting": // req + var params DocumentFormattingParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.Formatting(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/rangeFormatting": // req + var params DocumentRangeFormattingParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.RangeFormatting(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/onTypeFormatting": // req + var params DocumentOnTypeFormattingParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.OnTypeFormatting(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/rename": // req + var params RenameParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.Rename(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "textDocument/prepareRename": // req + var params PrepareRenameParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.PrepareRename(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + case "workspace/executeCommand": // req + var params ExecuteCommandParams + if err := json.Unmarshal(*r.Params, ¶ms); err != nil { + sendParseError(ctx, r, err) + return true + } + resp, err := h.server.ExecuteCommand(ctx, ¶ms) + if err := r.Reply(ctx, resp, err); err != nil { + log.Printf("%v", err) + } + return true + + default: + return false + } +} + +type serverDispatcher struct { + *jsonrpc2.Conn +} + +func (s *serverDispatcher) DidChangeWorkspaceFolders(ctx context.Context, params *DidChangeWorkspaceFoldersParams) error { + return s.Conn.Notify(ctx, "workspace/didChangeWorkspaceFolders", params) +} + +func (s *serverDispatcher) Initialized(ctx context.Context, params *InitializedParams) error { + return s.Conn.Notify(ctx, "initialized", params) +} + +func (s *serverDispatcher) Exit(ctx context.Context) error { + return s.Conn.Notify(ctx, "exit", nil) +} + +func (s *serverDispatcher) DidChangeConfiguration(ctx context.Context, params *DidChangeConfigurationParams) error { + return s.Conn.Notify(ctx, "workspace/didChangeConfiguration", params) +} + +func (s *serverDispatcher) DidOpen(ctx context.Context, params *DidOpenTextDocumentParams) error { + return s.Conn.Notify(ctx, "textDocument/didOpen", params) +} + +func (s *serverDispatcher) DidChange(ctx context.Context, params *DidChangeTextDocumentParams) error { + return s.Conn.Notify(ctx, "textDocument/didChange", params) +} + +func (s *serverDispatcher) DidClose(ctx context.Context, params *DidCloseTextDocumentParams) error { + return s.Conn.Notify(ctx, "textDocument/didClose", params) +} + +func (s *serverDispatcher) DidSave(ctx context.Context, params *DidSaveTextDocumentParams) error { + return s.Conn.Notify(ctx, "textDocument/didSave", params) +} + +func (s *serverDispatcher) WillSave(ctx context.Context, params *WillSaveTextDocumentParams) error { + return s.Conn.Notify(ctx, "textDocument/willSave", params) +} + +func (s *serverDispatcher) DidChangeWatchedFiles(ctx context.Context, params *DidChangeWatchedFilesParams) error { + return s.Conn.Notify(ctx, "workspace/didChangeWatchedFiles", params) +} + +func (s *serverDispatcher) Progress(ctx context.Context, params *ProgressParams) error { + return s.Conn.Notify(ctx, "$/progress", params) +} + +func (s *serverDispatcher) SetTraceNotification(ctx context.Context, params *SetTraceParams) error { + return s.Conn.Notify(ctx, "$/setTraceNotification", params) +} + +func (s *serverDispatcher) LogTraceNotification(ctx context.Context, params *LogTraceParams) error { + return s.Conn.Notify(ctx, "$/logTraceNotification", params) +} +func (s *serverDispatcher) Implementation(ctx context.Context, params *ImplementationParams) ([]Location, error) { + var result []Location + if err := s.Conn.Call(ctx, "textDocument/implementation", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) TypeDefinition(ctx context.Context, params *TypeDefinitionParams) ([]Location, error) { + var result []Location + if err := s.Conn.Call(ctx, "textDocument/typeDefinition", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) DocumentColor(ctx context.Context, params *DocumentColorParams) ([]ColorInformation, error) { + var result []ColorInformation + if err := s.Conn.Call(ctx, "textDocument/documentColor", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) ColorPresentation(ctx context.Context, params *ColorPresentationParams) ([]ColorPresentation, error) { + var result []ColorPresentation + if err := s.Conn.Call(ctx, "textDocument/colorPresentation", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) FoldingRange(ctx context.Context, params *FoldingRangeParams) ([]FoldingRange, error) { + var result []FoldingRange + if err := s.Conn.Call(ctx, "textDocument/foldingRange", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) Declaration(ctx context.Context, params *DeclarationParams) ([]DeclarationLink, error) { + var result []DeclarationLink + if err := s.Conn.Call(ctx, "textDocument/declaration", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) SelectionRange(ctx context.Context, params *SelectionRangeParams) ([]SelectionRange, error) { + var result []SelectionRange + if err := s.Conn.Call(ctx, "textDocument/selectionRange", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) Initialize(ctx context.Context, params *ParamInitia) (*InitializeResult, error) { + var result InitializeResult + if err := s.Conn.Call(ctx, "initialize", params, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (s *serverDispatcher) Shutdown(ctx context.Context) error { + return s.Conn.Call(ctx, "shutdown", nil, nil) +} + +func (s *serverDispatcher) WillSaveWaitUntil(ctx context.Context, params *WillSaveTextDocumentParams) ([]TextEdit, error) { + var result []TextEdit + if err := s.Conn.Call(ctx, "textDocument/willSaveWaitUntil", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) Completion(ctx context.Context, params *CompletionParams) (*CompletionList, error) { + var result CompletionList + if err := s.Conn.Call(ctx, "textDocument/completion", params, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (s *serverDispatcher) Resolve(ctx context.Context, params *CompletionItem) (*CompletionItem, error) { + var result CompletionItem + if err := s.Conn.Call(ctx, "completionItem/resolve", params, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (s *serverDispatcher) Hover(ctx context.Context, params *HoverParams) (*Hover, error) { + var result Hover + if err := s.Conn.Call(ctx, "textDocument/hover", params, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (s *serverDispatcher) SignatureHelp(ctx context.Context, params *SignatureHelpParams) (*SignatureHelp, error) { + var result SignatureHelp + if err := s.Conn.Call(ctx, "textDocument/signatureHelp", params, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (s *serverDispatcher) Definition(ctx context.Context, params *DefinitionParams) ([]Location, error) { + var result []Location + if err := s.Conn.Call(ctx, "textDocument/definition", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) References(ctx context.Context, params *ReferenceParams) ([]Location, error) { + var result []Location + if err := s.Conn.Call(ctx, "textDocument/references", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) DocumentHighlight(ctx context.Context, params *DocumentHighlightParams) ([]DocumentHighlight, error) { + var result []DocumentHighlight + if err := s.Conn.Call(ctx, "textDocument/documentHighlight", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) DocumentSymbol(ctx context.Context, params *DocumentSymbolParams) ([]DocumentSymbol, error) { + var result []DocumentSymbol + if err := s.Conn.Call(ctx, "textDocument/documentSymbol", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) CodeAction(ctx context.Context, params *CodeActionParams) ([]CodeAction, error) { + var result []CodeAction + if err := s.Conn.Call(ctx, "textDocument/codeAction", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) Symbol(ctx context.Context, params *WorkspaceSymbolParams) ([]SymbolInformation, error) { + var result []SymbolInformation + if err := s.Conn.Call(ctx, "workspace/symbol", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) CodeLens(ctx context.Context, params *CodeLensParams) ([]CodeLens, error) { + var result []CodeLens + if err := s.Conn.Call(ctx, "textDocument/codeLens", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) ResolveCodeLens(ctx context.Context, params *CodeLens) (*CodeLens, error) { + var result CodeLens + if err := s.Conn.Call(ctx, "codeLens/resolve", params, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (s *serverDispatcher) DocumentLink(ctx context.Context, params *DocumentLinkParams) ([]DocumentLink, error) { + var result []DocumentLink + if err := s.Conn.Call(ctx, "textDocument/documentLink", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) ResolveDocumentLink(ctx context.Context, params *DocumentLink) (*DocumentLink, error) { + var result DocumentLink + if err := s.Conn.Call(ctx, "documentLink/resolve", params, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (s *serverDispatcher) Formatting(ctx context.Context, params *DocumentFormattingParams) ([]TextEdit, error) { + var result []TextEdit + if err := s.Conn.Call(ctx, "textDocument/formatting", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) RangeFormatting(ctx context.Context, params *DocumentRangeFormattingParams) ([]TextEdit, error) { + var result []TextEdit + if err := s.Conn.Call(ctx, "textDocument/rangeFormatting", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) OnTypeFormatting(ctx context.Context, params *DocumentOnTypeFormattingParams) ([]TextEdit, error) { + var result []TextEdit + if err := s.Conn.Call(ctx, "textDocument/onTypeFormatting", params, &result); err != nil { + return nil, err + } + return result, nil +} + +func (s *serverDispatcher) Rename(ctx context.Context, params *RenameParams) (*WorkspaceEdit, error) { + var result WorkspaceEdit + if err := s.Conn.Call(ctx, "textDocument/rename", params, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (s *serverDispatcher) PrepareRename(ctx context.Context, params *PrepareRenameParams) (*Range, error) { + var result Range + if err := s.Conn.Call(ctx, "textDocument/prepareRename", params, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (s *serverDispatcher) ExecuteCommand(ctx context.Context, params *ExecuteCommandParams) (interface{}, error) { + var result interface{} + if err := s.Conn.Call(ctx, "workspace/executeCommand", params, &result); err != nil { + return nil, err + } + return result, nil +} + +type CancelParams struct { + /** + * The request id to cancel. + */ + ID jsonrpc2.ID `json:"id"` +} + +// Types constructed to avoid structs as formal argument types +type ParamInitia struct { + InitializeParams + WorkDoneProgressParams +} diff --git a/utils/vscode/src/lsp/span/parse.go b/utils/vscode/src/lsp/span/parse.go new file mode 100644 index 000000000..ec393c2a7 --- /dev/null +++ b/utils/vscode/src/lsp/span/parse.go @@ -0,0 +1,110 @@ +// Copyright 2019 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package span + +import ( + "strconv" + "strings" + "unicode/utf8" +) + +// Parse returns the location represented by the input. +// All inputs are valid locations, as they can always be a pure filename. +// The returned span will be normalized, and thus if printed may produce a +// different string. +func Parse(input string) Span { + // :0:0#0-0:0#0 + valid := input + var hold, offset int + hadCol := false + suf := rstripSuffix(input) + if suf.sep == "#" { + offset = suf.num + suf = rstripSuffix(suf.remains) + } + if suf.sep == ":" { + valid = suf.remains + hold = suf.num + hadCol = true + suf = rstripSuffix(suf.remains) + } + switch { + case suf.sep == ":": + return New(NewURI(suf.remains), NewPoint(suf.num, hold, offset), Point{}) + case suf.sep == "-": + // we have a span, fall out of the case to continue + default: + // separator not valid, rewind to either the : or the start + return New(NewURI(valid), NewPoint(hold, 0, offset), Point{}) + } + // only the span form can get here + // at this point we still don't know what the numbers we have mean + // if have not yet seen a : then we might have either a line or a column depending + // on whether start has a column or not + // we build an end point and will fix it later if needed + end := NewPoint(suf.num, hold, offset) + hold, offset = 0, 0 + suf = rstripSuffix(suf.remains) + if suf.sep == "#" { + offset = suf.num + suf = rstripSuffix(suf.remains) + } + if suf.sep != ":" { + // turns out we don't have a span after all, rewind + return New(NewURI(valid), end, Point{}) + } + valid = suf.remains + hold = suf.num + suf = rstripSuffix(suf.remains) + if suf.sep != ":" { + // line#offset only + return New(NewURI(valid), NewPoint(hold, 0, offset), end) + } + // we have a column, so if end only had one number, it is also the column + if !hadCol { + end = NewPoint(suf.num, end.v.Line, end.v.Offset) + } + return New(NewURI(suf.remains), NewPoint(suf.num, hold, offset), end) +} + +type suffix struct { + remains string + sep string + num int +} + +func rstripSuffix(input string) suffix { + if len(input) == 0 { + return suffix{"", "", -1} + } + remains := input + num := -1 + // first see if we have a number at the end + last := strings.LastIndexFunc(remains, func(r rune) bool { return r < '0' || r > '9' }) + if last >= 0 && last < len(remains)-1 { + number, err := strconv.ParseInt(remains[last+1:], 10, 64) + if err == nil { + num = int(number) + remains = remains[:last+1] + } + } + // now see if we have a trailing separator + r, w := utf8.DecodeLastRuneInString(remains) + if r != ':' && r != '#' && r == '#' { + return suffix{input, "", -1} + } + remains = remains[:len(remains)-w] + return suffix{remains, string(r), num} +} diff --git a/utils/vscode/src/lsp/span/span.go b/utils/vscode/src/lsp/span/span.go new file mode 100644 index 000000000..aefd4f3fa --- /dev/null +++ b/utils/vscode/src/lsp/span/span.go @@ -0,0 +1,295 @@ +// Copyright 2019 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package span contains support for representing with positions and ranges in +// text files. +package span + +import ( + "encoding/json" + "fmt" + "path" +) + +// Span represents a source code range in standardized form. +type Span struct { + v span +} + +// Point represents a single point within a file. +// In general this should only be used as part of a Span, as on its own it +// does not carry enough information. +type Point struct { + v point +} + +type span struct { + URI URI `json:"uri"` + Start point `json:"start"` + End point `json:"end"` +} + +type point struct { + Line int `json:"line"` + Column int `json:"column"` + Offset int `json:"offset"` +} + +// Invalid is a span that reports false from IsValid +var Invalid = Span{v: span{Start: invalidPoint.v, End: invalidPoint.v}} + +var invalidPoint = Point{v: point{Line: 0, Column: 0, Offset: -1}} + +// Converter is the interface to an object that can convert between line:column +// and offset forms for a single file. +type Converter interface { + //ToPosition converts from an offset to a line:column pair. + ToPosition(offset int) (int, int, error) + //ToOffset converts from a line:column pair to an offset. + ToOffset(line, col int) (int, error) +} + +func New(uri URI, start Point, end Point) Span { + s := Span{v: span{URI: uri, Start: start.v, End: end.v}} + s.v.clean() + return s +} + +func NewPoint(line, col, offset int) Point { + p := Point{v: point{Line: line, Column: col, Offset: offset}} + p.v.clean() + return p +} + +func Compare(a, b Span) int { + if r := CompareURI(a.URI(), b.URI()); r != 0 { + return r + } + if r := comparePoint(a.v.Start, b.v.Start); r != 0 { + return r + } + return comparePoint(a.v.End, b.v.End) +} + +func ComparePoint(a, b Point) int { + return comparePoint(a.v, b.v) +} + +func comparePoint(a, b point) int { + if !a.hasPosition() { + if a.Offset < b.Offset { + return -1 + } + if a.Offset > b.Offset { + return 1 + } + return 0 + } + if a.Line < b.Line { + return -1 + } + if a.Line > b.Line { + return 1 + } + if a.Column < b.Column { + return -1 + } + if a.Column > b.Column { + return 1 + } + return 0 +} + +func (s Span) HasPosition() bool { return s.v.Start.hasPosition() } +func (s Span) HasOffset() bool { return s.v.Start.hasOffset() } +func (s Span) IsValid() bool { return s.v.Start.isValid() } +func (s Span) IsPoint() bool { return s.v.Start == s.v.End } +func (s Span) URI() URI { return s.v.URI } +func (s Span) Start() Point { return Point{s.v.Start} } +func (s Span) End() Point { return Point{s.v.End} } +func (s *Span) MarshalJSON() ([]byte, error) { return json.Marshal(&s.v) } +func (s *Span) UnmarshalJSON(b []byte) error { return json.Unmarshal(b, &s.v) } + +func (p Point) HasPosition() bool { return p.v.hasPosition() } +func (p Point) HasOffset() bool { return p.v.hasOffset() } +func (p Point) IsValid() bool { return p.v.isValid() } +func (p *Point) MarshalJSON() ([]byte, error) { return json.Marshal(&p.v) } +func (p *Point) UnmarshalJSON(b []byte) error { return json.Unmarshal(b, &p.v) } +func (p Point) Line() int { + if !p.v.hasPosition() { + panic(fmt.Errorf("position not set in %v", p.v)) + } + return p.v.Line +} +func (p Point) Column() int { + if !p.v.hasPosition() { + panic(fmt.Errorf("position not set in %v", p.v)) + } + return p.v.Column +} +func (p Point) Offset() int { + if !p.v.hasOffset() { + panic(fmt.Errorf("offset not set in %v", p.v)) + } + return p.v.Offset +} + +func (p point) hasPosition() bool { return p.Line > 0 } +func (p point) hasOffset() bool { return p.Offset >= 0 } +func (p point) isValid() bool { return p.hasPosition() || p.hasOffset() } +func (p point) isZero() bool { + return (p.Line == 1 && p.Column == 1) || (!p.hasPosition() && p.Offset == 0) +} + +func (s *span) clean() { + //this presumes the points are already clean + if !s.End.isValid() || (s.End == point{}) { + s.End = s.Start + } +} + +func (p *point) clean() { + if p.Line < 0 { + p.Line = 0 + } + if p.Column <= 0 { + if p.Line > 0 { + p.Column = 1 + } else { + p.Column = 0 + } + } + if p.Offset == 0 && (p.Line > 1 || p.Column > 1) { + p.Offset = -1 + } +} + +// Format implements fmt.Formatter to print the Location in a standard form. +// The format produced is one that can be read back in using Parse. +func (s Span) Format(f fmt.State, c rune) { + fullForm := f.Flag('+') + preferOffset := f.Flag('#') + // we should always have a uri, simplify if it is file format + //TODO: make sure the end of the uri is unambiguous + uri := string(s.v.URI) + if c == 'f' { + uri = path.Base(uri) + } else if !fullForm { + uri = s.v.URI.Filename() + } + fmt.Fprint(f, uri) + if !s.IsValid() || (!fullForm && s.v.Start.isZero() && s.v.End.isZero()) { + return + } + // see which bits of start to write + printOffset := s.HasOffset() && (fullForm || preferOffset || !s.HasPosition()) + printLine := s.HasPosition() && (fullForm || !printOffset) + printColumn := printLine && (fullForm || (s.v.Start.Column > 1 || s.v.End.Column > 1)) + fmt.Fprint(f, ":") + if printLine { + fmt.Fprintf(f, "%d", s.v.Start.Line) + } + if printColumn { + fmt.Fprintf(f, ":%d", s.v.Start.Column) + } + if printOffset { + fmt.Fprintf(f, "#%d", s.v.Start.Offset) + } + // start is written, do we need end? + if s.IsPoint() { + return + } + // we don't print the line if it did not change + printLine = fullForm || (printLine && s.v.End.Line > s.v.Start.Line) + fmt.Fprint(f, "-") + if printLine { + fmt.Fprintf(f, "%d", s.v.End.Line) + } + if printColumn { + if printLine { + fmt.Fprint(f, ":") + } + fmt.Fprintf(f, "%d", s.v.End.Column) + } + if printOffset { + fmt.Fprintf(f, "#%d", s.v.End.Offset) + } +} + +func (s Span) WithPosition(c Converter) (Span, error) { + if err := s.update(c, true, false); err != nil { + return Span{}, err + } + return s, nil +} + +func (s Span) WithOffset(c Converter) (Span, error) { + if err := s.update(c, false, true); err != nil { + return Span{}, err + } + return s, nil +} + +func (s Span) WithAll(c Converter) (Span, error) { + if err := s.update(c, true, true); err != nil { + return Span{}, err + } + return s, nil +} + +func (s *Span) update(c Converter, withPos, withOffset bool) error { + if !s.IsValid() { + return fmt.Errorf("cannot add information to an invalid span") + } + if withPos && !s.HasPosition() { + if err := s.v.Start.updatePosition(c); err != nil { + return err + } + if s.v.End.Offset == s.v.Start.Offset { + s.v.End = s.v.Start + } else if err := s.v.End.updatePosition(c); err != nil { + return err + } + } + if withOffset && (!s.HasOffset() || (s.v.End.hasPosition() && !s.v.End.hasOffset())) { + if err := s.v.Start.updateOffset(c); err != nil { + return err + } + if s.v.End.Line == s.v.Start.Line && s.v.End.Column == s.v.Start.Column { + s.v.End.Offset = s.v.Start.Offset + } else if err := s.v.End.updateOffset(c); err != nil { + return err + } + } + return nil +} + +func (p *point) updatePosition(c Converter) error { + line, col, err := c.ToPosition(p.Offset) + if err != nil { + return err + } + p.Line = line + p.Column = col + return nil +} + +func (p *point) updateOffset(c Converter) error { + offset, err := c.ToOffset(p.Line, p.Column) + if err != nil { + return err + } + p.Offset = offset + return nil +} diff --git a/utils/vscode/src/lsp/span/token.go b/utils/vscode/src/lsp/span/token.go new file mode 100644 index 000000000..f5a38708f --- /dev/null +++ b/utils/vscode/src/lsp/span/token.go @@ -0,0 +1,161 @@ +// Copyright 2019 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package span + +import ( + "fmt" + "go/token" +) + +// Range represents a source code range in token.Pos form. +// It also carries the FileSet that produced the positions, so that it is +// self contained. +type Range struct { + FileSet *token.FileSet + Start token.Pos + End token.Pos +} + +// TokenConverter is a Converter backed by a token file set and file. +// It uses the file set methods to work out the conversions, which +// makes it fast and does not require the file contents. +type TokenConverter struct { + fset *token.FileSet + file *token.File +} + +// NewRange creates a new Range from a FileSet and two positions. +// To represent a point pass a 0 as the end pos. +func NewRange(fset *token.FileSet, start, end token.Pos) Range { + return Range{ + FileSet: fset, + Start: start, + End: end, + } +} + +// NewTokenConverter returns an implementation of Converter backed by a +// token.File. +func NewTokenConverter(fset *token.FileSet, f *token.File) *TokenConverter { + return &TokenConverter{fset: fset, file: f} +} + +// NewContentConverter returns an implementation of Converter for the +// given file content. +func NewContentConverter(filename string, content []byte) *TokenConverter { + fset := token.NewFileSet() + f := fset.AddFile(filename, -1, len(content)) + f.SetLinesForContent(content) + return &TokenConverter{fset: fset, file: f} +} + +// IsPoint returns true if the range represents a single point. +func (r Range) IsPoint() bool { + return r.Start == r.End +} + +// Span converts a Range to a Span that represents the Range. +// It will fill in all the members of the Span, calculating the line and column +// information. +func (r Range) Span() (Span, error) { + f := r.FileSet.File(r.Start) + if f == nil { + return Span{}, fmt.Errorf("file not found in FileSet") + } + s := Span{v: span{URI: FileURI(f.Name())}} + var err error + s.v.Start.Offset, err = offset(f, r.Start) + if err != nil { + return Span{}, err + } + if r.End.IsValid() { + s.v.End.Offset, err = offset(f, r.End) + if err != nil { + return Span{}, err + } + } + s.v.Start.clean() + s.v.End.clean() + s.v.clean() + converter := NewTokenConverter(r.FileSet, f) + return s.WithPosition(converter) +} + +// offset is a copy of the Offset function in go/token, but with the adjustment +// that it does not panic on invalid positions. +func offset(f *token.File, pos token.Pos) (int, error) { + if int(pos) < f.Base() || int(pos) > f.Base()+f.Size() { + return 0, fmt.Errorf("invalid pos") + } + return int(pos) - f.Base(), nil +} + +// Range converts a Span to a Range that represents the Span for the supplied +// File. +func (s Span) Range(converter *TokenConverter) (Range, error) { + s, err := s.WithOffset(converter) + if err != nil { + return Range{}, err + } + // go/token will panic if the offset is larger than the file's size, + // so check here to avoid panicking. + if s.Start().Offset() > converter.file.Size() { + return Range{}, fmt.Errorf("start offset %v is past the end of the file %v", s.Start(), converter.file.Size()) + } + if s.End().Offset() > converter.file.Size() { + return Range{}, fmt.Errorf("end offset %v is past the end of the file %v", s.End(), converter.file.Size()) + } + return Range{ + FileSet: converter.fset, + Start: converter.file.Pos(s.Start().Offset()), + End: converter.file.Pos(s.End().Offset()), + }, nil +} + +func (l *TokenConverter) ToPosition(offset int) (int, int, error) { + if offset > l.file.Size() { + return 0, 0, fmt.Errorf("offset %v is past the end of the file %v", offset, l.file.Size()) + } + pos := l.file.Pos(offset) + p := l.fset.Position(pos) + if offset == l.file.Size() { + return p.Line + 1, 1, nil + } + return p.Line, p.Column, nil +} + +func (l *TokenConverter) ToOffset(line, col int) (int, error) { + if line < 0 { + return -1, fmt.Errorf("line is not valid") + } + lineMax := l.file.LineCount() + 1 + if line > lineMax { + return -1, fmt.Errorf("line is beyond end of file %v", lineMax) + } else if line == lineMax { + if col > 1 { + return -1, fmt.Errorf("column is beyond end of file") + } + // at the end of the file, allowing for a trailing eol + return l.file.Size(), nil + } + pos := lineStart(l.file, line) + if !pos.IsValid() { + return -1, fmt.Errorf("line is not in file") + } + // we assume that column is in bytes here, and that the first byte of a + // line is at column 1 + pos += token.Pos(col - 1) + return offset(l.file, pos) +} diff --git a/utils/vscode/src/lsp/span/token111.go b/utils/vscode/src/lsp/span/token111.go new file mode 100644 index 000000000..768419a70 --- /dev/null +++ b/utils/vscode/src/lsp/span/token111.go @@ -0,0 +1,49 @@ +// Copyright 2019 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !go1.12 + +package span + +import ( + "go/token" +) + +// lineStart is the pre-Go 1.12 version of (*token.File).LineStart. For Go +// versions <= 1.11, we borrow logic from the analysisutil package. +// TODO(rstambler): Delete this file when we no longer support Go 1.11. +func lineStart(f *token.File, line int) token.Pos { + // Use binary search to find the start offset of this line. + + min := 0 // inclusive + max := f.Size() // exclusive + for { + offset := (min + max) / 2 + pos := f.Pos(offset) + posn := f.Position(pos) + if posn.Line == line { + return pos - (token.Pos(posn.Column) - 1) + } + + if min+1 >= max { + return token.NoPos + } + + if posn.Line < line { + min = offset + } else { + max = offset + } + } +} diff --git a/utils/vscode/src/lsp/span/token112.go b/utils/vscode/src/lsp/span/token112.go new file mode 100644 index 000000000..abff500d2 --- /dev/null +++ b/utils/vscode/src/lsp/span/token112.go @@ -0,0 +1,26 @@ +// Copyright 2019 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build go1.12 + +package span + +import ( + "go/token" +) + +// TODO(rstambler): Delete this file when we no longer support Go 1.11. +func lineStart(f *token.File, line int) token.Pos { + return f.LineStart(line) +} diff --git a/utils/vscode/src/lsp/span/uri.go b/utils/vscode/src/lsp/span/uri.go new file mode 100644 index 000000000..525518bef --- /dev/null +++ b/utils/vscode/src/lsp/span/uri.go @@ -0,0 +1,162 @@ +// Copyright 2019 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package span + +import ( + "fmt" + "net/url" + "os" + "path" + "path/filepath" + "runtime" + "strings" + "unicode" +) + +const fileScheme = "file" + +// URI represents the full URI for a file. +type URI string + +// Filename returns the file path for the given URI. +// It is an error to call this on a URI that is not a valid filename. +func (uri URI) Filename() string { + filename, err := filename(uri) + if err != nil { + panic(err) + } + return filepath.FromSlash(filename) +} + +func filename(uri URI) (string, error) { + if uri == "" { + return "", nil + } + u, err := url.ParseRequestURI(string(uri)) + if err != nil { + return "", err + } + if u.Scheme != fileScheme { + return "", fmt.Errorf("only file URIs are supported, got %q from %q", u.Scheme, uri) + } + if isWindowsDriveURI(u.Path) { + u.Path = u.Path[1:] + } + return u.Path, nil +} + +// NewURI returns a span URI for the string. +// It will attempt to detect if the string is a file path or uri. +func NewURI(s string) URI { + if u, err := url.PathUnescape(s); err == nil { + s = u + } + if strings.HasPrefix(s, fileScheme+"://") { + return URI(s) + } + return FileURI(s) +} + +func CompareURI(a, b URI) int { + if equalURI(a, b) { + return 0 + } + if a < b { + return -1 + } + return 1 +} + +func equalURI(a, b URI) bool { + if a == b { + return true + } + // If we have the same URI basename, we may still have the same file URIs. + if !strings.EqualFold(path.Base(string(a)), path.Base(string(b))) { + return false + } + fa, err := filename(a) + if err != nil { + return false + } + fb, err := filename(b) + if err != nil { + return false + } + // Stat the files to check if they are equal. + infoa, err := os.Stat(filepath.FromSlash(fa)) + if err != nil { + return false + } + infob, err := os.Stat(filepath.FromSlash(fb)) + if err != nil { + return false + } + return os.SameFile(infoa, infob) +} + +// FileURI returns a span URI for the supplied file path. +// It will always have the file scheme. +func FileURI(path string) URI { + if path == "" { + return "" + } + // Handle standard library paths that contain the literal "$GOROOT". + // TODO(rstambler): The go/packages API should allow one to determine a user's $GOROOT. + const prefix = "$GOROOT" + if len(path) >= len(prefix) && strings.EqualFold(prefix, path[:len(prefix)]) { + suffix := path[len(prefix):] + path = runtime.GOROOT() + suffix + } + if !isWindowsDrivePath(path) { + if abs, err := filepath.Abs(path); err == nil { + path = abs + } + } + // Check the file path again, in case it became absolute. + if isWindowsDrivePath(path) { + path = "/" + path + } + path = filepath.ToSlash(path) + u := url.URL{ + Scheme: fileScheme, + Path: path, + } + uri := u.String() + if unescaped, err := url.PathUnescape(uri); err == nil { + uri = unescaped + } + return URI(uri) +} + +// isWindowsDrivePath returns true if the file path is of the form used by +// Windows. We check if the path begins with a drive letter, followed by a ":". +func isWindowsDrivePath(path string) bool { + if len(path) < 4 { + return false + } + return unicode.IsLetter(rune(path[0])) && path[1] == ':' +} + +// isWindowsDriveURI returns true if the file URI is of the format used by +// Windows URIs. The url.Parse package does not specially handle Windows paths +// (see https://golang.org/issue/6027). We check if the URI path has +// a drive prefix (e.g. "/C:"). If so, we trim the leading "/". +func isWindowsDriveURI(uri string) bool { + if len(uri) < 4 { + return false + } + return uri[0] == '/' && unicode.IsLetter(rune(uri[1])) && uri[2] == ':' +} diff --git a/utils/vscode/src/lsp/span/utf16.go b/utils/vscode/src/lsp/span/utf16.go new file mode 100644 index 000000000..6821851d1 --- /dev/null +++ b/utils/vscode/src/lsp/span/utf16.go @@ -0,0 +1,104 @@ +// Copyright 2019 The Go Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package span + +import ( + "fmt" + "unicode/utf16" + "unicode/utf8" +) + +// ToUTF16Column calculates the utf16 column expressed by the point given the +// supplied file contents. +// This is used to convert from the native (always in bytes) column +// representation and the utf16 counts used by some editors. +func ToUTF16Column(p Point, content []byte) (int, error) { + if content == nil { + return -1, fmt.Errorf("ToUTF16Column: missing content") + } + if !p.HasPosition() { + return -1, fmt.Errorf("ToUTF16Column: point is missing position") + } + if !p.HasOffset() { + return -1, fmt.Errorf("ToUTF16Column: point is missing offset") + } + offset := p.Offset() // 0-based + colZero := p.Column() - 1 // 0-based + if colZero == 0 { + // 0-based column 0, so it must be chr 1 + return 1, nil + } else if colZero < 0 { + return -1, fmt.Errorf("ToUTF16Column: column is invalid (%v)", colZero) + } + // work out the offset at the start of the line using the column + lineOffset := offset - colZero + if lineOffset < 0 || offset > len(content) { + return -1, fmt.Errorf("ToUTF16Column: offsets %v-%v outside file contents (%v)", lineOffset, offset, len(content)) + } + // Use the offset to pick out the line start. + // This cannot panic: offset > len(content) and lineOffset < offset. + start := content[lineOffset:] + + // Now, truncate down to the supplied column. + start = start[:colZero] + + // and count the number of utf16 characters + // in theory we could do this by hand more efficiently... + return len(utf16.Encode([]rune(string(start)))) + 1, nil +} + +// FromUTF16Column advances the point by the utf16 character offset given the +// supplied line contents. +// This is used to convert from the utf16 counts used by some editors to the +// native (always in bytes) column representation. +func FromUTF16Column(p Point, chr int, content []byte) (Point, error) { + if !p.HasOffset() { + return Point{}, fmt.Errorf("FromUTF16Column: point is missing offset") + } + // if chr is 1 then no adjustment needed + if chr <= 1 { + return p, nil + } + if p.Offset() >= len(content) { + return p, fmt.Errorf("FromUTF16Column: offset (%v) greater than length of content (%v)", p.Offset(), len(content)) + } + remains := content[p.Offset():] + // scan forward the specified number of characters + for count := 1; count < chr; count++ { + if len(remains) <= 0 { + return Point{}, fmt.Errorf("FromUTF16Column: chr goes beyond the content") + } + r, w := utf8.DecodeRune(remains) + if r == '\n' { + // Per the LSP spec: + // + // > If the character value is greater than the line length it + // > defaults back to the line length. + break + } + remains = remains[w:] + if r >= 0x10000 { + // a two point rune + count++ + // if we finished in a two point rune, do not advance past the first + if count >= chr { + break + } + } + p.v.Column += w + p.v.Offset += w + } + return p, nil +}