Subject: bug#62116: RFE: eglot: support window.showDocument LSP RPC

From: Alan Donovan <[email-masked]>
Date: Fri, 5 May 2023 13:35:49 -0400

On Fri, 5 May 2023 at 13:17, João Távora <[email-masked]> wrote:
> Yes, but I don't really think this is a design problem with gopls.  Or
> at least I don't think Eglot should not make these nested calls in the
> first place.  So I would like to understand how this nested RPC requests
> takes place.  From my reading of the eglot.el's code, there aren't any -- that
> is, with Emacs -Q -- at least.
>
> So I would like to reproduce this situation to analyse what can be done.
>
> I have gopls on my archlinux machine, though I seldom program in Go.
> How does one go about setting up gopls in terms of workspace
> configuration, command line options, etc so that the feature is
> exercised?  Also, can I somehow make use of this feature with any small
> hello world project or do I need something bigger?  In that case can you
> point me to a git repository that I can download, or attach that
> project?

Sure. You can reproduce the experimental setup like so:

1. git clone golang.org/x/tools

2. Download and checkout this commit:
https://go-review.git.corp.google.com/c/tools/+/474735
(It's a stack of 2 messy CLs on top of an old master, but it works.)

3. (cd gopls && go install)
This puts gopls on your $PATH.

4. killall gopls
So that eglot uses the new executable.

5. Load the definition of the eglot-handle-request window/showDocument handler.

6. Also load this function.
(defun gopls--package-docs ()
  "Open the documentation for this Go package in a browser."
  (interactive)
  (save-excursion
    ;; TODO(adonovan): We currently cram this functionality into the
    ;; textDocument/definition RPC applied to the "package" keyword.
    ;; Do something more principled.
    (goto-char 0)
    (re-search-forward "^package ")
    (beginning-of-line)
    (xref-find-definitions 'package)))

7. Visit a Go file, e.g. go/analysis/analysis.go. Move cursor to the
"package" keyword.

8. Run the gopls--package-docs command. This sends an "definitions"
RPC request for the package keyword. The server has been modified to
interpret this as a (strange) request to open a web page of package
documentation. The server sends a showDocument request
(http://localhost...) to the client. The client handler
eglot-handle-request opens a browser. You should see a page full of
links to source declarations.

9. Click on one of these links. This causes the web server (gopls) to
send another showDocument request, this time for file://..., to the
client, which causes gopls to open the file containing the declaration
and move to the correct position.

Removing the asynchrony causes the file:// downcall to get stuck
because it makes an upcall to gopls while the server is still waiting
for the showDocument downcall to finish.

> My main curiosity is where does this "click" happen in the first
> place...  (that's related to my lack of hands-on experience with this
> feature, as described above)

See above.

> >> 2. if browse-url should be used for non-file: urls (it might open a browser window outside of Emacs, which IMO is fine.)
> >
> > What's the alternative? The very purpose of the operation is to open a
> > URL in a browser.
>
> Not always, IIUC.  Sometimes it's just to open a file.

I think "file:" URLs should be opened by find-file in Emacs, and all
other URLs should go to browse-url (and thence Chrome, etc).

cheers
alan