golang.org/x/tools/gopls@v0.15.3/internal/lsprpc/export_test.go (about) 1 // Copyright 2024 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package lsprpc 6 7 // This file defines things (and opens backdoors) needed only by tests. 8 9 import ( 10 "context" 11 "encoding/json" 12 "fmt" 13 14 "golang.org/x/tools/gopls/internal/protocol" 15 "golang.org/x/tools/internal/event" 16 jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2" 17 "golang.org/x/tools/internal/xcontext" 18 ) 19 20 const HandshakeMethod = handshakeMethod 21 22 // A ServerFunc is used to construct an LSP server for a given client. 23 type ServerFunc func(context.Context, protocol.ClientCloser) protocol.Server 24 25 type Canceler struct { 26 Conn *jsonrpc2_v2.Connection 27 } 28 29 func (c *Canceler) Preempt(ctx context.Context, req *jsonrpc2_v2.Request) (interface{}, error) { 30 if req.Method != "$/cancelRequest" { 31 return nil, jsonrpc2_v2.ErrNotHandled 32 } 33 var params protocol.CancelParams 34 if err := json.Unmarshal(req.Params, ¶ms); err != nil { 35 return nil, fmt.Errorf("%w: %v", jsonrpc2_v2.ErrParse, err) 36 } 37 var id jsonrpc2_v2.ID 38 switch raw := params.ID.(type) { 39 case float64: 40 id = jsonrpc2_v2.Int64ID(int64(raw)) 41 case string: 42 id = jsonrpc2_v2.StringID(raw) 43 default: 44 return nil, fmt.Errorf("%w: invalid ID type %T", jsonrpc2_v2.ErrParse, params.ID) 45 } 46 c.Conn.Cancel(id) 47 return nil, nil 48 } 49 50 type ForwardBinder struct { 51 dialer jsonrpc2_v2.Dialer 52 onBind func(*jsonrpc2_v2.Connection) 53 } 54 55 func NewForwardBinder(dialer jsonrpc2_v2.Dialer) *ForwardBinder { 56 return &ForwardBinder{ 57 dialer: dialer, 58 } 59 } 60 61 func (b *ForwardBinder) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) (opts jsonrpc2_v2.ConnectionOptions) { 62 client := protocol.ClientDispatcherV2(conn) 63 clientBinder := NewClientBinder(func(context.Context, protocol.Server) protocol.Client { return client }) 64 65 serverConn, err := jsonrpc2_v2.Dial(context.Background(), b.dialer, clientBinder) 66 if err != nil { 67 return jsonrpc2_v2.ConnectionOptions{ 68 Handler: jsonrpc2_v2.HandlerFunc(func(context.Context, *jsonrpc2_v2.Request) (interface{}, error) { 69 return nil, fmt.Errorf("%w: %v", jsonrpc2_v2.ErrInternal, err) 70 }), 71 } 72 } 73 74 if b.onBind != nil { 75 b.onBind(serverConn) 76 } 77 server := protocol.ServerDispatcherV2(serverConn) 78 preempter := &Canceler{ 79 Conn: conn, 80 } 81 detached := xcontext.Detach(ctx) 82 go func() { 83 conn.Wait() 84 if err := serverConn.Close(); err != nil { 85 event.Log(detached, fmt.Sprintf("closing remote connection: %v", err)) 86 } 87 }() 88 return jsonrpc2_v2.ConnectionOptions{ 89 Handler: protocol.ServerHandlerV2(server), 90 Preempter: preempter, 91 } 92 } 93 94 func NewClientBinder(newClient ClientFunc) *clientBinder { 95 return &clientBinder{newClient} 96 } 97 98 // A ClientFunc is used to construct an LSP client for a given server. 99 type ClientFunc func(context.Context, protocol.Server) protocol.Client 100 101 // clientBinder binds an LSP client to an incoming connection. 102 type clientBinder struct { 103 newClient ClientFunc 104 } 105 106 func (b *clientBinder) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions { 107 server := protocol.ServerDispatcherV2(conn) 108 client := b.newClient(ctx, server) 109 return jsonrpc2_v2.ConnectionOptions{ 110 Handler: protocol.ClientHandlerV2(client), 111 } 112 } 113 114 // HandlerMiddleware is a middleware that only modifies the jsonrpc2 handler. 115 type HandlerMiddleware func(jsonrpc2_v2.Handler) jsonrpc2_v2.Handler 116 117 // BindHandler transforms a HandlerMiddleware into a Middleware. 118 func BindHandler(hmw HandlerMiddleware) Middleware { 119 return Middleware(func(binder jsonrpc2_v2.Binder) jsonrpc2_v2.Binder { 120 return BinderFunc(func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions { 121 opts := binder.Bind(ctx, conn) 122 opts.Handler = hmw(opts.Handler) 123 return opts 124 }) 125 }) 126 } 127 128 // The BinderFunc type adapts a bind function to implement the jsonrpc2.Binder 129 // interface. 130 type BinderFunc func(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions 131 132 func (f BinderFunc) Bind(ctx context.Context, conn *jsonrpc2_v2.Connection) jsonrpc2_v2.ConnectionOptions { 133 return f(ctx, conn) 134 } 135 136 // Middleware defines a transformation of jsonrpc2 Binders, that may be 137 // composed to build jsonrpc2 servers. 138 type Middleware func(jsonrpc2_v2.Binder) jsonrpc2_v2.Binder 139 140 var GetGoEnv = getGoEnv 141 142 type StreamServer = streamServer