1 // Copyright 2020 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.
12 "golang.org/x/tools/internal/lsp/protocol"
15 // ClientHooks are called to handle the corresponding client LSP method.
16 type ClientHooks struct {
17 OnLogMessage func(context.Context, *protocol.LogMessageParams) error
18 OnDiagnostics func(context.Context, *protocol.PublishDiagnosticsParams) error
19 OnWorkDoneProgressCreate func(context.Context, *protocol.WorkDoneProgressCreateParams) error
20 OnProgress func(context.Context, *protocol.ProgressParams) error
21 OnShowMessage func(context.Context, *protocol.ShowMessageParams) error
22 OnShowMessageRequest func(context.Context, *protocol.ShowMessageRequestParams) error
23 OnRegistration func(context.Context, *protocol.RegistrationParams) error
24 OnUnregistration func(context.Context, *protocol.UnregistrationParams) error
27 // Client is an adapter that converts an *Editor into an LSP Client. It mosly
28 // delegates functionality to hooks that can be configured by tests.
34 func (c *Client) ShowMessage(ctx context.Context, params *protocol.ShowMessageParams) error {
35 if c.hooks.OnShowMessage != nil {
36 return c.hooks.OnShowMessage(ctx, params)
41 func (c *Client) ShowMessageRequest(ctx context.Context, params *protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error) {
42 if c.hooks.OnShowMessageRequest != nil {
43 if err := c.hooks.OnShowMessageRequest(ctx, params); err != nil {
47 if len(params.Actions) == 0 || len(params.Actions) > 1 {
48 return nil, fmt.Errorf("fake editor cannot handle multiple action items")
50 return ¶ms.Actions[0], nil
53 func (c *Client) LogMessage(ctx context.Context, params *protocol.LogMessageParams) error {
54 if c.hooks.OnLogMessage != nil {
55 return c.hooks.OnLogMessage(ctx, params)
60 func (c *Client) Event(ctx context.Context, event *interface{}) error {
64 func (c *Client) PublishDiagnostics(ctx context.Context, params *protocol.PublishDiagnosticsParams) error {
65 if c.hooks.OnDiagnostics != nil {
66 return c.hooks.OnDiagnostics(ctx, params)
71 func (c *Client) WorkspaceFolders(context.Context) ([]protocol.WorkspaceFolder, error) {
72 return []protocol.WorkspaceFolder{}, nil
75 func (c *Client) Configuration(_ context.Context, p *protocol.ParamConfiguration) ([]interface{}, error) {
76 results := make([]interface{}, len(p.Items))
77 for i, item := range p.Items {
78 if item.Section != "gopls" {
81 results[i] = c.editor.configuration()
86 func (c *Client) RegisterCapability(ctx context.Context, params *protocol.RegistrationParams) error {
87 if c.hooks.OnRegistration != nil {
88 return c.hooks.OnRegistration(ctx, params)
93 func (c *Client) UnregisterCapability(ctx context.Context, params *protocol.UnregistrationParams) error {
94 if c.hooks.OnUnregistration != nil {
95 return c.hooks.OnUnregistration(ctx, params)
100 func (c *Client) Progress(ctx context.Context, params *protocol.ProgressParams) error {
101 if c.hooks.OnProgress != nil {
102 return c.hooks.OnProgress(ctx, params)
107 func (c *Client) WorkDoneProgressCreate(ctx context.Context, params *protocol.WorkDoneProgressCreateParams) error {
108 if c.hooks.OnWorkDoneProgressCreate != nil {
109 return c.hooks.OnWorkDoneProgressCreate(ctx, params)
114 // ApplyEdit applies edits sent from the server.
115 func (c *Client) ApplyEdit(ctx context.Context, params *protocol.ApplyWorkspaceEditParams) (*protocol.ApplyWorkspaceEditResponse, error) {
116 if len(params.Edit.Changes) != 0 {
117 return &protocol.ApplyWorkspaceEditResponse{FailureReason: "Edit.Changes is unsupported"}, nil
119 for _, change := range params.Edit.DocumentChanges {
120 path := c.editor.sandbox.Workdir.URIToPath(change.TextDocument.URI)
121 edits := convertEdits(change.Edits)
122 if !c.editor.HasBuffer(path) {
123 err := c.editor.OpenFile(ctx, path)
124 if os.IsNotExist(err) {
125 c.editor.CreateBuffer(ctx, path, "")
132 if err := c.editor.EditBuffer(ctx, path, edits); err != nil {
136 return &protocol.ApplyWorkspaceEditResponse{Applied: true}, nil