mirror of
https://github.com/golang/go
synced 2024-11-19 03:34:41 -07:00
5d16bdd7b5
Also use it for errors that were otherwise silently dropped This makes it much easier to debug problems. Also added command line control over whether the rpc trace messages are printed, which allows you to read the log, otherwise the file edit messages swamp the log. Change-Id: I7b70fd18034a87b2964e6d6d5f6f33dcaf7d8ea8 Reviewed-on: https://go-review.googlesource.com/c/tools/+/170178 Reviewed-by: Rebecca Stambler <rstambler@golang.org>
209 lines
6.5 KiB
Go
209 lines
6.5 KiB
Go
// Copyright 2018 The Go 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 (
|
|
"context"
|
|
"encoding/json"
|
|
|
|
"golang.org/x/tools/internal/jsonrpc2"
|
|
"golang.org/x/tools/internal/lsp/xlog"
|
|
)
|
|
|
|
type Client interface {
|
|
ShowMessage(context.Context, *ShowMessageParams) error
|
|
ShowMessageRequest(context.Context, *ShowMessageRequestParams) (*MessageActionItem, error)
|
|
LogMessage(context.Context, *LogMessageParams) error
|
|
Telemetry(context.Context, interface{}) error
|
|
RegisterCapability(context.Context, *RegistrationParams) error
|
|
UnregisterCapability(context.Context, *UnregistrationParams) error
|
|
WorkspaceFolders(context.Context) ([]WorkspaceFolder, error)
|
|
Configuration(context.Context, *ConfigurationParams) ([]interface{}, error)
|
|
ApplyEdit(context.Context, *ApplyWorkspaceEditParams) (bool, error)
|
|
PublishDiagnostics(context.Context, *PublishDiagnosticsParams) error
|
|
}
|
|
|
|
func clientHandler(log xlog.Logger, client Client) jsonrpc2.Handler {
|
|
return func(ctx context.Context, conn *jsonrpc2.Conn, r *jsonrpc2.Request) {
|
|
switch r.Method {
|
|
case "$/cancelRequest":
|
|
var params CancelParams
|
|
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
|
sendParseError(ctx, log, conn, r, err)
|
|
return
|
|
}
|
|
conn.Cancel(params.ID)
|
|
|
|
case "window/showMessage":
|
|
var params ShowMessageParams
|
|
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
|
sendParseError(ctx, log, conn, r, err)
|
|
return
|
|
}
|
|
if err := client.ShowMessage(ctx, ¶ms); err != nil {
|
|
log.Errorf(ctx, "%v", err)
|
|
}
|
|
|
|
case "window/showMessageRequest":
|
|
var params ShowMessageRequestParams
|
|
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
|
sendParseError(ctx, log, conn, r, err)
|
|
return
|
|
}
|
|
resp, err := client.ShowMessageRequest(ctx, ¶ms)
|
|
if err := conn.Reply(ctx, r, resp, err); err != nil {
|
|
log.Errorf(ctx, "%v", err)
|
|
}
|
|
|
|
case "window/logMessage":
|
|
var params LogMessageParams
|
|
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
|
sendParseError(ctx, log, conn, r, err)
|
|
return
|
|
}
|
|
if err := client.LogMessage(ctx, ¶ms); err != nil {
|
|
log.Errorf(ctx, "%v", err)
|
|
}
|
|
|
|
case "telemetry/event":
|
|
var params interface{}
|
|
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
|
sendParseError(ctx, log, conn, r, err)
|
|
return
|
|
}
|
|
if err := client.Telemetry(ctx, ¶ms); err != nil {
|
|
log.Errorf(ctx, "%v", err)
|
|
}
|
|
|
|
case "client/registerCapability":
|
|
var params RegistrationParams
|
|
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
|
sendParseError(ctx, log, conn, r, err)
|
|
return
|
|
}
|
|
if err := client.RegisterCapability(ctx, ¶ms); err != nil {
|
|
log.Errorf(ctx, "%v", err)
|
|
}
|
|
|
|
case "client/unregisterCapability":
|
|
var params UnregistrationParams
|
|
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
|
sendParseError(ctx, log, conn, r, err)
|
|
return
|
|
}
|
|
if err := client.UnregisterCapability(ctx, ¶ms); err != nil {
|
|
log.Errorf(ctx, "%v", err)
|
|
}
|
|
|
|
case "workspace/workspaceFolders":
|
|
if r.Params != nil {
|
|
conn.Reply(ctx, r, nil, jsonrpc2.NewErrorf(jsonrpc2.CodeInvalidParams, "Expected no params"))
|
|
return
|
|
}
|
|
resp, err := client.WorkspaceFolders(ctx)
|
|
if err := conn.Reply(ctx, r, resp, err); err != nil {
|
|
log.Errorf(ctx, "%v", err)
|
|
}
|
|
|
|
case "workspace/configuration":
|
|
var params ConfigurationParams
|
|
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
|
sendParseError(ctx, log, conn, r, err)
|
|
return
|
|
}
|
|
resp, err := client.Configuration(ctx, ¶ms)
|
|
if err := conn.Reply(ctx, r, resp, err); err != nil {
|
|
log.Errorf(ctx, "%v", err)
|
|
}
|
|
|
|
case "workspace/applyEdit":
|
|
var params ApplyWorkspaceEditParams
|
|
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
|
sendParseError(ctx, log, conn, r, err)
|
|
return
|
|
}
|
|
resp, err := client.ApplyEdit(ctx, ¶ms)
|
|
if err := conn.Reply(ctx, r, resp, err); err != nil {
|
|
log.Errorf(ctx, "%v", err)
|
|
}
|
|
|
|
case "textDocument/publishDiagnostics":
|
|
var params PublishDiagnosticsParams
|
|
if err := json.Unmarshal(*r.Params, ¶ms); err != nil {
|
|
sendParseError(ctx, log, conn, r, err)
|
|
return
|
|
}
|
|
if err := client.PublishDiagnostics(ctx, ¶ms); err != nil {
|
|
log.Errorf(ctx, "%v", err)
|
|
}
|
|
|
|
default:
|
|
if r.IsNotify() {
|
|
conn.Reply(ctx, r, nil, jsonrpc2.NewErrorf(jsonrpc2.CodeMethodNotFound, "method %q not found", r.Method))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
type clientDispatcher struct {
|
|
*jsonrpc2.Conn
|
|
}
|
|
|
|
func (c *clientDispatcher) ShowMessage(ctx context.Context, params *ShowMessageParams) error {
|
|
return c.Conn.Notify(ctx, "window/showMessage", params)
|
|
}
|
|
|
|
func (c *clientDispatcher) ShowMessageRequest(ctx context.Context, params *ShowMessageRequestParams) (*MessageActionItem, error) {
|
|
var result MessageActionItem
|
|
if err := c.Conn.Call(ctx, "window/showMessageRequest", params, &result); err != nil {
|
|
return nil, err
|
|
}
|
|
return &result, nil
|
|
}
|
|
|
|
func (c *clientDispatcher) LogMessage(ctx context.Context, params *LogMessageParams) error {
|
|
return c.Conn.Notify(ctx, "window/logMessage", params)
|
|
}
|
|
|
|
func (c *clientDispatcher) Telemetry(ctx context.Context, params interface{}) error {
|
|
return c.Conn.Notify(ctx, "telemetry/event", params)
|
|
}
|
|
|
|
func (c *clientDispatcher) RegisterCapability(ctx context.Context, params *RegistrationParams) error {
|
|
return c.Conn.Notify(ctx, "client/registerCapability", params)
|
|
}
|
|
|
|
func (c *clientDispatcher) UnregisterCapability(ctx context.Context, params *UnregistrationParams) error {
|
|
return c.Conn.Notify(ctx, "client/unregisterCapability", params)
|
|
}
|
|
|
|
func (c *clientDispatcher) WorkspaceFolders(ctx context.Context) ([]WorkspaceFolder, error) {
|
|
var result []WorkspaceFolder
|
|
if err := c.Conn.Call(ctx, "workspace/workspaceFolders", nil, &result); err != nil {
|
|
return nil, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (c *clientDispatcher) Configuration(ctx context.Context, params *ConfigurationParams) ([]interface{}, error) {
|
|
var result []interface{}
|
|
if err := c.Conn.Call(ctx, "workspace/configuration", params, &result); err != nil {
|
|
return nil, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (c *clientDispatcher) ApplyEdit(ctx context.Context, params *ApplyWorkspaceEditParams) (bool, error) {
|
|
var result bool
|
|
if err := c.Conn.Call(ctx, "workspace/applyEdit", params, &result); err != nil {
|
|
return false, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (c *clientDispatcher) PublishDiagnostics(ctx context.Context, params *PublishDiagnosticsParams) error {
|
|
return c.Conn.Notify(ctx, "textDocument/publishDiagnostics", params)
|
|
}
|