joaotavora / eglot

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

Unable to get signature info in Clojure DEFN form... #1253

Closed zikajk closed 1 year ago

zikajk commented 1 year ago

Hi, I am getting an error wrong-type-argument number-or-marker-p nil when I move cursor inside a body of (defn). I have this problem with Clojure-LSP only. Dart-LSP or ClangD works without any issues.

Reproducible recipe:

1) ensure that clojure-lsp is installed and available in path

% clojure-lsp --version
clojure-lsp 2023.07.01-22.45.58-nightly
clj-kondo 2023.06.02-SNAPSHOT

2) Invoke Emacs 29.0.91 with Eglot master: emacs -Q -L straight/build/clojure-mode -l clojure-mode -L straight/build/eglot -l eglot ~/Code/Clojure/pacman/src/pacman/core.clj -f eglot 3) TypeM-x toggle-debug-on-error 4) Write / move inside form like (defn my-function [arg] "smth') 5) Get this unexpected error:

`Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p nil) eglot--sig-info((:label "(defn [name doc-string? attr-map? ([params] prepo..." :parameters [(:label "name") (:label "doc-string?") (:label "attr-map?") (:label "([params] prepost-map? body)") (:label "+") (:label "attr-map?")] :documentation "Same as (def name (fn [params ] exprs)) or (def\n...") nil nil)

f(compiled-function (s) #<bytecode -0x9fdf05533c2e94d>)((:label "(defn [name doc-string? attr-map? ([params] prepo..." :parameters [(:label "name") (:label "doc-string?") (:label "attr-map?") (:label "([params] prepost-map? body)") (:label "+") (:label "attr-map?")] :documentation "Same as (def name (fn [params ] exprs)) or (def\n..."))

mapconcat(#f(compiled-function (s) #<bytecode -0x9fdf05533c2e94d>) [(:label "(defn [name doc-string? attr-map? [params] prepos..." :parameters [(:label "name") (:label "doc-string?") (:label "attr-map?") (:label "[params]") (:label "prepost-map?") (:label "body")] :documentation "Same as (def name (fn [params ] exprs)) or (def\n...") (:label "(defn [name doc-string? attr-map? ([params] prepo..." :parameters [(:label "name") (:label "doc-string?") (:label "attr-map?") (:label "([params] prepost-map? body)") (:label "+") (:label "attr-map?")] :documentation "Same as (def name (fn [params ] exprs)) or (def\n...")] "\n")

f(compiled-function (jsonrpc-lambda-elem11) #<bytecode -0xf854fe77d439e90>)((:signatures [(:label "(defn [name doc-string? attr-map? [params] prepos..." :parameters [(:label "name") (:label "doc-string?") (:label "attr-map?") (:label "[params]") (:label "prepost-map?") (:label "body")] :documentation "Same as (def name (fn [params ] exprs)) or (def\n...") (:label "(defn [name doc-string? attr-map? ([params] prepo..." :parameters [(:label "name") (:label "doc-string?") (:label "attr-map?") (:label "([params] prepost-map? body)") (:label "+") (:label "attr-map?")] :documentation "Same as (def name (fn [params ] exprs)) or (def\n...")] :activeParameter 0 :activeSignature 0))

jsonrpc-connection-receive(# (:jsonrpc "2.0" :id 49 :result (:signatures [(:label "(defn [name doc-string? attr-map? [params] prepos..." :parameters [(:label "name") (:label "doc-string?") (:label "attr-map?") (:label "[params]") (:label "prepost-map?") (:label "body")] :documentation "Same as (def name (fn [params ] exprs)) or (def\n...") (:label "(defn [name doc-string? attr-map? ([params] prepo..." :parameters [(:label "name") (:label "doc-string?") (:label "attr-map?") (:label "([params] prepost-map? body)") (:label "+") (:label "attr-map?")] :documentation "Same as (def name (fn [params ] exprs)) or (def\n...")] :activeParameter 0 :activeSignature 0))) jsonrpc--process-filter(#<process EGLOT (pacman/(clojure-mode clojurescript-mode clojurec-mode))> "Content-Length: 117\15\n\15\n{\"jsonrpc\":\"2.0\",\"id\":48,\"r...") `

6) These are Eglot's events

[client-request] (id:53) Mon Jul 10 10:54:27 2023:
(:jsonrpc "2.0" :id 53 :method "textDocument/hover" :params
      (:textDocument
       (:uri "file:///Users/akiz/Code/Clojure/pacman/src/pacman/core.clj")
       :position
       (:line 102 :character 6)))
[client-request] (id:54) Mon Jul 10 10:54:27 2023:
(:jsonrpc "2.0" :id 54 :method "textDocument/documentHighlight" :params
      (:textDocument
       (:uri "file:///Users/akiz/Code/Clojure/pacman/src/pacman/core.clj")
       :position
       (:line 102 :character 6)))
[client-request] (id:55) Mon Jul 10 10:54:27 2023:
(:jsonrpc "2.0" :id 55 :method "textDocument/signatureHelp" :params
      (:textDocument
       (:uri "file:///Users/akiz/Code/Clojure/pacman/src/pacman/core.clj")
       :position
       (:line 102 :character 6)))
[server-reply] (id:54) Mon Jul 10 10:54:27 2023:
(:jsonrpc "2.0" :id 54 :result
      [(:range
        (:start
         (:line 102 :character 6)
         :end
         (:line 102 :character 11)))])
[server-reply] (id:55) Mon Jul 10 10:54:27 2023:
(:jsonrpc "2.0" :id 55 :result
      (:signatures
       [(:label "(defn [name doc-string? attr-map? [params*] prepost-map? body])" :parameters
            [(:label "name")
             (:label "doc-string?")
             (:label "attr-map?")
             (:label "[params*]")
             (:label "prepost-map?")
             (:label "body")]
            :documentation "Same as (def name (fn [params* ] exprs*)) or (def\n    name (fn ([params* ] exprs*)+)) with any doc-string or attrs added\n    to the var metadata. prepost-map defines a map with optional keys\n    :pre and :post that contain collections of pre or post conditions.")
        (:label "(defn [name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?])" :parameters
            [(:label "name")
             (:label "doc-string?")
             (:label "attr-map?")
             (:label "([params*] prepost-map? body)")
             (:label "+")
             (:label "attr-map?")]
            :documentation "Same as (def name (fn [params* ] exprs*)) or (def\n    name (fn ([params* ] exprs*)+)) with any doc-string or attrs added\n    to the var metadata. prepost-map defines a map with optional keys\n    :pre and :post that contain collections of pre or post conditions.")]
       :activeParameter 0 :activeSignature 0))
[internal] (id:53) Mon Jul 10 10:54:37 2023:
(:timed-out :textDocument/hover :id 53 :params
        (:textDocument
         (:uri "file:///Users/akiz/Code/Clojure/pacman/src/pacman/core.clj")
         :position
         (:line 102 :character 6)))
zikajk commented 1 year ago

Commenting out this part from eglot.el removes the error

    ;; ...perhaps highlight it in the formals list
         (when (= i active-param)
           (save-excursion
             (goto-char (point-min))
             (pcase-let
                 ((`(,beg ,end)
                   (if (stringp parlabel)
                       (let ((case-fold-search nil))
                         (and (search-forward parlabel (line-end-position) t)
                              (list (match-beginning 0) (match-end 0))))
                     (mapcar #'1+ (append parlabel nil)))))
               (if (and beg end)
                   (add-face-text-property
                    beg end
                    'eldoc-highlight-function-argument)))))
         ;; ...and/or maybe add its doc on a line by its own.
zikajk commented 1 year ago

When I runeglot-upgrade-eglotor eglot-update everytime Emacs starts, it works as it should. That's the best workaround so far, but I don't understand what the problem is. video

joaotavora commented 1 year ago

Invoke Emacs 29.0.91 with Eglot master:

emacs -Q -L straight/build/clojure-mode -l clojure-mode -L straight/build/eglot -l eglot ~/Code/Clojure/pacman/src/pacman/core.clj -f eglot

This assumes you're in a directory where the straight directory exists, but you didn't tell us in the recipe how this directory came to be. (also you didn't tell us how the ~/Code came to be). This recipe is not complete.

But it's probably due to the fact that somewhere your copy of eglot which lives in straight/build/eglot is picking up a bug which I introduced recently and thought I had fixed, but I didn't . Have fixed it now. See https://git.savannah.gnu.org/cgit/emacs.git/commit/lisp/progmodes/eglot.el?id=d0f65fbdbbba945a97c97b4b34ba8f9671e68f35.

When I runeglot-upgrade-eglotor eglot-update everytime Emacs starts, it works as it should. That's the best workaround so far, but I don't understand what the problem is.

When you run this, depending on your package-archives you are probably upgrading Emacs 29's stock eglot to 1.15 which doesn't have the aforementioned bug yet.

zikajk commented 1 year ago

Thanks for the explanation and fix. Straight directory is in .emacs.d, eglot is installed via (use-package eglot) and Code is the directory in my home where the Clojure code is. But it can be any clj code so you can use a different path...

zikajk commented 1 year ago

By the way, coloring in *eldoc*is strange. image

joaotavora commented 1 year ago

By the way, coloring in eldoc is strange.

Clojure-lsp has very poor parameter information in the signature info, so I brought back an old heuristic. See latest Eglot. and give it some testing if you can.

zikajk commented 1 year ago

Ok. Seems fine, no extra colouring in eldoc so far.