Skip to content

Improve support of extend-protocol forms #96

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 17, 2025
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## main (unreleased)

- [#96](https://github.com/clojure-emacs/clojure-ts-mode/pull/96): Highlight function name properly in `extend-protocol` form.
- [#96](https://github.com/clojure-emacs/clojure-ts-mode/pull/96): Add support for extend-protocol forms to `clojure-ts-add-arity` refactoring
command.

## 0.4.0 (2025-05-15)

- [#16](https://github.com/clojure-emacs/clojure-ts-mode/issues/16): Introduce `clojure-ts-align`.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ set. The following commands are available:
`clojure-ts-add-arity`: Add a new arity to an existing single-arity or
multi-arity function or macro. Function can be defined using `defn`, `fn` or
`defmethod` form. This command also supports functions defined inside forms like
`letfn`, `defprotol`, `reify` or `proxy`.
`letfn`, `defprotol`, `reify`, `extend-protocol` or `proxy`.

### Default keybindings

Expand Down
19 changes: 17 additions & 2 deletions clojure-ts-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,12 @@ literals with regex grammar."
(sym_lit name: (sym_name) @font-lock-function-name-face))))
((list_lit
((sym_lit name: (sym_name) @def)
((:equal "reify" @def)))
((:match ,(rx-to-string
`(seq bol
(or "reify"
"extend-protocol")
eol))
@def)))
(list_lit
(sym_lit name: (sym_name) @font-lock-function-name-face))))
;; letfn
Expand Down Expand Up @@ -2186,6 +2191,12 @@ type, etc. See `treesit-thing-settings' for more details."
(and (clojure-ts--list-node-p node)
(string= (clojure-ts--list-node-sym-text parent) "reify"))))

(defun clojure-ts--extend-protocol-defn-p (node)
"Return non-nil if NODE is a function definition in an extend-protocol form."
(when-let* ((parent (treesit-node-parent node)))
(and (clojure-ts--list-node-p node)
(string= (clojure-ts--list-node-sym-text parent) "extend-protocol"))))

(defun clojure-ts-add-arity ()
"Add an arity to a function or macro."
(interactive)
Expand All @@ -2196,6 +2207,7 @@ type, etc. See `treesit-thing-settings' for more details."
"defmacro"
"defmethod"
"defprotocol"
"extend-protocol"
"reify"
"proxy")
eol))
Expand All @@ -2210,13 +2222,16 @@ type, etc. See `treesit-thing-settings' for more details."
(clojure-ts--parent-until #'clojure-ts--defprotocol-defn-p))
((string= parent-def-sym "reify")
(clojure-ts--parent-until #'clojure-ts--reify-defn-p))
((string= parent-def-sym "extend-protocol")
(clojure-ts--parent-until #'clojure-ts--extend-protocol-defn-p))
(t parent-def-node))))
(let ((beg-marker (copy-marker (treesit-node-start parent-def-node)))
(end-marker (copy-marker (treesit-node-end parent-def-node))))
(cond
((string= parent-def-sym "defprotocol")
(clojure-ts--add-arity-defprotocol-internal fn-node))
((string= parent-def-sym "reify")
((or (string= parent-def-sym "reify")
(string= parent-def-sym "extend-protocol"))
(clojure-ts--add-arity-reify-internal fn-node))
(t (clojure-ts--add-arity-internal fn-node)))
(indent-region beg-marker end-marker))
Expand Down
8 changes: 7 additions & 1 deletion test/clojure-ts-mode-font-lock-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,10 @@ DESCRIPTION is the description of the spec."
(2 12 font-lock-keyword-face)
(14 14 font-lock-type-face)
(19 21 font-lock-function-name-face)
(34 39 font-lock-function-name-face))))
(34 39 font-lock-function-name-face))

("(extend-protocol prepare/SettableParameter
clojure.lang.IPersistentMap
(set-parameter [m ^PreparedStatement s i]
(.setObject s i (->pgobject m))))"
(81 93 font-lock-function-name-face))))
14 changes: 14 additions & 0 deletions test/clojure-ts-mode-refactor-add-arity-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,20 @@

(clojure-ts-add-arity))

(when-refactoring-with-point-it "should handle an extend-protocol"
"(extend-protocol prepare/SettableParameter
clojure.lang.IPersistentMap
(set-parameter [m ^PreparedStatement s i]
(.setObject| s i (->pgobject m))))"

"(extend-protocol prepare/SettableParameter
clojure.lang.IPersistentMap
(set-parameter [|])
(set-parameter [m ^PreparedStatement s i]
(.setObject s i (->pgobject m))))"

(clojure-ts-add-arity))

(it "should signal a user error when point is not inside a function body"
(with-clojure-ts-buffer-point "
(letf|n [(foo
Expand Down
6 changes: 6 additions & 0 deletions test/samples/refactoring.clj
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,9 @@

(when-not true
(println "Hello world"))

(extend-protocol prepare/SettableParameter
clojure.lang.IPersistentMap
(set-parameter [])
(set-parameter [m ^PreparedStatement s i]
(.setObject| s i (->pgobject m))))