Skip to content

Commit c6b5122

Browse files
committed
Enhance add arity refactoring.
Support reader conditionals, letfn, defprotocol, reify and proxy in addition to defn.
1 parent 2f90ebc commit c6b5122

File tree

3 files changed

+178
-23
lines changed

3 files changed

+178
-23
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Bugs fixed
66

77
* [#520](https://github.com/clojure-emacs/clojure-mode/issues/508): Fix allow `clojure-align-cond-forms` to recognize qualified forms.
8+
* Enhance add arity refactoring to support reader conditionals, letfn, defprotocol, reify and proxy.
89

910
## 5.11.0 (2019-07-16)
1011

clojure-mode.el

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2738,37 +2738,76 @@ With a numeric prefix argument the let is introduced N lists up."
27382738
(clojure--rename-ns-alias-internal current-alias new-alias))
27392739
(message "Cannot find namespace alias: '%s'" current-alias))))))
27402740

2741-
;;;###autoload
2742-
(defun clojure-add-arity ()
2743-
"Add an arity to a function."
2744-
(interactive)
2745-
(let ((end (save-excursion (end-of-defun)
2746-
(point)))
2747-
(beg (progn (beginning-of-defun)
2748-
(point))))
2741+
(defun clojure-add-arity-defprotocol-internal ()
2742+
"Add an arity to a signature inside a defprotocol.
2743+
2744+
Assumes cursor is at beginning of signature."
2745+
(re-search-forward "\\[")
2746+
(save-excursion (insert "] [")))
2747+
2748+
(defun clojure-add-arity-reify-internal ()
2749+
"Add an arity to a function inside a reify.
2750+
2751+
Assumes cursor is at beginning of function."
2752+
(re-search-forward "\\(\\w+ \\)")
2753+
(insert "[")
2754+
(save-excursion (insert "])\n(" (match-string 0))))
2755+
2756+
(defun clojure-add-arity-internal ()
2757+
"Add an arity to a function.
2758+
2759+
Assumes cursor is at beginning of function."
2760+
(let ((beg-line (what-line))
2761+
(end (save-excursion (forward-sexp)
2762+
(point))))
27492763
(down-list 2)
27502764
(when (looking-back "{" 1) ;; skip metadata if present
27512765
(up-list)
27522766
(down-list))
27532767
(cond
2754-
((looking-back "(" 1) ;; multi-arity defn
2768+
((looking-back "(" 1) ;; multi-arity fn
27552769
(insert "[")
2756-
(save-excursion (insert "])\n("))
2757-
(indent-region beg end))
2758-
((looking-back "\\[" 1) ;; single-arity defn
2759-
(let* ((bol (save-excursion (beginning-of-line) (point)))
2760-
(same-line (save-excursion (re-search-backward "defn" bol t)))
2761-
(new-arity-text (concat (when same-line "\n") "([])\n[")))
2762-
(re-search-backward " +\\[")
2763-
(replace-match new-arity-text)
2770+
(save-excursion (insert "])\n(")))
2771+
((looking-back "\\[" 1) ;; single-arity fn
2772+
(let* ((same-line (string= beg-line (what-line)))
2773+
(new-arity-text (concat (when same-line "\n") "([")))
27642774
(save-excursion
2765-
(end-of-defun)
2766-
(re-search-backward ")")
2775+
(goto-char end)
27672776
(insert ")"))
2768-
(left-char)
2769-
(insert "(")
2770-
(indent-region beg end)
2771-
(left-char 6))))))
2777+
2778+
(re-search-backward " +\\[")
2779+
(replace-match new-arity-text)
2780+
(save-excursion (insert "])\n([")))))))
2781+
2782+
;;;###autoload
2783+
(defun clojure-add-arity ()
2784+
"Add an arity to a function."
2785+
(interactive)
2786+
(let ((original-pos (point))
2787+
(n 0))
2788+
(while (not (looking-at-p "(\\(defn\\|letfn\\|defprotocol\\|reify\\|proxy\\)"))
2789+
(setq n (1+ n))
2790+
(backward-up-list 1 t))
2791+
(let ((beg (point))
2792+
(end-marker (make-marker))
2793+
(end (save-excursion (forward-sexp)
2794+
(point))))
2795+
(set-marker end-marker end)
2796+
(cond
2797+
((looking-at-p "(defn") (clojure-add-arity-internal))
2798+
((looking-at-p "(letfn") (progn (goto-char original-pos)
2799+
(backward-up-list (- n 2) t)
2800+
(clojure-add-arity-internal)))
2801+
((looking-at-p "(proxy") (progn (goto-char original-pos)
2802+
(backward-up-list (- n 1) t)
2803+
(clojure-add-arity-internal)))
2804+
((looking-at-p "(defprotocol") (progn (goto-char original-pos)
2805+
(backward-up-list (- n 1) t)
2806+
(clojure-add-arity-defprotocol-internal)))
2807+
((looking-at-p "(reify") (progn (goto-char original-pos)
2808+
(backward-up-list (- n 1) t)
2809+
(clojure-add-arity-reify-internal))))
2810+
(indent-region beg end-marker))))
27722811

27732812

27742813
;;; ClojureScript

test/clojure-mode-refactor-add-arity-test.el

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,121 @@ DESCRIPTION is a string with the description of the spec."
149149
([arg]
150150
body))"
151151

152+
(clojure-add-arity))
153+
154+
(when-refactoring-with-point-it "should handle a defn inside a reader conditional"
155+
"#?(:clj
156+
(defn foo
157+
\"some docstring\"
158+
^{:bla \"meta\"}
159+
|([arg]
160+
body)))"
161+
162+
"#?(:clj
163+
(defn foo
164+
\"some docstring\"
165+
^{:bla \"meta\"}
166+
([|])
167+
([arg]
168+
body)))"
169+
170+
(clojure-add-arity))
171+
172+
(when-refactoring-with-point-it "should handle a defn inside a reader conditional with 2 platform tags"
173+
"#?(:clj
174+
(defn foo
175+
\"some docstring\"
176+
^{:bla \"meta\"}
177+
|([arg]
178+
body))
179+
:cljs
180+
(defn foo
181+
\"some docstring\"
182+
^{:bla \"meta\"}
183+
([arg]
184+
body)))"
185+
186+
"#?(:clj
187+
(defn foo
188+
\"some docstring\"
189+
^{:bla \"meta\"}
190+
([|])
191+
([arg]
192+
body))
193+
:cljs
194+
(defn foo
195+
\"some docstring\"
196+
^{:bla \"meta\"}
197+
([arg]
198+
body)))"
199+
200+
(clojure-add-arity))
201+
202+
(when-refactoring-with-point-it "should handle a single-arity fn inside a letfn"
203+
"(letfn [(foo [x]
204+
bo|dy)]
205+
(foo 3))"
206+
207+
"(letfn [(foo
208+
([|])
209+
([x]
210+
body))]
211+
(foo 3))"
212+
213+
(clojure-add-arity))
214+
215+
(when-refactoring-with-point-it "should handle a multi-arity fn inside a letfn"
216+
"(letfn [(foo
217+
([x]
218+
body)
219+
|([x y]
220+
body))]
221+
(foo 3))"
222+
223+
"(letfn [(foo
224+
([|])
225+
([x]
226+
body)
227+
([x y]
228+
body))]
229+
(foo 3))"
230+
231+
(clojure-add-arity))
232+
233+
(when-refactoring-with-point-it "should handle a proxy"
234+
"(proxy [Foo] []
235+
(bar [arg]
236+
body|))"
237+
238+
"(proxy [Foo] []
239+
(bar
240+
([|])
241+
([arg]
242+
body)))"
243+
244+
(clojure-add-arity))
245+
246+
(when-refactoring-with-point-it "should handle a defprotocol"
247+
"(defprotocol Foo
248+
\"some docstring\"
249+
(bar [arg] [x |y] \"some docstring\"))"
250+
251+
"(defprotocol Foo
252+
\"some docstring\"
253+
(bar [|] [arg] [x y] \"some docstring\"))"
254+
255+
(clojure-add-arity))
256+
257+
(when-refactoring-with-point-it "should handle a reify"
258+
"(reify Foo
259+
(bar [arg] body)
260+
(blahs [arg]| body))"
261+
262+
"(reify Foo
263+
(bar [arg] body)
264+
(blahs [|])
265+
(blahs [arg] body))"
266+
152267
(clojure-add-arity)))
153268

154269
(provide 'clojure-mode-refactor-add-arity-test)

0 commit comments

Comments
 (0)