Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 26 additions & 26 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ import (
"bytes"
"context"
"fmt"
"log/slog"

"github.com/segmentio/encoding/json"
"go.uber.org/zap"

"go.lsp.dev/jsonrpc2"
"go.lsp.dev/pkg/xcontext"
)

// ClientDispatcher returns a Client that dispatches LSP requests across the
// given jsonrpc2 connection.
func ClientDispatcher(conn jsonrpc2.Conn, logger *zap.Logger) Client {
func ClientDispatcher(conn jsonrpc2.Conn, logger *slog.Logger) Client {
return &client{
Conn: conn,
logger: logger,
Expand Down Expand Up @@ -57,7 +57,7 @@ func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier,

switch req.Method() {
case MethodProgress: // notification
defer logger.Debug(MethodProgress, zap.Error(err))
defer logger.Debug(MethodProgress, "error", err)

var params ProgressParams
if err := dec.Decode(&params); err != nil {
Expand All @@ -69,7 +69,7 @@ func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier,
return true, reply(ctx, nil, err)

case MethodWorkDoneProgressCreate: // request
defer logger.Debug(MethodWorkDoneProgressCreate, zap.Error(err))
defer logger.Debug(MethodWorkDoneProgressCreate, "error", err)

var params WorkDoneProgressCreateParams
if err := dec.Decode(&params); err != nil {
Expand All @@ -81,7 +81,7 @@ func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier,
return true, reply(ctx, nil, err)

case MethodWindowLogMessage: // notification
defer logger.Debug(MethodWindowLogMessage, zap.Error(err))
defer logger.Debug(MethodWindowLogMessage, "error", err)

var params LogMessageParams
if err := dec.Decode(&params); err != nil {
Expand All @@ -93,7 +93,7 @@ func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier,
return true, reply(ctx, nil, err)

case MethodTextDocumentPublishDiagnostics: // notification
defer logger.Debug(MethodTextDocumentPublishDiagnostics, zap.Error(err))
defer logger.Debug(MethodTextDocumentPublishDiagnostics, "error", err)

var params PublishDiagnosticsParams
if err := dec.Decode(&params); err != nil {
Expand All @@ -105,7 +105,7 @@ func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier,
return true, reply(ctx, nil, err)

case MethodWindowShowMessage: // notification
defer logger.Debug(MethodWindowShowMessage, zap.Error(err))
defer logger.Debug(MethodWindowShowMessage, "error", err)

var params ShowMessageParams
if err := dec.Decode(&params); err != nil {
Expand All @@ -117,7 +117,7 @@ func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier,
return true, reply(ctx, nil, err)

case MethodWindowShowMessageRequest: // request
defer logger.Debug(MethodWindowShowMessageRequest, zap.Error(err))
defer logger.Debug(MethodWindowShowMessageRequest, "error", err)

var params ShowMessageRequestParams
if err := dec.Decode(&params); err != nil {
Expand All @@ -129,7 +129,7 @@ func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier,
return true, reply(ctx, resp, err)

case MethodTelemetryEvent: // notification
defer logger.Debug(MethodTelemetryEvent, zap.Error(err))
defer logger.Debug(MethodTelemetryEvent, "error", err)

var params interface{}
if err := dec.Decode(&params); err != nil {
Expand All @@ -141,7 +141,7 @@ func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier,
return true, reply(ctx, nil, err)

case MethodClientRegisterCapability: // request
defer logger.Debug(MethodClientRegisterCapability, zap.Error(err))
defer logger.Debug(MethodClientRegisterCapability, "error", err)

var params RegistrationParams
if err := dec.Decode(&params); err != nil {
Expand All @@ -153,7 +153,7 @@ func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier,
return true, reply(ctx, nil, err)

case MethodClientUnregisterCapability: // request
defer logger.Debug(MethodClientUnregisterCapability, zap.Error(err))
defer logger.Debug(MethodClientUnregisterCapability, "error", err)

var params UnregistrationParams
if err := dec.Decode(&params); err != nil {
Expand All @@ -165,7 +165,7 @@ func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier,
return true, reply(ctx, nil, err)

case MethodWorkspaceApplyEdit: // request
defer logger.Debug(MethodWorkspaceApplyEdit, zap.Error(err))
defer logger.Debug(MethodWorkspaceApplyEdit, "error", err)

var params ApplyWorkspaceEditParams
if err := dec.Decode(&params); err != nil {
Expand All @@ -177,7 +177,7 @@ func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier,
return true, reply(ctx, resp, err)

case MethodWorkspaceConfiguration: // request
defer logger.Debug(MethodWorkspaceConfiguration, zap.Error(err))
defer logger.Debug(MethodWorkspaceConfiguration, "error", err)

var params ConfigurationParams
if err := dec.Decode(&params); err != nil {
Expand All @@ -189,7 +189,7 @@ func clientDispatch(ctx context.Context, client Client, reply jsonrpc2.Replier,
return true, reply(ctx, resp, err)

case MethodWorkspaceWorkspaceFolders: // request
defer logger.Debug(MethodWorkspaceWorkspaceFolders, zap.Error(err))
defer logger.Debug(MethodWorkspaceWorkspaceFolders, "error", err)

if len(req.Params()) > 0 {
return true, reply(ctx, nil, fmt.Errorf("expected no params: %w", jsonrpc2.ErrInvalidParams))
Expand Down Expand Up @@ -263,7 +263,7 @@ const (
type client struct {
jsonrpc2.Conn

logger *zap.Logger
logger *slog.Logger
}

// compiler time check whether the Client implements ClientInterface interface.
Expand All @@ -277,7 +277,7 @@ var _ Client = (*client)(nil)
// @since 3.16.0.
func (c *client) Progress(ctx context.Context, params *ProgressParams) (err error) {
c.logger.Debug("call " + MethodProgress)
defer c.logger.Debug("end "+MethodProgress, zap.Error(err))
defer c.logger.Debug("end "+MethodProgress, "error", err)

return c.Conn.Notify(ctx, MethodProgress, params)
}
Expand All @@ -287,15 +287,15 @@ func (c *client) Progress(ctx context.Context, params *ProgressParams) (err erro
// @since 3.16.0.
func (c *client) WorkDoneProgressCreate(ctx context.Context, params *WorkDoneProgressCreateParams) (err error) {
c.logger.Debug("call " + MethodWorkDoneProgressCreate)
defer c.logger.Debug("end "+MethodWorkDoneProgressCreate, zap.Error(err))
defer c.logger.Debug("end "+MethodWorkDoneProgressCreate, "error", err)

return Call(ctx, c.Conn, MethodWorkDoneProgressCreate, params, nil)
}

// LogMessage sends the notification from the server to the client to ask the client to log a particular message.
func (c *client) LogMessage(ctx context.Context, params *LogMessageParams) (err error) {
c.logger.Debug("call " + MethodWindowLogMessage)
defer c.logger.Debug("end "+MethodWindowLogMessage, zap.Error(err))
defer c.logger.Debug("end "+MethodWindowLogMessage, "error", err)

return c.Conn.Notify(ctx, MethodWindowLogMessage, params)
}
Expand All @@ -312,7 +312,7 @@ func (c *client) LogMessage(ctx context.Context, params *LogMessageParams) (err
// Newly pushed diagnostics always replace previously pushed diagnostics. There is no merging that happens on the client side.
func (c *client) PublishDiagnostics(ctx context.Context, params *PublishDiagnosticsParams) (err error) {
c.logger.Debug("call " + MethodTextDocumentPublishDiagnostics)
defer c.logger.Debug("end "+MethodTextDocumentPublishDiagnostics, zap.Error(err))
defer c.logger.Debug("end "+MethodTextDocumentPublishDiagnostics, "error", err)

return c.Conn.Notify(ctx, MethodTextDocumentPublishDiagnostics, params)
}
Expand All @@ -328,7 +328,7 @@ func (c *client) ShowMessage(ctx context.Context, params *ShowMessageParams) (er
// In addition to the show message notification the request allows to pass actions and to wait for an answer from the client.
func (c *client) ShowMessageRequest(ctx context.Context, params *ShowMessageRequestParams) (_ *MessageActionItem, err error) {
c.logger.Debug("call " + MethodWindowShowMessageRequest)
defer c.logger.Debug("end "+MethodWindowShowMessageRequest, zap.Error(err))
defer c.logger.Debug("end "+MethodWindowShowMessageRequest, "error", err)

var result *MessageActionItem
if err := Call(ctx, c.Conn, MethodWindowShowMessageRequest, params, &result); err != nil {
Expand All @@ -341,7 +341,7 @@ func (c *client) ShowMessageRequest(ctx context.Context, params *ShowMessageRequ
// Telemetry sends the notification from the server to the client to ask the client to log a telemetry event.
func (c *client) Telemetry(ctx context.Context, params interface{}) (err error) {
c.logger.Debug("call " + MethodTelemetryEvent)
defer c.logger.Debug("end "+MethodTelemetryEvent, zap.Error(err))
defer c.logger.Debug("end "+MethodTelemetryEvent, "error", err)

return c.Conn.Notify(ctx, MethodTelemetryEvent, params)
}
Expand All @@ -354,23 +354,23 @@ func (c *client) Telemetry(ctx context.Context, params interface{}) (err error)
// A client can even provide dynamic registration for capability A but not for capability B (see TextDocumentClientCapabilities as an example).
func (c *client) RegisterCapability(ctx context.Context, params *RegistrationParams) (err error) {
c.logger.Debug("call " + MethodClientRegisterCapability)
defer c.logger.Debug("end "+MethodClientRegisterCapability, zap.Error(err))
defer c.logger.Debug("end "+MethodClientRegisterCapability, "error", err)

return Call(ctx, c.Conn, MethodClientRegisterCapability, params, nil)
}

// UnregisterCapability sends the request from the server to the client to unregister a previously registered capability.
func (c *client) UnregisterCapability(ctx context.Context, params *UnregistrationParams) (err error) {
c.logger.Debug("call " + MethodClientUnregisterCapability)
defer c.logger.Debug("end "+MethodClientUnregisterCapability, zap.Error(err))
defer c.logger.Debug("end "+MethodClientUnregisterCapability, "error", err)

return Call(ctx, c.Conn, MethodClientUnregisterCapability, params, nil)
}

// ApplyEdit sends the request from the server to the client to modify resource on the client side.
func (c *client) ApplyEdit(ctx context.Context, params *ApplyWorkspaceEditParams) (result *ApplyWorkspaceEditResponse, err error) {
c.logger.Debug("call " + MethodWorkspaceApplyEdit)
defer c.logger.Debug("end "+MethodWorkspaceApplyEdit, zap.Error(err))
defer c.logger.Debug("end "+MethodWorkspaceApplyEdit, "error", err)

if err := Call(ctx, c.Conn, MethodWorkspaceApplyEdit, params, &result); err != nil {
return nil, err
Expand All @@ -386,7 +386,7 @@ func (c *client) ApplyEdit(ctx context.Context, params *ApplyWorkspaceEditParams
// passed ConfigurationItems (e.g. the first item in the response is the result for the first configuration item in the params).
func (c *client) Configuration(ctx context.Context, params *ConfigurationParams) (_ []interface{}, err error) {
c.logger.Debug("call " + MethodWorkspaceConfiguration)
defer c.logger.Debug("end "+MethodWorkspaceConfiguration, zap.Error(err))
defer c.logger.Debug("end "+MethodWorkspaceConfiguration, "error", err)

var result []interface{}
if err := Call(ctx, c.Conn, MethodWorkspaceConfiguration, params, &result); err != nil {
Expand All @@ -403,7 +403,7 @@ func (c *client) Configuration(ctx context.Context, params *ConfigurationParams)
// @since 3.6.0.
func (c *client) WorkspaceFolders(ctx context.Context) (result []WorkspaceFolder, err error) {
c.logger.Debug("call " + MethodWorkspaceWorkspaceFolders)
defer c.logger.Debug("end "+MethodWorkspaceWorkspaceFolders, zap.Error(err))
defer c.logger.Debug("end "+MethodWorkspaceWorkspaceFolders, "error", err)

if err := Call(ctx, c.Conn, MethodWorkspaceWorkspaceFolders, nil, &result); err != nil {
return nil, err
Expand Down
16 changes: 8 additions & 8 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@ package protocol

import (
"context"

"go.uber.org/zap"
"io"
"log/slog"
)

type (
ctxLogger struct{}
ctxClient struct{}
)

// WithLogger returns the context with zap.Logger value.
func WithLogger(ctx context.Context, logger *zap.Logger) context.Context {
// WithLogger returns the context with slog.Logger value.
func WithLogger(ctx context.Context, logger *slog.Logger) context.Context {
return context.WithValue(ctx, ctxLogger{}, logger)
}

// LoggerFromContext extracts zap.Logger from context.
func LoggerFromContext(ctx context.Context) *zap.Logger {
logger, ok := ctx.Value(ctxLogger{}).(*zap.Logger)
// LoggerFromContext extracts slog.Logger from context.
func LoggerFromContext(ctx context.Context) *slog.Logger {
logger, ok := ctx.Value(ctxLogger{}).(*slog.Logger)
if !ok {
return zap.NewNop()
return slog.New(slog.NewTextHandler(io.Discard, nil))
}

return logger
Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
module go.lsp.dev/protocol

go 1.22.2
go 1.23

require (
github.com/google/go-cmp v0.6.0
github.com/segmentio/encoding v0.4.0
go.lsp.dev/jsonrpc2 v0.10.0
go.lsp.dev/pkg v0.0.0-20210717090340-384b27a52fb2
go.lsp.dev/uri v0.3.0
go.uber.org/zap v1.27.0
)

require (
github.com/segmentio/asm v1.1.3 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 // indirect
)
14 changes: 0 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,30 +1,16 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/segmentio/asm v1.1.3 h1:WM03sfUOENvvKexOLp+pCqgb/WDjsi7EK8gIsICtzhc=
github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg=
github.com/segmentio/encoding v0.4.0 h1:MEBYvRqiUB2nfR2criEXWqwdY6HJOUrCn5hboVOVmy8=
github.com/segmentio/encoding v0.4.0/go.mod h1:/d03Cd8PoaDeceuhUUUQWjU0KhWjrmYrWPgtJHYZSnI=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
go.lsp.dev/jsonrpc2 v0.10.0 h1:Pr/YcXJoEOTMc/b6OTmcR1DPJ3mSWl/SWiU1Cct6VmI=
go.lsp.dev/jsonrpc2 v0.10.0/go.mod h1:fmEzIdXPi/rf6d4uFcayi8HpFP1nBF99ERP1htC72Ac=
go.lsp.dev/pkg v0.0.0-20210717090340-384b27a52fb2 h1:hCzQgh6UcwbKgNSRurYWSqh8MufqRRPODRBblutn4TE=
go.lsp.dev/pkg v0.0.0-20210717090340-384b27a52fb2/go.mod h1:gtSHRuYfbCT0qnbLnovpie/WEmqyJ7T4n6VXiFMBtcw=
go.lsp.dev/uri v0.3.0 h1:KcZJmh6nFIBeJzTugn5JTU6OOyG0lDOo3R9KwTxTYbo=
go.lsp.dev/uri v0.3.0/go.mod h1:P5sbO1IQR+qySTWOCnhnK7phBx+W3zbLqSMDJNTw88I=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
11 changes: 5 additions & 6 deletions protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ package protocol

import (
"context"

"go.uber.org/zap"
"log/slog"

"go.lsp.dev/jsonrpc2"
)

// NewServer returns the context in which client is embedded, jsonrpc2.Conn, and the Client.
func NewServer(ctx context.Context, server Server, stream jsonrpc2.Stream, logger *zap.Logger) (context.Context, jsonrpc2.Conn, Client) {
func NewServer(ctx context.Context, server Server, stream jsonrpc2.Stream, logger *slog.Logger) (context.Context, jsonrpc2.Conn, Client) {
conn := jsonrpc2.NewConn(stream)
cliint := ClientDispatcher(conn, logger.Named("client"))
cliint := ClientDispatcher(conn, logger.With("component", "client"))
ctx = WithClient(ctx, cliint)

conn.Go(ctx,
Expand All @@ -27,7 +26,7 @@ func NewServer(ctx context.Context, server Server, stream jsonrpc2.Stream, logge
}

// NewClient returns the context in which Client is embedded, jsonrpc2.Conn, and the Server.
func NewClient(ctx context.Context, client Client, stream jsonrpc2.Stream, logger *zap.Logger) (context.Context, jsonrpc2.Conn, Server) {
func NewClient(ctx context.Context, client Client, stream jsonrpc2.Stream, logger *slog.Logger) (context.Context, jsonrpc2.Conn, Server) {
ctx = WithClient(ctx, client)

conn := jsonrpc2.NewConn(stream)
Expand All @@ -36,7 +35,7 @@ func NewClient(ctx context.Context, client Client, stream jsonrpc2.Stream, logge
ClientHandler(client, jsonrpc2.MethodNotFoundHandler),
),
)
server := ServerDispatcher(conn, logger.Named("server"))
server := ServerDispatcher(conn, logger.With("component", "server"))

return ctx, conn, server
}
Loading