Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .markdownlint-cli2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
config:
default: true

line-length:
line_length: 100
code_blocks: false
tables: false

no-duplicate-heading:
allow_different_nesting: true

no-inline-html: false

first-line-heading: false
49 changes: 27 additions & 22 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Changelog

<!-- Entries are one line per item and section headings repeat for every release,
so the line-length and duplicate-heading rules don't fit this file. -->
<!-- markdownlint-disable MD013 MD024 -->

## Unreleased

- **(Breaking)** Use refactor-nrepl's namespaced op names (`refactor/find-symbol`, `refactor/clean-ns`, …) instead of the bare ones. refactor-nrepl treats the namespaced forms as canonical and plans to drop the bare names, and namespacing avoids op-name collisions with other middleware. This requires refactor-nrepl 3.13.0+ (the injected version is now 3.14.0).
- Use refactor-nrepl's namespaced op names (`refactor/find-symbol`, `refactor/clean-ns`, …) when the middleware advertises them (refactor-nrepl 3.13.0+, the injected version is now 3.14.0), falling back to the bare names on older versions. refactor-nrepl treats the namespaced forms as canonical and plans to drop the bare names, and namespacing avoids op-name collisions with other middleware.
- Don't error out of `cider-connected-hook` when the refactor-nrepl middleware is missing: the connect-time version probe now degrades to the existing "out of sync" warning instead of aborting the startup checks with a cryptic error (visible with CIDER 2.0, whose senders reject unsupported ops client-side).
- `cljr-rename-symbol`, `cljr-find-usages`, `cljr-inline-symbol` and `cljr-change-function-signature` now send an explicit `ignore-errors` value that matches `cljr-ignore-analyzer-errors`, instead of a nil value that was dropped on the wire. With the default (nil) this means the strict behavior the option documents actually takes effect - a project with an unanalyzable namespace now surfaces a warning rather than silently skipping it.
- `cljr-slash` no longer sends the obsolete `language-context` parameter to the `suggest-libspecs` op (superseded by `buffer-language-context`/`input-language-context` in refactor-nrepl 3.7.0).

Expand Down Expand Up @@ -64,39 +69,39 @@
## 3.11.2

- [Upgrade refactor-nrepl](https://github.com/clojure-emacs/refactor-nrepl/blob/v3.9.1/CHANGELOG.md#391).
- Fixes https://github.com/clojure-emacs/clj-refactor.el/issues/556
- Fixes <https://github.com/clojure-emacs/clj-refactor.el/issues/556>

## 3.11.1

* [#555](https://github.com/clojure-emacs/clj-refactor.el/pull/555): expand default `cljr-magic-require-namespaces` aliases.
* [#555](https://github.com/clojure-emacs/clj-refactor.el/pull/555): Handle an edge case for `cljr-slash`.
- [#555](https://github.com/clojure-emacs/clj-refactor.el/pull/555): expand default `cljr-magic-require-namespaces` aliases.
- [#555](https://github.com/clojure-emacs/clj-refactor.el/pull/555): Handle an edge case for `cljr-slash`.

## 3.11.0

* [#554](https://github.com/clojure-emacs/clj-refactor.el/pull/554): Enable `cljr-slash-uses-suggest-libspec` by default.
- [#554](https://github.com/clojure-emacs/clj-refactor.el/pull/554): Enable `cljr-slash-uses-suggest-libspec` by default.

## 3.10.0

* [#552](https://github.com/clojure-emacs/clj-refactor.el/issues/552): support TRAMP connections.
- [#552](https://github.com/clojure-emacs/clj-refactor.el/issues/552): support TRAMP connections.

## 3.9.4

* Fix `cljr-version`.
- Fix `cljr-version`.

## 3.9.3

* Internal: avoid the use of deprecated Elisp functions.
- Internal: avoid the use of deprecated Elisp functions.

## 3.9.2

* [#523](https://github.com/clojure-emacs/clj-refactor.el/issues/523): Increase `js/` namespace detection accuracy for .cljc files.
* [#517](https://github.com/clojure-emacs/clj-refactor.el/issues/517): Remove `pkg-info` dependency.
- [#523](https://github.com/clojure-emacs/clj-refactor.el/issues/523): Increase `js/` namespace detection accuracy for .cljc files.
- [#517](https://github.com/clojure-emacs/clj-refactor.el/issues/517): Remove `pkg-info` dependency.

## 3.9.1

* [#430](https://github.com/clojure-emacs/clj-refactor.el/issues/430) `cljr-add-missing-libspec`: produce more friendly prompts.
* `cljr-add-missing-libspec`: don't suggest members that are already interned into the current namespace.
* e.g. the class `Thread` or the var `+` are already interned by default in Clojure namespaces, so they are redundant to suggest or insert into the `ns` form.
- [#430](https://github.com/clojure-emacs/clj-refactor.el/issues/430) `cljr-add-missing-libspec`: produce more friendly prompts.
- `cljr-add-missing-libspec`: don't suggest members that are already interned into the current namespace.
- e.g. the class `Thread` or the var `+` are already interned by default in Clojure namespaces, so they are redundant to suggest or insert into the `ns` form.

## 3.9.0

Expand Down Expand Up @@ -127,33 +132,33 @@

## 3.5.6

* [Upgrade refactor-nrepl](https://github.com/clojure-emacs/refactor-nrepl/blob/v3.5.5/CHANGELOG.md#355).
- [Upgrade refactor-nrepl](https://github.com/clojure-emacs/refactor-nrepl/blob/v3.5.5/CHANGELOG.md#355).

## 3.5.5

* [Upgrade refactor-nrepl](https://github.com/clojure-emacs/refactor-nrepl/blob/v3.5.4/CHANGELOG.md#354).
- [Upgrade refactor-nrepl](https://github.com/clojure-emacs/refactor-nrepl/blob/v3.5.4/CHANGELOG.md#354).

## 3.5.4

* [Upgrade refactor-nrepl](https://github.com/clojure-emacs/refactor-nrepl/blob/v3.5.3/CHANGELOG.md#353).
- [Upgrade refactor-nrepl](https://github.com/clojure-emacs/refactor-nrepl/blob/v3.5.3/CHANGELOG.md#353).

## 3.5.3

* Upgrade `cider`, `parseedn` and `inflections` dependencies.
- Upgrade `cider`, `parseedn` and `inflections` dependencies.

## 3.5.2

* Use refactor-nrepl [3.5.2](https://github.com/clojure-emacs/refactor-nrepl/blob/v3.5.2/CHANGELOG.md#352).
- Use refactor-nrepl [3.5.2](https://github.com/clojure-emacs/refactor-nrepl/blob/v3.5.2/CHANGELOG.md#352).

## 3.5.1

* Use refactor-nrepl [3.5.1](https://github.com/clojure-emacs/refactor-nrepl/blob/v3.5.1/CHANGELOG.md#351).
- Use refactor-nrepl [3.5.1](https://github.com/clojure-emacs/refactor-nrepl/blob/v3.5.1/CHANGELOG.md#351).

## 3.5.0

* Use refactor-nrepl [3.5.0](https://github.com/clojure-emacs/refactor-nrepl/blob/v3.5.0/CHANGELOG.md#350).
* Improve integration with Clojure 1.11's new `:as-alias` namespace directive.
* Closes [#515](https://github.com/clojure-emacs/clj-refactor.el/issues/515), [#516](https://github.com/clojure-emacs/clj-refactor.el/issues/516)
- Use refactor-nrepl [3.5.0](https://github.com/clojure-emacs/refactor-nrepl/blob/v3.5.0/CHANGELOG.md#350).
- Improve integration with Clojure 1.11's new `:as-alias` namespace directive.
- Closes [#515](https://github.com/clojure-emacs/clj-refactor.el/issues/515), [#516](https://github.com/clojure-emacs/clj-refactor.el/issues/516)

## 3.4.3

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ clj-refactor | refactor-nrepl | CIDER | Clojure | Java |
2.4.0 | 2.4.0 | 0.17, 0.18 | 1.7+ | 8+ |
2.5.0 | 2.5.0 | 0.24 | 1.8+ | 8+ |
3.0.0+ | 3.0.0+ | 1.0 | 1.9+ | 11+ |
4.0.0+ | 3.13.0+ | 1.11+ | 1.10+ | 8+ |
4.0.0+ | 3.x (3.13.0+ recommended) | 1.11+ | 1.10+ | 8+ |

clj-refactor 4.0.0+ requires Emacs 28.1 or newer.

Expand Down
44 changes: 35 additions & 9 deletions clj-refactor.el
Original file line number Diff line number Diff line change
Expand Up @@ -1010,15 +1010,29 @@ with those of other middleware.")
"Return refactor-nrepl op OP as its canonical namespaced name."
(concat cljr--middleware-op-prefix op))

(defun cljr--resolve-op (op)
"Resolve the bare refactor-nrepl OP name against the current connection.
Prefer the canonical namespaced form (see `cljr--middleware-op'), but fall
back to the bare name when only that is advertised - refactor-nrepl older
than 3.13.0 doesn't know the namespaced ops. When there's no connection to
consult, or neither form is supported, return the namespaced form so error
messages show the canonical name."
(let ((namespaced (cljr--middleware-op op)))
(cond ((not (cider-connected-p)) namespaced)
((cider-nrepl-op-supported-p namespaced) namespaced)
((cider-nrepl-op-supported-p op) op)
(t namespaced))))

(defun cljr--create-msg (op &rest kvs)
"Create a msg for the middleware for OP and optionally include the kv pairs KVS.

OP is given as its bare refactor-nrepl name and is namespaced here (see
`cljr--middleware-op'). All config settings are included in the created msg."
OP is given as its bare refactor-nrepl name and is resolved to the form the
connected middleware supports (see `cljr--resolve-op'). All config settings
are included in the created msg."
(cl-assert (cl-evenp (length kvs)) nil "Can't create msg to send to the middleware.\
Received an uneven number of kv pairs: %s " kvs)
(apply #'list
"op" (cljr--middleware-op op)
"op" (cljr--resolve-op op)

"prefix-rewriting"
(if cljr-favor-prefix-notation
Expand Down Expand Up @@ -1245,14 +1259,16 @@ See: https://github.com/clojure-emacs/clj-refactor.el/wiki/cljr-rename-file-or-d

(defun cljr--op-supported-p (op)
"Is the refactor-nrepl OP (bare name) provided by the current middleware?
OP is namespaced (see `cljr--middleware-op') so this checks for the
canonical op, matching what `cljr--create-msg' actually sends."
Checks the canonical namespaced form (see `cljr--middleware-op') as well as
the bare one, so old middleware that only advertises the bare names counts
as support too - matching the op resolution `cljr--create-msg' performs."
;; Guard on the connection first: `cider-nrepl-op-supported-p' resolves the
;; REPL with the `ensure' flag and signals `No linked CIDER sessions' when
;; nothing is connected. We want a plain nil there, so the offline fallbacks
;; that gate on this predicate (`cljr-slash', `cljr-clean-ns', ...) can kick in.
(and (cider-connected-p)
(cider-nrepl-op-supported-p (cljr--middleware-op op))))
(or (cider-nrepl-op-supported-p (cljr--middleware-op op))
(cider-nrepl-op-supported-p op))))

(defun cljr--assert-middleware ()
(unless (featurep 'cider)
Expand Down Expand Up @@ -3889,7 +3905,7 @@ See: https://github.com/clojure-emacs/clj-refactor.el/wiki/cljr-inline-symbol"
(ns (or (nrepl-dict-get var-info "ns") (cider-current-ns)))
(symbol-name (or (nrepl-dict-get var-info "name") symbol))
(extract-definition-request (list
"op" (cljr--middleware-op "extract-definition")
"op" (cljr--resolve-op "extract-definition")
"ns" ns
"dir" dir
"file" filename
Expand Down Expand Up @@ -3942,7 +3958,17 @@ for avoiding a warning that would be irrelevant for this case."
:package-version "3.0.0")

(defun cljr--middleware-version ()
(cljr--call-middleware-sync (cljr--create-msg "version") "version"))
"Return the version of the connected refactor-nrepl, or nil.
A failed probe returns nil (with the error reported as a message)
instead of signaling: CIDER 2.0's senders reject unsupported ops
client-side, and this probe runs from `cider-connected-hook' where an
error would abort the rest of the startup checks - including the
out-of-sync warning itself."
(condition-case err
(cljr--call-middleware-sync (cljr--create-msg "version") "version")
(error (message "clj-refactor: middleware version probe failed: %s"
(error-message-string err))
nil)))

(defun cljr--check-middleware-version ()
"Check whether clj-refactor and nrepl-refactor versions are the same."
Expand All @@ -3968,7 +3994,7 @@ warning by customizing `cljr-suppress-no-project-warning'.)"))))
(interactive)
(message "clj-refactor %s, refactor-nrepl %s"
(cljr--version)
(or (ignore-errors (cljr--middleware-version))
(or (cljr--middleware-version)
"is unreachable")))

;;;###autoload
Expand Down
40 changes: 39 additions & 1 deletion tests/unit-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,45 @@ str/"))))
(describe "cljr--op-supported-p"
(it "returns nil (rather than erroring) when no REPL is connected"
(spy-on 'cider-connected-p :and-return-value nil)
(expect (cljr--op-supported-p "clean-ns") :to-be nil)))
(expect (cljr--op-supported-p "clean-ns") :to-be nil))
(it "counts middleware that only advertises the bare op names as support"
(spy-on 'cider-connected-p :and-return-value t)
(spy-on 'cider-nrepl-op-supported-p :and-call-fake
(lambda (op) (member op '("clean-ns"))))
(expect (cljr--op-supported-p "clean-ns") :to-be-truthy)))

(describe "cljr--resolve-op"
;; refactor-nrepl >= 3.13.0 advertises every op under both its bare name
;; and the namespaced `refactor/' form; older versions only know the bare
;; names. We prefer the canonical namespaced form but must keep working
;; against the old middleware.
(it "prefers the namespaced form when the middleware advertises it"
(spy-on 'cider-connected-p :and-return-value t)
(spy-on 'cider-nrepl-op-supported-p :and-call-fake
(lambda (op) (member op '("refactor/clean-ns" "clean-ns"))))
(expect (cljr--resolve-op "clean-ns") :to-equal "refactor/clean-ns"))
(it "falls back to the bare name on old middleware"
(spy-on 'cider-connected-p :and-return-value t)
(spy-on 'cider-nrepl-op-supported-p :and-call-fake
(lambda (op) (member op '("clean-ns"))))
(expect (cljr--resolve-op "clean-ns") :to-equal "clean-ns")
(expect (cadr (cljr--create-msg "clean-ns")) :to-equal "clean-ns"))
(it "returns the namespaced form when disconnected"
(spy-on 'cider-connected-p :and-return-value nil)
(expect (cljr--resolve-op "clean-ns") :to-equal "refactor/clean-ns"))
(it "returns the namespaced form when neither form is supported"
(spy-on 'cider-connected-p :and-return-value t)
(spy-on 'cider-nrepl-op-supported-p :and-return-value nil)
(expect (cljr--resolve-op "clean-ns") :to-equal "refactor/clean-ns")))

(describe "cljr--middleware-version"
(it "returns nil (rather than erroring) when the version probe fails"
;; CIDER 2.0's senders signal a `user-error' client-side for unsupported
;; ops; this probe runs from `cider-connected-hook', where an error would
;; abort the startup checks - including the out-of-sync warning itself.
(spy-on 'cljr--call-middleware-sync :and-call-fake
(lambda (&rest _) (user-error "unsupported op")))
(expect (cljr--middleware-version) :to-be nil)))

(describe "cljr-clean-ns offline fallback"
;; Drive the real `cljr--op-supported-p' by faking a disconnected REPL,
Expand Down
Loading