2020-08-07 13:52:01 -06:00
|
|
|
// Copyright 2020 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 lsp
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2020-08-17 20:50:34 -06:00
|
|
|
"sync"
|
2020-08-07 13:52:01 -06:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"golang.org/x/tools/internal/lsp/protocol"
|
|
|
|
)
|
|
|
|
|
|
|
|
type fakeClient struct {
|
|
|
|
protocol.Client
|
|
|
|
|
|
|
|
token protocol.ProgressToken
|
|
|
|
|
2020-08-17 20:50:34 -06:00
|
|
|
mu sync.Mutex
|
|
|
|
created, begun, reported, messages, ended int
|
2020-08-07 13:52:01 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *fakeClient) checkToken(token protocol.ProgressToken) {
|
|
|
|
if token == nil {
|
|
|
|
panic("nil token in progress message")
|
|
|
|
}
|
|
|
|
if c.token != nil && c.token != token {
|
|
|
|
panic(fmt.Errorf("invalid token in progress message: got %v, want %v", token, c.token))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *fakeClient) WorkDoneProgressCreate(ctx context.Context, params *protocol.WorkDoneProgressCreateParams) error {
|
2020-08-17 20:50:34 -06:00
|
|
|
c.mu.Lock()
|
|
|
|
defer c.mu.Unlock()
|
2020-08-07 13:52:01 -06:00
|
|
|
c.checkToken(params.Token)
|
|
|
|
c.created++
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *fakeClient) Progress(ctx context.Context, params *protocol.ProgressParams) error {
|
2020-08-17 20:50:34 -06:00
|
|
|
c.mu.Lock()
|
|
|
|
defer c.mu.Unlock()
|
2020-08-07 13:52:01 -06:00
|
|
|
c.checkToken(params.Token)
|
|
|
|
switch params.Value.(type) {
|
|
|
|
case *protocol.WorkDoneProgressBegin:
|
|
|
|
c.begun++
|
|
|
|
case *protocol.WorkDoneProgressReport:
|
|
|
|
c.reported++
|
|
|
|
case *protocol.WorkDoneProgressEnd:
|
|
|
|
c.ended++
|
|
|
|
default:
|
|
|
|
panic(fmt.Errorf("unknown progress value %T", params.Value))
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-08-17 20:50:34 -06:00
|
|
|
func (c *fakeClient) ShowMessage(context.Context, *protocol.ShowMessageParams) error {
|
|
|
|
c.mu.Lock()
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
c.messages++
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-08-07 13:52:01 -06:00
|
|
|
func setup(token protocol.ProgressToken) (context.Context, *progressTracker, *fakeClient) {
|
internal/lsp: improvements for command messages
When falling back to messages for progress reporting, don't try to
implement cancellation via ShowMessageCommand dialogs. They are an
imperfect solution, as the dialog stays open even after the command
completed. Also, among the LSP clients that don't support workDone
reporting, I suspect many also don't support ShowMessageCommand (for
example, govim), so the audience for this feature is probably quite
small.
Just remove it, and instead show a (non-cancellable) message. If clients
want cancellation, workDone progress support is the way to provide it.
Also remove a redundant message on go-generate success, and attach logs
when tests fail. Without logs on failure, I find that the test command
is not very useful. I tested a bit with very verbose test output, and
both VS Code and coc.nvim handled it gracefully.
Finally, fix a bug causing benchmarks not to be run.
Change-Id: I05422bcefc857c25cd99e643e614a0bc33870586
Reviewed-on: https://go-review.googlesource.com/c/tools/+/249702
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2020-08-21 12:18:37 -06:00
|
|
|
c := &fakeClient{}
|
2020-08-07 13:52:01 -06:00
|
|
|
tracker := newProgressTracker(c)
|
|
|
|
tracker.supportsWorkDoneProgress = true
|
|
|
|
return context.Background(), tracker, c
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestProgressTracker_Reporting(t *testing.T) {
|
|
|
|
for _, test := range []struct {
|
|
|
|
name string
|
|
|
|
supported bool
|
|
|
|
token protocol.ProgressToken
|
|
|
|
wantReported, wantCreated, wantBegun, wantEnded int
|
2020-08-17 20:50:34 -06:00
|
|
|
wantMessages int
|
2020-08-07 13:52:01 -06:00
|
|
|
}{
|
|
|
|
{
|
2020-08-17 20:50:34 -06:00
|
|
|
name: "unsupported",
|
internal/lsp: improvements for command messages
When falling back to messages for progress reporting, don't try to
implement cancellation via ShowMessageCommand dialogs. They are an
imperfect solution, as the dialog stays open even after the command
completed. Also, among the LSP clients that don't support workDone
reporting, I suspect many also don't support ShowMessageCommand (for
example, govim), so the audience for this feature is probably quite
small.
Just remove it, and instead show a (non-cancellable) message. If clients
want cancellation, workDone progress support is the way to provide it.
Also remove a redundant message on go-generate success, and attach logs
when tests fail. Without logs on failure, I find that the test command
is not very useful. I tested a bit with very verbose test output, and
both VS Code and coc.nvim handled it gracefully.
Finally, fix a bug causing benchmarks not to be run.
Change-Id: I05422bcefc857c25cd99e643e614a0bc33870586
Reviewed-on: https://go-review.googlesource.com/c/tools/+/249702
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2020-08-21 12:18:37 -06:00
|
|
|
wantMessages: 2,
|
2020-08-07 13:52:01 -06:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "random token",
|
|
|
|
supported: true,
|
|
|
|
wantCreated: 1,
|
|
|
|
wantBegun: 1,
|
|
|
|
wantReported: 1,
|
|
|
|
wantEnded: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "string token",
|
|
|
|
supported: true,
|
|
|
|
token: "token",
|
|
|
|
wantBegun: 1,
|
|
|
|
wantReported: 1,
|
|
|
|
wantEnded: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "numeric token",
|
|
|
|
supported: true,
|
|
|
|
token: 1,
|
|
|
|
wantReported: 1,
|
|
|
|
wantBegun: 1,
|
|
|
|
wantEnded: 1,
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
test := test
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
ctx, tracker, client := setup(test.token)
|
2020-08-17 20:50:34 -06:00
|
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
|
|
defer cancel()
|
2020-08-07 13:52:01 -06:00
|
|
|
tracker.supportsWorkDoneProgress = test.supported
|
|
|
|
work := tracker.start(ctx, "work", "message", test.token, nil)
|
2020-08-17 20:50:34 -06:00
|
|
|
client.mu.Lock()
|
|
|
|
gotCreated, gotBegun := client.created, client.begun
|
|
|
|
client.mu.Unlock()
|
|
|
|
if gotCreated != test.wantCreated {
|
|
|
|
t.Errorf("got %d created tokens, want %d", gotCreated, test.wantCreated)
|
2020-08-07 13:52:01 -06:00
|
|
|
}
|
2020-08-17 20:50:34 -06:00
|
|
|
if gotBegun != test.wantBegun {
|
|
|
|
t.Errorf("got %d work begun, want %d", gotBegun, test.wantBegun)
|
2020-08-07 13:52:01 -06:00
|
|
|
}
|
|
|
|
// Ignore errors: this is just testing the reporting behavior.
|
2020-08-17 20:50:34 -06:00
|
|
|
work.report("report", 50)
|
|
|
|
client.mu.Lock()
|
|
|
|
gotReported := client.reported
|
|
|
|
client.mu.Unlock()
|
|
|
|
if gotReported != test.wantReported {
|
|
|
|
t.Errorf("got %d progress reports, want %d", gotReported, test.wantCreated)
|
2020-08-07 13:52:01 -06:00
|
|
|
}
|
2020-08-17 20:50:34 -06:00
|
|
|
work.end("done")
|
|
|
|
client.mu.Lock()
|
|
|
|
gotEnded, gotMessages := client.ended, client.messages
|
|
|
|
client.mu.Unlock()
|
|
|
|
if gotEnded != test.wantEnded {
|
|
|
|
t.Errorf("got %d ended reports, want %d", gotEnded, test.wantEnded)
|
|
|
|
}
|
|
|
|
if gotMessages != test.wantMessages {
|
|
|
|
t.Errorf("got %d messages, want %d", gotMessages, test.wantMessages)
|
2020-08-07 13:52:01 -06:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestProgressTracker_Cancellation(t *testing.T) {
|
|
|
|
for _, token := range []protocol.ProgressToken{nil, 1, "a"} {
|
|
|
|
ctx, tracker, _ := setup(token)
|
2020-08-17 20:50:34 -06:00
|
|
|
var canceled bool
|
|
|
|
cancel := func() { canceled = true }
|
2020-08-07 13:52:01 -06:00
|
|
|
work := tracker.start(ctx, "work", "message", token, cancel)
|
|
|
|
if err := tracker.cancel(ctx, work.token); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2020-08-17 20:50:34 -06:00
|
|
|
if !canceled {
|
2020-08-07 13:52:01 -06:00
|
|
|
t.Errorf("tracker.cancel(...): cancel not called")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|