mirror of
https://github.com/golang/go
synced 2024-11-06 02:16:10 -07:00
9938a07982
Our current usage of WorkDone progress reporting (new in v3.15 of the LSP spec) is in reporting progress on `go generate` commands. In preparation for using this API more widely, factor out the reporting API from the current io.WriteCloser wrapper (workDoneWriter). Change-Id: Ib528093d81d4fc065528df90e100859e850b10df Reviewed-on: https://go-review.googlesource.com/c/tools/+/229459 Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
124 lines
3.3 KiB
Go
124 lines
3.3 KiB
Go
// 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"
|
|
"errors"
|
|
"math/rand"
|
|
"strconv"
|
|
|
|
"golang.org/x/tools/internal/event"
|
|
"golang.org/x/tools/internal/lsp/protocol"
|
|
)
|
|
|
|
// WorkDone represents a unit of work that is reported to the client via the
|
|
// progress API.
|
|
type WorkDone struct {
|
|
client protocol.Client
|
|
startErr error
|
|
token string
|
|
cancel func()
|
|
cleanup func()
|
|
}
|
|
|
|
// StartWork creates a unique token and issues a $/progress notification to
|
|
// begin a unit of work on the server. The returned WorkDone handle may be used
|
|
// to report incremental progress, and to report work completion. In
|
|
// particular, it is an error to call StartWork and not call End(...) on the
|
|
// returned WorkDone handle.
|
|
//
|
|
// The progress item is considered cancellable if the given cancel func is
|
|
// non-nil.
|
|
//
|
|
// Example:
|
|
// func Generate(ctx) (err error) {
|
|
// ctx, cancel := context.WithCancel(ctx)
|
|
// defer cancel()
|
|
// work := s.StartWork(ctx, "generate", "running go generate", cancel)
|
|
// defer func() {
|
|
// if err != nil {
|
|
// work.End(ctx, fmt.Sprintf("generate failed: %v", err))
|
|
// } else {
|
|
// work.End(ctx, "done")
|
|
// }
|
|
// }()
|
|
// // Do the work...
|
|
// }
|
|
//
|
|
func (s *Server) StartWork(ctx context.Context, title, message string, cancel func()) *WorkDone {
|
|
wd := &WorkDone{
|
|
client: s.client,
|
|
token: strconv.FormatInt(rand.Int63(), 10),
|
|
cancel: cancel,
|
|
}
|
|
if !s.supportsWorkDoneProgress {
|
|
wd.startErr = errors.New("workdone reporting is not supported")
|
|
return wd
|
|
}
|
|
err := wd.client.WorkDoneProgressCreate(ctx, &protocol.WorkDoneProgressCreateParams{
|
|
Token: wd.token,
|
|
})
|
|
if err != nil {
|
|
wd.startErr = err
|
|
event.Error(ctx, "starting work for "+title, err)
|
|
return wd
|
|
}
|
|
s.addInProgress(wd)
|
|
wd.cleanup = func() {
|
|
s.removeInProgress(wd.token)
|
|
}
|
|
err = wd.client.Progress(ctx, &protocol.ProgressParams{
|
|
Token: wd.token,
|
|
Value: &protocol.WorkDoneProgressBegin{
|
|
Kind: "begin",
|
|
Cancellable: wd.cancel != nil,
|
|
Message: message,
|
|
Title: title,
|
|
},
|
|
})
|
|
if err != nil {
|
|
event.Error(ctx, "generate progress begin", err)
|
|
}
|
|
return wd
|
|
}
|
|
|
|
// Progress reports an update on WorkDone progress back to the client.
|
|
func (wd *WorkDone) Progress(ctx context.Context, message string, percentage float64) error {
|
|
if wd.startErr != nil {
|
|
return wd.startErr
|
|
}
|
|
return wd.client.Progress(ctx, &protocol.ProgressParams{
|
|
Token: wd.token,
|
|
Value: &protocol.WorkDoneProgressReport{
|
|
Kind: "report",
|
|
// Note that in the LSP spec, the value of Cancellable may be changed to
|
|
// control whether the cancel button in the UI is enabled. Since we don't
|
|
// yet use this feature, the value is kept constant here.
|
|
Cancellable: wd.cancel != nil,
|
|
Message: message,
|
|
Percentage: percentage,
|
|
},
|
|
})
|
|
}
|
|
|
|
// End reports a workdone completion back to the client.
|
|
func (wd *WorkDone) End(ctx context.Context, message string) error {
|
|
if wd.startErr != nil {
|
|
return wd.startErr
|
|
}
|
|
err := wd.client.Progress(ctx, &protocol.ProgressParams{
|
|
Token: wd.token,
|
|
Value: protocol.WorkDoneProgressEnd{
|
|
Kind: "end",
|
|
Message: message,
|
|
},
|
|
})
|
|
if wd.cleanup != nil {
|
|
wd.cleanup()
|
|
}
|
|
return err
|
|
}
|