joaotavora / eglot

A client for Language Server Protocol servers
GNU General Public License v3.0
2.25k stars 200 forks source link

gopls reporting is delayed when `flymake-no-changes-timeout` is set to nil #1296

Open ipvych opened 1 year ago

ipvych commented 1 year ago

Steps to reproduce

;; download dependencies to file-system (shell-command "git clone --depth=1 https://github.com/joaotavora/eglot") (shell-command "git clone --depth=1 https://github.com/dominikh/go-mode.el go-mode")

;; add packages to load-path (add-to-list 'load-path "~/eglot") (add-to-list 'load-path "~/go-mode")

(require 'go-mode) (require 'eglot) (add-hook 'go-mode-hook #'eglot-ensure) (setq flymake-no-changes-timeout nil)

(make-directory "~/repr" t) (find-file "~/repr/test.go") (insert " package main import \"fmt\" func main() { fmt.Println(\"test\") }") (save-buffer)

- Run `emacs -Q -l ~/mre.el`
- Add or remove comment from `fmt.Println` statement and save buffer - flymake diagnostic will be outdated and contain diagnostic from previous save.

Contents of `M-x eglot-events-buffer`: https://gist.github.com/ipvych/391ac3103e168b9d0ae75f8322191fa9
# System information
- `(emacs-build-description)`:

In GNU Emacs 29.1 (build 1, x86_64-pc-linux-gnu, X toolkit, cairo version 1.16.0, Xaw3d scroll bars) Windowing system distributor 'The X.Org Foundation', version 11.0.12101008 System Description: NixOS 23.11 (Tapir)

Configured using: 'configure --prefix=/nix/store/956mdihpqbh2x1bm75xw80zjksgsbpgn-emacs-29.1 --disable-build-details --with-modules --with-x-toolkit=lucid --with-xft --with-cairo --with-native-compilation --with-tree-sitter --with-xinput2'

- `gopls version`:

golang.org/x/tools/gopls v0.13.2 golang.org/x/tools/gopls@v0.13.2 h1:Pyvx6MKvatbX3zzZmdGiFRfQZl0ohPlt2sFxO/5j6Ro=

joaotavora commented 1 year ago

ACK. There's not much to do here, except recommending you don't do this customization for Eglot.

When the buffer is saved, Flymake asks for diagnostics, and at that time, the server hasn't yet published the notification that says there are no diagnostics at all. According to the LSP spec, it can take all the time in the world for that.

There is now a "pull diagnostics" specification in LSP that would presumably fix this, but Eglot does not yet support this feature.

Maybe this 100% untested hack will work for you:

(cl-defmethod eglot-handle-notification :after
  (_server (_method (eql textDocument/publishDiagnostics)) &key uri
           &allow-other-keys)
  (when-let ((buffer (find-buffer-visiting (eglot-uri-to-path uri))))
    (with-current-buffer buffer
      (if (and (eq nil flymake-no-changes-timeout)
               (not (buffer-modified-p)))
          (flymake-start t)))))