From dd02d791572988f0cf95cb07b0c09925cd28bc72 Mon Sep 17 00:00:00 2001 From: Oleksandr Yakushev Date: Fri, 19 Sep 2025 10:42:33 +0300 Subject: [PATCH 1/9] Bump Orchard to 0.37.0 --- CHANGELOG.md | 2 ++ project.clj | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1c959cc4..ad87ed113 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) +* Bump `orchard` to [0.37.0](https://github.com/clojure-emacs/orchard/blob/master/CHANGELOG.md#0370-2025-09-19). + ## 0.57.0 (2025-06-29) * Bump `orchard` to [0.36.0](https://github.com/clojure-emacs/orchard/blob/master/CHANGELOG.md#0360-2025-06-29). diff --git a/project.clj b/project.clj index b7516355b..9f699bc12 100644 --- a/project.clj +++ b/project.clj @@ -20,8 +20,8 @@ :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :scm {:name "git" :url "https://github.com/clojure-emacs/cider-nrepl"} - :dependencies [[nrepl/nrepl "1.3.1" :exclusions [org.clojure/clojure]] - [cider/orchard "0.36.0" :exclusions [org.clojure/clojure]] + :dependencies [[nrepl/nrepl "1.4.0" :exclusions [org.clojure/clojure]] + [cider/orchard "0.37.0" :exclusions [org.clojure/clojure]] ^:inline-dep [compliment "0.7.0"] ^:inline-dep [org.rksm/suitable "0.6.2" :exclusions [org.clojure/clojure org.clojure/clojurescript]] @@ -78,13 +78,13 @@ :password :env/clojars_password :sign-releases false}]] - :profiles {:provided {:dependencies [[org.clojure/clojure "1.12.0"]]} + :profiles {:provided {:dependencies [[org.clojure/clojure "1.12.2"]]} :1.10 {:dependencies [[org.clojure/clojure "1.10.3"] [org.clojure/clojurescript "1.10.520" :scope "provided"]]} :1.11 {:dependencies [[org.clojure/clojure "1.11.4"] [org.clojure/clojurescript "1.11.60" :scope "provided"]]} - :1.12 {:dependencies [[org.clojure/clojure "1.12.0"] + :1.12 {:dependencies [[org.clojure/clojure "1.12.2"] [org.clojure/clojurescript "1.11.132" :scope "provided"]]} :maint {:source-paths ["src" "maint"] From f320d90b837e2c2a7a1134f53c6a2d9532086655 Mon Sep 17 00:00:00 2001 From: Oleksandr Yakushev Date: Fri, 19 Sep 2025 11:35:23 +0300 Subject: [PATCH 2/9] Bump Compliment to 0.7.1 --- CHANGELOG.md | 1 + project.clj | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad87ed113..7cb57a1ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## master (unreleased) * Bump `orchard` to [0.37.0](https://github.com/clojure-emacs/orchard/blob/master/CHANGELOG.md#0370-2025-09-19). +* Bump `compliment` to [0.7.1](https://github.com/alexander-yakushev/compliment/blob/master/CHANGELOG.md#071-2025-09-19). ## 0.57.0 (2025-06-29) diff --git a/project.clj b/project.clj index 9f699bc12..e23abab0c 100644 --- a/project.clj +++ b/project.clj @@ -22,7 +22,7 @@ :scm {:name "git" :url "https://github.com/clojure-emacs/cider-nrepl"} :dependencies [[nrepl/nrepl "1.4.0" :exclusions [org.clojure/clojure]] [cider/orchard "0.37.0" :exclusions [org.clojure/clojure]] - ^:inline-dep [compliment "0.7.0"] + ^:inline-dep [compliment "0.7.1"] ^:inline-dep [org.rksm/suitable "0.6.2" :exclusions [org.clojure/clojure org.clojure/clojurescript]] ^:inline-dep [cljfmt "0.9.2" :exclusions [org.clojure/clojurescript From ceb934c09188225628ca43db5715dfd44613b323 Mon Sep 17 00:00:00 2001 From: Oleksandr Yakushev Date: Fri, 19 Sep 2025 11:30:58 +0300 Subject: [PATCH 3/9] [ci] Use latest images --- .circleci/config.yml | 10 +++++----- Makefile | 2 -- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 99240b31f..052e13769 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,23 +16,23 @@ defaults: &defaults executors: jdk8: docker: - - image: clojure:temurin-8-lein-2.11.2-noble + - image: clojure:temurin-8-lein-2.12.0-noble <<: *defaults jdk11: docker: - - image: clojure:temurin-11-lein-2.11.2-noble + - image: clojure:temurin-11-lein-2.12.0-noble <<: *defaults jdk17: docker: - - image: clojure:temurin-17-lein-2.11.2-noble + - image: clojure:temurin-17-lein-2.12.0-noble <<: *defaults jdk21: docker: - - image: clojure:temurin-21-lein-2.11.2-noble + - image: clojure:temurin-21-lein-2.12.0-noble <<: *defaults jdk24: docker: - - image: clojure:temurin-24-lein-2.11.2-noble + - image: clojure:temurin-24-lein-2.12.0-noble <<: *defaults # Runs a given set of steps, with some standard pre- and post- diff --git a/Makefile b/Makefile index f01a1229d..b3e02b78a 100644 --- a/Makefile +++ b/Makefile @@ -67,12 +67,10 @@ lint: kondo cljfmt eastwood # PROJECT_VERSION=x.y.z make install install: dump-version check-install-env target/srcdeps CIDER_NO_PEDANTIC="true" lein with-profile -user,-dev,+$(CLOJURE_VERSION),+plugin.mranderson/config install - git checkout resources/cider/nrepl/version.edn # PROJECT_VERSION=x.y.z make fast-install fast-install: dump-version check-install-env lein with-profile -user,-dev,+$(CLOJURE_VERSION) install - git checkout resources/cider/nrepl/version.edn smoketest: install cd test/smoketest && \ From 0eb5ec655c40d4531a449983c5fc17126a9fccdf Mon Sep 17 00:00:00 2001 From: Oleksandr Yakushev Date: Fri, 19 Sep 2025 15:10:00 +0300 Subject: [PATCH 4/9] [inspect] Tidy qualified keywords --- CHANGELOG.md | 1 + src/cider/nrepl/middleware/inspect.clj | 13 ++++--- .../cider/nrepl/middleware/inspect_test.clj | 34 +++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cb57a1ec..88dad4fcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Bump `orchard` to [0.37.0](https://github.com/clojure-emacs/orchard/blob/master/CHANGELOG.md#0370-2025-09-19). * Bump `compliment` to [0.7.1](https://github.com/alexander-yakushev/compliment/blob/master/CHANGELOG.md#071-2025-09-19). +* [#950](https://github.com/clojure-emacs/cider-nrepl/pull/950): Inspect: support tidying qualified keywords. ## 0.57.0 (2025-06-29) diff --git a/src/cider/nrepl/middleware/inspect.clj b/src/cider/nrepl/middleware/inspect.clj index d210fa38e..5e5a7239d 100644 --- a/src/cider/nrepl/middleware/inspect.clj +++ b/src/cider/nrepl/middleware/inspect.clj @@ -39,10 +39,15 @@ m keys)) (defn- msg->inspector-config [msg] - (-> (select-keys msg [:page-size :max-atom-length :max-coll-size - :max-value-length :max-nested-depth :display-analytics-hint - :pretty-print :sort-maps :only-diff]) - (booleanize [:pretty-print :sort-maps :only-diff]))) + (as-> msg config + (select-keys config [:page-size :sort-maps :max-atom-length :max-coll-size + :max-value-length :max-nested-depth :pretty-print + :display-analytics-hint :only-diff]) + (booleanize config [:pretty-print :sort-maps :only-diff]) + (let [pov-ns (when (= (:tidy-qualified-keywords msg) "true") + (some-> msg :ns symbol))] + (cond-> config + pov-ns (assoc :pov-ns pov-ns))))) (defn inspect-reply* [{:keys [view-mode] :as msg} value] (let [config (msg->inspector-config msg) diff --git a/test/clj/cider/nrepl/middleware/inspect_test.clj b/test/clj/cider/nrepl/middleware/inspect_test.clj index b6be55194..c51c51aba 100644 --- a/test/clj/cider/nrepl/middleware/inspect_test.clj +++ b/test/clj/cider/nrepl/middleware/inspect_test.clj @@ -554,6 +554,40 @@ " ●normal table object pretty sort-maps"] (value-skip-header (session/message {:op "inspect-toggle-pretty-print"})))))) +(deftest tidy-qualified-keywords-integration-test + (testing "tidy keywords disabled" + (is+ ["--- Contents:" [:newline] + " 0. " [:value ":cider.nrepl.middleware.inspect-test/own-kw" pos?]] + (-> (session/message {:op "eval" + :inspect "true" + :ns "cider.nrepl.middleware.inspect-test" + :code "[::own-kw]"}) + value (section "Contents"))) + (is+ ["--- Contents:" [:newline] + " 0. " [:value ":clojure.string/alias-kw" pos?]] + (-> (session/message {:op "eval" + :inspect "true" + :ns "cider.nrepl.middleware.inspect-test" + :code "[::str/alias-kw]"}) + value (section "Contents")))) + (testing "tidy keywords enabled" + (is+ ["--- Contents:" [:newline] + " 0. " [:value "::own-kw" pos?]] + (-> (session/message {:op "eval" + :inspect "true" + :tidy-qualified-keywords "true" + :ns "cider.nrepl.middleware.inspect-test" + :code "[::own-kw]"}) + value (section "Contents"))) + (is+ ["--- Contents:" [:newline] + " 0. " [:value "::str/alias-kw" pos?]] + (-> (session/message {:op "eval" + :inspect "true" + :tidy-qualified-keywords "true" + :ns "cider.nrepl.middleware.inspect-test" + :code "[::str/alias-kw]"}) + value (section "Contents"))))) + (deftest print-length-independence-test (testing "*print-length* doesn't break rendering of long collections" (is (re-find #"showing page: \d+ of \d+" From 149e687909f31dc730620d37398afeb7e59be917 Mon Sep 17 00:00:00 2001 From: Oleksandr Yakushev Date: Mon, 29 Sep 2025 11:45:21 +0300 Subject: [PATCH 5/9] [ci] Test against JDK25 --- .circleci/config.yml | 12 ++++++------ Makefile | 4 ++-- doc/modules/ROOT/pages/compatibility.adoc | 22 ++++++++-------------- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 052e13769..1e2c9ae35 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,9 +30,9 @@ executors: docker: - image: clojure:temurin-21-lein-2.12.0-noble <<: *defaults - jdk24: + jdk25: docker: - - image: clojure:temurin-24-lein-2.12.0-noble + - image: clojure:temurin-25-lein-2.12.0-noble <<: *defaults # Runs a given set of steps, with some standard pre- and post- @@ -82,7 +82,7 @@ commands: - base-src-jdk11.zip - base-src-jdk17.zip - base-src-jdk21.zip - - base-src-jdk24.zip + - base-src-jdk25.zip key: clojure-<< parameters.cache_version >>-{{ checksum "/tmp/clojure_cache_seed" }} # The jobs are relatively simple. One runs utility commands against @@ -93,7 +93,7 @@ jobs: lint: description: | Running linters - executor: jdk24 + executor: jdk25 environment: CLOJURE_VERSION: "1.12" steps: @@ -199,7 +199,7 @@ workflows: alias: "test" parameters: clojure_version: ["1.10", "1.11", "1.12"] - jdk_version: [jdk8, jdk11, jdk17, jdk21, jdk24] + jdk_version: [jdk8, jdk11, jdk17, jdk21, jdk25] <<: *run_always - full-test: # Full tests against selected versions. @@ -207,7 +207,7 @@ workflows: alias: "full-test" parameters: clojure_version: ["1.12"] - jdk_version: [jdk8, jdk24] + jdk_version: [jdk8, jdk25] <<: *run_always - lint: <<: *run_always diff --git a/Makefile b/Makefile index b3e02b78a..b2894bc79 100644 --- a/Makefile +++ b/Makefile @@ -25,8 +25,8 @@ base-src-jdk17.zip: base-src-jdk21.zip: bash .circleci/download-jdk-sources.sh https://github.com/adoptium/jdk21u/archive/refs/tags/jdk-21.0.7+5.zip jdk21 $@ -base-src-jdk24.zip: - bash .circleci/download-jdk-sources.sh https://github.com/adoptium/jdk/archive/refs/tags/jdk-24+36.zip jdk24 $@ +base-src-jdk25.zip: + bash .circleci/download-jdk-sources.sh https://github.com/adoptium/jdk/archive/refs/tags/jdk-25+36.zip jdk25 $@ copy-sources-to-jdk: base-src-$(JDK_SRC_VERSION).zip mkdir -p $(JAVA_HOME)/lib && cp base-src-$(JDK_SRC_VERSION).zip $(JAVA_HOME)/lib/src.zip diff --git a/doc/modules/ROOT/pages/compatibility.adoc b/doc/modules/ROOT/pages/compatibility.adoc index 1d9a485c7..d33697d65 100644 --- a/doc/modules/ROOT/pages/compatibility.adoc +++ b/doc/modules/ROOT/pages/compatibility.adoc @@ -2,9 +2,13 @@ == Java -`cider-nrepl` officially targets Java 8, 11, 17, 21, and the most recent release -version. More generally speaking - we aim to support all Java releases that are -currently officially supported by Oracle. +`cider-nrepl` officially targets Java 8, 11, 17, 21, 25, and the most recent +release version. More generally speaking - we aim to support all Java releases +that are currently officially supported by Oracle. + +NOTE: Java 8 is soft-deprecated in Orchard (and hence cider-nrepl). Core +cider-nrepl functionality continues to work on JDK 8, but these following +features don't: *Java sources parsing*. == Clojure @@ -29,7 +33,7 @@ Currently `cider-nrepl` requires Piggieback 0.4+ to work properly. == nREPL -`cider-nrepl` supports nREPL 0.6+. +`cider-nrepl` supports nREPL 1.0+. NOTE: We pay special attention to supporting whatever nREPL is bundled with the current stable Leiningen release. @@ -45,16 +49,6 @@ given compatibility tuple. |=== | cider-nrepl | Required JDK | Required Clojure | Required nREPL -| 0.19 -| 8 -| 1.8 -| 0.2.13 - -| 0.20 -| 8 -| 1.8 -| 0.4.x - | 0.25 | 8 | 1.8 From b87d068d650cece660701b086e95a42b13d55c5c Mon Sep 17 00:00:00 2001 From: Oleksandr Yakushev Date: Mon, 29 Sep 2025 11:49:49 +0300 Subject: [PATCH 6/9] Bump dependencies --- project.clj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/project.clj b/project.clj index e23abab0c..976e94b81 100644 --- a/project.clj +++ b/project.clj @@ -27,9 +27,9 @@ org.clojure/clojurescript]] ^:inline-dep [cljfmt "0.9.2" :exclusions [org.clojure/clojurescript org.clojure/tools.cli]] - ^:inline-dep [org.clojure/tools.namespace "1.3.0" :exclusions [org.clojure/clojurescript + ^:inline-dep [org.clojure/tools.namespace "1.5.0" :exclusions [org.clojure/clojurescript org.clojure/tools.cli]] - ^:inline-dep [io.github.tonsky/clj-reload "0.6.0" :exclusions [org.clojure/clojure]] + ^:inline-dep [io.github.tonsky/clj-reload "1.0.0" :exclusions [org.clojure/clojure]] ^:inline-dep [org.clojure/tools.reader "1.4.1"] [mx.cider/logjam "0.3.0" :exclusions [org.clojure/clojure]]] ; see Clojure version matrix in profiles below @@ -85,10 +85,10 @@ :1.11 {:dependencies [[org.clojure/clojure "1.11.4"] [org.clojure/clojurescript "1.11.60" :scope "provided"]]} :1.12 {:dependencies [[org.clojure/clojure "1.12.2"] - [org.clojure/clojurescript "1.11.132" :scope "provided"]]} + [org.clojure/clojurescript "1.12.42" :scope "provided"]]} :maint {:source-paths ["src" "maint"] - :dependencies [[org.clojure/tools.cli "1.1.230"]]} + :dependencies [[org.clojure/tools.cli "1.2.245"]]} :dev ~dev-test-common-profile From b9ff56fa3e911dda736ed144fe3e8799b6a3c436 Mon Sep 17 00:00:00 2001 From: Oleksandr Yakushev Date: Tue, 30 Sep 2025 00:48:05 +0300 Subject: [PATCH 7/9] [test] Fix tests --- .../cider/nrepl/middleware/reload_test.clj | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/clj/cider/nrepl/middleware/reload_test.clj b/test/clj/cider/nrepl/middleware/reload_test.clj index d9a292c4d..699ff0255 100644 --- a/test/clj/cider/nrepl/middleware/reload_test.clj +++ b/test/clj/cider/nrepl/middleware/reload_test.clj @@ -2,8 +2,10 @@ (:require [cider.nrepl.middleware.reload :as rl] [cider.nrepl.test-session :as session] + [cider.test-helpers :refer :all] [clojure.string :as str] - [clojure.test :refer :all])) + [clojure.test :refer :all] + [matcher-combinators.matchers :as mc])) (use-fixtures :each session/session-fixture) @@ -29,21 +31,19 @@ ;; but the message does come from clj-reload.core/reload. ;; It's two separate messages, but in (:progress response) they are ;; concatenated. - (is (= "Nothing to unloadNothing to reload" (:progress response))) - (is (= #{"done" "ok"} (:status response)))))) + (is+ {:progress #"Reloading 0 namespaces\.\.\.Reloaded 0 namespaces in \d+ ms" + :status #{"done" "ok"}} + response)))) (deftest reload-all-op-test (testing "reload-all op works" - (let [response (session/message {:op "cider.clj-reload/reload-all"}) - progress-str (:progress response)] - (is (str/includes? progress-str "Unloading cider.nrepl.middleware.util.meta-test")) - (is (str/includes? progress-str "Loading cider.nrepl.middleware.util.meta-test")) - (is (= #{"done" "ok"} (:status response)))))) + (is+ {:progress (mc/all-of #"Reloading 3 namespaces" + #"Reloaded 3 namespaces in \d+ ms") + :status #{"done" "ok"}} + (session/message {:op "cider.clj-reload/reload-all"})))) (deftest reload-clear-op-test (testing "reload-all op works" - (let [response (session/message {:op "cider.clj-reload/reload-clear"})] - (is (seq (:progress response))) - (is (= "Nothing to unload" (:progress response))) - (is (= #{"done" "ok"} (:status response)))))) - + (is+ {:progress "Reloading 0 namespaces..." + :status #{"done" "ok"}} + (session/message {:op "cider.clj-reload/reload-clear"})))) From 4fbcc0c6614021f031e363e992b6b5f26190999f Mon Sep 17 00:00:00 2001 From: Oleksandr Yakushev Date: Thu, 9 Oct 2025 13:06:48 +0300 Subject: [PATCH 8/9] [ci] Test against multiple nREPL versions --- .circleci/config.yml | 17 ++++++++++++++++- Makefile | 30 +++++++++++++++--------------- project.clj | 12 ++++++++---- test/clj/cider/nrepl_test.clj | 11 ++++++++--- 4 files changed, 47 insertions(+), 23 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1e2c9ae35..e67e373dc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -137,14 +137,19 @@ jobs: clojure_version: description: Version of Clojure to test against type: string + nrepl_version: + description: Version of nREPL to test against + type: string + default: "1.4" executor: << parameters.jdk_version >> environment: CLOJURE_VERSION: << parameters.clojure_version >> JDK_SRC_VERSION: << parameters.jdk_version >> + NREPL_VERSION: << parameters.nrepl_version >> steps: - checkout - with_cache: - cache_version: "test_v1_<< parameters.clojure_version >>_<< parameters.jdk_version >>" + cache_version: "test_v1_<< parameters.clojure_version >>_<< parameters.jdk_version >>_<< parameters.nrepl_version >>" steps: - run: name: Running quick tests @@ -209,12 +214,22 @@ workflows: clojure_version: ["1.12"] jdk_version: [jdk8, jdk25] <<: *run_always + - test: + # Test against multiple nREPL versions. + matrix: + alias: "nrepl-test" + parameters: + clojure_version: ["1.12"] + jdk_version: [jdk25] + nrepl_version: ["1.0", "1.3", "1.4"] + <<: *run_always - lint: <<: *run_always - deploy: requires: - test - full-test + - nrepl-test - lint filters: branches: diff --git a/Makefile b/Makefile index b2894bc79..512880740 100644 --- a/Makefile +++ b/Makefile @@ -3,9 +3,11 @@ # Set bash instead of sh for the @if [[ conditions, # and use the usual safety flags: -SHELL = /bin/bash -Ee +SHELL = /bin/bash -Eex CLOJURE_VERSION ?= 1.12 +NREPL_VERSION ?= 1.4 +COMMON_PROFILES = "+$(CLOJURE_VERSION),+nrepl-$(NREPL_VERSION)" TEST_PROFILES ?= "-user,-dev,+test" # We need Java sources to test Java parsing functionality, but the Docker images @@ -39,42 +41,40 @@ target/srcdeps: project.clj # Remove cljfmt.main because it depends on tools.cli which we explicitly removed. rm -f target/srcdeps/cider/nrepl/inlined/deps/cljfmt/*/cljfmt/main.clj -test_impl: copy-sources-to-jdk - lein with-profile $(TEST_PROFILES),+$(CLOJURE_VERSION) test +quick-test: copy-sources-to-jdk + lein with-profile $(COMMON_PROFILES),$(TEST_PROFILES) test test: target/srcdeps - @make test_impl TEST_PROFILES="$(TEST_PROFILES),+plugin.mranderson/config" - -quick-test: test_impl + lein with-profile $(COMMON_PROFILES),$(TEST_PROFILES),+plugin.mranderson/config test eastwood: - lein with-profile -user,-dev,+$(CLOJURE_VERSION),+deploy,+eastwood eastwood + lein with-profile -user,-dev,$(COMMON_PROFILES),+deploy,+eastwood eastwood cljfmt: - lein with-profile -user,-dev,+$(CLOJURE_VERSION),+cljfmt cljfmt check + lein with-profile -user,-dev,$(COMMON_PROFILES),+cljfmt cljfmt check cljfmt-fix: - lein with-profile -user,-dev,+$(CLOJURE_VERSION),+cljfmt cljfmt fix + lein with-profile -user,-dev,$(COMMON_PROFILES),+cljfmt cljfmt fix .make_kondo_prep: project.clj .clj-kondo/config.edn - CIDER_NO_MRANDERSON="true" CIDER_NO_PEDANTIC="true" lein with-profile -user,-dev,+test,+clj-kondo,+deploy,+$(CLOJURE_VERSION) clj-kondo --copy-configs --dependencies --lint '$$classpath' > $@ + CIDER_NO_MRANDERSON="true" CIDER_NO_PEDANTIC="true" lein with-profile -user,-dev,+test,+clj-kondo,+deploy,$(COMMON_PROFILES) clj-kondo --copy-configs --dependencies --lint '$$classpath' > $@ kondo: .make_kondo_prep clean - CIDER_NO_MRANDERSON="true" CIDER_NO_PEDANTIC="true" lein with-profile -user,-dev,+test,+clj-kondo,+deploy,+$(CLOJURE_VERSION) clj-kondo + CIDER_NO_MRANDERSON="true" CIDER_NO_PEDANTIC="true" lein with-profile -user,-dev,+test,+clj-kondo,+deploy,$(COMMON_PROFILES) clj-kondo lint: kondo cljfmt eastwood # PROJECT_VERSION=x.y.z make install install: dump-version check-install-env target/srcdeps - CIDER_NO_PEDANTIC="true" lein with-profile -user,-dev,+$(CLOJURE_VERSION),+plugin.mranderson/config install + CIDER_NO_PEDANTIC="true" lein with-profile -user,-dev,$(COMMON_PROFILES),+plugin.mranderson/config install # PROJECT_VERSION=x.y.z make fast-install fast-install: dump-version check-install-env - lein with-profile -user,-dev,+$(CLOJURE_VERSION) install + lein with-profile -user,-dev,$(COMMON_PROFILES) install smoketest: install cd test/smoketest && \ - lein with-profile -user,-dev,+$(CLOJURE_VERSION) uberjar && \ + lein with-profile -user,-dev,$(COMMON_PROFILES) uberjar && \ java -jar target/smoketest-0.1.0-SNAPSHOT-standalone.jar # Deployment is performed via CI by creating a git tag prefixed with "v". @@ -87,7 +87,7 @@ deploy: check-env target/srcdeps rm -f .no-mranderson export PROJECT_VERSION=$$(echo "$(CIRCLE_TAG)" | sed 's/^v//'); \ echo "\"$$PROJECT_VERSION\"" > resources/cider/nrepl/version.edn; \ - lein with-profile -user,-dev,-provided,+$(CLOJURE_VERSION),+plugin.mranderson/config deploy clojars + lein with-profile -user,-dev,-provided,$(COMMON_PROFILES),+plugin.mranderson/config deploy clojars check-env: ifndef CLOJARS_USERNAME diff --git a/project.clj b/project.clj index 976e94b81..0706268c8 100644 --- a/project.clj +++ b/project.clj @@ -20,8 +20,7 @@ :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :scm {:name "git" :url "https://github.com/clojure-emacs/cider-nrepl"} - :dependencies [[nrepl/nrepl "1.4.0" :exclusions [org.clojure/clojure]] - [cider/orchard "0.37.0" :exclusions [org.clojure/clojure]] + :dependencies [[cider/orchard "0.37.0" :exclusions [org.clojure/clojure]] ^:inline-dep [compliment "0.7.1"] ^:inline-dep [org.rksm/suitable "0.6.2" :exclusions [org.clojure/clojure org.clojure/clojurescript]] @@ -78,15 +77,20 @@ :password :env/clojars_password :sign-releases false}]] - :profiles {:provided {:dependencies [[org.clojure/clojure "1.12.2"]]} + :profiles {:provided {:dependencies [[org.clojure/clojure "1.12.3"] + [nrepl/nrepl "1.4.0" :exclusions [org.clojure/clojure]]]} :1.10 {:dependencies [[org.clojure/clojure "1.10.3"] [org.clojure/clojurescript "1.10.520" :scope "provided"]]} :1.11 {:dependencies [[org.clojure/clojure "1.11.4"] [org.clojure/clojurescript "1.11.60" :scope "provided"]]} - :1.12 {:dependencies [[org.clojure/clojure "1.12.2"] + :1.12 {:dependencies [[org.clojure/clojure "1.12.3"] [org.clojure/clojurescript "1.12.42" :scope "provided"]]} + :nrepl-1.0 {:dependencies [[nrepl/nrepl "1.0.0" :exclusions [org.clojure/clojure]]]} + :nrepl-1.3 {:dependencies [[nrepl/nrepl "1.3.0" :exclusions [org.clojure/clojure]]]} + :nrepl-1.4 {:dependencies [[nrepl/nrepl "1.4.0" :exclusions [org.clojure/clojure]]]} + :maint {:source-paths ["src" "maint"] :dependencies [[org.clojure/tools.cli "1.2.245"]]} diff --git a/test/clj/cider/nrepl_test.clj b/test/clj/cider/nrepl_test.clj index 9562d58d5..3ad87dac5 100644 --- a/test/clj/cider/nrepl_test.clj +++ b/test/clj/cider/nrepl_test.clj @@ -1,9 +1,14 @@ (ns cider.nrepl-test (:require [cider.nrepl :as sut] - [clojure.test :refer [deftest is testing]])) + [clojure.test :refer [deftest is testing]] + [nrepl.version])) -(deftest clojure-version-sanity-check +(deftest versions-sanity-check (is (let [v (System/getenv "CLOJURE_VERSION")] (println "Running on Clojure" (clojure-version)) - (or (nil? v) (.startsWith ^String (clojure-version) v))))) + (or (nil? v) (.startsWith ^String (clojure-version) v)))) + (is (let [v (System/getenv "NREPL_VERSION") + nver (:version-string nrepl.version/version)] + (println "Running on nREPL" nver) + (or (nil? v) (.startsWith ^String nver v))))) From d5eaf72b1ccd0ec8e98fb5d048f87d6845a48ee4 Mon Sep 17 00:00:00 2001 From: Oleksandr Yakushev Date: Sat, 11 Oct 2025 15:53:53 +0300 Subject: [PATCH 9/9] [debug] Correctly process #dbg during load-file (#951) * [debug] Correctly process #dbg during load-file * Fix broken tests --- .circleci/config.yml | 4 +- CHANGELOG.md | 1 + Makefile | 2 +- project.clj | 5 +- src/cider/nrepl.clj | 5 +- src/cider/nrepl/middleware/debug.clj | 117 ++++++++++---- src/cider/nrepl/middleware/util/eval.clj | 15 ++ .../nrepl/middleware/util/instrument.clj | 49 +++++- src/cider/nrepl/middleware/util/nrepl.clj | 13 +- .../middleware/debug_integration_test.clj | 22 +++ .../clj/cider/nrepl/middleware/debug_test.clj | 12 +- .../cider/nrepl/middleware/inspect_test.clj | 40 ++--- .../cider/nrepl/middleware/refresh_test.clj | 145 +++++++++--------- 13 files changed, 293 insertions(+), 137 deletions(-) create mode 100644 src/cider/nrepl/middleware/util/eval.clj diff --git a/.circleci/config.yml b/.circleci/config.yml index e67e373dc..a1b408791 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -140,7 +140,7 @@ jobs: nrepl_version: description: Version of nREPL to test against type: string - default: "1.4" + default: "1.5" executor: << parameters.jdk_version >> environment: CLOJURE_VERSION: << parameters.clojure_version >> @@ -221,7 +221,7 @@ workflows: parameters: clojure_version: ["1.12"] jdk_version: [jdk25] - nrepl_version: ["1.0", "1.3", "1.4"] + nrepl_version: ["1.0", "1.3", "1.4", "1.5"] <<: *run_always - lint: <<: *run_always diff --git a/CHANGELOG.md b/CHANGELOG.md index 88dad4fcc..ee3039921 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Bump `orchard` to [0.37.0](https://github.com/clojure-emacs/orchard/blob/master/CHANGELOG.md#0370-2025-09-19). * Bump `compliment` to [0.7.1](https://github.com/alexander-yakushev/compliment/blob/master/CHANGELOG.md#071-2025-09-19). * [#950](https://github.com/clojure-emacs/cider-nrepl/pull/950): Inspect: support tidying qualified keywords. +* [#951](https://github.com/clojure-emacs/cider-nrepl/pull/951): Debug: correctly process #dbg tag during load-file. ## 0.57.0 (2025-06-29) diff --git a/Makefile b/Makefile index 512880740..92e971359 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ SHELL = /bin/bash -Eex CLOJURE_VERSION ?= 1.12 -NREPL_VERSION ?= 1.4 +NREPL_VERSION ?= 1.5 COMMON_PROFILES = "+$(CLOJURE_VERSION),+nrepl-$(NREPL_VERSION)" TEST_PROFILES ?= "-user,-dev,+test" diff --git a/project.clj b/project.clj index 0706268c8..3cf6b4397 100644 --- a/project.clj +++ b/project.clj @@ -78,7 +78,7 @@ :sign-releases false}]] :profiles {:provided {:dependencies [[org.clojure/clojure "1.12.3"] - [nrepl/nrepl "1.4.0" :exclusions [org.clojure/clojure]]]} + [nrepl/nrepl "1.5.0-alpha2" :exclusions [org.clojure/clojure]]]} :1.10 {:dependencies [[org.clojure/clojure "1.10.3"] [org.clojure/clojurescript "1.10.520" :scope "provided"]]} @@ -90,6 +90,7 @@ :nrepl-1.0 {:dependencies [[nrepl/nrepl "1.0.0" :exclusions [org.clojure/clojure]]]} :nrepl-1.3 {:dependencies [[nrepl/nrepl "1.3.0" :exclusions [org.clojure/clojure]]]} :nrepl-1.4 {:dependencies [[nrepl/nrepl "1.4.0" :exclusions [org.clojure/clojure]]]} + :nrepl-1.5 {:dependencies [[nrepl/nrepl "1.5.0-alpha2" :exclusions [org.clojure/clojure]]]} :maint {:source-paths ["src" "maint"] :dependencies [[org.clojure/tools.cli "1.2.245"]]} @@ -142,5 +143,7 @@ :eastwood [:test {:plugins [[jonase/eastwood "1.4.3"]] :eastwood {:config-files ["eastwood.clj"] + :ignored-faults {:unused-ret-vals {orchard.java {:line 84} + cider.nrepl.middleware.util.instrument {:line 396}}} :exclude-namespaces [cider.nrepl.middleware.debug-test cider.nrepl.middleware.test-filter-tests]}}]}) diff --git a/src/cider/nrepl.clj b/src/cider/nrepl.clj index 248d59cbf..91e3029dd 100644 --- a/src/cider/nrepl.clj +++ b/src/cider/nrepl.clj @@ -207,12 +207,15 @@ Depending on the type of the return value of the evaluation this middleware may "complete-flush-caches" {:doc "Forces the completion backend to repopulate all its caches"}}})) +;; `wrap-debug` has to be sandwiched between `load-file` and `eval`. First +;; `load-file` transforms its message into an `eval`, then `wrap-debug` attaches +;; its instrumenting functions to the message, and finally `eval` does the work. (def-wrapper wrap-debug cider.nrepl.middleware.debug/handle-debug #{"eval"} (cljs/requires-piggieback {:doc "Provide instrumentation and debugging functionality." :expects #{"eval"} - :requires #{#'wrap-print #'session} + :requires #{#'wrap-print #'session "load-file"} :handles {"debug-input" {:doc "Read client input on debug action." :requires {"input" "The user's reply to the input request." diff --git a/src/cider/nrepl/middleware/debug.clj b/src/cider/nrepl/middleware/debug.clj index eb956caaa..1f04f34b2 100644 --- a/src/cider/nrepl/middleware/debug.clj +++ b/src/cider/nrepl/middleware/debug.clj @@ -2,12 +2,14 @@ "Expression-based debugger for clojure code" {:author "Artur Malabarba"} (:require + [clojure.string :as str] [cider.nrepl.middleware.inspect :refer [swap-inspector!]] [cider.nrepl.middleware.util :as util :refer [respond-to]] [cider.nrepl.middleware.util.cljs :as cljs] + [cider.nrepl.middleware.util.eval] [cider.nrepl.middleware.util.instrument :as ins] [cider.nrepl.middleware.util.nrepl :refer [notify-client]] - [nrepl.middleware.interruptible-eval :refer [*msg*]] + [nrepl.middleware.interruptible-eval :as ieval :refer [*msg*]] [nrepl.middleware.print :as print] [orchard.info :as info] [orchard.inspect :as inspect] @@ -175,6 +177,9 @@ this map (identified by a key), and will `dissoc` it afterwards."} (defonce print-options (atom nil)) (defonce step-in-to-next? (atom false)) +(def ^:private nrepl-1-5+? + (cider.nrepl.middleware.util.nrepl/satisfies-version? 1 5)) + (defn pr-short "Like `pr-str` but limited in length and depth." [x] @@ -466,6 +471,10 @@ this map (identified by a key), and will `dissoc` it afterwards."} (def ^:dynamic *tmp-forms* (atom {})) (def ^:dynamic *do-locals* true) +#_:clj-kondo/ignore +(def ^:dynamic ^:private *found-debugger-tag*) +#_:clj-kondo/ignore +(def ^:dynamic ^:private *top-level-form-meta*) (defmacro with-initial-debug-bindings "Let-wrap `body` with STATE__ map containing code, file, line, column etc. @@ -476,17 +485,26 @@ this map (identified by a key), and will `dissoc` it afterwards."} {:style/indent 0} [& body] ;; NOTE: *msg* is the message that instrumented the function, - `(let [~'STATE__ {:msg ~(let [{:keys [code id file line column ns]} *msg*] - {:code code - ;; Passing clojure.lang.Namespace object - ;; as :original-ns breaks nREPL in bewildering - ;; ways. - ;; NOTE: column numbers in the response map - ;; start from 1 according to Clojure. - ;; This is not a bug and should be converted to - ;; 0-based indexing by the client if necessary. - :original-id id, :original-ns (str (or ns *ns*)) - :file file, :line line, :column column}) + `(let [~'STATE__ {:msg ~(if (bound? #'*top-level-form-meta*) + (let [{:keys [line column ns], form-info ::form-info} + *top-level-form-meta* + {:keys [code file original-id]} form-info] + {:code code + ;; Passing clojure.lang.Namespace object + ;; as :original-ns breaks nREPL in bewildering + ;; ways. + ;; NOTE: column numbers in the response map + ;; start from 1 according to Clojure. + ;; This is not a bug and should be converted to + ;; 0-based indexing by the client if necessary. + :original-ns (str (or ns *ns*)) + :original-id original-id + :file file, :line line, :column column}) + (let [{:keys [code file line column ns id]} *msg*] + {:code code + :original-ns (str (or ns *ns*)) + :original-id id + :file file, :line line, :column column})) ;; the coor of first form is used as the debugger session id :session-id (atom nil) :skip (atom false) @@ -626,50 +644,59 @@ this map (identified by a key), and will `dissoc` it afterwards."} ;;; ## Data readers ;; ;; Set in `src/data_readers.clj`. + +(defn- found-debugger-tag [] + (when (bound? #'*found-debugger-tag*) + (set! *found-debugger-tag* true))) + (defn breakpoint-reader "#break reader. Mark `form` for breakpointing." [form] + (found-debugger-tag) (ins/tag-form form #'breakpoint-with-initial-debug-bindings true)) (defn debug-reader "#dbg reader. Mark all forms in `form` for breakpointing. `form` itself is also marked." [form] + (found-debugger-tag) (ins/tag-form (ins/tag-form-recursively form #'breakpoint-if-interesting) #'breakpoint-if-interesting-with-initial-debug-bindings)) (defn break-on-exception-reader "#exn reader. Wrap `form` in try-catch and break only on exception" [form] + (found-debugger-tag) (ins/tag-form form #'breakpoint-if-exception-with-initial-debug-bindings true)) (defn debug-on-exception-reader "#dbgexn reader. Mark all forms in `form` for breakpointing on exception. `form` itself is also marked." [form] + (found-debugger-tag) (ins/tag-form (ins/tag-form-recursively form #'breakpoint-if-exception) #'breakpoint-if-exception-with-initial-debug-bindings)) (defn instrument-and-eval [form] - (let [form1 (ins/instrument-tagged-code form)] - ;; (ins/print-form form1 true false) - (try - (binding [*tmp-forms* (atom {})] - (eval form1)) - (catch java.lang.RuntimeException e - (if (some #(when % - (re-matches #".*Method code too large!.*" - (.getMessage ^Throwable %))) - [e (.getCause e)]) - (do (notify-client *msg* - (str "Method code too large!\n" - "Locals and evaluation in local context won't be available.") - :warning) - ;; re-try without locals - (binding [*tmp-forms* (atom {}) - *do-locals* false] - (eval form1))) - (throw e)))))) + (with-bindings (if nrepl-1-5+? {#'*top-level-form-meta* (meta form)} {}) + (let [form1 (ins/instrument-tagged-code form)] + (try + (binding [*tmp-forms* (atom {})] + (eval form1)) + (catch java.lang.RuntimeException e + (if (some #(when % + (re-matches #".*Method code too large!.*" + (.getMessage ^Throwable %))) + [e (.getCause e)]) + (do (notify-client *msg* + (str "Method code too large!\n" + "Locals and evaluation in local context won't be available.") + :warning) + ;; re-try without locals + (binding [*tmp-forms* (atom {}) + *do-locals* false] + (eval form1))) + (throw e))))))) (def ^:dynamic *debug-data-readers* "Reader macros like #dbg which cause code to be instrumented when present." @@ -701,6 +728,30 @@ this map (identified by a key), and will `dissoc` it afterwards."} ;; If there was no reader macro, fallback on regular eval. msg))) +(defn- maybe-debug-nrepl-1-5+ + "Alternative implementation of `maybe-debug` that is only supported with nREPL + 1.5+ or higher. This version supports forms compiled by `load-file` and + doesn't perform double read like the older version." + [msg] + (let [read-fn + (fn [options reader] + (binding [*found-debugger-tag* false] + ;; Read the form normally and then check if the flag turned on that + ;; tells us the form contains any debugger reader tags. + (let [[form code] (ins/comment-trimming-read+string options reader)] + (if *found-debugger-tag* + ;; Attach the original (but cleaned up) source code for the + ;; instrumenter to set up correct debugger state later. + (vary-meta form assoc + ::form-info {:code code + :file (:file msg) + :original-id (:id msg)}) + form))))] + (assoc msg + ::ieval/read-fn read-fn + ::ieval/eval-fn (cider.nrepl.middleware.util.eval/eval-dispatcher + instrument-and-eval ::form-info)))) + (defn- initialize "Initialize the channel used for debug-input requests." [{:keys [:nrepl.middleware.print/options] :as msg}] @@ -723,7 +774,9 @@ this map (identified by a key), and will `dissoc` it afterwards."} (case op "eval" (do (when (instance? clojure.lang.Atom session) (swap! session assoc #'*skip-breaks* (atom nil))) - (handler (maybe-debug msg))) + (handler (if nrepl-1-5+? + (maybe-debug-nrepl-1-5+ msg) + (maybe-debug msg)))) "debug-instrumented-defs" (instrumented-defs-reply msg) "debug-input" (when-let [pro (@promises (:key msg))] (deliver pro input)) diff --git a/src/cider/nrepl/middleware/util/eval.clj b/src/cider/nrepl/middleware/util/eval.clj new file mode 100644 index 000000000..5e70c391a --- /dev/null +++ b/src/cider/nrepl/middleware/util/eval.clj @@ -0,0 +1,15 @@ +(ns cider.nrepl.middleware.util.eval + (:import clojure.lang.Compiler)) + +;; The sole reason for this namespace to exist is to prevent +;; `cider.nrepl.middleware.debug/instrument-and-eval` from appearing on the +;; stacktrace when we don't, in fact, compile with the debugger. Sure, this may +;; seem minor, but I don't want to confuse users and send them on wild geese +;; chases thinking that the debugger may be somehow related to the thrown +;; exceptions when it is not enabled at all. + +(defn eval-dispatcher [debugger-eval-fn dispatch-kw] + (fn [form] + (if (get (meta form) dispatch-kw) + (debugger-eval-fn form) + (Compiler/eval form true)))) diff --git a/src/cider/nrepl/middleware/util/instrument.clj b/src/cider/nrepl/middleware/util/instrument.clj index 1fb28238c..c0d2182ec 100644 --- a/src/cider/nrepl/middleware/util/instrument.clj +++ b/src/cider/nrepl/middleware/util/instrument.clj @@ -4,7 +4,8 @@ (:require clojure.pprint [clojure.walk :as walk] - [orchard.meta :as m])) + [orchard.meta :as m]) + (:import (clojure.lang LineNumberingPushbackReader))) ;;;; # Instrumentation ;;; @@ -382,6 +383,52 @@ (filter (comp :cider/instrumented meta second)) (map first)))) +;; Utilities for correctly mapping the read form to its string content. Default +;; Clojure `read+string` returns leading comments and other garbage as if it is +;; part of the read form, making our lives harder when we want to align that +;; with the content of Emacs buffer. + +(defn- skip-n-lines + "Find the character offset where the nth line starts (after n newlines)." + [s lines-to-skip] + (try + (let [matcher (re-matcher #"\r?\n" s)] + (dotimes [_ lines-to-skip] (re-find matcher)) + (.end matcher)) + (catch IllegalStateException _ 0))) + +(defn- trim-to-form + "Trim captured string from reader start position to actual form start position" + [captured-string start-line start-col form-line form-col] + (if (and (= start-line form-line) (= start-col form-col)) + ;; No trimming needed - form starts exactly where we started reading + captured-string + ;; Need to trim: walk through the string counting lines and columns + (let [lines-to-skip (- form-line start-line) + final-offset (if (= lines-to-skip 0) + (- form-col start-col) + (+ (skip-n-lines captured-string lines-to-skip) + (dec form-col)))] ;; 1-based to 0-based + (subs captured-string final-offset)))) + +(defn comment-trimming-read+string + "Like `read+string` but trims comments and skipped forms from the string result, + thus only returning the string that actually backs the read form, without the + cruft could be before it." + [opts, ^LineNumberingPushbackReader reader] + (let [start-line (.getLineNumber reader) + start-col (.getColumnNumber reader)] + (.captureString reader) + (let [form (read opts reader) + captured-string (.getString reader) + {:keys [line column]} (meta form) + ;; If form has line/column metadata, trim the captured string. + trimmed-string (if (and line column) + (trim-to-form captured-string start-line start-col + line column) + captured-string)] + [form trimmed-string]))) + ;;; Instrumentation test support ;;; ;;; This code migrated out of the test namespace to avoid a dependency diff --git a/src/cider/nrepl/middleware/util/nrepl.clj b/src/cider/nrepl/middleware/util/nrepl.clj index f41d0b9f2..690593037 100644 --- a/src/cider/nrepl/middleware/util/nrepl.clj +++ b/src/cider/nrepl/middleware/util/nrepl.clj @@ -1,9 +1,18 @@ (ns cider.nrepl.middleware.util.nrepl - "Common utilities for interaction with the client." + "Common nREPL-related utilities." (:require [nrepl.middleware.interruptible-eval :refer [*msg*]] [nrepl.misc :refer [response-for]] - [nrepl.transport :as transport])) + [nrepl.transport :as transport] + [nrepl.version :refer [version]])) + +(defn satisfies-version? + "Check if the nREPL version is of the provided major and minor parts or newer." + [major minor] + (>= (compare ((juxt :major :minor) version) [major minor]) 0)) + +#_(satisfies-version? 0 9) +#_(satisfies-version? 1 10) (defn notify-client "Send user level notification to client as a response to request `msg`. diff --git a/test/clj/cider/nrepl/middleware/debug_integration_test.clj b/test/clj/cider/nrepl/middleware/debug_integration_test.clj index 9b4a98d03..6545c7b96 100644 --- a/test/clj/cider/nrepl/middleware/debug_integration_test.clj +++ b/test/clj/cider/nrepl/middleware/debug_integration_test.clj @@ -98,6 +98,10 @@ (defmethod debugger-send :eval [_ code] (nrepl-send {:op "eval" :code code})) +(defmethod debugger-send :load-file [_ code] + (nrepl-send {:op "load-file", :file code + :file-path "path/to/file.clj", :file-name "file.clj"})) + (defmacro def-debug-op [op] `(defmethod debugger-send ~op [_#] (nrepl-send {:op "debug-input" :input ~(str op) :key (current-key)}))) @@ -712,3 +716,21 @@ (--> :continue-all) (<-- {:value "{:transport 23}"}) (<-- {:status ["done"]})) + +(when @#'d/nrepl-1-5+? + (deftest load-file-enables-debugger-test + (--> :load-file ";; comments before form + #_(redundant stuff) + (defn foo [a b] #dbg (+ a b))") + (<-- {:value "#'user/foo"}) + (<-- {:status ["done"]}) + + (--> :eval "(foo 4 5)") + (<-- {:debug-value "4" :coor [3 1] + :code "(defn foo [a b] #dbg (+ a b))"}) + (--> :next) + (<-- {:debug-value "5" :coor [3 2]}) + (--> :next) + (<-- {:debug-value "9" :coor [3]}) + (--> :next) + (<-- {:value "9"}))) diff --git a/test/clj/cider/nrepl/middleware/debug_test.clj b/test/clj/cider/nrepl/middleware/debug_test.clj index c017eb36a..682d20a5f 100644 --- a/test/clj/cider/nrepl/middleware/debug_test.clj +++ b/test/clj/cider/nrepl/middleware/debug_test.clj @@ -208,12 +208,12 @@ v) d/debugger-message (atom [:fake]) d/*skip-breaks* (atom nil)] - (binding [*msg* {:session (atom {}) - :code :code - :id :id - :file :file - :line :line - :column :column}] + (with-bindings {#'d/*top-level-form-meta* + {::d/form-info {:code :code + :file :file + :original-id :id} + :line :line + :column :column}} (let [form `(d/with-initial-debug-bindings (d/breakpoint-if-interesting (inc 10) {:coor [6]} ~'(inc 10))) m (eval form)] diff --git a/test/clj/cider/nrepl/middleware/inspect_test.clj b/test/clj/cider/nrepl/middleware/inspect_test.clj index c51c51aba..a32628831 100644 --- a/test/clj/cider/nrepl/middleware/inspect_test.clj +++ b/test/clj/cider/nrepl/middleware/inspect_test.clj @@ -598,18 +598,19 @@ (deftest inspect-print-current-value-test (testing "inspect-print-current-value returns the currently inspected value as a printed string" - (is (= [(str/join "\n" ["{:a -1," - " :bb \"111\"," - " :ccc (1)," - " :d" - " ({:a 0, :bb \"000\", :ccc ()}" - " {:a -1, :bb \"111\", :ccc (1)}" - " {:a -2, :bb \"222\", :ccc (2 1)}" - " {:a -3, :bb \"333\", :ccc (3 2 1)}" - " {:a -4, :bb \"444\", :ccc (4 3 2 1)})}"])] - (:value (do - (session/message {:op "eval" - :code "(def test-val + (is+ {:value ["{:a -1, + :bb \"111\", + :ccc (1), + :d + ({:a 0, :bb \"000\", :ccc ()} + {:a -1, :bb \"111\", :ccc (1)} + {:a -2, :bb \"222\", :ccc (2 1)} + {:a -3, :bb \"333\", :ccc (3 2 1)} + {:a -4, :bb \"444\", :ccc (4 3 2 1)})} +"]} + (do + (session/message {:op "eval" + :code "(def test-val (for [i (range 2)] {:a (- i) :bb (str i i i) @@ -618,13 +619,14 @@ {:a (- i) :bb (str i i i) :ccc (range i 0 -1)})}))"}) - (session/message {:op "eval" - :inspect "true" - :code "test-val"}) - (session/message {:op "inspect-push" - :idx 2}) - (session/message {:op "inspect-print-current-value" - :nrepl.middleware.print/print "cider.nrepl.pprint/pprint"}))))))) + (session/message {:op "eval" + :inspect "true" + :code "test-val"}) + (session/message {:op "inspect-push" + :idx 2}) + (session/message {:op "inspect-print-current-value" + :nrepl.middleware.print/buffer-size 2048 + :nrepl.middleware.print/print "cider.nrepl.pprint/orchard-pprint"}))))) (deftest inspect-print-current-value-no-value-test (testing "inspect-print-current-value returns nil if nothing has been inspected yet" diff --git a/test/clj/cider/nrepl/middleware/refresh_test.clj b/test/clj/cider/nrepl/middleware/refresh_test.clj index 60cea6778..506fad7a5 100644 --- a/test/clj/cider/nrepl/middleware/refresh_test.clj +++ b/test/clj/cider/nrepl/middleware/refresh_test.clj @@ -3,7 +3,9 @@ [cider.nrepl.middleware.refresh :as r] [cider.nrepl.middleware.util.reload :as reload-utils] [cider.nrepl.test-session :as session] - [clojure.test :refer :all])) + [cider.test-helpers :refer :all] + [clojure.test :refer :all] + [matcher-combinators.matchers :as mc])) (use-fixtures :each session/session-fixture) @@ -30,99 +32,98 @@ (deftest refresh-op-test (testing "refresh op works" - (let [response (session/message {:op "refresh" - :dirs dirs-to-reload})] - (is (:reloading response)) - (is (= #{"done" "ok"} (:status response))))) + (is+ {:reloading some? + :status #{"done" "ok"}} + (session/message {:op "refresh" + :dirs dirs-to-reload}))) (testing "nothing to refresh after refreshing" - (let [response (session/message {:op "refresh" - :dirs dirs-to-reload})] - (is (= [] (:reloading response))) - (is (= #{"done" "ok"} (:status response)))))) + (is+ {:reloading [] + :status #{"done" "ok"}} + (session/message {:op "refresh" + :dirs dirs-to-reload})))) (deftest before-fn-test (testing "before fn works" - (let [response (session/message {:op "refresh" - :dirs dirs-to-reload - :before "cider.nrepl.middleware.refresh-test/before-fn"})] - (is (:reloading response)) - (is (= #{"done" "invoked-before" "invoking-before" "ok"} (:status response))) - (is (= "before-fn invoked\n" (:out response))))) + (is+ {:reloading some? + :status #{"done" "invoked-before" "invoking-before" "ok"} + :out "before-fn invoked\n"} + (session/message {:op "refresh" + :dirs dirs-to-reload + :before "cider.nrepl.middleware.refresh-test/before-fn"}))) (testing "bad before fn results in not resolved response" - (let [response (session/message {:op "refresh" - :dirs dirs-to-reload - :before "foo"})] - (is (= #{"done" "invoked-not-resolved" "ok" "invoking-before"} (:status response)))) - - (let [response (session/message {:op "refresh" - :dirs dirs-to-reload - :before "clojure.core/seq"})] - (is (= #{"done" "error" "invoking-before"} (:status response))) - (is (:err response)) - (is (:error response))) - - (let [response (session/message {:op "refresh" - :dirs dirs-to-reload - :before "java.lang.Thread"})] - (is (= #{"done" "invoked-not-resolved" "invoking-before" "ok"} - (:status response)))))) + (is+ {:status #{"done" "invoked-not-resolved" "ok" "invoking-before"}} + (session/message {:op "refresh" + :dirs dirs-to-reload + :before "non-existent/foo"})) + + (is+ {:status #{"done" "error" "invoking-before"} + :err some? + :error some?} + (session/message {:op "refresh" + :dirs dirs-to-reload + :before "clojure.core/seq"})) + + (is+ {:status #{"done" "invoked-not-resolved" "invoking-before" "ok"}} + (session/message {:op "refresh" + :dirs dirs-to-reload + :before "java.lang.Thread"})))) (deftest after-fn-test (testing "after fn with zero arity works" - (let [response (session/message {:op "refresh" - :dirs dirs-to-reload - :after "cider.nrepl.middleware.refresh-test/after-fn"})] - (is (:reloading response)) - (is (= #{"done" "invoked-after" "invoking-after" "ok"} (:status response))) - (is (= "after-fn invoked\n" (:out response))))) + (is+ {:reloading some? + :status #{"done" "invoked-after" "invoking-after" "ok"} + :out "after-fn invoked\n"} + (session/message {:op "refresh" + :dirs dirs-to-reload + :after "cider.nrepl.middleware.refresh-test/after-fn"}))) (testing "after fn with optional arg works" - (let [response (session/message {:op "refresh" - :dirs dirs-to-reload - :after "cider.nrepl.middleware.refresh-test/after-fn-optional-arg"})] - (is (:reloading response)) - (is (= #{"done" "invoked-after" "invoking-after" "ok"} (:status response))) - (is (= "after with optional argument works\n" (:out response))))) + (is+ {:reloading some? + :status #{"done" "invoked-after" "invoking-after" "ok"} + :out "after with optional argument works\n"} + (session/message {:op "refresh" + :dirs dirs-to-reload + :after "cider.nrepl.middleware.refresh-test/after-fn-optional-arg"}))) (testing "bad after fn results in error" - (let [response (session/message {:op "refresh" - :dirs dirs-to-reload - :after "foo"})] - (is (= #{"done" "invoked-not-resolved" "invoking-after" "ok"} (:status response)))) - - (let [response (session/message {:op "refresh" - :dirs dirs-to-reload - :after "clojure.core/seq"})] - (is (= #{"done" "error" "invoking-after" "ok"} (:status response))) - (is (:error response)) - (is (:err response))) - - (let [response (session/message {:op "refresh" - :dirs dirs-to-reload - :after "java.lang.Thread"})] - (is (= #{"done" "invoked-not-resolved" "invoking-after" "ok"} (:status response)))))) + (is+ {:status #{"done" "invoked-not-resolved" "invoking-after" "ok"}} + (session/message {:op "refresh" + :dirs dirs-to-reload + :after "non-existent/foo"})) + + (is+ {:status #{"done" "error" "invoking-after" "ok"} + :err some? + :error some?} + (session/message {:op "refresh" + :dirs dirs-to-reload + :after "clojure.core/seq"})) + + (is+ {:status #{"done" "invoked-not-resolved" "invoking-after" "ok"}} + (session/message {:op "refresh" + :dirs dirs-to-reload + :after "java.lang.Thread"})))) (deftest refresh-all-op-test (testing "refresh-all op works" - (let [response (session/message {:op "refresh-all" - :dirs dirs-to-reload})] - (is (seq (:reloading response))) - (is (= #{"done" "ok"} (:status response)))))) + (is+ {:reloading not-empty + :status #{"done" "ok"}} + (session/message {:op "refresh-all" + :dirs dirs-to-reload})))) (deftest refresh-clear-op-test (testing "refresh-clear op works" - (let [_ (session/message {:op "refresh" - :dirs dirs-to-reload}) - response (session/message {:op "refresh-clear"})] - (is (= #{"done"} (:status response))))) + (is+ {:status #{"done"}} + (do (session/message {:op "refresh" + :dirs dirs-to-reload}) + (session/message {:op "refresh-clear"})))) (testing "refresh op works after refresh clear" - (let [response (session/message {:op "refresh" - :dirs dirs-to-reload})] - (is (seq (:reloading response))) - (is (= #{"done" "ok"} (:status response)))))) + (is+ {:reloading not-empty + :status #{"done" "ok"}} + (session/message {:op "refresh" + :dirs dirs-to-reload})))) (deftest user-refresh-dirs-test (testing "returns nil if clojure.tools.namespace isn't loaded"