From 1d73a0447d68a658376f25b255b0667e95277842 Mon Sep 17 00:00:00 2001 From: Roman Rudakov Date: Fri, 16 May 2025 16:07:26 +0200 Subject: [PATCH] Improve support of extend-protocol forms --- CHANGELOG.md | 4 ++++ README.md | 2 +- clojure-ts-mode.el | 19 +++++++++++++++++-- test/clojure-ts-mode-font-lock-test.el | 8 +++++++- ...clojure-ts-mode-refactor-add-arity-test.el | 14 ++++++++++++++ test/samples/refactoring.clj | 6 ++++++ 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e042df9..5b31208 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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`. diff --git a/README.md b/README.md index d10ca0c..4a25a7d 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/clojure-ts-mode.el b/clojure-ts-mode.el index a4263b4..8b6bca7 100644 --- a/clojure-ts-mode.el +++ b/clojure-ts-mode.el @@ -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 @@ -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) @@ -2196,6 +2207,7 @@ type, etc. See `treesit-thing-settings' for more details." "defmacro" "defmethod" "defprotocol" + "extend-protocol" "reify" "proxy") eol)) @@ -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)) diff --git a/test/clojure-ts-mode-font-lock-test.el b/test/clojure-ts-mode-font-lock-test.el index 8611211..1fa9ed1 100644 --- a/test/clojure-ts-mode-font-lock-test.el +++ b/test/clojure-ts-mode-font-lock-test.el @@ -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)))) diff --git a/test/clojure-ts-mode-refactor-add-arity-test.el b/test/clojure-ts-mode-refactor-add-arity-test.el index 9c31f27..f119607 100644 --- a/test/clojure-ts-mode-refactor-add-arity-test.el +++ b/test/clojure-ts-mode-refactor-add-arity-test.el @@ -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 diff --git a/test/samples/refactoring.clj b/test/samples/refactoring.clj index 10f12b5..5a87bf7 100644 --- a/test/samples/refactoring.clj +++ b/test/samples/refactoring.clj @@ -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))))