Skip to content

Commit 307890f

Browse files
quanticlevemv
authored andcommitted
Fix #3307: Incorrect special-form eldocs
This fix is the CIDER companion to [this PR](clojure-emacs/orchard#166) in orchard, which lets us know if the symbol we're querying eldocs for is a special form or an ordinary function. This changes uses that information to deduplicate the arglists for the special form. In the process, the change adds a `cider-eldoc-format-special-form` function, which serves as a home for special form formatting. This change also adds a unit test for cider-eldoc to ensure that it calls the appropriate formatting methods.
1 parent 5d91ffc commit 307890f

File tree

3 files changed

+79
-3
lines changed

3 files changed

+79
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
- Bump the injected `cider-nrepl` to 0.30.
3030
- [#3219](https://github.com/clojure-emacs/cider/issues/3219): Disable by default forcing the display of output when the REPL prompt is at the first line of the of the REPL window. This behavior is desirable, but very slow and rarely needed. It can be re-enabled by setting `cider-repl-display-output-before-window-boundaries` to `t`.
3131
- [#3335](https://github.com/clojure-emacs/cider/issues/3335): Disable the Paredit binding of RET in cider-repl-mode buffers, which can cause unexpected behaviour by appearing to hang instead of evaluating forms.
32+
- [#3307](https://github.com/clojure-emacs/cider/issues/3307): Make eldoc highlighting on emacs special forms better match the location of the point when latest `cider-nrepl` is used.
3233

3334
## 1.6.0 (2022-12-21)
3435

cider-eldoc.el

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,22 @@ arglists. ELDOC-INFO is a p-list containing the eldoc information."
230230
(cider-eldoc-format-thing ns symbol thing 'fn)
231231
(cider-eldoc-format-arglist arglists pos))))
232232

233+
(defun cider-eldoc-format-special-form (thing pos eldoc-info)
234+
"Return the formatted eldoc string for a special-form.
235+
THING is the special form's name. POS is the argument index of the
236+
special-form's arglists. ELDOC-INFO is a p-list containing the eldoc
237+
information."
238+
(let* ((ns (lax-plist-get eldoc-info "ns"))
239+
(symbol (lax-plist-get eldoc-info "symbol"))
240+
(arglists (mapcar (lambda (arglist)
241+
(if (equal (car arglist) symbol)
242+
(cdr arglist)
243+
arglist))
244+
(lax-plist-get eldoc-info "arglists"))))
245+
(format "%s: %s"
246+
(cider-eldoc-format-thing ns symbol thing 'fn)
247+
(cider-eldoc-format-arglist arglists pos))))
248+
233249
(defun cider-highlight-args (arglist pos)
234250
"Format the the function ARGLIST for eldoc.
235251
POS is the index of the currently highlighted argument."
@@ -470,9 +486,12 @@ Only useful for interop forms. Clojure forms would be returned unchanged."
470486
(pos (lax-plist-get sexp-eldoc-info "pos"))
471487
(thing (lax-plist-get sexp-eldoc-info "thing")))
472488
(when eldoc-info
473-
(if (eq (cider-eldoc-thing-type eldoc-info) 'var)
474-
(cider-eldoc-format-variable thing eldoc-info)
475-
(cider-eldoc-format-function thing pos eldoc-info))))))
489+
(cond
490+
((eq (cider-eldoc-thing-type eldoc-info) 'var)
491+
(cider-eldoc-format-variable thing eldoc-info))
492+
((eq (cider-eldoc-thing-type eldoc-info) 'special-form)
493+
(cider-eldoc-format-special-form thing pos eldoc-info))
494+
(t (cider-eldoc-format-function thing pos eldoc-info)))))))
476495

477496
(defun cider-eldoc-setup ()
478497
"Setup eldoc in the current buffer.

test/cider-eldoc-tests.el

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,37 @@
6969
(expect (cider--eldoc-format-class-names class-names)
7070
:to-equal "(String StringBuffer CharSequence & 1 more)")))))
7171

72+
(describe "cider-eldoc-thing-type"
73+
(it "Identifies special forms correctly"
74+
(let ((eldoc-info '("type" "special-form")))
75+
(expect (cider-eldoc-thing-type eldoc-info) :to-equal 'special-form)))
76+
(it "Identifies functions correctly"
77+
(let ((eldoc-info '("type" "function")))
78+
(expect (cider-eldoc-thing-type eldoc-info) :to-equal 'fn))))
79+
80+
(describe "cider-eldoc-format-special-form"
81+
(before-each
82+
(spy-on 'cider-eldoc-format-thing :and-return-value "formatted thing!")
83+
(spy-on 'cider-eldoc-format-arglist :and-return-value "formatted arglist!"))
84+
(it "Should remove duplicates from special-form arglists that have duplicates"
85+
(let ((eldoc-info '("ns" nil
86+
"symbol" "if"
87+
"arglists" (("if" "test" "then" "else?"))
88+
"type" "special-form")))
89+
(cider-eldoc-format-special-form 'if 0 eldoc-info)
90+
(expect 'cider-eldoc-format-arglist :to-have-been-called-with '(("test" "then" "else?")) 0)))
91+
(it "Should not remove duplicates from special-form arglists that do not have duplicates"
92+
(let ((eldoc-info '("ns" nil
93+
"symbol" "."
94+
"arglists" ((".instanceMember" "instance" "args*") (".instanceMember" "Classname" "args*") ("Classname/staticMethod" "args*") ("Classname/staticField"))
95+
"type" "special-form")))
96+
(cider-eldoc-format-special-form 'if 0 eldoc-info)
97+
(expect 'cider-eldoc-format-arglist :to-have-been-called-with '((".instanceMember" "instance" "args*")
98+
(".instanceMember" "Classname" "args*")
99+
("Classname/staticMethod" "args*")
100+
("Classname/staticField"))
101+
0))))
102+
72103
(describe "cider-eldoc-format-thing"
73104
:var (class-names)
74105
(before-each
@@ -238,6 +269,31 @@
238269
(expect (cider-eldoc-info-in-current-sexp) :to-equal
239270
'("eldoc-info" (("java.lang.String") ".length" (("this"))) "thing" "java.lang.String/.length" "pos" 0)))))))
240271

272+
(describe "cider-eldoc"
273+
(before-each
274+
(spy-on 'cider-connected-p :and-return-value t)
275+
(spy-on 'cider-eldoc--edn-file-p :and-return-value nil))
276+
(it "Should call cider-eldoc-format-variable for vars"
277+
(spy-on 'cider-eldoc-info-in-current-sexp :and-return-value '("thing" "foo" "pos" 0 "eldoc-info" ("ns" "clojure.core" "symbol" "foo" "type" "variable" "docstring" "test docstring")))
278+
(spy-on 'cider-eldoc-format-variable)
279+
(cider-eldoc)
280+
(expect 'cider-eldoc-format-variable :to-have-been-called-with "foo" '("ns" "clojure.core" "symbol" "foo" "type" "variable" "docstring" "test docstring")))
281+
(it "Should call cider-eldoc-format-special-form for special forms"
282+
(spy-on 'cider-eldoc-info-in-current-sexp :and-return-value '("thing" "if" "pos" 0 "eldoc-info" ("ns" "clojure.core" "symbol" "if" "type" "special-form" "arglists" ("special form arglist"))))
283+
(spy-on 'cider-eldoc-format-special-form)
284+
(cider-eldoc)
285+
(expect 'cider-eldoc-format-special-form :to-have-been-called-with "if" 0 '("ns" "clojure.core" "symbol" "if" "type" "special-form" "arglists" ("special form arglist"))))
286+
(it "Should call cider-eldoc-format-function for functions"
287+
(spy-on 'cider-eldoc-info-in-current-sexp :and-return-value '("thing" "a-fn" "pos" 0 "eldoc-info" ("ns" "foo.bar" "symbol" "a-fn" "type" "function" "arglists" ("function arglist"))))
288+
(spy-on 'cider-eldoc-format-function)
289+
(cider-eldoc)
290+
(expect 'cider-eldoc-format-function :to-have-been-called-with "a-fn" 0 '("ns" "foo.bar" "symbol" "a-fn" "type" "function" "arglists" ("function arglist"))))
291+
(it "Should call cider-eldoc-format-function for macros"
292+
(spy-on 'cider-eldoc-info-in-current-sexp :and-return-value '("thing" "a-macro" "pos" 0 "eldoc-info" ("ns" "clojure.core" "symbol" "a-macro" "type" "macro" "arglists" ("macro arglist"))))
293+
(spy-on 'cider-eldoc-format-function)
294+
(cider-eldoc)
295+
(expect 'cider-eldoc-format-function :to-have-been-called-with "a-macro" 0 '("ns" "clojure.core" "symbol" "a-macro" "type" "macro" "arglists" ("macro arglist")))))
296+
241297
(describe "cider-eldoc-format-sym-doc"
242298
:var (eldoc-echo-area-use-multiline-p)
243299
(before-each

0 commit comments

Comments
 (0)