This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-03-31
Channels
- # announcements (5)
- # babashka (5)
- # beginners (24)
- # calva (21)
- # cherry (1)
- # clerk (20)
- # clj-kondo (3)
- # clj-otel (12)
- # clojure (50)
- # clojure-austin (2)
- # clojure-conj (3)
- # clojure-europe (40)
- # clojure-nl (1)
- # clojure-norway (203)
- # clojure-spec (3)
- # clojure-uk (6)
- # clojurescript (8)
- # conjure (1)
- # datomic (1)
- # deps-new (1)
- # emacs (5)
- # graphql (8)
- # gratitude (5)
- # holy-lambda (16)
- # honeysql (18)
- # hyperfiddle (12)
- # java (1)
- # jobs (1)
- # lsp (24)
- # membrane (8)
- # nbb (1)
- # off-topic (19)
- # portal (28)
- # proletarian (11)
- # rdf (63)
- # re-frame (38)
- # reagent (8)
- # reitit (1)
- # releases (6)
- # remote-jobs (1)
- # scittle (4)
- # shadow-cljs (20)
- # spacemacs (4)
- # sql (7)
- # transit (1)
Hi, using eglot + corfu
, I don’t get popup documentation with Clojure but I do get it with Dart (for example). With Clojure-LSP I am getting.
(:jsonrpc "2.0" :id 97 :method "completionItem/resolve" :params
(:label
#("foo" 0 1 ...)
:kind 3 :data
(:unresolved
[["documentation" ...]])))
Honestly, it’s not very clear to me how to debug it further. Why Clojure server doesn’t provide the necessary information?The documentation is one of the fields that are provided in a next request of the spec completion/resolveItem, basically the spec recommends that for items with long texts, like documentation, the client should do the request right after completion for the selected item, being completely transparent for the user
@UKFSJSM38 Thank you. The message I posted is the last message logged, what else should i look for in logs to see what Eglot is missing?
so looks correct, not sure why eglot is not rendering that, maybe you could debug with Dart and see what difference the LSPs return for completion in that log?
This is DartLSP <-> Eglot on popup
[client-request] (id:67) Fri Mar 31 14:58:45 2023:
(:jsonrpc "2.0" :id 67 :method "completionItem/resolve" :params
(:data
(:file "/Users/akiz/Code/ClojureDart/game/lib/main.dart" :importUris
["dart:async"]
:ref "dart:async;dart:async/zone.dart;PrintHandler")
:detail "(Zone self, ZoneDelegate parent, Zone zone, String line) → void" :label
#("PrintHandler" 0 1 ...)
:sortText "9999562" :textEdit
(:newText "PrintHandler" :range ...)))
[server-reply] (id:67) Fri Mar 31 14:58:45 2023:
(:id 67 :jsonrpc "2.0" :result
(:additionalTextEdits
[...]
:data
(:file "/Users/akiz/Code/ClojureDart/game/lib/main.dart" :importUris
["dart:async"]
:ref "dart:async;dart:async/zone.dart;PrintHandler")
:detail "Auto import from 'dart:async'\n\n(Zone self, ZoneDelegate parent, Zone zone, String line) → void" :documentation "The type of a custom [Zone.print] implementation function.\n\nReceives the [Zone] that the handler was registered on as [self],\na delegate forwarding to the handlers of [self]'s parent zone as [parent],\nand the current zone where the error was uncaught as [zone],\nwhich will have [self] as a parent zone.\n\nThe string [line] is the one which was passed to [Zone.print] of [zone],\n(possibly through the global [print] function).\n\nThe custom handler can intercept print operations and\nredirect them to other targets than the console.\n\nThe function must only access zone-related functionality through\n[self], [parent] or [zone].\nIt should not depend on the current zone ([Zone.current])." :label "PrintHandler" :sortText "9999562" :textEdit
(:newText "PrintHandler" :range ...)))
This is Clojure-LSP + Eglot
[client-request] (id:2067) Fri Mar 31 14:46:22 2023:
(:jsonrpc "2.0" :id 2067 :method "completionItem/resolve" :params
(:label
#("print" 0 1 ...)
:kind 3 :detail "clojure.core/print" :data
(:unresolved
[["documentation" ...]])))
[server-reply] (id:2067) Fri Mar 31 14:46:22 2023:
(:jsonrpc "2.0" :id 2067 :result nil)
oh, just look a closer look, it seem the server is responding with nil
for the completionItem/resolve
, for some cases that is expected when there is nothing to add to that item, could you check if before that request there was a textDocument/completion
response and if your item had the documentation there?
textDocument/completion
request looks like this.
This is called when i input def
and wait for auto-completion candidates…
[client-request] (id:2538) Fri Mar 31 16:13:40 2023:
(:jsonrpc "2.0" :id 2538 :method "textDocument/completion" :params
(:textDocument
(:uri "file:///Users/akiz/Projects/BIM/backend-api/src/cljs/user_interface/components/molecules/sidebar.cljs")
:position
(:line 81 :character 4)
:context
(:triggerKind 1)))
[server-reply] (id:2538) Fri Mar 31 16:13:40 2023:
(:jsonrpc "2.0" :id 2538 :result
[(:label "defstyled" :kind 18 :detail "refer to: lambdaisland.ornament" :data
(:unresolved
[["documentation"
(:name "defstyled" :uri "file:///Users/akiz/Projects/BIM/backend-api/src/cljs/user_interface/components/molecules/sidebar.cljs" :name-row 3 :name-col 51)]]))
(:label "default-data-readers" :kind 6 :detail "clojure.core/default-data-readers" :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "default-data-readers" :ns "clojure.core")]]))
(:label "definline" :kind 3 :detail "clojure.core/definline" :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "definline" :ns "clojure.core")]]))
(:label "definterface" :kind 3 :detail "clojure.core/definterface" :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "definterface" :ns "clojure.core")]]))
(:label "defmacro" :kind 3 :detail "clojure.core/defmacro" :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "defmacro" :ns "clojure.core")]]))
(:label "defonce" :kind 3 :detail "clojure.core/defonce" :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "defonce" :ns "clojure.core")]]))
(:label "defstruct" :kind 3 :detail "clojure.core/defstruct" :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "defstruct" :ns "clojure.core")]]))
(:label "default-dispatch-val" :kind 3 :detail "cljs.core/default-dispatch-val" :data
(:unresolved
[["documentation"
(:uri "file:///cljs.core.cljs" :name "default-dispatch-val" :ns "cljs.core")]]))
(:label "def" :functionCall t :insertText "def ${1:name} $0" :detail "Insert def" :kind 15 :insertTextFormat 2 :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "def" :ns "clojure.core")]]
:snippet-kind 18))
(:label "def-" :functionCall t :detail "Insert def private" :insertText "def ^:private ${1:name} $0" :kind 15 :insertTextFormat 2)
(:label "def-doc" :functionCall t :insertText "def ${1:name}\n \"${2:docstring}\"\n $0" :detail "Insert def with docstring" :kind 15 :insertTextFormat 2)
(:label "defmethod" :functionCall t :detail "Insert defmethod" :insertText "defmethod ${1:name} ${2:match}\n [${3:args}]\n $0" :kind 15 :insertTextFormat 2 :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "defmethod" :ns "clojure.core")]]
:snippet-kind 3))
(:label "defmulti" :functionCall t :detail "Insert defmulti" :insertText "defmulti ${1:name} ${2:dispatch-fn}" :kind 15 :insertTextFormat 2 :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "defmulti" :ns "clojure.core")]]
:snippet-kind 3))
(:label "defn" :functionCall t :insertText "defn ${1:name} [$2]\n $0" :detail "Insert public defn" :kind 15 :insertTextFormat 2 :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "defn" :ns "clojure.core")]]
:snippet-kind 3))
(:label "defn-" :functionCall t :detail "Insert private defn" :insertText "defn- ${1:name} [$2]\n $0" :kind 15 :insertTextFormat 2 :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "defn-" :ns "clojure.core")]]
:snippet-kind 3))
(:label "defn-doc" :functionCall t :detail "Insert public defn with docstring" :insertText "defn ${1:name}\n \"${2:docstring}\"\n [${3:args}]\n $0" :kind 15 :insertTextFormat 2)
(:label "defprotocol" :functionCall t :detail "Insert defprotocol" :insertText "defprotocol ${1:Name}\n $0" :kind 15 :insertTextFormat 2 :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "defprotocol" :ns "clojure.core")]]
:snippet-kind 3))
(:label "defrecord" :functionCall t :detail "Insert defrecord" :insertText "defrecord ${1:Name} [${2:fields}]\n ${3:Protocol}\n $0" :kind 15 :insertTextFormat 2 :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "defrecord" :ns "clojure.core")]]
:snippet-kind 3))
(:label "deftest" :detail "Insert deftest clojure.test" :insertText "(deftest ${1:name}-test\n (testing \"${2:Context of the test assertions}\"\n (is (= ${3:assertion-values}))$4)) $0" :kind 15 :insertTextFormat 2)
(:label "deftype" :functionCall t :detail "Insert deftype" :insertText "deftype ${1:Name} [${2:fields}]\n ${3:Protocol}\n $0" :kind 15 :insertTextFormat 2 :data
(:unresolved
[["documentation"
(:uri "file:///clojure.core.clj" :name "deftype" :ns "clojure.core")]]
:snippet-kind 3))])
Do you mean that Insert def private for def
is the right documentation that should be used for completionItem/resolve
?
If so, then it works.
Was I wrong assuming that I can get the same documentation with LSP as I get with Cider (attached image)?
While this is what I am getting with Eglot (the “short documentation” is on the right side)
Hum, def is really a corner case that it might be fixed on master but not on latest release (it uses arglists docs) What about other functions? Hum, TBH I never used that feature, but it looks useful indeed and clojure-lsp provides everything to clients present that
Okay, it’s no big deal 😉 . Now I found out that the short documentation on the right side was only because I got snippets loaded. Once i turn yas-minor-mode off, they are gone. I couldn’t find any function that would return pop-up documentation. (Documentation works in all other places though). I’ll play around with it for a while, try lsp-mode, compare and hopefully figure out what’s missing. The differences in lsp-servers won’t make it easier, which is a pity, because Dart works perfectly 🙂
yeah, I almost sure I saw somewhere it's possible to present that documentation popup for completion items in lsp-mode and thought "Oh, cool, I should enable that some day" 😂
As a kinda workaround I created this fn that is hooked to cider startup. Then I can run Eglot and get Cider docs in pop-up etc.
(defun my/remove-eglot-documentation-functions ()
(remove-hook 'eldoc-documentation-functions #'eglot-hover-eldoc-function t)
(remove-hook 'eldoc-documentation-functions #'eglot-signature-eldoc-function t)
(remove-hook 'eldoc-documentation-functions #'eglot-completion-at-point t))
Just remembered how to call the documentation in completion :) https://github.com/company-mode/company-quickhelp