Skip to content

Commit

Permalink
[info] Add support for sources JAR downloading on `info' events
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-yakushev committed Jan 5, 2025
1 parent 356c2bd commit 7db186f
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 17 deletions.
47 changes: 37 additions & 10 deletions cider-client.el
Original file line number Diff line number Diff line change
Expand Up @@ -189,16 +189,20 @@ the current connection. Return the id of the sent message.
If TOOLING is truthy then the tooling session is used."
(nrepl-send-request request callback (or connection (cider-current-repl 'any 'ensure)) tooling))

(defun cider-nrepl-send-sync-request (request &optional connection abort-on-input)
(defun cider-nrepl-send-sync-request (request &optional connection
abort-on-input callback)
"Send REQUEST to the nREPL server synchronously using CONNECTION.
Hold till final \"done\" message has arrived and join all response messages
of the same \"op\" that came along and return the accumulated response.
If ABORT-ON-INPUT is non-nil, the function will return nil
at the first sign of user input, so as not to hang the
interface."
interface.
if CALLBACK is non-nil, it will additionally be called on all received messages."
(nrepl-send-sync-request request
(or connection (cider-current-repl 'any 'ensure))
abort-on-input))
abort-on-input
nil
callback))

(defun cider-nrepl-send-unhandled-request (request &optional connection)
"Send REQUEST to the nREPL CONNECTION and ignore any responses.
Expand Down Expand Up @@ -342,6 +346,17 @@ The default value in nREPL is 1024."
:group 'cider
:package-version '(cider . "0.25.0"))

(defcustom cider-download-sources-jars nil
"Whether to automatically download source artifacts for 3rd-party Java classes.
When enabled, CIDER will attempt to download source JARs from Maven for
Java classes if the source file is not found locally. This downloading only
happens once per artifact, and only when the user jumps to the definition
or requests `cider-doc' on a Java class or a member of the class."
:type 'boolean
:group 'cider
:package-version '(cider . "1.17.0"))

(defun cider--print-fn ()
"Return the value to send in the nrepl.middleware.print/print slot."
(pcase cider-print-fn
Expand Down Expand Up @@ -681,13 +696,25 @@ CONTEXT represents a completion context for compliment."

(defun cider-sync-request:info (symbol &optional class member context)
"Send \"info\" op with parameters SYMBOL or CLASS and MEMBER, honor CONTEXT."
(let ((var-info (thread-first `("op" "info"
"ns" ,(cider-current-ns)
,@(when symbol `("sym" ,symbol))
,@(when class `("class" ,class))
,@(when member `("member" ,member))
,@(when context `("context" ,context)))
(cider-nrepl-send-sync-request (cider-current-repl)))))
(let* ((req
`("op" "info"
"ns" ,(cider-current-ns)
,@(when symbol `("sym" ,symbol))
,@(when class `("class" ,class))
,@(when member `("member" ,member))
,@(when context `("context" ,context))
,@(when cider-download-sources-jars `("download-sources-jar" "1"))))
(callback
(lambda (resp)
(let ((status (nrepl-dict-get resp "status"))
(coords (nrepl-dict-get resp "coords")))
(when (member "download-sources-jar" status)
(message "Local source not found, downloading Java sources for artifact %s/%s %s..."
(nrepl-dict-get coords "group")
(nrepl-dict-get coords "artifact")
(nrepl-dict-get coords "version"))))))
(var-info
(cider-nrepl-send-sync-request req (cider-current-repl) nil callback)))
(if (member "no-info" (nrepl-dict-get var-info "status"))
nil
var-info)))
Expand Down
18 changes: 11 additions & 7 deletions nrepl-client.el
Original file line number Diff line number Diff line change
Expand Up @@ -939,21 +939,25 @@ the standard session."
(declare-function cider-repl-emit-interactive-stderr "cider-repl")
(declare-function cider--render-stacktrace-causes "cider-eval")

(defun nrepl-send-sync-request (request connection &optional abort-on-input tooling)
(defun nrepl-send-sync-request (request connection &optional abort-on-input
tooling callback)
"Send REQUEST to the nREPL server synchronously using CONNECTION.
Hold till final \"done\" message has arrived and join all response messages
of the same \"op\" that came along.
If ABORT-ON-INPUT is non-nil, the function will return nil at the first
sign of user input, so as not to hang the interface.
If TOOLING, use the tooling session rather than the standard session."
If TOOLING, use the tooling session rather than the standard session.
If CALLBACK is non-nil, it will additionally be called on all received messages."
(let* ((time0 (current-time))
(response (cons 'dict nil))
(nrepl-ongoing-sync-request t)
(cb (lambda (resp)
;; If caller has provided `callback', call it on the response.
(when callback
(funcall callback resp))
(nrepl--merge response resp)))
status)
(nrepl-send-request request
(lambda (resp) (nrepl--merge response resp))
connection
tooling)
(nrepl-send-request request cb connection tooling)
(while (and (not (member "done" status))
(not (and abort-on-input
(input-pending-p))))
Expand All @@ -962,7 +966,7 @@ If TOOLING, use the tooling session rather than the standard session."
;; anywhere, and we'll just timeout. So we forward it to the user.
(if (member "need-input" status)
(progn (cider-need-input (current-buffer))
;; If the used took a few seconds to respond, we might
;; If the user took a few seconds to respond, we might
;; unnecessarily timeout, so let's reset the timer.
(setq time0 (current-time)))
;; break out in case we don't receive a response for a while
Expand Down

0 comments on commit 7db186f

Please sign in to comment.