Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/tools/gopls: support "go generate" via CodeLens #37680

Closed
marwan-at-work opened this issue Mar 5, 2020 · 4 comments
Closed

x/tools/gopls: support "go generate" via CodeLens #37680

marwan-at-work opened this issue Mar 5, 2020 · 4 comments
Assignees
Milestone

Comments

@marwan-at-work
Copy link
Contributor

@marwan-at-work marwan-at-work commented Mar 5, 2020

TL;DR:

It would be helpful if gopls recognized //go:generate directives in Go files and offered the option to run "go generate" from the editor through a CodeLens. Here's a demonstration video: https://vimeo.com/395630819

Motivation - feel free to skip if you are already convinced :)
Code generation is widely used in Go projects. The //go:generate command makes long and tedious commands much easier to execute by just running go generate or go generate ./....

However, whenever a programmer wants to regenerate the code, they end up doing some context switching from their editor to the terminal to regenerate the code.

Therefore, if the editor understood the //go:generate detective and offered to run go generate on the user's behalf, then the programmer can remain within the editor and not worry about switching contexts.

VSCode already does this with Go Test functions by giving you the option to run tests from within the UI. The "go generate" feature was actually requested for a few years in the VSCode extension but was never implemented: microsoft/vscode-go#263

Therefore, I think gopls is the right place to offer this functionality as the feature is very Go-specific.

Implementation question

The video above is from an initial implementation I wrote here: https://github.com/golang/tools/compare/master...marwan-at-work:gg?expand=1

The CodeLens part seems super straightforward. However, the moment we click on "go generate" and the client sends the command back to gopls, we need to show the stdout/stderr of "go generate" back to the client.

The one supported way I saw was using the $/progress server->client rpc which lets you show one message at a time. Each message shows as a progress bar on the bottom right in VSCode. However, would it be more appropriate to show this as a window instead of a progress bar?

If so, does the LSP provide a way to tell the editor to open a window and show a stream of logs?

In any case, if everyone is happy with this proposal, I'm happy to add tests and contribute the implementation above!

@gopherbot gopherbot added this to the Unreleased milestone Mar 5, 2020
@stamblerre
Copy link
Contributor

@stamblerre stamblerre commented Mar 5, 2020

Completely agree with the idea. We've had a similar issue opened here: #31817. I think the code lenses are a great starting point.

I'm not sure if LSP has that functionality, as we haven't used any of the in-progress RPC features. Let's experiment with what's currently available, and if something seems to be missing, we can open issues with the LSP specification.

Thanks for doing this work, @marwan-at-work! Looking forward to getting these features in gopls!

marwan-at-work added a commit to marwan-at-work/tools that referenced this issue Mar 6, 2020
This change adds support for recognizing a //go:generate directive
and offering a CodeLens that will then send a "generate" command to
the server to run "go generate" or "go generate ./...". Because
"go generate" can only be executed per package, there is no need to show
the CodeLens on top of every //go:generate comment. Therefore, only the
top directive will be considered.

The stdout/stderr of the go generate command will be piped to the logger
while stderr will also be sent to the editor as a $/progress notification.
Stderr in this case shows every command that go generate is running through
the "-x" flag so that the user can be aware of the work in progress.

Fixes golang/go#37680

Change-Id: I89a9617521eab20859cb2215db133f34fda856c7
@gopherbot
Copy link

@gopherbot gopherbot commented Mar 6, 2020

Change https://golang.org/cl/222247 mentions this issue: x/tools/gopls: run go generate through CodeLens

marwan-at-work added a commit to marwan-at-work/tools that referenced this issue Mar 11, 2020
This change adds support for recognizing a //go:generate directive
and offering a CodeLens that will then send a "generate" command to
the server to run "go generate" or "go generate ./...". Because
"go generate" can only be executed per package, there is no need to show
the CodeLens on top of every //go:generate comment. Therefore, only the
top directive will be considered.

The stdout/stderr of the go generate command will be piped to the logger
while stderr will also be sent to the editor as a $/progress notification
or a window/showMessage based on client capabilities.

In the case of $/progress, Stderr shows every command that go generate
is running through the "-x" flag so that the user can be aware of the
work in progress. While with window/showMessage, the user will only
know when the process starts and when it ends so that they wouldn't
get bogged with a large number of message windows popping up.

If a user wants to cancel the "go generate" command, they will be able
to do so with either the window/workDoneProgress/cancel request or with
a showMessageRequest ActionItem based on client capabilities.

Fixes golang/go#37680

Change-Id: I89a9617521eab20859cb2215db133f34fda856c7
@gopherbot
Copy link

@gopherbot gopherbot commented Mar 11, 2020

Change https://golang.org/cl/222981 mentions this issue: x/tools/gopls: add support for $/progress functionality

gopherbot pushed a commit to golang/tools that referenced this issue Mar 16, 2020
This CL adds support for sending progress notifications through $/progress
calls as well as being able to cancel them through window/workDoneProgress/cancel.
This feature is only supported in clients running LSP 3.15 and therefore the initialize
request will check for client capabilities for its progress support.

Updates golang/go#37680

Change-Id: Iff8c016694746a9dd553e5cc49444df7afcc21f5
Reviewed-on: https://go-review.googlesource.com/c/tools/+/222981
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
@gopherbot
Copy link

@gopherbot gopherbot commented Mar 17, 2020

Change https://golang.org/cl/223739 mentions this issue: x/tools/gopls: 'go generate' should use $/progress if available

gopherbot pushed a commit to golang/tools that referenced this issue Mar 17, 2020
This commit will make the 'go generate' CodeLens command check the client
capabilities to use $/progress to report the progress of the command or otherwise
it will fallback to showing the message box already in place. The $/progress will
give you a play by play update while the message box shows only the beginning and
the end. The gopls logs will have all the details in either case.

Note that the $/progress is an LSP 3.15+ feature and not yet supported in all clients.

Updates golang/go#37680

Change-Id: I5ba37448be8e388f728394795e1bb5f1d50cc30d
Reviewed-on: https://go-review.googlesource.com/c/tools/+/223739
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.