diff --git a/CHANGELOG.md b/CHANGELOG.md index f50e79da8..963e4958c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Bump the injected nREPL version to 1.3. - Bump the injected `cider-nrepl` to [0.49.3](https://github.com/clojure-emacs/cider-nrepl/blob/master/CHANGELOG.md#0493-2024-08-13). +- [#3733](https://github.com/clojure-emacs/cider/issues/3733): Remove support for sideloading. (this experimental feature was removed from nREPL 1.3) ### Bugs fixed diff --git a/ROADMAP.md b/ROADMAP.md index 3f6bab656..bcdff55dc 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -49,7 +49,6 @@ There's a bit of info on the subject [here](https://github.com/clojure-emacs/cid ## Implement new nREPL features -* sideloading (there's some experimental support for this) * dynamic middleware loading * ~~completion~~ * ~~lookup~~ diff --git a/cider-eval.el b/cider-eval.el index 0a422fe43..e5a68c464 100644 --- a/cider-eval.el +++ b/cider-eval.el @@ -204,190 +204,6 @@ When invoked with a prefix ARG the command doesn't prompt for confirmation." (save-excursion (quit-window nil error-win)))) - -;;; Sideloader -;; -;; nREPL includes sideloader middleware which provides a Java classloader that -;; is able to dynamically load classes and resources at runtime by interacting -;; with the nREPL client (as opposed to using the classpath of the JVM hosting -;; nREPL server). -;; -;; This performs a similar functionality as the load-file -;; operation, where we can load Clojure namespaces (as source files) or Java -;; classes (as bytecode) by simply requiring or importing them. -;; -;; See https://nrepl.org/nrepl/design/middleware.html#sideloading - -(defcustom cider-sideloader-path nil - "List of directories and jar files to scan for sideloader resources. -When not set the cider-nrepl jar will be added automatically when upgrading -an nREPL connection." - :type 'list - :group 'cider - :package-version '(cider . "1.2.0")) - -(defcustom cider-dynload-cider-nrepl-version nil - "Version of the cider-nrepl jar used for dynamically upgrading a connection. -Defaults to `cider-required-middleware-version'." - :type 'string - :group 'cider - :package-version '(cider . "1.2.0")) - -(defun cider-read-bytes (path) - "Read binary data from PATH. -Return the binary data as unibyte string." - ;; based on f-read-bytes - (with-temp-buffer - (set-buffer-multibyte nil) - (setq buffer-file-coding-system 'binary) - (insert-file-contents-literally path nil) - (buffer-substring-no-properties (point-min) (point-max)))) - -(defun cider-retrieve-resource (dirs name) - "Find a resource NAME in a list DIRS of directories or jar files. -Similar to a classpath lookup. Returns the file contents as a string." - (seq-some - (lambda (path) - (cond - ((file-directory-p path) - (let ((expanded (expand-file-name name path))) - (when (file-exists-p expanded) - (cider-read-bytes expanded)))) - ((and (file-exists-p path) (string-suffix-p ".jar" path)) - (cider-jar-retrieve-resource path name)))) - dirs)) - -(defun cider-provide-file (file) - "Provide FILE in a format suitable for sideloading." - (let ((contents (cider-retrieve-resource cider-sideloader-path file))) - (if contents - (base64-encode-string contents 'no-line-breaks) - ;; if we can't find the file we should return an empty string - (base64-encode-string "")))) - -(defun cider-sideloader-lookup-handler () - "Make a sideloader-lookup handler." - (lambda (response) - (nrepl-dbind-response response (id status type name) - (if status - (when (member "sideloader-lookup" status) - (cider-request:sideloader-provide id type name)))))) - -(defun cider-add-middleware-handler (continue) - "Make a add-middleware handler. -CONTINUE is an optional continuation function." - (lambda (response) - (nrepl-dbind-response response (status unresolved-middleware) ;; id middleware - (when unresolved-middleware - (seq-do - (lambda (mw) - (cider-repl-emit-interactive-stderr - (concat "WARNING: middleware " mw " was not found or failed to load.\n"))) - unresolved-middleware)) - (when (and status (member "done" status) continue) - (funcall continue))))) - -(defun cider-request:sideloader-start (&optional connection tooling) - "Perform the nREPL \"sideloader-start\" op. -If CONNECTION is nil, use `cider-current-repl'. -If TOOLING is truthy then the operation is performed over the tooling -session, rather than the regular session." - (cider-ensure-op-supported "sideloader-start") - (cider-nrepl-send-request `("op" "sideloader-start") - (cider-sideloader-lookup-handler) - connection - tooling)) - -(defun cider-request:sideloader-provide (id type file &optional connection) - "Perform the nREPL \"sideloader-provide\" op for ID, TYPE and FILE. -If CONNECTION is nil, use `cider-current-repl'." - (cider-nrepl-send-request `("id" ,id - "op" "sideloader-provide" - "type" ,type - "name" ,file - "content" ,(cider-provide-file file)) - (cider-sideloader-lookup-handler) - connection)) - -(defun cider-sideloader-start (&optional connection) - "Start nREPL's sideloader. -If CONNECTION is nil, use `cider-current-repl'." - (interactive) - (message "Starting nREPL's sideloader") - (cider-request:sideloader-start connection) - (cider-request:sideloader-start connection 'tooling)) - -(defvar cider-nrepl-middlewares - '("cider.nrepl/wrap-apropos" - "cider.nrepl/wrap-classpath" - "cider.nrepl/wrap-clojuredocs" - "cider.nrepl/wrap-complete" - "cider.nrepl/wrap-content-type" - "cider.nrepl/wrap-debug" - "cider.nrepl/wrap-enlighten" - "cider.nrepl/wrap-format" - "cider.nrepl/wrap-info" - "cider.nrepl/wrap-inspect" - "cider.nrepl/wrap-log" - "cider.nrepl/wrap-macroexpand" - "cider.nrepl/wrap-ns" - "cider.nrepl/wrap-out" - "cider.nrepl/wrap-slurp" - "cider.nrepl/wrap-profile" - "cider.nrepl/wrap-refresh" - "cider.nrepl/wrap-resource" - "cider.nrepl/wrap-spec" - "cider.nrepl/wrap-stacktrace" - "cider.nrepl/wrap-test" - "cider.nrepl/wrap-trace" - "cider.nrepl/wrap-tracker" - "cider.nrepl/wrap-undef" - "cider.nrepl/wrap-version" - "cider.nrepl/wrap-xref")) - -(defun cider-request:add-middleware (middlewares - &optional connection tooling continue) - "Use the nREPL dynamic loader to add MIDDLEWARES to the nREPL session. - -- If CONNECTION is nil, use `cider-current-repl'. -- If TOOLING it truthy, use the tooling session instead of the main session. -- CONTINUE is an optional continuation function, which will be called when the -add-middleware op has finished successfully." - (cider-nrepl-send-request `("op" "add-middleware" - "middleware" ,middlewares) - (cider-add-middleware-handler continue) - connection - tooling)) - -(defun cider-add-cider-nrepl-middlewares (&optional connection) - "Use dynamic loading to add the cider-nrepl middlewares to nREPL. -If CONNECTION is nil, use `cider-current-repl'." - (cider-request:add-middleware - cider-nrepl-middlewares connection nil - (lambda () - ;; When the main session is done adding middleware, then do the tooling - ;; session. At this point all the namespaces have been sideloaded so this - ;; is faster, we don't want these to race to sideload resources. - (cider-request:add-middleware - cider-nrepl-middlewares connection 'tooling - (lambda () - ;; Ask nREPL again what its capabilities are, so we know which new - ;; operations are supported. - (nrepl--init-capabilities (or connection (cider-current-repl)))))))) - -(defvar cider-required-middleware-version) -(defun cider-upgrade-nrepl-connection (&optional connection) - "Sideload cider-nrepl middleware. -If CONNECTION is nil, use `cider-current-repl'." - (interactive) - (when (not cider-sideloader-path) - (setq cider-sideloader-path (list (cider-jar-find-or-fetch - "cider" "cider-nrepl" - (or cider-dynload-cider-nrepl-version - cider-required-middleware-version))))) - (cider-sideloader-start connection) - (cider-add-cider-nrepl-middlewares connection)) - ;;; Dealing with compilation (evaluation) errors and warnings (defun cider-find-property (property &optional backward) diff --git a/cider-repl.el b/cider-repl.el index 675db2e28..9fd17c4f6 100644 --- a/cider-repl.el +++ b/cider-repl.el @@ -1692,7 +1692,6 @@ constructs." (declare-function cider-version "cider") (declare-function cider-test-run-loaded-tests "cider-test") (declare-function cider-test-run-project-tests "cider-test") -(declare-function cider-sideloader-start "cider-eval") (cider-repl-add-shortcut "clear-output" #'cider-repl-clear-output) (cider-repl-add-shortcut "clear" #'cider-repl-clear-buffer) (cider-repl-add-shortcut "clear-banners" #'cider-repl-clear-banners) @@ -1706,7 +1705,6 @@ constructs." (cider-repl-add-shortcut "classpath" #'cider-classpath) (cider-repl-add-shortcut "history" #'cider-repl-history) (cider-repl-add-shortcut "trace-ns" #'cider-toggle-trace-ns) -(cider-repl-add-shortcut "sideloader-start" #'cider-sideloader-start) (cider-repl-add-shortcut "undef" #'cider-undef) (cider-repl-add-shortcut "refresh" #'cider-ns-refresh) (cider-repl-add-shortcut "reload" #'cider-ns-reload) diff --git a/test/cider-eval-tests.el b/test/cider-eval-tests.el index 113012d08..fda7b7a23 100644 --- a/test/cider-eval-tests.el +++ b/test/cider-eval-tests.el @@ -30,26 +30,6 @@ ;; Please, for each `describe', ensure there's an `it' block, so that its execution is visible in CI. -(describe "cider-provide-file" - (let ((tmp-dir (temporary-file-directory))) - (it "returns an empty string when the file is not found" - (expect (cider-provide-file "abc.clj") :to-equal "")) - (it "base64 encodes without newlines" - (let ((cider-sideloader-path (list tmp-dir)) - (default-directory tmp-dir) - (filename (make-temp-file "abc.clj"))) - (with-temp-file filename - (dotimes (_ 60) (insert "x"))) - (expect (cider-provide-file filename) :not :to-match "\n"))) - (it "can handle multibyte characters" - (let ((cider-sideloader-path (list tmp-dir)) - (default-directory tmp-dir) - (filename (make-temp-file "abc.clj")) - (coding-system-for-write 'utf-8-unix)) - (with-temp-file filename - (insert "🍻")) - (expect (cider-provide-file filename) :to-equal "8J+Nuw=="))))) - (describe "cider-extract-error-info" (it "Matches Clojure compilation exceptions" (expect (cider-extract-error-info cider-compilation-regexp "Syntax error compiling clojure.core/let at (src/haystack/analyzer.clj:18:1).\n[1] - failed: even-number-of-forms? at: [:bindings] spec: :clojure.core.specs.alpha/bindings\n")