Skip to content

Commit

Permalink
all: support go-language-server/[email protected] interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
zchee committed Feb 12, 2020
1 parent acb4cc5 commit 18652be
Show file tree
Hide file tree
Showing 13 changed files with 1,383 additions and 1,137 deletions.
2 changes: 1 addition & 1 deletion .errcheckignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
(*github.com/go-language-server/jsonrpc2.Conn).Reply
(*github.com/go-language-server/jsonrpc2.Request).Reply
(*github.com/go-language-server/jsonrpc2.Conn).Notify
73 changes: 73 additions & 0 deletions canceller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright 2020 The go-language-server Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package protocol

import (
"bytes"
"context"
"encoding/json"

"github.com/go-language-server/jsonrpc2"
"go.uber.org/zap"
)

// RequestCancelledError should be used when a request is canceled early.
const RequestCancelledError jsonrpc2.Code = -32800

type canceller struct {
logger *zap.Logger
}

// compile time check whether the canceller implements jsonrpc2.Handler interface.
var _ jsonrpc2.Handler = (*canceller)(nil)

// Deliver implements Handler interface.
func (canceller) Deliver(ctx context.Context, r *jsonrpc2.Request, delivered bool) bool {
// Hide cancellations from downstream handlers.
return r.Method == MethodCancelRequest
}

// Cancel implements Handler interface.
func (canceller) Cancel(ctx context.Context, conn *jsonrpc2.Conn, id jsonrpc2.ID, canceled bool) bool {
if canceled {
return false
}

conn.Notify(ctx, MethodCancelRequest, &CancelParams{ID: id})
return true
}

// Request implements Handler interface.
func (c *canceller) Request(ctx context.Context, conn *jsonrpc2.Conn, direction jsonrpc2.Direction, r *jsonrpc2.WireRequest) context.Context {
if direction == jsonrpc2.Receive && r.Method == MethodCancelRequest {
dec := json.NewDecoder(bytes.NewReader(*r.Params))
var params CancelParams
if err := dec.Decode(&params); err != nil {
c.logger.Error("Request", zap.Error(err))
return ctx
}

conn.Cancel(params.ID)
}

return ctx
}

// Response implements Handler interface.
func (canceller) Response(ctx context.Context, conn *jsonrpc2.Conn, direction jsonrpc2.Direction, r *jsonrpc2.WireResponse) context.Context {
return ctx
}

// Done implements Handler interface.
func (canceller) Done(ctx context.Context, err error) {}

// Read implements Handler interface.
func (canceller) Read(ctx context.Context, n int64) context.Context { return ctx }

// Write implements Handler interface.
func (canceller) Write(ctx context.Context, n int64) context.Context { return ctx }

// Error implements Handler interface.
func (canceller) Error(ctx context.Context, err error) {}
63 changes: 49 additions & 14 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,41 @@ import (
"go.uber.org/zap"
)

// clientHandler represents a client handler.
type clientHandler struct {
client ClientInterface
}

// compile time check whether the clientHandler implements jsonrpc2.Handler interface.
var _ jsonrpc2.Handler = &clientHandler{}

// Cancel implements Handler interface.
func (clientHandler) Cancel(ctx context.Context, conn *jsonrpc2.Conn, id jsonrpc2.ID, canceled bool) bool {
return false
}

// Request implements Handler interface.
func (clientHandler) Request(ctx context.Context, conn *jsonrpc2.Conn, direction jsonrpc2.Direction, r *jsonrpc2.WireRequest) context.Context {
return ctx
}

// Response implements Handler interface.
func (clientHandler) Response(ctx context.Context, conn *jsonrpc2.Conn, direction jsonrpc2.Direction, r *jsonrpc2.WireResponse) context.Context {
return ctx
}

// Done implements Handler interface.
func (clientHandler) Done(ctx context.Context, err error) {}

// Read implements Handler interface.
func (clientHandler) Read(ctx context.Context, bytes int64) context.Context { return ctx }

// Write implements Handler interface.
func (clientHandler) Write(ctx context.Context, bytes int64) context.Context { return ctx }

// Error implements Handler interface.
func (clientHandler) Error(ctx context.Context, err error) {}

// ClientInterface represents a Language Server Protocol client.
type ClientInterface interface {
Run(ctx context.Context) (err error)
Expand Down Expand Up @@ -58,23 +93,23 @@ const (
MethodWorkspaceWorkspaceFolders = "workspace/workspaceFolders"
)

// Client implements a Language Server Protocol client.
type Client struct {
// client implements a Language Server Protocol client.
type client struct {
*jsonrpc2.Conn
logger *zap.Logger
}

// compiler time check whether the Client implements ClientInterface interface.
var _ ClientInterface = (*Client)(nil)
var _ ClientInterface = (*client)(nil)

// Run runs the Language Server Protocol client.
func (c *Client) Run(ctx context.Context) (err error) {
func (c *client) Run(ctx context.Context) (err error) {
err = c.Conn.Run(ctx)
return
}

// 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) {
func (c *client) LogMessage(ctx context.Context, params *LogMessageParams) (err error) {
err = c.Conn.Notify(ctx, MethodWindowLogMessage, params)
return
}
Expand All @@ -89,30 +124,30 @@ func (c *Client) LogMessage(ctx context.Context, params *LogMessageParams) (err
// When a file changes it is the server’s responsibility to re-compute diagnostics and push them to the client.
// If the computed set is empty it has to push the empty array to clear former diagnostics.
// 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) {
func (c *client) PublishDiagnostics(ctx context.Context, params *PublishDiagnosticsParams) (err error) {
err = c.Conn.Notify(ctx, MethodTextDocumentPublishDiagnostics, params)
return
}

// ShowMessage sends the notification from a server to a client to ask the
// client to display a particular message in the user interface.
func (c *Client) ShowMessage(ctx context.Context, params *ShowMessageParams) (err error) {
func (c *client) ShowMessage(ctx context.Context, params *ShowMessageParams) (err error) {
err = c.Conn.Notify(ctx, MethodWindowShowMessage, params)
return
}

// ShowMessageRequest sends the request from a server to a client to ask the client to display a particular message in the user interface.
//
// 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) (result *MessageActionItem, err error) {
func (c *client) ShowMessageRequest(ctx context.Context, params *ShowMessageRequestParams) (result *MessageActionItem, err error) {
result = new(MessageActionItem)
err = c.Conn.Call(ctx, MethodWindowShowMessageRequest, params, result)

return result, err
}

// 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) {
func (c *client) Telemetry(ctx context.Context, params interface{}) (err error) {
err = c.Conn.Notify(ctx, MethodTelemetryEvent, params)
return
}
Expand All @@ -123,19 +158,19 @@ func (c *Client) Telemetry(ctx context.Context, params interface{}) (err error)
//
// A client opts in via the dynamicRegistration property on the specific client capabilities.
// 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) {
func (c *client) RegisterCapability(ctx context.Context, params *RegistrationParams) (err error) {
err = c.Conn.Call(ctx, MethodClientRegisterCapability, params, nil)
return
}

// 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) {
func (c *client) UnregisterCapability(ctx context.Context, params *UnregistrationParams) (err error) {
err = c.Conn.Call(ctx, MethodClientUnregisterCapability, params, nil)
return
}

// WorkspaceApplyEdit sends the request from the server to the client to modify resource on the client side.
func (c *Client) WorkspaceApplyEdit(ctx context.Context, params *ApplyWorkspaceEditParams) (result bool, err error) {
func (c *client) WorkspaceApplyEdit(ctx context.Context, params *ApplyWorkspaceEditParams) (result bool, err error) {
err = c.Conn.Call(ctx, MethodWorkspaceApplyEdit, params, &result)

return result, err
Expand All @@ -146,7 +181,7 @@ func (c *Client) WorkspaceApplyEdit(ctx context.Context, params *ApplyWorkspaceE
// The request can fetch several configuration settings in one roundtrip.
// The order of the returned configuration settings correspond to the order of the
// passed ConfigurationItems (e.g. the first item in the response is the result for the first configuration item in the params).
func (c *Client) WorkspaceConfiguration(ctx context.Context, params *ConfigurationParams) ([]interface{}, error) {
func (c *client) WorkspaceConfiguration(ctx context.Context, params *ConfigurationParams) ([]interface{}, error) {
var result []interface{}
err := c.Conn.Call(ctx, MethodWorkspaceConfiguration, params, &result)

Expand All @@ -158,7 +193,7 @@ func (c *Client) WorkspaceConfiguration(ctx context.Context, params *Configurati
// Returns null in the response if only a single file is open in the tool. Returns an empty array if a workspace is open but no folders are configured.
//
// Since version 3.6.0.
func (c *Client) WorkspaceFolders(ctx context.Context) (result []WorkspaceFolder, err error) {
func (c *client) WorkspaceFolders(ctx context.Context) (result []WorkspaceFolder, err error) {
err = c.Conn.Call(ctx, MethodWorkspaceWorkspaceFolders, nil, &result)

return result, err
Expand Down
Loading

0 comments on commit 18652be

Please sign in to comment.