Subject: 28.2; eglot overrides imenu without fallback even when unsupported by server

From: Phil Hagelberg <[email-masked]>
Date: Sat, 09 Mar 2024 23:19:25 +0000

When invoking M-x imenu in a buffer with eglot enabled, it uses eglot's
LSP-aware implementation of imenu. However, not all LSP servers handle
that functionality. When connected to a server that does not offer this
functionality, eglot signals an error:

  jsonrpc-error: "request id=11 failed:", (jsonrpc-error-code . -32601), (jsonrpc-error-message . "\"textDocument/documentSymbol\" is not in the request-handlers table"), (jsonrpc-error-data)

However, usually there is a perfectly good functional imenu
implementation that the user wants to invoke; they just can't do it
because eglot took over the imenu command.

Ideally eglot should only add its functionality to the imenu command
when it's connected to a server that actually supports the endpoint
needed to handle it.

You can reproduce this problem with fennel-mode and fennel-ls.

* Install fennel-mode: https://git.sr.ht/~technomancy/fennel-mode
  Cloning and running M-x eval-buffer on fennel-mode.el is sufficient.

* Install fennel-ls: https://git.sr.ht/~xerool/fennel-ls
  Clone and run `make install PREFIX=$WHATEVER', then evaluate this:
  (with-eval-after-load 'eglot
    (add-to-list 'eglot-server-programs '(fennel-mode . ("fennel-ls"))))

* Open a new file, say /tmp/scratch.fnl and insert: (fn abc [])

* Run M-x imenu, and see the error.

* Run M-x eglot-shutdown.

* Run M-x imenu, and it succeeds.

I'm sure you could reproduce the same problem in another language where
the Emacs mode supports imenu but the language server doesn't. But I
don't know what other language fits that criteria.

In GNU Emacs 28.2 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.37, cairo version 1.16.0)
 of 2023-05-14, modified by Debian built on x86-ubc-01
Windowing system distributor 'The X.Org Foundation', version 11.0.12101007
System Description: Debian GNU/Linux 12 (bookworm)

Configured using:
 'configure --build x86_64-linux-gnu --prefix=/usr
 --sharedstatedir=/var/lib --libexecdir=/usr/libexec
 --localstatedir=/var/lib --infodir=/usr/share/info
 --mandir=/usr/share/man --with-libsystemd --with-pop=yes
 --enable-locallisppath=/etc/emacs:/usr/local/share/emacs/28.2/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/28.2/site-lisp:/usr/share/emacs/site-lisp
 --with-sound=alsa --without-gconf --with-mailutils
 --with-native-compilation --build x86_64-linux-gnu --prefix=/usr
 --sharedstatedir=/var/lib --libexecdir=/usr/libexec
 --localstatedir=/var/lib --infodir=/usr/share/info
 --mandir=/usr/share/man --with-libsystemd --with-pop=yes
 --enable-locallisppath=/etc/emacs:/usr/local/share/emacs/28.2/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/28.2/site-lisp:/usr/share/emacs/site-lisp
 --with-sound=alsa --without-gconf --with-mailutils
 --with-native-compilation --with-cairo --with-x=yes
 --with-x-toolkit=gtk3 --with-toolkit-scroll-bars 'CFLAGS=-g -O2
 -ffile-prefix-map=/build/emacs-mPr7Vr/emacs-28.2+1=. -fstack-protector-strong
 -Wformat -Werror=format-security -Wall' 'CPPFLAGS=-Wdate-time
 -D_FORTIFY_SOURCE=2' LDFLAGS=-Wl,-z,relro'

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG
JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES
NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND THREADS TIFF
TOOLKIT_SCROLL_BARS X11 XDBE XIM XPM GTK3 ZLIB

Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Fennel

Minor modes in effect:
  recentf-mode: t
  eglot--managed-mode: t
  flymake-mode: t
  paredit-mode: t
  whitespace-mode: t
  idle-highlight-mode: t
  hl-line-mode: t
  company-mode: t
  shell-dirtrack-mode: t
  winner-mode: t
  display-battery-mode: t
  display-time-mode: t
  save-place-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  prettify-symbols-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  column-number-mode: t
  line-number-mode: t
  transient-mark-mode: t

Load-path shadows:
/usr/share/emacs/site-lisp/elpa/caml-4.6/caml-mode-site-file hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/caml-mode-site-file
/usr/share/emacs/site-lisp/elpa/caml-4.6/caml-autoloads hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/caml-autoloads
/usr/share/emacs/site-lisp/elpa/caml-4.6/inf-caml hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/inf-caml
/usr/share/emacs/site-lisp/elpa/caml-4.6/caml-hilit hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/caml-hilit
/usr/share/emacs/site-lisp/elpa/caml-4.6/caml-types hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/caml-types
/usr/share/emacs/site-lisp/elpa/caml-4.6/caml-compat hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/caml-compat
/usr/share/emacs/site-lisp/elpa/caml-4.6/caml-pkg hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/caml-pkg
/usr/share/emacs/site-lisp/elpa/caml-4.6/caml hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/caml
/usr/share/emacs/site-lisp/elpa/caml-4.6/caml-emacs hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/caml-emacs
/usr/share/emacs/site-lisp/elpa/caml-4.6/caml-font-old hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/caml-font-old
/usr/share/emacs/site-lisp/elpa/caml-4.6/caml-font hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/caml-font
/usr/share/emacs/site-lisp/elpa/caml-4.6/caml-help hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/caml-help
/usr/share/emacs/site-lisp/elpa/caml-4.6/caml-xemacs hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/caml-xemacs
/usr/share/emacs/site-lisp/elpa/caml-4.6/camldebug hides /usr/share/emacs/site-lisp/elpa-src/caml-4.6/camldebug
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-folders hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-folders
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-mark hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-mark
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-contrib hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-contrib
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-context hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-context
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-speedbar hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-speedbar
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-contacts hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-contacts
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-actions hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-actions
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-search hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-search
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-lists hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-lists
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-message hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-message
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-headers hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-headers
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-helpers hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-helpers
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-view hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-view
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-compose hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-compose
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-bookmarks hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-bookmarks
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-draft hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-draft
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-update hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-update
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-config hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-config
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-main hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-main
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-vars hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-vars
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-org hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-org
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-server hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-server
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-pkg hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-pkg
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-autoloads hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-autoloads
/usr/share/emacs/site-lisp/elpa/mu4e-1.8.14/mu4e-icalendar hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.8.14/mu4e-icalendar
/usr/share/emacs/site-lisp/elpa/tuareg-2.2.0/tuareg-pkg hides /usr/share/emacs/site-lisp/elpa-src/tuareg-2.2.0/tuareg-pkg
/usr/share/emacs/site-lisp/elpa/tuareg-2.2.0/tuareg-opam hides /usr/share/emacs/site-lisp/elpa-src/tuareg-2.2.0/tuareg-opam
/usr/share/emacs/site-lisp/elpa/tuareg-2.2.0/tuareg-jbuild hides /usr/share/emacs/site-lisp/elpa-src/tuareg-2.2.0/tuareg-jbuild
/usr/share/emacs/site-lisp/elpa/tuareg-2.2.0/tuareg hides /usr/share/emacs/site-lisp/elpa-src/tuareg-2.2.0/tuareg
/usr/share/emacs/site-lisp/elpa/tuareg-2.2.0/tuareg-menhir hides /usr/share/emacs/site-lisp/elpa-src/tuareg-2.2.0/tuareg-menhir
/usr/share/emacs/site-lisp/elpa/tuareg-2.2.0/ocamldebug hides /usr/share/emacs/site-lisp/elpa-src/tuareg-2.2.0/ocamldebug
/usr/share/emacs/site-lisp/elpa/tuareg-2.2.0/dot-emacs hides /usr/share/emacs/site-lisp/elpa-src/tuareg-2.2.0/dot-emacs
/usr/share/emacs/site-lisp/elpa/tuareg-2.2.0/tuareg-autoloads hides /usr/share/emacs/site-lisp/elpa-src/tuareg-2.2.0/tuareg-autoloads
/usr/share/emacs/site-lisp/elpa/tuareg-2.2.0/tuareg-site-file hides /usr/share/emacs/site-lisp/elpa-src/tuareg-2.2.0/tuareg-site-file
/usr/share/emacs/site-lisp/utop hides /usr/share/emacs/site-lisp/elpa-src/utop-1.11/utop
~/.emacs.d//phil/../custom hides /usr/share/emacs/28.2/lisp/custom

Features:
(shadow sort mail-extr emacsbug sendmail wdired goto-addr vc-dir
vc-filewise expand loadhist em-tramp em-rebind em-smart woman thai-util
thai-word vc-annotate utop utop-minor-mode tuareg caml caml-help
caml-types caml-emacs novice epa-file apropos mode-local perl-mode
scheme rcirc info ibuf-ext pulse etags fileloop completion org-element
avl-tree generator ol-eww ol-rmail ol-mhe ol-irc ol-info ol-gnus
nnselect gnus-search gnus-art mm-uu mml2015 mm-view mml-smime smime dig
gnus-sum gnus-group gnus-undo gnus-start gnus-dbus gnus-cloud checkdoc
bug-reference scpaste htmlize nroff-mode tar-mode dired-aux tmm log-view
hippie-exp mhtml-mode css-mode eww xdg url-queue shr kinsoku svg mm-url
sgml-mode facemenu dom url-file url-dired eieio-opt speedbar ezimage
dframe shortdoc nnimap nnmail mail-source utf7 netrc nnoo gnus-spec
gnus-int gnus-range gnus-win gnus nnheader ol-docview doc-view jka-compr
ol-bibtex ol-bbdb ol-w3m ol-doi org-link-doi org ob ob-tangle ob-ref
ob-lob ob-table ob-exp org-macro org-footnote org-src ob-comint
org-pcomplete org-list org-faces org-entities org-version ob-emacs-lisp
ob-core ob-eval org-table oc-basic bibtex ol org-keys oc org-compat
org-macs org-loaddefs cal-menu calendar cal-loaddefs mm-archive gnutls
url-cache url-dav parse-time iso8601 url-http url-auth url-gw help-fns
radix-tree arc-mode archive-mode js cc-mode cc-fonts cc-guess cc-menus
cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs network-stream nsm
image-mode exif cl-print ielm sh-script smie executable conf-mode tabify
man files-x grep pcmpl-gnu view monroe clojure-mode lisp-mnt align
smerge-mode diff misearch multi-isearch yaml-mode magit-bisect
magit-key-mode magit log-edit message rmc puny dired dired-loaddefs
rfc822 mml mml-sec epa epg rfc6068 epg-config gnus-util rmail
rmail-loaddefs mm-decode mm-bodies mm-encode mail-parse rfc2231 rfc2047
rfc2045 mm-util ietf-drums mail-prsvr mailabbrev mail-utils gmm-utils
mailheader pcvs-util add-log mule-util ibuffer ibuffer-loaddefs
make-mode hi-lock flyspell ispell markdown-mode color noutline outline
recentf tree-widget face-remap antifennel lua-mode time-date vc-mtn
vc-hg vc-git diff-mode vc-bzr vc-src vc-sccs vc-svn vc-cvs vc-rcs vc
vc-dispatcher eglot derived easy-mmode array filenotify jsonrpc ert ewoc
debug backtrace find-func flymake-proc flymake compile
text-property-search imenu fennel-mode xref project inf-lisp pcmpl-unix
paredit whitespace idle-highlight-mode thingatpt hl-line
company-dabbrev-code company-dabbrev company-files company-capf
cus-start smex company pcase em-unix em-term term disp-table shell ehelp
em-script em-prompt em-ls em-hist em-pred em-glob em-cmpl em-dirs
esh-var pcomplete comint ansi-color em-basic em-banner em-alias esh-mode
eshell esh-cmd esh-ext esh-opt esh-proc esh-io esh-arg esh-module
esh-groups esh-util winner ring exwm-randr xcb-randr format-spec battery
dbus ido-completing-read+ cus-edit pp cus-load wid-edit minibuf-eldef
xml time exwm-systemtray xcb-systemtray xcb-xembed exwm-config exwm
exwm-input xcb-keysyms xcb-xkb exwm-manage exwm-floating xcb-cursor
xcb-render exwm-layout exwm-workspace exwm-core xcb-ewmh xcb-icccm xcb
xcb-xproto xcb-types xcb-debug server advice my-autoload comp comp-cstr
warnings rx cl-extra help-mode edmacro kmacro saveplace ido package
browse-url url url-proxy url-privacy url-expand url-methods url-history
url-cookie url-domsuf url-util mailcap url-handlers url-parse
auth-source cl-seq eieio eieio-core cl-macs eieio-loaddefs
password-cache json subr-x map url-vars seq byte-opt gv bytecomp
byte-compile cconv cl-loaddefs cl-lib iso-transl tooltip eldoc paren
electric uniquify ediff-hook vc-hooks lisp-float-type elisp-mode mwheel
term/x-win x-win term/common-win x-dnd tool-bar dnd fontset image
regexp-opt fringe tabulated-list replace newcomment text-mode lisp-mode
prog-mode register page tab-bar menu-bar rfn-eshadow isearch easymenu
timer select scroll-bar mouse jit-lock font-lock syntax font-core
term/tty-colors frame minibuffer cl-generic cham georgian utf-8-lang
misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms
cp51932 hebrew greek romanian slovak czech european ethiopic indian
cyrillic chinese composite emoji-zwj charscript charprop case-table
epa-hook jka-cmpr-hook help simple abbrev obarray cl-preloaded nadvice
button loaddefs faces cus-face macroexp files window text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget
hashtable-print-readable backquote threads dbusbind inotify lcms2
dynamic-setting system-font-setting font-render-setting cairo
move-toolbar gtk x-toolkit x multi-tty make-network-process
native-compile emacs)

Memory information:
((conses 16 2259837 441168)
 (symbols 48 65692 26)
 (strings 32 294146 27789)
 (string-bytes 1 11657421)
 (vectors 16 137620)
 (vector-slots 8 3750584 290488)
 (floats 8 1069 2257)
 (intervals 56 269565 5487)
 (buffers 992 410))