mirror of
https://github.com/golang/go
synced 2024-11-18 11:04:42 -07:00
internal/jsonrpc2: split reply from request
reply is now passed to handlers separately from request, which allows it to be substituted by handlers. This also makes the handler signature much closer to http (which has ResponseWriter) Change-Id: I12be2e8e8b9bd508982ba43c9092709429284eaf Reviewed-on: https://go-review.googlesource.com/c/tools/+/227839 Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
b854406a88
commit
1f08ef6002
@ -13,23 +13,25 @@ import (
|
||||
)
|
||||
|
||||
// Handler 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.
|
||||
// The handler should return ErrNotHandled if it could not handle the request.
|
||||
type Handler func(context.Context, *Request) error
|
||||
// The Replier sends a reply to the request and must be called exactly once.
|
||||
type Handler func(ctx context.Context, reply Replier, req *Request) error
|
||||
|
||||
// Replier is passed to handlers to allow them to reply to the request.
|
||||
// If err is set then result will be ignored.
|
||||
type Replier func(ctx context.Context, result interface{}, err error) error
|
||||
|
||||
// MethodNotFound is a Handler that replies to all call requests with the
|
||||
// standard method not found response.
|
||||
// This should normally be the final handler in a chain.
|
||||
func MethodNotFound(ctx context.Context, r *Request) error {
|
||||
return r.Reply(ctx, nil, fmt.Errorf("%w: %q", ErrMethodNotFound, r.Method))
|
||||
func MethodNotFound(ctx context.Context, reply Replier, r *Request) error {
|
||||
return reply(ctx, nil, fmt.Errorf("%w: %q", ErrMethodNotFound, r.Method))
|
||||
}
|
||||
|
||||
// MustReply creates a Handler that panics if the wrapped handler does
|
||||
// MustReplyHandler creates a Handler that panics if the wrapped handler does
|
||||
// not call Reply for every request that it is passed.
|
||||
func MustReply(handler Handler) Handler {
|
||||
return func(ctx context.Context, req *Request) error {
|
||||
err := handler(ctx, req)
|
||||
func MustReplyHandler(handler Handler) Handler {
|
||||
return func(ctx context.Context, reply Replier, req *Request) error {
|
||||
err := handler(ctx, reply, req)
|
||||
if req.done != nil {
|
||||
panic(fmt.Errorf("request %q was never replied to", req.Method))
|
||||
}
|
||||
@ -42,7 +44,7 @@ func MustReply(handler Handler) Handler {
|
||||
func CancelHandler(handler Handler) (Handler, func(id ID)) {
|
||||
var mu sync.Mutex
|
||||
handling := make(map[ID]context.CancelFunc)
|
||||
wrapped := func(ctx context.Context, req *Request) error {
|
||||
wrapped := func(ctx context.Context, reply Replier, req *Request) error {
|
||||
if req.ID != nil {
|
||||
cancelCtx, cancel := context.WithCancel(ctx)
|
||||
ctx = cancelCtx
|
||||
@ -55,7 +57,7 @@ func CancelHandler(handler Handler) (Handler, func(id ID)) {
|
||||
mu.Unlock()
|
||||
})
|
||||
}
|
||||
return handler(ctx, req)
|
||||
return handler(ctx, reply, req)
|
||||
}
|
||||
return wrapped, func(id ID) {
|
||||
mu.Lock()
|
||||
@ -76,7 +78,7 @@ func CancelHandler(handler Handler) (Handler, func(id ID)) {
|
||||
func AsyncHandler(handler Handler) Handler {
|
||||
nextRequest := make(chan struct{})
|
||||
close(nextRequest)
|
||||
return func(ctx context.Context, req *Request) error {
|
||||
return func(ctx context.Context, reply Replier, req *Request) error {
|
||||
waitForPrevious := nextRequest
|
||||
nextRequest = make(chan struct{})
|
||||
unlockNext := nextRequest
|
||||
@ -85,7 +87,7 @@ func AsyncHandler(handler Handler) Handler {
|
||||
go func() {
|
||||
<-waitForPrevious
|
||||
queueDone()
|
||||
if err := handler(ctx, req); err != nil {
|
||||
if err := handler(ctx, reply, req); err != nil {
|
||||
event.Error(ctx, "jsonrpc2 async message delivery failed", err)
|
||||
}
|
||||
}()
|
||||
|
@ -170,62 +170,59 @@ func (r *Request) IsNotify() bool {
|
||||
return r.ID == nil
|
||||
}
|
||||
|
||||
// Reply sends a reply to the given request.
|
||||
// You must call this exactly once for any given request.
|
||||
// If err is set then result will be ignored.
|
||||
// This will mark the request as done, triggering any done
|
||||
// handlers
|
||||
func (r *Request) Reply(ctx context.Context, result interface{}, err error) error {
|
||||
if r.done == nil {
|
||||
return fmt.Errorf("reply invoked more than once")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
recordStatus(ctx, err)
|
||||
for i := len(r.done); i > 0; i-- {
|
||||
r.done[i-1]()
|
||||
func replier(r *Request) Replier {
|
||||
return func(ctx context.Context, result interface{}, err error) error {
|
||||
if r.done == nil {
|
||||
return fmt.Errorf("reply invoked more than once")
|
||||
}
|
||||
r.done = nil
|
||||
}()
|
||||
|
||||
if r.IsNotify() {
|
||||
return nil
|
||||
}
|
||||
defer func() {
|
||||
recordStatus(ctx, err)
|
||||
for i := len(r.done); i > 0; i-- {
|
||||
r.done[i-1]()
|
||||
}
|
||||
r.done = nil
|
||||
}()
|
||||
|
||||
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.(*wireError); ok {
|
||||
response.Error = callErr
|
||||
} else {
|
||||
response.Error = &wireError{Message: err.Error()}
|
||||
var wrapped *wireError
|
||||
if errors.As(err, &wrapped) {
|
||||
// if we wrapped a wire error, keep the code from the wrapped error
|
||||
// but the message from the outer error
|
||||
response.Error.Code = wrapped.Code
|
||||
if r.IsNotify() {
|
||||
return nil
|
||||
}
|
||||
|
||||
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.(*wireError); ok {
|
||||
response.Error = callErr
|
||||
} else {
|
||||
response.Error = &wireError{Message: err.Error()}
|
||||
var wrapped *wireError
|
||||
if errors.As(err, &wrapped) {
|
||||
// if we wrapped a wire error, keep the code from the wrapped error
|
||||
// but the message from the outer error
|
||||
response.Error.Code = wrapped.Code
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n, err := r.conn.stream.Write(ctx, data)
|
||||
event.Record(ctx, tag.SentBytes.Of(n))
|
||||
data, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n, err := r.conn.stream.Write(ctx, data)
|
||||
event.Record(ctx, tag.SentBytes.Of(n))
|
||||
|
||||
if err != nil {
|
||||
// TODO(iancottrell): if a stream write fails, we really need to shut down
|
||||
// the whole stream
|
||||
return err
|
||||
if err != nil {
|
||||
// TODO(iancottrell): if a stream write fails, we really need to shut down
|
||||
// the whole stream
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// OnReply adds a done callback to the request.
|
||||
@ -283,7 +280,7 @@ func (c *Conn) Run(runCtx context.Context, handler Handler) error {
|
||||
}
|
||||
req.OnReply(func() { spanDone() })
|
||||
|
||||
if err := handler(reqCtx, req); err != nil {
|
||||
if err := handler(reqCtx, replier(req), req); err != nil {
|
||||
// delivery failed, not much we can do
|
||||
event.Error(reqCtx, "jsonrpc2 message delivery failed", err)
|
||||
}
|
||||
|
@ -119,33 +119,33 @@ func run(ctx context.Context, t *testing.T, withHeaders bool, r io.ReadCloser, w
|
||||
}
|
||||
|
||||
func testHandler(log bool) jsonrpc2.Handler {
|
||||
return func(ctx context.Context, r *jsonrpc2.Request) error {
|
||||
switch r.Method {
|
||||
return func(ctx context.Context, reply jsonrpc2.Replier, req *jsonrpc2.Request) error {
|
||||
switch req.Method {
|
||||
case "no_args":
|
||||
if r.Params != nil {
|
||||
return r.Reply(ctx, nil, fmt.Errorf("%w: expected no params", jsonrpc2.ErrInvalidParams))
|
||||
if req.Params != nil {
|
||||
return reply(ctx, nil, fmt.Errorf("%w: expected no params", jsonrpc2.ErrInvalidParams))
|
||||
}
|
||||
return r.Reply(ctx, true, nil)
|
||||
return reply(ctx, true, nil)
|
||||
case "one_string":
|
||||
var v string
|
||||
if err := json.Unmarshal(*r.Params, &v); err != nil {
|
||||
return r.Reply(ctx, nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err))
|
||||
if err := json.Unmarshal(*req.Params, &v); err != nil {
|
||||
return reply(ctx, nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err))
|
||||
}
|
||||
return r.Reply(ctx, "got:"+v, nil)
|
||||
return reply(ctx, "got:"+v, nil)
|
||||
case "one_number":
|
||||
var v int
|
||||
if err := json.Unmarshal(*r.Params, &v); err != nil {
|
||||
return r.Reply(ctx, nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err))
|
||||
if err := json.Unmarshal(*req.Params, &v); err != nil {
|
||||
return reply(ctx, nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err))
|
||||
}
|
||||
return r.Reply(ctx, fmt.Sprintf("got:%d", v), nil)
|
||||
return reply(ctx, fmt.Sprintf("got:%d", v), nil)
|
||||
case "join":
|
||||
var v []string
|
||||
if err := json.Unmarshal(*r.Params, &v); err != nil {
|
||||
return r.Reply(ctx, nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err))
|
||||
if err := json.Unmarshal(*req.Params, &v); err != nil {
|
||||
return reply(ctx, nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err))
|
||||
}
|
||||
return r.Reply(ctx, path.Join(v...), nil)
|
||||
return reply(ctx, path.Join(v...), nil)
|
||||
default:
|
||||
return jsonrpc2.MethodNotFound(ctx, r)
|
||||
return jsonrpc2.MethodNotFound(ctx, reply, req)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ type msg struct {
|
||||
Msg string
|
||||
}
|
||||
|
||||
func fakeHandler(ctx context.Context, r *jsonrpc2.Request) error {
|
||||
return r.Reply(ctx, &msg{"pong"}, nil)
|
||||
func fakeHandler(ctx context.Context, reply jsonrpc2.Replier, req *jsonrpc2.Request) error {
|
||||
return reply(ctx, &msg{"pong"}, nil)
|
||||
}
|
||||
|
||||
func TestTestServer(t *testing.T) {
|
||||
|
@ -416,7 +416,7 @@ func OverrideExitFuncsForTest() func() {
|
||||
// instance from exiting. In the future it may also intercept 'shutdown' to
|
||||
// provide more graceful shutdown of the client connection.
|
||||
func forwarderHandler(handler jsonrpc2.Handler) jsonrpc2.Handler {
|
||||
return func(ctx context.Context, r *jsonrpc2.Request) error {
|
||||
return func(ctx context.Context, reply jsonrpc2.Replier, r *jsonrpc2.Request) error {
|
||||
// TODO(golang.org/issues/34111): we should more gracefully disconnect here,
|
||||
// once that process exists.
|
||||
if r.Method == "exit" {
|
||||
@ -424,9 +424,9 @@ func forwarderHandler(handler jsonrpc2.Handler) jsonrpc2.Handler {
|
||||
// reply nil here to consume the message: in
|
||||
// tests, ForwarderExitFunc may be overridden to something that doesn't
|
||||
// exit the process.
|
||||
return r.Reply(ctx, nil, nil)
|
||||
return reply(ctx, nil, nil)
|
||||
}
|
||||
return handler(ctx, r)
|
||||
return handler(ctx, reply, r)
|
||||
}
|
||||
}
|
||||
|
||||
@ -486,12 +486,12 @@ const (
|
||||
)
|
||||
|
||||
func handshaker(client *debugClient, goplsPath string, handler jsonrpc2.Handler) jsonrpc2.Handler {
|
||||
return func(ctx context.Context, r *jsonrpc2.Request) error {
|
||||
return func(ctx context.Context, reply jsonrpc2.Replier, r *jsonrpc2.Request) error {
|
||||
switch r.Method {
|
||||
case handshakeMethod:
|
||||
var req handshakeRequest
|
||||
if err := json.Unmarshal(*r.Params, &req); err != nil {
|
||||
sendError(ctx, r, err)
|
||||
sendError(ctx, reply, r, err)
|
||||
return nil
|
||||
}
|
||||
client.debugAddress = req.DebugAddr
|
||||
@ -508,7 +508,7 @@ func handshaker(client *debugClient, goplsPath string, handler jsonrpc2.Handler)
|
||||
resp.DebugAddr = di.ListenedDebugAddress
|
||||
}
|
||||
|
||||
return r.Reply(ctx, resp, nil)
|
||||
return reply(ctx, resp, nil)
|
||||
case sessionsMethod:
|
||||
resp := ServerState{
|
||||
GoplsPath: goplsPath,
|
||||
@ -526,15 +526,15 @@ func handshaker(client *debugClient, goplsPath string, handler jsonrpc2.Handler)
|
||||
})
|
||||
}
|
||||
}
|
||||
return r.Reply(ctx, resp, nil)
|
||||
return reply(ctx, resp, nil)
|
||||
}
|
||||
return handler(ctx, r)
|
||||
return handler(ctx, reply, r)
|
||||
}
|
||||
}
|
||||
|
||||
func sendError(ctx context.Context, req *jsonrpc2.Request, err error) {
|
||||
func sendError(ctx context.Context, reply jsonrpc2.Replier, req *jsonrpc2.Request, err error) {
|
||||
err = fmt.Errorf("%w: %v", jsonrpc2.ErrParse, err)
|
||||
if err := req.Reply(ctx, nil, err); err != nil {
|
||||
if err := reply(ctx, nil, err); err != nil {
|
||||
event.Error(ctx, "", err)
|
||||
}
|
||||
}
|
||||
|
@ -35,27 +35,27 @@ func Handlers(handler jsonrpc2.Handler) jsonrpc2.Handler {
|
||||
return CancelHandler(
|
||||
CancelHandler(
|
||||
jsonrpc2.AsyncHandler(
|
||||
jsonrpc2.MustReply(handler))))
|
||||
jsonrpc2.MustReplyHandler(handler))))
|
||||
}
|
||||
|
||||
func CancelHandler(handler jsonrpc2.Handler) jsonrpc2.Handler {
|
||||
handler, canceller := jsonrpc2.CancelHandler(handler)
|
||||
return func(ctx context.Context, req *jsonrpc2.Request) error {
|
||||
return func(ctx context.Context, reply jsonrpc2.Replier, req *jsonrpc2.Request) error {
|
||||
if req.Method != "$/cancelRequest" {
|
||||
return handler(ctx, req)
|
||||
return handler(ctx, reply, req)
|
||||
}
|
||||
var params CancelParams
|
||||
if err := json.Unmarshal(*req.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, req, err)
|
||||
return sendParseError(ctx, reply, req, err)
|
||||
}
|
||||
if n, ok := params.ID.(float64); ok {
|
||||
canceller(*jsonrpc2.NewIntID(int64(n)))
|
||||
} else if s, ok := params.ID.(string); ok {
|
||||
canceller(*jsonrpc2.NewStringID(s))
|
||||
} else {
|
||||
return sendParseError(ctx, req, fmt.Errorf("request ID %v malformed", params.ID))
|
||||
return sendParseError(ctx, reply, req, fmt.Errorf("request ID %v malformed", params.ID))
|
||||
}
|
||||
return req.Reply(ctx, nil, nil)
|
||||
return reply(ctx, nil, nil)
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,6 +75,6 @@ func cancelCall(ctx context.Context, conn *jsonrpc2.Conn, id jsonrpc2.ID) {
|
||||
conn.Notify(ctx, "$/cancelRequest", &CancelParams{ID: &id})
|
||||
}
|
||||
|
||||
func sendParseError(ctx context.Context, req *jsonrpc2.Request, err error) error {
|
||||
return req.Reply(ctx, nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err))
|
||||
func sendParseError(ctx context.Context, reply jsonrpc2.Replier, req *jsonrpc2.Request, err error) error {
|
||||
return reply(ctx, nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err))
|
||||
}
|
||||
|
@ -32,97 +32,97 @@ type Client interface {
|
||||
}
|
||||
|
||||
func ClientHandler(client Client, handler jsonrpc2.Handler) jsonrpc2.Handler {
|
||||
return func(ctx context.Context, r *jsonrpc2.Request) error {
|
||||
return func(ctx context.Context, reply jsonrpc2.Replier, r *jsonrpc2.Request) error {
|
||||
if ctx.Err() != nil {
|
||||
ctx := xcontext.Detach(ctx)
|
||||
return r.Reply(ctx, nil, RequestCancelledError)
|
||||
return reply(ctx, nil, RequestCancelledError)
|
||||
}
|
||||
switch r.Method {
|
||||
case "window/showMessage": // notif
|
||||
var params ShowMessageParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := client.ShowMessage(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "window/logMessage": // notif
|
||||
var params LogMessageParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := client.LogMessage(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "telemetry/event": // notif
|
||||
var params interface{}
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := client.Event(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "textDocument/publishDiagnostics": // notif
|
||||
var params PublishDiagnosticsParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := client.PublishDiagnostics(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "$/progress": // notif
|
||||
var params ProgressParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := client.Progress(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "workspace/workspaceFolders": // req
|
||||
if r.Params != nil {
|
||||
return r.Reply(ctx, nil, fmt.Errorf("%w: expected no params", jsonrpc2.ErrInvalidParams))
|
||||
return reply(ctx, nil, fmt.Errorf("%w: expected no params", jsonrpc2.ErrInvalidParams))
|
||||
}
|
||||
resp, err := client.WorkspaceFolders(ctx)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "workspace/configuration": // req
|
||||
var params ParamConfiguration
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := client.Configuration(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "window/workDoneProgress/create": // req
|
||||
var params WorkDoneProgressCreateParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := client.WorkDoneProgressCreate(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "client/registerCapability": // req
|
||||
var params RegistrationParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := client.RegisterCapability(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "client/unregisterCapability": // req
|
||||
var params UnregistrationParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := client.UnregisterCapability(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "window/showMessageRequest": // req
|
||||
var params ShowMessageRequestParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := client.ShowMessageRequest(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "workspace/applyEdit": // req
|
||||
var params ApplyWorkspaceEditParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := client.ApplyEdit(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
default:
|
||||
return handler(ctx, r)
|
||||
return handler(ctx, reply, r)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -70,356 +70,356 @@ type Server interface {
|
||||
}
|
||||
|
||||
func ServerHandler(server Server, handler jsonrpc2.Handler) jsonrpc2.Handler {
|
||||
return func(ctx context.Context, r *jsonrpc2.Request) error {
|
||||
return func(ctx context.Context, reply jsonrpc2.Replier, r *jsonrpc2.Request) error {
|
||||
if ctx.Err() != nil {
|
||||
ctx := xcontext.Detach(ctx)
|
||||
return r.Reply(ctx, nil, RequestCancelledError)
|
||||
return reply(ctx, nil, RequestCancelledError)
|
||||
}
|
||||
switch r.Method {
|
||||
case "workspace/didChangeWorkspaceFolders": // notif
|
||||
var params DidChangeWorkspaceFoldersParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := server.DidChangeWorkspaceFolders(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "window/workDoneProgress/cancel": // notif
|
||||
var params WorkDoneProgressCancelParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := server.WorkDoneProgressCancel(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "initialized": // notif
|
||||
var params InitializedParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := server.Initialized(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "exit": // notif
|
||||
return server.Exit(ctx)
|
||||
case "workspace/didChangeConfiguration": // notif
|
||||
var params DidChangeConfigurationParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := server.DidChangeConfiguration(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "textDocument/didOpen": // notif
|
||||
var params DidOpenTextDocumentParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := server.DidOpen(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "textDocument/didChange": // notif
|
||||
var params DidChangeTextDocumentParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := server.DidChange(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "textDocument/didClose": // notif
|
||||
var params DidCloseTextDocumentParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := server.DidClose(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "textDocument/didSave": // notif
|
||||
var params DidSaveTextDocumentParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := server.DidSave(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "textDocument/willSave": // notif
|
||||
var params WillSaveTextDocumentParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := server.WillSave(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "workspace/didChangeWatchedFiles": // notif
|
||||
var params DidChangeWatchedFilesParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := server.DidChangeWatchedFiles(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "$/setTraceNotification": // notif
|
||||
var params SetTraceParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := server.SetTraceNotification(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "$/logTraceNotification": // notif
|
||||
var params LogTraceParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err := server.LogTraceNotification(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "textDocument/implementation": // req
|
||||
var params ImplementationParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.Implementation(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/typeDefinition": // req
|
||||
var params TypeDefinitionParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.TypeDefinition(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/documentColor": // req
|
||||
var params DocumentColorParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.DocumentColor(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/colorPresentation": // req
|
||||
var params ColorPresentationParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.ColorPresentation(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/foldingRange": // req
|
||||
var params FoldingRangeParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.FoldingRange(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/declaration": // req
|
||||
var params DeclarationParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.Declaration(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/selectionRange": // req
|
||||
var params SelectionRangeParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.SelectionRange(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "initialize": // req
|
||||
var params ParamInitialize
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.Initialize(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "shutdown": // req
|
||||
if r.Params != nil {
|
||||
return r.Reply(ctx, nil, fmt.Errorf("%w: expected no params", jsonrpc2.ErrInvalidParams))
|
||||
return reply(ctx, nil, fmt.Errorf("%w: expected no params", jsonrpc2.ErrInvalidParams))
|
||||
}
|
||||
err := server.Shutdown(ctx)
|
||||
return r.Reply(ctx, nil, err)
|
||||
return reply(ctx, nil, err)
|
||||
case "textDocument/willSaveWaitUntil": // req
|
||||
var params WillSaveTextDocumentParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.WillSaveWaitUntil(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/completion": // req
|
||||
var params CompletionParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.Completion(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "completionItem/resolve": // req
|
||||
var params CompletionItem
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.Resolve(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/hover": // req
|
||||
var params HoverParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.Hover(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/signatureHelp": // req
|
||||
var params SignatureHelpParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.SignatureHelp(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/definition": // req
|
||||
var params DefinitionParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.Definition(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/references": // req
|
||||
var params ReferenceParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.References(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/documentHighlight": // req
|
||||
var params DocumentHighlightParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.DocumentHighlight(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/documentSymbol": // req
|
||||
var params DocumentSymbolParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.DocumentSymbol(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/codeAction": // req
|
||||
var params CodeActionParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.CodeAction(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "workspace/symbol": // req
|
||||
var params WorkspaceSymbolParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.Symbol(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/codeLens": // req
|
||||
var params CodeLensParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.CodeLens(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "codeLens/resolve": // req
|
||||
var params CodeLens
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.ResolveCodeLens(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/documentLink": // req
|
||||
var params DocumentLinkParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.DocumentLink(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "documentLink/resolve": // req
|
||||
var params DocumentLink
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.ResolveDocumentLink(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/formatting": // req
|
||||
var params DocumentFormattingParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.Formatting(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/rangeFormatting": // req
|
||||
var params DocumentRangeFormattingParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.RangeFormatting(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/onTypeFormatting": // req
|
||||
var params DocumentOnTypeFormattingParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.OnTypeFormatting(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/rename": // req
|
||||
var params RenameParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.Rename(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/prepareRename": // req
|
||||
var params PrepareRenameParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.PrepareRename(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "workspace/executeCommand": // req
|
||||
var params ExecuteCommandParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.ExecuteCommand(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/prepareCallHierarchy": // req
|
||||
var params CallHierarchyPrepareParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.PrepareCallHierarchy(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "callHierarchy/incomingCalls": // req
|
||||
var params CallHierarchyIncomingCallsParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.IncomingCalls(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "callHierarchy/outgoingCalls": // req
|
||||
var params CallHierarchyOutgoingCallsParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.OutgoingCalls(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/semanticTokens": // req
|
||||
var params SemanticTokensParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.SemanticTokens(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/semanticTokens/edits": // req
|
||||
var params SemanticTokensEditsParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.SemanticTokensEdits(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
case "textDocument/semanticTokens/range": // req
|
||||
var params SemanticTokensRangeParams
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.SemanticTokensRange(ctx, ¶ms)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
default:
|
||||
var params interface{}
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.NonstandardRequest(ctx, r.Method, params)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -908,7 +908,7 @@ let server: side = {
|
||||
|
||||
// commonly used output
|
||||
const notNil = `if r.Params != nil {
|
||||
return r.Reply(ctx, nil, fmt.Errorf("%w: expected no params", jsonrpc2.CodeInvalidParams))
|
||||
return reply(ctx, nil, fmt.Errorf("%w: expected no params", jsonrpc2.ErrInvalidParams))
|
||||
}`;
|
||||
|
||||
// Go code for notifications. Side is client or server, m is the request
|
||||
@ -924,10 +924,10 @@ function goNot(side: side, m: string) {
|
||||
if (a != '' && a != 'void') {
|
||||
case1 = `var params ${a}
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
err:= ${side.name}.${nm}(ctx, ¶ms)
|
||||
return r.Reply(ctx, nil, err)`
|
||||
return reply(ctx, nil, err)`
|
||||
} else {
|
||||
case1 = `return ${side.name}.${nm}(ctx)`;
|
||||
}
|
||||
@ -959,7 +959,7 @@ function goReq(side: side, m: string) {
|
||||
if (extraTypes.has('Param' + nm)) a = 'Param' + nm
|
||||
case1 = `var params ${a}
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}`;
|
||||
}
|
||||
const arg2 = a == '' ? '' : ', ¶ms';
|
||||
@ -968,10 +968,10 @@ function goReq(side: side, m: string) {
|
||||
}`;
|
||||
if (b != '' && b != 'void') {
|
||||
case2 = `resp, err := ${side.name}.${nm}(ctx${arg2})
|
||||
return r.Reply(ctx, resp, err)`;
|
||||
return reply(ctx, resp, err)`;
|
||||
} else { // response is nil
|
||||
case2 = `err := ${side.name}.${nm}(ctx${arg2})
|
||||
return r.Reply(ctx, nil, err)`
|
||||
return reply(ctx, nil, err)`
|
||||
}
|
||||
|
||||
side.cases.push(`${caseHdr}\n${case1}\n${case2}`);
|
||||
@ -1082,10 +1082,10 @@ function output(side: side) {
|
||||
side.methods.forEach((v) => {f(v)});
|
||||
f('}\n');
|
||||
f(`func ${a}Handler(${side.name} ${a}, handler jsonrpc2.Handler) jsonrpc2.Handler {
|
||||
return func(ctx context.Context, r *jsonrpc2.Request) error {
|
||||
return func(ctx context.Context, reply jsonrpc2.Replier, r *jsonrpc2.Request) error {
|
||||
if ctx.Err() != nil {
|
||||
ctx := xcontext.Detach(ctx)
|
||||
return r.Reply(ctx, nil, RequestCancelledError)
|
||||
return reply(ctx, nil, RequestCancelledError)
|
||||
}
|
||||
switch r.Method {`);
|
||||
side.cases.forEach((v) => {f(v)});
|
||||
@ -1115,14 +1115,14 @@ function nonstandardRequests() {
|
||||
}
|
||||
`)
|
||||
client.cases.push(`default:
|
||||
return handler(ctx, r)`)
|
||||
return handler(ctx, reply, r)`)
|
||||
server.cases.push(`default:
|
||||
var params interface{}
|
||||
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
||||
return sendParseError(ctx, r, err)
|
||||
return sendParseError(ctx, reply, r, err)
|
||||
}
|
||||
resp, err := server.NonstandardRequest(ctx, r.Method, params)
|
||||
return r.Reply(ctx, resp, err)
|
||||
return reply(ctx, resp, err)
|
||||
`)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user